Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
S’applique uniquement au :Portail Foundry (classique). Cet article n’est pas disponible pour le nouveau portail Foundry.
En savoir plus sur le nouveau portail.
Note
Les liens de cet article peuvent ouvrir du contenu dans la nouvelle documentation Microsoft Foundry au lieu de la documentation Foundry (classique) que vous affichez maintenant.
Ce tutoriel vous guide tout au long du réglage d’un gpt-4o-mini-2024-07-18 modèle.
Dans ce tutoriel, vous allez apprendre à :
- Créez des échantillons de jeux de données d'ajustement fin.
- Créez des variables d’environnement pour votre point de terminaison de ressource et votre clé API.
- Préparez vos exemples de jeux de données d’entraînement et de validation pour le réglage précis.
- Chargez votre fichier d’entraînement et votre fichier de validation pour le réglage précis.
- Créez un travail de réglage précis pour
gpt-4o-mini-2024-07-18. - Déployez un modèle affiné personnalisé.
Conditions préalables
- Un abonnement Azure - Create one gratuitement.
- Python version 3.8 ou ultérieure
- Bibliothèques Python suivantes :
json,requests,os,tiktoken,time,openai,numpy. - Jupyter Notebooks
- Ressource OpenAI Azure dans une region où
gpt-4o-mini-2024-07-18réglage précis est disponible. Si vous n’avez pas de ressource, le processus de création d’une ressource est documenté dans notre guide de déploiement de ressources. - L’accès au réglage précis nécessite le rôle Azure AI User.
- Si vous n'avez pas encore accès au quota et au déploiement de modèles dans le portail Microsoft Foundry, vous avez besoin de plus d'autorisations.
Important
Nous vous recommandons de consulter les informations de tarification pour un ajustement précis et ainsi vous familiariser avec les coûts associés. Le test de ce tutoriel a entraîné la facturation de 48 000 jetons (4 800 jetons d’entraînement * 10 époques d’entraînement). Les coûts de formation s'ajoutent aux coûts associés à l'ajustement fin de l'inférence et aux coûts d'hébergement par heure pour le déploiement d'un modèle affiné. Une fois que vous avez terminé le tutoriel, vous devez supprimer votre déploiement de modèle ajusté, sinon vous continuerez à engager des frais d’hébergement horaires.
Configurer
bibliothèques de Python
Ce tutoriel fournit des exemples de certaines des dernières fonctionnalités OpenAI : seed/events/checkpoints. Pour tirer parti de ces fonctionnalités, vous devrez peut-être exécuter pip install openai --upgrade pour effectuer une mise à niveau vers la dernière version.
pip install openai requests tiktoken numpy
Récupérer la clé et le point de terminaison
Pour effectuer un appel sur Azure OpenAI, vous avez besoin d’un endpoint et d’une key.
| Nom de la variable | Valeur |
|---|---|
ENDPOINT |
Le point de terminaison de service se trouve dans le https://docs-test-001.openai.azure.com/. |
API-KEY |
Cette valeur se trouve dans la KEY1 ou KEY2. |
Accédez à votre ressource dans le portail Azure. La section Clés et point de terminaison se trouve dans la section Gestion des ressources . Copiez votre point de terminaison et votre clé d’accès, car vous aurez besoin des deux pour authentifier vos appels d’API. Vous pouvez utiliser l’un ou l’autre KEY1 ou KEY2. Toujours avoir deux clés vous permet de faire pivoter et de régénérer en toute sécurité les clés sans provoquer d’interruption de service.
Variables d’environnement
Créez et affectez des variables d’environnement persistantes pour votre clé et votre point de terminaison.
Important
Utilisez des clés API avec précaution. N’incluez pas la clé API directement dans votre code et ne la publiez jamais publiquement. Si vous utilisez une clé API, stockez-la en toute sécurité dans Azure Key Vault. Pour plus d’informations sur l’utilisation sécurisée des clés API dans vos applications, consultez les API avec Azure Key Vault.
Pour plus d’informations sur la sécurité des services d’INTELLIGENCE artificielle, consultez Demandes d’authentification à Azure AI services.
setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
Créer un exemple de jeu de données
Le réglage gpt-4o-mini-2024-07-18 précis nécessite un fichier d’entraînement JSONL spécialement mis en forme. OpenAI fournit l’exemple suivant dans sa documentation :
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital/major city of France?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters."}]}
Pour cet exemple, nous modifions ceci légèrement en changeant pour :
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital/major city of France?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters."}]}
Bien que ces trois exemples soient utiles pour vous donner le format général, si vous souhaitez diriger votre modèle affiné personnalisé pour répondre de la même façon, vous aurez besoin d’autres exemples. En règle générale, vous voulez au moins 50 exemples de haute qualité pour commencer. Toutefois, il est tout à fait possible d’avoir un cas d’usage qui peut nécessiter 1 000 exemples de formation de haute qualité pour réussir.
En général, le doublement de la taille du jeu de données peut entraîner une augmentation linéaire de la qualité du modèle. Mais gardez à l’esprit que les exemples de faible qualité peuvent affecter négativement les performances. Si vous entraînez le modèle sur une grande quantité de données internes sans d’abord écarter le jeu de données pour les exemples de la plus haute qualité, vous pourriez aboutir à un modèle qui fonctionne moins bien que prévu.
Vous devez créer deux fichiers training_set.jsonl et validation_set.jsonl.
Créez les fichiers dans le même répertoire que celui que vous exécutez Jupyter Notebook, puis copiez le contenu des blocs de code suivants dans les fichiers correspondants :
training_set.jsonl
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who discovered Antarctica?"}, {"role": "assistant", "content": "Some chaps named Fabian Gottlieb von Bellingshausen and Mikhail Lazarev, as if they don't teach that in every school!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the biggest ocean?"}, {"role": "assistant", "content": "The Pacific Ocean. It's not like it's a small pond or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest planet?"}, {"role": "assistant", "content": "It's called Jupiter, you might have heard of it...or not."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who painted the Mona Lisa?"}, {"role": "assistant", "content": "Oh, some obscure artist named Leonardo da Vinci. Not that he is famous or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the boiling point of water?"}, {"role": "assistant", "content": "Exciting fact of the day: it's 100 degrees Celsius. Life-changing, isn't it?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'The Odyssey'?"}, {"role": "assistant", "content": "Oh, just some poet named Homer. Nothing special, really."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the largest mammal?"}, {"role": "assistant", "content": "Blue Whale. Quite a big fish isn't it? Oh wait, it's not a fish!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the highest mountain peak?"}, {"role": "assistant", "content": "Everest. Brace yourself, it's not a walk in the park."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who invented the telephone?"}, {"role": "assistant", "content": "A guy named Alexander Graham Bell. Bet you didn't guess that one!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the distance from Earth to the Sun?"}, {"role": "assistant", "content": "About 93 million miles. Just a quick drive, really."}]}
validation_set.jsonl
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of Australia?"}, {"role": "assistant", "content": "It's Canberra, not Sydney. Shocking, I know!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'The Great Gatsby'?"}, {"role": "assistant", "content": "Some guy named F. Scott Fitzgerald. Ever heard of him?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the deepest part of the ocean?"}, {"role": "assistant", "content": "Mariana Trench, makes your swimming pool seem a bit shallow, doesn't it?"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who composed the 'Moonlight Sonata'?"}, {"role": "assistant", "content": "Just a little-known guy named Beethoven. No big deal."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What are the colors of the rainbow?"}, {"role": "assistant", "content": "ROYGBIV. Red, orange, yellow, green, blue, indigo, violet. Not that we learned this in preschool or anything!"}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the smallest planet?"}, {"role": "assistant", "content": "Meet Mercury, the runt of the solar system family."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Pride and Prejudice'?"}, {"role": "assistant", "content": "Do the words Jane Austen ring a bell? No? Well, she wrote it."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the largest desert?"}, {"role": "assistant", "content": "Antarctica. Surprise, surprise! Deserts aren't just full of sand, you know."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What is the longest river?"}, {"role": "assistant", "content": "The Nile River. It's not like it's famous or anything."}]}
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of Germany?"}, {"role": "assistant", "content": "Berlin. Shocking news, right?"}]}
Vous devez maintenant exécuter des vérifications préliminaires sur nos fichiers de formation et de validation.
# Run preliminary checks
import json
# Load the training set
with open('training_set.jsonl', 'r', encoding='utf-8') as f:
training_dataset = [json.loads(line) for line in f]
# Training dataset stats
print("Number of examples in training set:", len(training_dataset))
print("First example in training set:")
for message in training_dataset[0]["messages"]:
print(message)
# Load the validation set
with open('validation_set.jsonl', 'r', encoding='utf-8') as f:
validation_dataset = [json.loads(line) for line in f]
# Validation dataset stats
print("\nNumber of examples in validation set:", len(validation_dataset))
print("First example in validation set:")
for message in validation_dataset[0]["messages"]:
print(message)
Sortie:
Number of examples in training set: 10
First example in training set:
{'role': 'system', 'content': 'Clippy is a factual chatbot that is also sarcastic.'}
{'role': 'user', 'content': 'Who discovered America?'}
{'role': 'assistant', 'content': "Some chap named Christopher Columbus, as if they don't teach that in every school!"}
Number of examples in validation set: 10
First example in validation set:
{'role': 'system', 'content': 'Clippy is a factual chatbot that is also sarcastic.'}
{'role': 'user', 'content': "What's the capital of Australia?"}
{'role': 'assistant', 'content': "It's Canberra, not Sydney. Shocking, I know!"}
Dans ce cas, nous n’avons que 10 exemples d'entraînement et 10 exemples de validation, bien que cela illustre la mécanique de base de l'affinage d’un modèle, ce qui est peu probable pour être un nombre suffisant d’exemples pour produire un effet tangible de manière cohérente.
Vous pouvez maintenant utiliser la bibliothèque tiktoken pour valider le nombre de jetons. Le comptage de jetons à l’aide de cette méthode ne va pas vous donner le nombre exact de jetons utilisés pour le réglage précis, mais doit fournir une bonne estimation.
Note
Les exemples individuels doivent rester sous la longueur actuelle de l’exemple gpt-4o-mini-2024-07-18 de contexte d’entraînement du modèle : 64 536 jetons. La limite de jetons d’entrée du modèle reste de 128 000 jetons.
# Validate token counts
import json
import tiktoken
import numpy as np
from collections import defaultdict
encoding = tiktoken.get_encoding("o200k_base") # default encoding for gpt-4o models. This requires the latest version of tiktoken to be installed.
def num_tokens_from_messages(messages, tokens_per_message=3, tokens_per_name=1):
num_tokens = 0
for message in messages:
num_tokens += tokens_per_message
for key, value in message.items():
num_tokens += len(encoding.encode(value))
if key == "name":
num_tokens += tokens_per_name
num_tokens += 3
return num_tokens
def num_assistant_tokens_from_messages(messages):
num_tokens = 0
for message in messages:
if message["role"] == "assistant":
num_tokens += len(encoding.encode(message["content"]))
return num_tokens
def print_distribution(values, name):
print(f"\n#### Distribution of {name}:")
print(f"min / max: {min(values)}, {max(values)}")
print(f"mean / median: {np.mean(values)}, {np.median(values)}")
print(f"p5 / p95: {np.quantile(values, 0.1)}, {np.quantile(values, 0.9)}")
files = ['training_set.jsonl', 'validation_set.jsonl']
for file in files:
print(f"Processing file: {file}")
with open(file, 'r', encoding='utf-8') as f:
dataset = [json.loads(line) for line in f]
total_tokens = []
assistant_tokens = []
for ex in dataset:
messages = ex.get("messages", {})
total_tokens.append(num_tokens_from_messages(messages))
assistant_tokens.append(num_assistant_tokens_from_messages(messages))
print_distribution(total_tokens, "total tokens")
print_distribution(assistant_tokens, "assistant tokens")
print('*' * 50)
Sortie:
Processing file: training_set.jsonl
#### Distribution of total tokens:
min / max: 46, 59
mean / median: 49.8, 48.5
p5 / p95: 46.0, 53.599999999999994
#### Distribution of assistant tokens:
min / max: 13, 28
mean / median: 16.5, 14.0
p5 / p95: 13.0, 19.9
**************************************************
Processing file: validation_set.jsonl
#### Distribution of total tokens:
min / max: 41, 64
mean / median: 48.9, 47.0
p5 / p95: 43.7, 54.099999999999994
#### Distribution of assistant tokens:
min / max: 8, 29
mean / median: 15.0, 12.5
p5 / p95: 10.7, 19.999999999999996
****************************
Charger des fichiers de réglage précis
# Upload fine-tuning files
import os
from openai import OpenAI
client = OpenAI(
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
)
training_file_name = 'training_set.jsonl'
validation_file_name = 'validation_set.jsonl'
# Upload the training and validation dataset files to Azure OpenAI with the SDK.
training_response = client.files.create(
file = open(training_file_name, "rb"), purpose="fine-tune"
)
training_file_id = training_response.id
validation_response = client.files.create(
file = open(validation_file_name, "rb"), purpose="fine-tune"
)
validation_file_id = validation_response.id
print("Training file ID:", training_file_id)
print("Validation file ID:", validation_file_id)
Sortie:
Training file ID: file-0e3aa3f2e81e49a5b8b96166ea214626
Validation file ID: file-8556c3bb41b7416bb7519b47fcd1dd6b
Commencer le réglage précis
Maintenant que les fichiers de réglage précis sont correctement chargés, vous pouvez soumettre votre travail de formation de réglage précis :
Dans cet exemple, nous transmettons également le paramètre seed. La graine détermine la reproductibilité de la tâche. La transmission des mêmes paramètres de départ et de travail doit produire les mêmes résultats, mais peut différer dans de rares cas. Si aucune graine n’est spécifiée, une graine est générée pour vous.
# Submit fine-tuning training job
response = client.fine_tuning.jobs.create(
training_file = training_file_id,
validation_file = validation_file_id,
model = "gpt-4o-mini-2024-07-18", # Enter base model name. Note that in Azure OpenAI the model name contains dashes and cannot contain dot/period characters.
seed = 105 # seed parameter controls reproducibility of the fine-tuning job. If no seed is specified one will be generated automatically.
)
job_id = response.id
# You can use the job ID to monitor the status of the fine-tuning job.
# The fine-tuning job will take some time to start and complete.
print("Job ID:", response.id)
print("Status:", response.status)
print(response.model_dump_json(indent=2))
Sortie:
Job ID: ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6
Status: pending
{
"id": "ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6",
"created_at": 1715824115,
"error": null,
"fine_tuned_model": null,
"finished_at": null,
"hyperparameters": {
"n_epochs": -1,
"batch_size": -1,
"learning_rate_multiplier": 1
},
"model": "gpt-4o-mini-2024-07-18",
"object": "fine_tuning.job",
"organization_id": null,
"result_files": null,
"seed": 105,
"status": "pending",
"trained_tokens": null,
"training_file": "file-0e3aa3f2e81e49a5b8b96166ea214626",
"validation_file": "file-8556c3bb41b7416bb7519b47fcd1dd6b",
"estimated_finish": null,
"integrations": null
}
Suivre l’état du travail d’entraînement
Si vous souhaitez interroger l’état du travail de formation jusqu’à ce qu’il soit terminé, vous pouvez exécuter :
# Track training status
from IPython.display import clear_output
import time
start_time = time.time()
# Get the status of our fine-tuning job.
response = client.fine_tuning.jobs.retrieve(job_id)
status = response.status
# If the job isn't done yet, poll it every 10 seconds.
while status not in ["succeeded", "failed"]:
time.sleep(10)
response = client.fine_tuning.jobs.retrieve(job_id)
print(response.model_dump_json(indent=2))
print("Elapsed time: {} minutes {} seconds".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))
status = response.status
print(f'Status: {status}')
clear_output(wait=True)
print(f'Fine-tuning job {job_id} finished with status: {status}')
# List all fine-tuning jobs for this resource.
print('Checking other fine-tune jobs for this resource.')
response = client.fine_tuning.jobs.list()
print(f'Found {len(response.data)} fine-tune jobs.')
Sortie:
Job ID: ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6
Status: pending
{
"id": "ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6",
"created_at": 1715824115,
"error": null,
"fine_tuned_model": null,
"finished_at": null,
"hyperparameters": {
"n_epochs": -1,
"batch_size": -1,
"learning_rate_multiplier": 1
},
"model": "gpt-4o-mini-2024-07-18",
"object": "fine_tuning.job",
"organization_id": null,
"result_files": null,
"seed": 105,
"status": "pending",
"trained_tokens": null,
"training_file": "file-0e3aa3f2e81e49a5b8b96166ea214626",
"validation_file": "file-8556c3bb41b7416bb7519b47fcd1dd6b",
"estimated_finish": null,
"integrations": null
}
Il n’est pas rare que l’entraînement prenne plus d’une heure. Une fois l’entraînement terminé, le message de sortie passe à quelque chose comme suit :
Fine-tuning job ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6 finished with status: succeeded
Checking other fine-tune jobs for this resource.
Found 4 fine-tune jobs.
Répertorier les événements de réglage précis
Version de l’API : 2024-08-01-preview ou une version ultérieure est requise pour cette commande.
Bien qu’il ne soit pas nécessaire d’effectuer un réglage précis, il peut être utile d’examiner les événements de réglage précis individuels générés lors de l’entraînement. Les résultats complets de l’entraînement peuvent également être examinés une fois la formation terminée dans le fichier de résultats de l’entraînement.
response = client.fine_tuning.jobs.list_events(fine_tuning_job_id=job_id, limit=10)
print(response.model_dump_json(indent=2))
Sortie:
{
"data": [
{
"id": "ftevent-179d02d6178f4a0486516ff8cbcdbfb6",
"created_at": 1715826339,
"level": "info",
"message": "Training hours billed: 0.500",
"object": "fine_tuning.job.event",
"type": "message"
},
{
"id": "ftevent-467bc5e766224e97b5561055dc4c39c0",
"created_at": 1715826339,
"level": "info",
"message": "Completed results file: file-175c81c590074388bdb49e8e0d91bac3",
"object": "fine_tuning.job.event",
"type": "message"
},
{
"id": "ftevent-a30c44da4c304180b327c3be3a7a7e51",
"created_at": 1715826337,
"level": "info",
"message": "Postprocessing started.",
"object": "fine_tuning.job.event",
"type": "message"
},
{
"id": "ftevent-ea10a008f1a045e9914de98b6b47514b",
"created_at": 1715826303,
"level": "info",
"message": "Job succeeded.",
"object": "fine_tuning.job.event",
"type": "message"
},
{
"id": "ftevent-008dc754dc9e61b008dc754dc9e61b00",
"created_at": 1715825614,
"level": "info",
"message": "Step 100: training loss=0.001647822093218565",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 100,
"train_loss": 0.001647822093218565,
"train_mean_token_accuracy": 1,
"valid_loss": 1.5170825719833374,
"valid_mean_token_accuracy": 0.75,
"full_valid_loss": 1.7539110545870624,
"full_valid_mean_token_accuracy": 0.7215189873417721
}
},
{
"id": "ftevent-008dc754dc3f03a008dc754dc3f03a00",
"created_at": 1715825604,
"level": "info",
"message": "Step 90: training loss=0.00971441250294447",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 90,
"train_loss": 0.00971441250294447,
"train_mean_token_accuracy": 1,
"valid_loss": 1.3702410459518433,
"valid_mean_token_accuracy": 0.75,
"full_valid_loss": 1.7371194453179082,
"full_valid_mean_token_accuracy": 0.7278481012658228
}
},
{
"id": "ftevent-008dc754dbdfa59008dc754dbdfa5900",
"created_at": 1715825594,
"level": "info",
"message": "Step 80: training loss=0.0032251903321594",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 80,
"train_loss": 0.0032251903321594,
"train_mean_token_accuracy": 1,
"valid_loss": 1.4242165088653564,
"valid_mean_token_accuracy": 0.75,
"full_valid_loss": 1.6554046099698996,
"full_valid_mean_token_accuracy": 0.7278481012658228
}
},
{
"id": "ftevent-008dc754db80478008dc754db8047800",
"created_at": 1715825584,
"level": "info",
"message": "Step 70: training loss=0.07380199432373047",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 70,
"train_loss": 0.07380199432373047,
"train_mean_token_accuracy": 1,
"valid_loss": 1.2011798620224,
"valid_mean_token_accuracy": 0.75,
"full_valid_loss": 1.508960385865803,
"full_valid_mean_token_accuracy": 0.740506329113924
}
},
{
"id": "ftevent-008dc754db20e97008dc754db20e9700",
"created_at": 1715825574,
"level": "info",
"message": "Step 60: training loss=0.245253324508667",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 60,
"train_loss": 0.245253324508667,
"train_mean_token_accuracy": 0.875,
"valid_loss": 1.0585949420928955,
"valid_mean_token_accuracy": 0.75,
"full_valid_loss": 1.3787144045286541,
"full_valid_mean_token_accuracy": 0.7341772151898734
}
},
{
"id": "ftevent-008dc754dac18b6008dc754dac18b600",
"created_at": 1715825564,
"level": "info",
"message": "Step 50: training loss=0.1696014404296875",
"object": "fine_tuning.job.event",
"type": "metrics",
"data": {
"step": 50,
"train_loss": 0.1696014404296875,
"train_mean_token_accuracy": 0.8999999761581421,
"valid_loss": 0.8862184286117554,
"valid_mean_token_accuracy": 0.8125,
"full_valid_loss": 1.2814022257358213,
"full_valid_mean_token_accuracy": 0.7151898734177216
}
}
],
"has_more": true,
"object": "list"
}
Répertorier les points de contrôle
Version de l’API : 2024-08-01-preview ou une version ultérieure est requise pour cette commande.
Lorsque chaque époque d’apprentissage termine un point de contrôle est généré. Un point de contrôle est une version entièrement fonctionnelle d’un modèle qui peut être déployée et utilisée comme modèle cible pour les travaux de réglage précis suivants. Les points de contrôle peuvent être utiles, car ils peuvent fournir un instantané de votre modèle avant le surajustement qui s’est produit. Lorsqu’un travail de réglage précis est terminé, vous disposez des trois versions les plus récentes du modèle disponibles pour le déploiement. L’époque finale sera représentée par votre modèle affiné, les deux époques précédentes sont disponibles en tant que points de contrôle.
response = client.fine_tuning.jobs.checkpoints.list(job_id)
print(response.model_dump_json(indent=2))
Sortie:
{
"data": [
{
"id": "ftchkpt-148ab69f0a404cf9ab55a73d51b152de",
"created_at": 1715743077,
"fine_tuned_model_checkpoint": "gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678",
"fine_tuning_job_id": "ftjob-372c72db22c34e6f9ccb62c26ee0fbd9",
"metrics": {
"full_valid_loss": 1.8258173013035255,
"full_valid_mean_token_accuracy": 0.7151898734177216,
"step": 100.0,
"train_loss": 0.004080486483871937,
"train_mean_token_accuracy": 1.0,
"valid_loss": 1.5915886163711548,
"valid_mean_token_accuracy": 0.75
},
"object": "fine_tuning.job.checkpoint",
"step_number": 100
},
{
"id": "ftchkpt-e559c011ecc04fc68eaa339d8227d02d",
"created_at": 1715743013,
"fine_tuned_model_checkpoint": "gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678:ckpt-step-90",
"fine_tuning_job_id": "ftjob-372c72db22c34e6f9ccb62c26ee0fbd9",
"metrics": {
"full_valid_loss": 1.7958603267428241,
"full_valid_mean_token_accuracy": 0.7215189873417721,
"step": 90.0,
"train_loss": 0.0011079151881858706,
"train_mean_token_accuracy": 1.0,
"valid_loss": 1.6084896326065063,
"valid_mean_token_accuracy": 0.75
},
"object": "fine_tuning.job.checkpoint",
"step_number": 90
},
{
"id": "ftchkpt-8ae8beef3dcd4dfbbe9212e79bb53265",
"created_at": 1715742984,
"fine_tuned_model_checkpoint": "gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678:ckpt-step-80",
"fine_tuning_job_id": "ftjob-372c72db22c34e6f9ccb62c26ee0fbd9",
"metrics": {
"full_valid_loss": 1.6909511662736725,
"full_valid_mean_token_accuracy": 0.7088607594936709,
"step": 80.0,
"train_loss": 0.000667572021484375,
"train_mean_token_accuracy": 1.0,
"valid_loss": 1.4677599668502808,
"valid_mean_token_accuracy": 0.75
},
"object": "fine_tuning.job.checkpoint",
"step_number": 80
}
],
"has_more": false,
"object": "list"
}
Résultats de la dernière exécution d'entraînement
Pour obtenir les résultats finaux, exécutez ce qui suit :
# Retrieve fine_tuned_model name
response = client.fine_tuning.jobs.retrieve(job_id)
print(response.model_dump_json(indent=2))
fine_tuned_model = response.fine_tuned_model
Déployer un modèle affiné
Contrairement aux commandes précédentes du KIT de développement logiciel (SDK) Python dans ce didacticiel, étant donné que l’introduction de la fonctionnalité de quota, le déploiement de modèle doit être effectué à l’aide de l’API REST, qui nécessite une autorisation distincte, un chemin d’ACCÈS d’API différent et une autre version de l’API.
Vous pouvez également déployer votre modèle affiné à l’aide d’une des autres méthodes de déploiement courantes telles que Foundry portal ou Azure CLI.
| Variable | Définition |
|---|---|
| Jeton | Il existe plusieurs façons de générer un jeton d’autorisation. La méthode la plus simple pour les tests initiaux consiste à lancer le Cloud Shell à partir du portail Azure. Ensuite, exécutez az account get-access-token. Vous pouvez utiliser ce jeton comme jeton d’autorisation temporaire pour les tests d’API. Nous vous recommandons de le stocker dans une nouvelle variable d’environnement |
| Abonnement | ID d’abonnement de la ressource OpenAI associée Azure |
| groupe de ressources | Nom du groupe de ressources de votre ressource OpenAI Azure |
| resource_name | Nom de la ressource OpenAI Azure |
| model_deployment_name | Nom personnalisé de votre nouveau déploiement de modèle affiné. Il s’agit du nom mentionné dans votre code lors de l’exécution d’appels de complétion de chat. |
| modèle ajusté finement | Récupérez cette valeur à partir de votre travail d’optimisation des résultats à l’étape précédente. On dirait gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678. Vous devez ajouter cette valeur au deploy_data json. |
Important
Après avoir déployé un modèle personnalisé, si à tout moment le déploiement reste inactif pendant plus de 15 jours, le déploiement est supprimé. Le déploiement d'un modèle personnalisé est inactif si le modèle a été déployé il y a plus de 15 jours et qu'aucun appel d'API de complétion de chat ou de réponse n'a été effectué pendant une période continue de 15 jours.
La suppression d’un déploiement inactif ne supprime pas ou n’affecte pas le modèle personnalisé sous-jacent. Le modèle personnalisé peut être redéployé à tout moment.
Comme décrit dans la tarification des modèles Microsoft Foundry d'Azure OpenAI, chaque modèle personnalisé (affiné) déployé entraîne un coût d'hébergement horaire, que des appels d'API de chat ou de réponse soient effectués sur le modèle. Pour en savoir plus sur la planification et la gestion des coûts avec Azure OpenAI, consultez Plan et gérer les coûts pour Azure OpenAI.
# Deploy fine-tuned model
import json
import requests
token = os.getenv("TEMP_AUTH_TOKEN")
subscription = "<YOUR_SUBSCRIPTION_ID>"
resource_group = "<YOUR_RESOURCE_GROUP_NAME>"
resource_name = "<YOUR_AZURE_OPENAI_RESOURCE_NAME>"
model_deployment_name = "gpt-4o-mini-2024-07-18-ft" # Custom deployment name you chose for your fine-tuning model
deploy_params = {'api-version': "2024-10-01"} # Control plane API version
deploy_headers = {'Authorization': 'Bearer {}'.format(token), 'Content-Type': 'application/json'}
deploy_data = {
"sku": {"name": "standard", "capacity": 1},
"properties": {
"model": {
"format": "OpenAI",
"name": "<YOUR_FINE_TUNED_MODEL>", #retrieve this value from the previous call, it will look like gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678
"version": "1"
}
}
}
deploy_data = json.dumps(deploy_data)
request_url = f'https://management.azure.com/subscriptions/{subscription}/resourceGroups/{resource_group}/providers/Microsoft.CognitiveServices/accounts/{resource_name}/deployments/{model_deployment_name}'
print('Creating a new deployment...')
r = requests.put(request_url, params=deploy_params, headers=deploy_headers, data=deploy_data)
print(r)
print(r.reason)
print(r.json())
Vous pouvez vérifier la progression de votre déploiement dans le portail Foundry.
Il n’est pas rare que ce processus prenne un certain temps lors du déploiement de modèles affinés.
Utiliser un modèle personnalisé déployé
Une fois votre modèle affiné déployé, vous pouvez l'utiliser comme tout autre modèle déployé, soit sur les terrains de jeu du chat du portail Foundry, soit via l'API de finalisation de conversation. Par exemple, vous pouvez envoyer un appel de complétion de chat à votre modèle déployé, comme illustré dans l'exemple Python suivant. Vous pouvez continuer à utiliser les mêmes paramètres avec votre modèle personnalisé, comme la température et le max_tokens, que vous pouvez avec d’autres modèles déployés.
# Use the deployed customized model
import os
from openai import OpenAI
client = OpenAI(
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
)
response = client.chat.completions.create(
model = "gpt-4o-mini-2024-07-18-ft", # model = "Custom deployment name you chose for your fine-tuning model"
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},
{"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},
{"role": "user", "content": "Do other Azure services support this too?"}
]
)
print(response.choices[0].message.content)
Supprimer le déploiement
Contrairement à d'autres types de modèles OpenAI Azure, les modèles affinés/personnalisés ont un coût d'hébergement horaire associé à eux une fois qu'ils sont déployés. Nous vous recommandons vivement qu'une fois que vous aurez terminé ce tutoriel et testé quelques appels de saisie semi-automatique sur votre modèle affiné, que vous supprimiez le déploiement du modèle.
La suppression du déploiement n’affecte pas le modèle lui-même. Vous pouvez donc redéployer le modèle affiné que vous avez entraîné pour ce didacticiel à tout moment.
Vous pouvez supprimer le déploiement dans le portail Foundry, via l’API REST, Azure CLI ou d’autres méthodes de déploiement prises en charge.
Dépannage
Comment activer le réglage précis ? Créer un modèle personnalisé est désactivé.
Pour accéder à l'ajustement fin, vous avez besoin du rôle Azure AI User attribué. Même une personne disposant d’autorisations d’administrateur de service de haut niveau aurait toujours besoin de ce compte explicitement défini pour accéder au réglage précis. Pour plus d’informations, consultez les conseils de contrôle d’accès en fonction du rôle.
Étapes suivantes
- En savoir plus sur fine-tuning dans Azure OpenAI
- En savoir plus sur les modèles sous-jacents qui alimentent Azure OpenAI.