Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten samouczek przeprowadzi Cię przez precyzyjne dostrajanie gpt-4o-mini-2024-07-18
modelu.
Z tego samouczka dowiesz się, jak wykonywać następujące działania:
- Tworzenie przykładowych zestawów danych dostrajania.
- Utwórz zmienne środowiskowe dla punktu końcowego zasobu i klucza interfejsu API.
- Przygotuj przykładowe zestawy danych trenowania i sprawdzania poprawności na potrzeby dostrajania.
- Przekaż plik szkoleniowy i plik weryfikacji w celu dostrajania.
- Utwórz zadanie dostrajania dla elementu
gpt-4o-mini-2024-07-18
. - Wdróż niestandardowy model dostrojony.
Wymagania wstępne
- Subskrypcja platformy Azure — utwórz bezpłatnie.
- Środowisko Python w wersji 3.8 lub nowszej
- Następujące biblioteki języka Python:
json
, ,requests
os
,tiktoken
,time
,openai
, .numpy
- Jupyter Notebooks
- Zasób usługi Azure OpenAI w regionie, w którym dostrajanie jest dostępne. Jeśli nie masz zasobu, proces tworzenia zasobu jest udokumentowany w naszym przewodniku wdrażania zasobów.
- Dostrajanie dostępu wymaga kontrybutora usług Cognitive Services OpenAI.
- Jeśli nie masz jeszcze dostępu do wyświetlania limitów przydziału i wdrażania modeli w portalu usługi Azure AI Foundry, potrzebujesz więcej uprawnień.
Ważne
Zalecamy przejrzenie informacji o cenach, aby lepiej dostosować się i zapoznać z powiązanymi kosztami. Testowanie tego samouczka spowodowało naliczenie 48 000 tokenów (4 800 tokenów treningowych * 10 epok trenowania). Koszty trenowania są dodatkiem do kosztów związanych z dostrajaniem wnioskowania oraz godzinowymi kosztami hostowania wdrożonych modeli. Po ukończeniu samouczka należy usunąć wdrożenie swojego dostosowanego modelu, w przeciwnym razie nadal będziesz ponosić koszt hostingu godzinowego.
Ustawienia
Biblioteki języka Python
Ten samouczek zawiera przykłady niektórych najnowszych funkcji interfejsu OpenAI, takich jak inicjator/zdarzenia/punkty kontrolne. Aby móc korzystać z tych funkcji, może być konieczne uruchomienie polecenia pip install openai --upgrade
w celu uaktualnienia do najnowszej wersji.
pip install openai requests tiktoken numpy
Pobierz klucz i punkt końcowy
Aby pomyślnie wykonać wywołanie usługi Azure OpenAI, potrzebujesz punktu końcowegoi klucza.
Nazwa zmiennej | Wartość |
---|---|
ENDPOINT |
Punkt końcowy usługi można znaleźć w sekcji Klucze i punkt końcowy podczas badania zasobu w witrynie Azure Portal. Możesz też znaleźć punkt końcowy za pośrednictwem strony Wdrożenia w portalu usługi Azure AI Foundry. Przykładowy punkt końcowy to: https://docs-test-001.openai.azure.com/ . |
API-KEY |
Tę wartość można znaleźć w sekcji Klucze i punkt końcowy podczas badania zasobu z poziomu witryny Azure Portal. Możesz użyć wartości KEY1 lub KEY2 . |
Przejdź do zasobu w witrynie Azure Portal. Sekcję Klucze i punkt końcowy można znaleźć w sekcji Zarządzanie zasobami. Skopiuj punkt końcowy i klucz dostępu, ponieważ będziesz potrzebować obu do uwierzytelniania wywołań API. Możesz użyć wartości KEY1
lub KEY2
. Zawsze posiadanie dwóch kluczy umożliwia bezpieczne obracanie i ponowne generowanie kluczy bez powodowania zakłóceń usługi.
Zmienne środowiskowe
Tworzenie i przypisywanie trwałych zmiennych środowiskowych dla klucza i punktu końcowego.
Ważne
Używaj kluczy interfejsu API z ostrożnością. Nie dołączaj klucza interfejsu API bezpośrednio do kodu i nigdy nie publikuj go publicznie. Jeśli używasz klucza interfejsu API, zapisz go bezpiecznie w usłudze Azure Key Vault. Aby uzyskać więcej informacji na temat bezpiecznego używania kluczy interfejsu API w aplikacjach, zobacz Klucze interfejsu API w usłudze Azure Key Vault.
Aby uzyskać więcej informacji na temat zabezpieczeń usług sztucznej inteligencji, zobacz Uwierzytelnianie żądań w usługach Azure AI.
setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
Tworzenie przykładowego zestawu danych
Dostrajanie gpt-4o-mini-2024-07-18
wymaga specjalnie sformatowanego pliku szkoleniowego JSONL. OpenAI podaje następujący przykład w swojej dokumentacji:
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital 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."}]}
W tym przykładzie zmodyfikujemy to nieco przez zmianę na:
{"messages": [{"role": "system", "content": "Clippy is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital 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."}]}
Chociaż te trzy przykłady są przydatne do nadania ogólnego formatu, jeśli chcesz kierować niestandardowym dostrojonym modelem, aby reagować w podobny sposób, potrzebujesz więcej przykładów. Ogólnie rzecz biorąc, potrzebujesz co najmniej 50 przykładów wysokiej jakości, aby rozpocząć. Jednak w całości można mieć przypadek użycia, który może wymagać 1000 przykładów treningowych wysokiej jakości, aby odnieść sukces.
Ogólnie rzecz biorąc, podwojenie rozmiaru zestawu danych może prowadzić do liniowego wzrostu jakości modelu. Należy jednak pamiętać, że przykłady niskiej jakości mogą negatywnie wpływać na wydajność. Jeśli wytrenujesz model na dużej ilości danych wewnętrznych bez uprzedniego przycinania zestawu danych tylko w celu uzyskania najwyższej jakości przykładów, możesz utworzyć model, który działa gorzej niż oczekiwano.
Musisz utworzyć dwa pliki training_set.jsonl
i validation_set.jsonl
.
Utwórz pliki w tym samym katalogu, w którym jest uruchomiony notes Jupyter Notebook, i skopiuj zawartość następujących bloków kodu do odpowiednich plików:
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?"}]}
Teraz musisz uruchomić wstępne kontrole naszych plików szkoleniowych i weryfikacyjnych.
# 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)
Wyjście:
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!"}
W tym przypadku mamy tylko 10 przykładów treningowych i 10 przykładów walidacyjnych, więc chociaż demonstruje to podstawową mechanikę dostosowywania modelu, nie wydaje się to wystarczająco dużą liczbą przykładów, aby wywołać spójny zauważalny efekt.
Teraz możesz użyć biblioteki tiktoken, aby zweryfikować liczbę tokenów. Zliczanie tokenów przy użyciu tej metody nie da dokładnych liczb tokenów, które są używane do dostrajania, ale powinno zapewnić dobre oszacowanie.
Uwaga / Notatka
Poszczególne przykłady muszą pozostać w ramach bieżącej długości kontekstu przykładowego gpt-4o-mini-2024-07-18
trenowania modelu: 64 536 tokenów. Limit tokenu wejściowego modelu pozostaje 128 000 tokenów.
# 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)
Wyjście:
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
****************************
Prześlij pliki dostosowywania
# Upload fine-tuning files
import os
from openai import AzureOpenAI
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
api_version = "2025-02-01-preview"
)
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)
Wyjście:
Training file ID: file-0e3aa3f2e81e49a5b8b96166ea214626
Validation file ID: file-8556c3bb41b7416bb7519b47fcd1dd6b
Rozpocznij dostrajanie
Teraz, gdy pliki dostrajania zostały pomyślnie przekazane, możesz przesłać zadanie trenowania dostrajania:
Również w tym przykładzie przekazujemy parametr początkowy. Nasiono kontroluje reproduktywność procesu. Podanie tych samych parametrów ziarna i zadania powinno dawać te same wyniki, ale mogą się różnić w rzadkich przypadkach. Jeśli nie określono ziarna, zostanie ono wygenerowane automatycznie.
# 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))
Wyjście:
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
}
Śledzenie stanu pracy szkoleniowej
Jeśli chcesz monitorować stan zadania trenowania do momentu jego ukończenia, możesz uruchomić następujące polecenie:
# 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.')
Wyjście:
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
}
Nie jest to niezwykłe, aby szkolenie zajęło ponad godzinę. Po zakończeniu trenowania komunikat wyjściowy zmieni się na podobny do następującego:
Fine-tuning job ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6 finished with status: succeeded
Checking other fine-tune jobs for this resource.
Found 4 fine-tune jobs.
Lista zdarzeń dostrajania
Wersja interfejsu API: 2024-08-01-preview
lub nowsza jest wymagana dla tego polecenia.
Chociaż nie jest to konieczne do ukończenia dostrajania, pomocne może być sprawdzenie poszczególnych zdarzeń dostrajania, które zostały wygenerowane podczas trenowania. Pełne wyniki szkolenia można również zbadać po zakończeniu trenowania w pliku wyników trenowania.
response = client.fine_tuning.jobs.list_events(fine_tuning_job_id=job_id, limit=10)
print(response.model_dump_json(indent=2))
Wyjście:
{
"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"
}
Lista punktów kontrolnych
Wersja interfejsu API: 2024-08-01-preview
lub nowsza jest wymagana dla tego polecenia.
Po zakończeniu każdej epoki trenowania generowany jest punkt kontrolny. Punkt kontrolny to w pełni funkcjonalna wersja modelu, która może być wdrożona i używana jako model docelowy dla kolejnych zadań dostrajania. Punkty kontrolne mogą być przydatne, ponieważ mogą udostępniać migawkę modelu przed nadmiernym dopasowaniem. Po zakończeniu zadania dostrajania dostępne są trzy najnowsze wersje modelu do wdrożenia. Ostatnia epoka będzie reprezentowana przez świetnie dostosowany model, a poprzednich dwóch epok można używać jako punktów kontrolnych.
response = client.fine_tuning.jobs.checkpoints.list(job_id)
print(response.model_dump_json(indent=2))
Wyjście:
{
"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"
}
Końcowe wyniki przebiegu trenowania
Aby uzyskać końcowe wyniki, uruchom następujące:
# 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
Wdrażanie dostosowanego modelu
W przeciwieństwie do poprzednich poleceń zestawu SDK dla języka Python w tym samouczku, odkąd wprowadzono funkcję limitu przydziału, wdrożenie modelu musi być przeprowadzone za pomocą interfejsu API REST, co wymaga oddzielnej autoryzacji, innej ścieżki API i innej wersji API.
Alternatywnie możesz wdrożyć dostosowany model przy użyciu dowolnej z innych typowych metod wdrażania, takich jak portal Azure AI Foundry lub interfejs wiersza polecenia platformy Azure.
zmienna | Definicja |
---|---|
kod przedpłaty | Istnieje wiele sposobów generowania tokenu autoryzacji. Najprostszą metodą testowania początkowego jest uruchomienie usługi Cloud Shell w witrynie Azure Portal. Następnie należy uruchomić polecenie az account get-access-token . Możesz użyć tego tokenu jako tymczasowego tokenu autoryzacji na potrzeby testowania interfejsu API. Zalecamy przechowywanie tego w nowej zmiennej środowiskowej |
abonament | Identyfikator subskrypcji skojarzonego zasobu usługi Azure OpenAI |
grupa_zasobów | Nazwa grupy zasobów dla zasobu usługi Azure OpenAI |
nazwa_zasobu | Nazwa zasobu usługi Azure OpenAI |
nazwa_deploymentu_modelu | Niestandardowa nazwa dla nowego, zoptymalizowanego wdrożenia modelu. Jest to nazwa, do której odwołuje się kod podczas wywoływania funkcji zakończenia czatu. |
model dostrojony | Pobierz tę wartość z wyników zadania dostrajania w poprzednim kroku. Wygląda następująco: gpt-4o-mini-2024-07-18.ft-0e208cf33a6a466994aff31a08aba678 . Musisz dodać wartość do pliku json deploy_data. |
Ważne
Po wdrożeniu dostosowanego modelu, jeśli w dowolnym momencie wdrożenie pozostanie nieaktywne przez ponad piętnaście (15) dni, wdrożenie zostanie usunięte. Wdrożenie dostosowanego modelu jest nieaktywne, jeśli model został wdrożony ponad piętnaście (15) dni temu i nie wykonano do niego żadnych wywołań ani ukończeń czatu w ciągu nieprzerwanego 15-dniowego okresu.
Usunięcie nieaktywnego wdrożenia nie powoduje usunięcia lub wpływu na bazowy dostosowany model, a dostosowany model można wdrożyć ponownie w dowolnym momencie. Zgodnie z opisem w Cenniku modeli w Azure OpenAI in Azure AI Foundry, każdy precyzyjnie dostosowany model, który został wdrożony, powoduje naliczanie godzinowego kosztu hostingu, niezależnie od tego, czy są wykonywane połączenia w celu ukończenia operacji lub czatu do modelu. Aby dowiedzieć się więcej na temat planowania kosztów i zarządzania nimi za pomocą usługi Azure OpenAI, zapoznaj się ze wskazówkami w artykule Planowanie zarządzania kosztami usługi 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())
Postęp wdrażania można sprawdzić w portalu usługi Azure AI Foundry.
Nie jest niczym niezwykłym, że ukończenie tego procesu zajmuje trochę czasu podczas wdrażania dostosowanych modeli.
Korzystanie z wdrożonego modelu dostosowanego.
Po wdrożeniu dostosowanego modelu można go użyć jak każdy inny wdrożony model w portalu Chat Playground of Azure AI Foundry lub za pośrednictwem interfejsu API uzupełniania czatu. Możesz na przykład wysłać wywołanie ukończenia czatu do wdrożonego modelu, jak pokazano w poniższym przykładzie języka Python. Możesz nadal używać tych samych parametrów w dostosowanym modelu, takim jak temperatura i max_tokens, podobnie jak w przypadku innych wdrożonych modeli.
# Use the deployed customized model
import os
from openai import AzureOpenAI
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
api_version = "2024-10-21"
)
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)
Usuń wdrożenie
W przeciwieństwie do innych typów modeli usługi Azure OpenAI, dostosowane/spersonalizowane modele mają związany z nimi godzinowy koszt hostingu po ich wdrożeniu. Zdecydowanie zaleca się, aby po zakończeniu pracy z tym samouczkiem i przetestowaniu kilku wywołań ukończenia czatu względem dostosowanego modelu, usunąć wdrożenie modelu.
Usunięcie wdrożenia nie wpłynie na sam model, więc w dowolnym momencie można ponownie wdrożyć dostosowany model, który został wytrenowany na potrzeby tego samouczka.
Wdrożenie można usunąć w portalu Azure AI Foundry, za pośrednictwem interfejsu API REST, interfejsu wiersza polecenia platformy Azure lub innych obsługiwanych metod wdrażania.
Rozwiązywanie problemów
Jak mogę włączyć dostrajanie? Opcje tworzenia modelu niestandardowego są wyszarzone.
Aby pomyślnie uzyskać dostęp do korekcji, musisz mieć przypisanego współautora usługi Cognitive Services OpenAI. Nawet osoba z uprawnieniami administratora usługi wysokiego poziomu będzie nadal potrzebować tego konta jawnie ustawionego w celu uzyskania dostępu do dostrajania. Aby uzyskać więcej informacji, zapoznaj się ze wskazówkami dotyczącymi kontroli dostępu opartej na rolach.
Dalsze kroki
- Dowiedz się więcej o szczegółowym dostrajaniu w usłudze Azure OpenAI
- Dowiedz się więcej o modelach bazowych, które zasilają usługę Azure OpenAI.