Skip to content

Commit 696d9d1

Browse files
jayesh-tannaJayesh Tanna
andauthored
Add training type support for fine-tuning jobs (#44036)
* Add training type support for fine-tuning jobs * updating readme.md --------- Co-authored-by: Jayesh Tanna <[email protected]>
1 parent acbf01f commit 696d9d1

11 files changed

+83
-94
lines changed

sdk/ai/azure-ai-projects/README.md

Lines changed: 11 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -737,9 +737,9 @@ print(f"Successfully deleted file: {deleted_file.id}")
737737

738738
### Fine-tuning operations
739739

740-
The code below shows Fine-tuning operations using the OpenAI client, which allow you to create, retrieve, list, cancel, pause, resume, and manage fine-tuning jobs. These operations support various fine-tuning techniques like Supervised Fine-Tuning (SFT), Reinforcement Fine-Tuning (RFT), and Direct Performance Optimization (DPO). Full samples can be found under the "finetuning" folder in the [package samples][samples].
740+
The code below shows how to create fine-tuning jobs using the OpenAI client. These operations support various fine-tuning techniques like Supervised Fine-Tuning (SFT), Reinforcement Fine-Tuning (RFT), and Direct Performance Optimization (DPO). Full samples can be found under the "finetuning" folder in the [package samples][samples].
741741

742-
<!-- SNIPPET:sample_finetuning_supervised_job.finetuning_supervised_job_sample-->
742+
<!-- SNIPPET:sample_finetuning_oss_models_supervised_job.finetuning_oss_model_supervised_job_sample-->
743743

744744
```python
745745
print("Uploading training file...")
@@ -752,8 +752,10 @@ with open(validation_file_path, "rb") as f:
752752
validation_file = openai_client.files.create(file=f, purpose="fine-tune")
753753
print(f"Uploaded validation file with ID: {validation_file.id}")
754754

755-
# For OpenAI model supervised fine-tuning jobs, "Standard" is the default training type.
756-
# To use global standard training, uncomment the extra_body parameter below.
755+
print("Waits for the training and validation files to be processed...")
756+
openai_client.files.wait_for_processing(train_file.id)
757+
openai_client.files.wait_for_processing(validation_file.id)
758+
757759
print("Creating supervised fine-tuning job")
758760
fine_tuning_job = openai_client.fine_tuning.jobs.create(
759761
training_file=train_file.id,
@@ -763,76 +765,13 @@ fine_tuning_job = openai_client.fine_tuning.jobs.create(
763765
"type": "supervised",
764766
"supervised": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
765767
},
766-
# extra_body={"trainingType":"GlobalStandard"}
768+
extra_body={
769+
"trainingType": "GlobalStandard"
770+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
771+
# Preferred trainingtype is GlobalStandard. Note: Global training offers cost savings , but copies data and weights outside the current resource region.
772+
# Learn more - https://azure.microsoft.com/en-us/pricing/details/cognitive-services/openai-service/ and https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/
767773
)
768774
print(fine_tuning_job)
769-
770-
print(f"Getting fine-tuning job with ID: {fine_tuning_job.id}")
771-
retrieved_job = openai_client.fine_tuning.jobs.retrieve(fine_tuning_job.id)
772-
print(retrieved_job)
773-
774-
print("Listing all fine-tuning jobs:")
775-
for job in openai_client.fine_tuning.jobs.list():
776-
print(job)
777-
778-
print("Listing only 10 fine-tuning jobs:")
779-
for job in openai_client.fine_tuning.jobs.list(limit=10):
780-
print(job)
781-
782-
print(f"Pausing fine-tuning job with ID: {fine_tuning_job.id}")
783-
paused_job = openai_client.fine_tuning.jobs.pause(fine_tuning_job.id)
784-
print(paused_job)
785-
786-
print(f"Resuming fine-tuning job with ID: {fine_tuning_job.id}")
787-
resumed_job = openai_client.fine_tuning.jobs.resume(fine_tuning_job.id)
788-
print(resumed_job)
789-
790-
print(f"Listing events of fine-tuning job: {fine_tuning_job.id}")
791-
for event in openai_client.fine_tuning.jobs.list_events(fine_tuning_job.id):
792-
print(event)
793-
794-
# Note that to retrieve the checkpoints, job needs to be in terminal state.
795-
print(f"Listing checkpoints of fine-tuning job: {fine_tuning_job.id}")
796-
for checkpoint in openai_client.fine_tuning.jobs.checkpoints.list(fine_tuning_job.id):
797-
print(checkpoint)
798-
799-
print(f"Cancelling fine-tuning job with ID: {fine_tuning_job.id}")
800-
cancelled_job = openai_client.fine_tuning.jobs.cancel(fine_tuning_job.id)
801-
print(f"Successfully cancelled fine-tuning job: {cancelled_job.id}, Status: {cancelled_job.status}")
802-
803-
# Deploy model (using Azure Management SDK - azure-mgmt-cognitiveservices)
804-
# Note: Deployment can only be started after the fine-tuning job completes successfully.
805-
print(f"Getting fine-tuning job with ID: {fine_tuning_job.id}")
806-
fine_tuned_model_name = openai_client.fine_tuning.jobs.retrieve(fine_tuning_job.id).fine_tuned_model
807-
deployment_name = "gpt-4-1-fine-tuned"
808-
809-
with CognitiveServicesManagementClient(credential=credential, subscription_id=subscription_id) as cogsvc_client:
810-
811-
deployment_model = DeploymentModel(format="OpenAI", name=fine_tuned_model_name, version="1")
812-
813-
deployment_properties = DeploymentProperties(model=deployment_model)
814-
815-
deployment_sku = Sku(name="GlobalStandard", capacity=100)
816-
817-
deployment_config = Deployment(properties=deployment_properties, sku=deployment_sku)
818-
819-
deployment = cogsvc_client.deployments.begin_create_or_update(
820-
resource_group_name=resource_group,
821-
account_name=account_name,
822-
deployment_name=deployment_name,
823-
deployment=deployment_config,
824-
)
825-
826-
while deployment.status() not in ["Succeeded", "Failed"]:
827-
time.sleep(30)
828-
print(f"Status: {deployment.status()}")
829-
830-
print(f"Testing fine-tuned model via deployment: {deployment_name}")
831-
832-
response = openai_client.responses.create(
833-
model=deployment_name, input=[{"role": "user", "content": "Who invented the telephone?"}]
834-
)
835-
print(f"Model response: {response.output_text}")
836775
```
837776

838777
<!-- END SNIPPET -->

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_dpo_job.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@
5656
validation_file = openai_client.files.create(file=f, purpose="fine-tune")
5757
print(f"Uploaded validation file with ID: {validation_file.id}")
5858

59-
# For OpenAI model DPO fine-tuning jobs, "Standard" is the default training type.
60-
# To use global standard training, uncomment the extra_body parameter below.
59+
print("Waits for the training and validation files to be processed...")
60+
openai_client.files.wait_for_processing(train_file.id)
61+
openai_client.files.wait_for_processing(validation_file.id)
62+
6163
print("Creating DPO fine-tuning job")
6264
fine_tuning_job = openai_client.fine_tuning.jobs.create(
6365
training_file=train_file.id,
@@ -67,6 +69,8 @@
6769
"type": "dpo",
6870
"dpo": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
6971
},
70-
# extra_body={"trainingType":"GlobalStandard"}
72+
extra_body={
73+
"trainingType": "Standard"
74+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
7175
)
7276
print(fine_tuning_job)

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_dpo_job_async.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ async def main():
6161
validation_file = await openai_client.files.create(file=f, purpose="fine-tune")
6262
print(f"Uploaded validation file with ID: {validation_file.id}")
6363

64-
# For OpenAI model DPO fine-tuning jobs, "Standard" is the default training type.
65-
# To use global standard training, uncomment the extra_body parameter below.
64+
print("Waits for the training and validation files to be processed...")
65+
await openai_client.files.wait_for_processing(train_file.id)
66+
await openai_client.files.wait_for_processing(validation_file.id)
67+
6668
print("Creating DPO fine-tuning job")
6769
fine_tuning_job = await openai_client.fine_tuning.jobs.create(
6870
training_file=train_file.id,
@@ -78,7 +80,9 @@ async def main():
7880
}
7981
},
8082
},
81-
# extra_body={"trainingType":"GlobalStandard"}
83+
extra_body={
84+
"trainingType": "Standard"
85+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
8286
)
8387
print(fine_tuning_job)
8488

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_oss_models_supervised_job.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@
5858
validation_file = openai_client.files.create(file=f, purpose="fine-tune")
5959
print(f"Uploaded validation file with ID: {validation_file.id}")
6060

61+
print("Waits for the training and validation files to be processed...")
62+
openai_client.files.wait_for_processing(train_file.id)
63+
openai_client.files.wait_for_processing(validation_file.id)
64+
6165
print("Creating supervised fine-tuning job")
6266
fine_tuning_job = openai_client.fine_tuning.jobs.create(
6367
training_file=train_file.id,
@@ -67,6 +71,11 @@
6771
"type": "supervised",
6872
"supervised": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
6973
},
74+
extra_body={
75+
"trainingType": "GlobalStandard"
76+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
77+
# Preferred trainingtype is GlobalStandard. Note: Global training offers cost savings , but copies data and weights outside the current resource region.
78+
# Learn more - https://azure.microsoft.com/en-us/pricing/details/cognitive-services/openai-service/ and https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/
7079
)
7180
print(fine_tuning_job)
7281
# [END finetuning_oss_model_supervised_job_sample]

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_oss_models_supervised_job_async.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ async def main():
6161
validation_file = await openai_client.files.create(file=f, purpose="fine-tune")
6262
print(f"Uploaded validation file with ID: {validation_file.id}")
6363

64+
print("Waits for the training and validation files to be processed...")
65+
await openai_client.files.wait_for_processing(train_file.id)
66+
await openai_client.files.wait_for_processing(validation_file.id)
67+
6468
print("Creating supervised fine-tuning job")
6569
fine_tuning_job = await openai_client.fine_tuning.jobs.create(
6670
training_file=train_file.id,
@@ -70,6 +74,11 @@ async def main():
7074
"type": "supervised",
7175
"supervised": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
7276
},
77+
extra_body={
78+
"trainingType": "GlobalStandard"
79+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
80+
# Preferred trainingtype is GlobalStandard. Note: Global training offers cost savings , but copies data and weights outside the current resource region.
81+
# Learn more - https://azure.microsoft.com/en-us/pricing/details/cognitive-services/openai-service/ and https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/
7382
)
7483
print(fine_tuning_job)
7584

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_reinforcement_job.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@
5858
validation_file = openai_client.files.create(file=f, purpose="fine-tune")
5959
print(f"Uploaded validation file with ID: {validation_file.id}")
6060

61+
print("Waits for the training and validation files to be processed...")
62+
openai_client.files.wait_for_processing(train_file.id)
63+
openai_client.files.wait_for_processing(validation_file.id)
64+
6165
grader: Dict[str, Any] = {
6266
"name": "Response Quality Grader",
6367
"type": "score_model",
@@ -71,8 +75,6 @@
7175
"range": [0.0, 10.0],
7276
}
7377

74-
# For OpenAI model RFT fine-tuning jobs, "Standard" is the default training type.
75-
# To use global standard training, uncomment the extra_body parameter below.
7678
print("Creating reinforcement fine-tuning job")
7779
fine_tuning_job = openai_client.fine_tuning.jobs.create(
7880
training_file=train_file.id,
@@ -92,6 +94,8 @@
9294
},
9395
},
9496
},
95-
# extra_body={"trainingType":"GlobalStandard"}
97+
extra_body={
98+
"trainingType": "Standard"
99+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
96100
)
97101
print(fine_tuning_job)

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_reinforcement_job_async.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ async def main():
6060
validation_file = await openai_client.files.create(file=f, purpose="fine-tune")
6161
print(f"Uploaded validation file with ID: {validation_file.id}")
6262

63+
print("Waits for the training and validation files to be processed...")
64+
await openai_client.files.wait_for_processing(train_file.id)
65+
await openai_client.files.wait_for_processing(validation_file.id)
66+
6367
grader = {
6468
"name": "Response Quality Grader",
6569
"type": "score_model",
@@ -73,8 +77,6 @@ async def main():
7377
"range": [0.0, 10.0],
7478
}
7579

76-
# For OpenAI model RFT fine-tuning jobs, "Standard" is the default training type.
77-
# To use global standard training, uncomment the extra_body parameter below.
7880
fine_tuning_job = await openai_client.fine_tuning.jobs.create(
7981
training_file=train_file.id,
8082
validation_file=validation_file.id,
@@ -93,7 +95,9 @@ async def main():
9395
},
9496
},
9597
},
96-
# extra_body={"trainingType":"GlobalStandard"}
98+
extra_body={
99+
"trainingType": "Standard"
100+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
97101
)
98102
print(fine_tuning_job)
99103

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_supervised_job.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@
7272
validation_file = openai_client.files.create(file=f, purpose="fine-tune")
7373
print(f"Uploaded validation file with ID: {validation_file.id}")
7474

75-
# For OpenAI model supervised fine-tuning jobs, "Standard" is the default training type.
76-
# To use global standard training, uncomment the extra_body parameter below.
75+
print("Waits for the training and validation files to be processed...")
76+
openai_client.files.wait_for_processing(train_file.id)
77+
openai_client.files.wait_for_processing(validation_file.id)
78+
7779
print("Creating supervised fine-tuning job")
7880
fine_tuning_job = openai_client.fine_tuning.jobs.create(
7981
training_file=train_file.id,
@@ -83,7 +85,9 @@
8385
"type": "supervised",
8486
"supervised": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
8587
},
86-
# extra_body={"trainingType":"GlobalStandard"}
88+
extra_body={
89+
"trainingType": "Standard"
90+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
8791
)
8892
print(fine_tuning_job)
8993

sdk/ai/azure-ai-projects/samples/finetuning/sample_finetuning_supervised_job_async.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ async def main():
7575
validation_file = await openai_client.files.create(file=f, purpose="fine-tune")
7676
print(f"Uploaded validation file with ID: {validation_file.id}")
7777

78-
# For OpenAI model supervised fine-tuning jobs, "Standard" is the default training type.
79-
# To use global standard training, uncomment the extra_body parameter below.
78+
print("Waits for the training and validation files to be processed...")
79+
await openai_client.files.wait_for_processing(train_file.id)
80+
await openai_client.files.wait_for_processing(validation_file.id)
81+
8082
print("Creating supervised fine-tuning job")
8183
fine_tuning_job = await openai_client.fine_tuning.jobs.create(
8284
training_file=train_file.id,
@@ -86,7 +88,9 @@ async def main():
8688
"type": "supervised",
8789
"supervised": {"hyperparameters": {"n_epochs": 3, "batch_size": 1, "learning_rate_multiplier": 1.0}},
8890
},
89-
# extra_body={"trainingType":"GlobalStandard"}
91+
extra_body={
92+
"trainingType": "Standard"
93+
}, # Recommended approach to set trainingType. Omitting this field may lead to unsupported behavior.
9094
)
9195
print(fine_tuning_job)
9296

sdk/ai/azure-ai-projects/tests/finetuning/test_finetuning.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
)
1616
class TestFineTuning(TestBase):
1717

18-
def _create_sft_finetuning_job(self, openai_client, train_file_id, validation_file_id, model_type="openai"):
18+
def _create_sft_finetuning_job(
19+
self, openai_client, train_file_id, validation_file_id, model_type="openai", training_type="Standard"
20+
):
1921
"""Helper method to create a supervised fine-tuning job."""
2022
return openai_client.fine_tuning.jobs.create(
2123
training_file=train_file_id,
@@ -31,6 +33,7 @@ def _create_sft_finetuning_job(self, openai_client, train_file_id, validation_fi
3133
}
3234
},
3335
},
36+
extra_body={"trainingType": training_type},
3437
)
3538

3639
def _create_dpo_finetuning_job(self, openai_client, train_file_id, validation_file_id):
@@ -49,6 +52,7 @@ def _create_dpo_finetuning_job(self, openai_client, train_file_id, validation_fi
4952
}
5053
},
5154
},
55+
extra_body={"trainingType": "Standard"},
5256
)
5357

5458
def _create_rft_finetuning_job(self, openai_client, train_file_id, validation_file_id):
@@ -84,6 +88,7 @@ def _create_rft_finetuning_job(self, openai_client, train_file_id, validation_fi
8488
},
8589
},
8690
},
91+
extra_body={"trainingType": "Standard"},
8792
)
8893

8994
def _upload_test_files(self, openai_client, job_type="sft"):
@@ -323,7 +328,7 @@ def test_sft_finetuning_create_job_oss_model(self, **kwargs):
323328
train_file, validation_file = self._upload_test_files(openai_client, "sft")
324329

325330
fine_tuning_job = self._create_sft_finetuning_job(
326-
openai_client, train_file.id, validation_file.id, "oss"
331+
openai_client, train_file.id, validation_file.id, "oss", "GlobalStandard"
327332
)
328333
print(f"[test_finetuning_sft_oss] Created fine-tuning job: {fine_tuning_job.id}")
329334

0 commit comments

Comments
 (0)