Bagikan melalui


Tutorial penyempurnaan Azure OpenAI GPT-3.5 Turbo

Tutorial ini memandikan Anda melalui penyempurnaan gpt-35-turbo-0613 model.

Dalam tutorial ini, Anda akan mempelajari cara:

  • Buat sampel himpunan data penyempurnaan.
  • Buat variabel lingkungan untuk titik akhir sumber daya dan kunci API Anda.
  • Siapkan sampel himpunan data pelatihan dan validasi Anda untuk penyempurnaan.
  • Unggah file pelatihan dan file validasi Anda untuk penyempurnaan.
  • Buat pekerjaan penyempurnaan untuk gpt-35-turbo-0613.
  • Menyebarkan model kustom yang disempurnakan.

Prasyarat

  • Langganan Azure - Buat langganan gratis.
  • Akses yang diberikan ke Azure OpenAI dalam langganan Azure yang diinginkan Saat ini, akses ke layanan ini hanya diberikan oleh aplikasi. Anda dapat mengajukan permohonan akses ke Azure OpenAI dengan melengkapi formulir di https://aka.ms/oai/access.
  • Python 3.8 atau versi yang lebih baru
  • Pustaka Python berikut: json, , requests, os, tiktokentime, openai, numpy.
  • Jupyter Notebooks
  • Sumber daya Azure OpenAI di wilayah tempat gpt-35-turbo-0613 penyempurnaan tersedia. Jika Anda tidak memiliki sumber daya, proses pembuatan sumber daya didokumentasikan dalam panduan penyebaran sumber daya kami.
  • Akses penyempurnaan memerlukan Kontributor OpenAI Cognitive Services.
  • Jika Anda belum memiliki akses untuk melihat kuota, dan menyebarkan model di Azure OpenAI Studio, Anda akan memerlukan izin tambahan.

Penting

Kami sangat menyarankan untuk meninjau informasi harga untuk penyempurnaan sebelum memulai tutorial ini untuk memastikan Anda nyaman dengan biaya terkait. Dalam pengujian, tutorial ini menghasilkan satu jam pelatihan yang ditagih, selain biaya yang terkait dengan inferensi penyempurnaan, dan biaya hosting per jam agar model yang disempurnakan disebarkan. Setelah menyelesaikan tutorial, Anda harus menghapus penyebaran model yang disempurnakan jika tidak, Anda akan terus dikenakan biaya hosting per jam.

Penyiapan

Pustaka Python

Tutorial ini memberikan contoh beberapa fitur OpenAI terbaru termasuk seed/events/checkpoints. Untuk memanfaatkan fitur-fitur ini, Anda mungkin perlu menjalankan pip install openai --upgrade untuk meningkatkan ke rilis terbaru.

pip install openai requests tiktoken numpy

Mengambil kunci dan titik akhir

Agar berhasil melakukan panggilan terhadap Azure OpenAI, Anda memerlukan titik akhir dan kunci.

Nama variabel Nilai
ENDPOINT Nilai ini dapat ditemukan di bagian Kunci & Titik Akhir saat memeriksa sumber daya Anda dari portal Microsoft Azure. Atau, Anda dapat menemukan nilainya di Azure OpenAI Studio>Playground>Tampilan Kode. Contoh titik akhir adalah: https://docs-test-001.openai.azure.com/.
API-KEY Nilai ini dapat ditemukan di bagian Kunci & Titik Akhir saat memeriksa sumber daya Anda dari portal Microsoft Azure. Anda dapat menggunakan KEY1 atau KEY2.

Buka sumber daya Anda di portal Azure. Bagian Kunci & Titik Akhir dapat ditemukan di bagian Manajemen Sumber Daya. Salin titik akhir dan kunci akses Anda karena keduanya diperlukan untuk mengautentikasi panggilan API Anda. Anda dapat menggunakan KEY1 atau KEY2. Selalu miliki dua kunci untuk memungkinkan Anda memutar dan meregenerasi kunci dengan aman tanpa menyebabkan gangguan layanan.

Cuplikan layar antarmuka pengguna gambaran umum untuk sumber daya Azure OpenAI di portal Azure dengan titik akhir dan lokasi kunci akses yang dilingkari dengan warna merah.

Variabel lingkungan

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"

Membuat himpunan data sampel

Penyempurnaan gpt-35-turbo-0613 memerlukan file pelatihan JSONL yang diformat khusus. OpenAI memberikan contoh berikut dalam dokumentasi mereka:

{"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."}]}

Untuk contoh ini kita akan memodifikasi ini sedikit dengan mengubah ke:

{"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."}]}

Meskipun ketiga contoh ini berguna untuk memberi Anda format umum, jika Anda ingin mengarahkan model kustom yang disempurnakan untuk merespons dengan cara yang sama, Anda akan membutuhkan lebih banyak contoh. Umumnya Anda ingin setidaknya 50 contoh berkualitas tinggi untuk memulai. Namun, sepenuhnya mungkin untuk memiliki kasus penggunaan yang mungkin memerlukan 1.000 contoh pelatihan berkualitas tinggi agar berhasil.

Secara umum, menggandakan ukuran himpunan data dapat menyebabkan peningkatan linier dalam kualitas model. Tetapi perlu diingat, contoh kualitas rendah dapat berdampak negatif pada performa. Jika Anda melatih model pada sejumlah besar data internal, tanpa terlebih dahulu memangkas himpunan data hanya untuk contoh kualitas tertinggi, Anda dapat berakhir dengan model yang berkinerja jauh lebih buruk dari yang diharapkan.

Anda harus membuat dua file training_set.jsonl dan validation_set.jsonl.

Buat file di direktori yang sama dengan yang Anda jalankan Jupyter Notebook, dan salin konten blok kode berikut ke file yang sesuai:

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 may 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?"}]}

Sekarang Anda perlu menjalankan beberapa pemeriksaan awal pada file pelatihan dan validasi kami.

# 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)

Output:

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!"}

Dalam hal ini kami hanya memiliki 10 contoh pelatihan dan 10 validasi sehingga sementara ini akan menunjukkan mekanisme dasar penyempurnaan model ini tidak mungkin menjadi sejumlah besar contoh untuk menghasilkan dampak yang terlihat secara konsisten.

Sekarang Anda kemudian dapat menjalankan beberapa kode tambahan dari OpenAI menggunakan pustaka tiktoken untuk memvalidasi jumlah token. Contoh individual harus tetap berada gpt-35-turbo-0613 di bawah batas token input model sebesar 4096 token.

# Validate token counts

import json
import tiktoken
import numpy as np
from collections import defaultdict

encoding = tiktoken.get_encoding("cl100k_base") # default encoding used by gpt-4, turbo, and text-embedding-ada-002 models

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)

Output:

Processing file: training_set.jsonl

#### Distribution of total tokens:
min / max: 47, 62
mean / median: 52.1, 50.5
p5 / p95: 47.9, 57.5

#### Distribution of assistant tokens:
min / max: 13, 30
mean / median: 17.6, 15.5
p5 / p95: 13.0, 21.9
**************************************************
Processing file: validation_set.jsonl

#### Distribution of total tokens:
min / max: 43, 65
mean / median: 51.4, 49.0
p5 / p95: 45.7, 56.9

#### Distribution of assistant tokens:
min / max: 8, 29
mean / median: 15.9, 13.5
p5 / p95: 11.6, 20.9
**************************************************

Mengunggah file penyempurnaan

# 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 = "2024-05-01-preview"  # This API version or later is required to access seed/events/checkpoint features
)

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)

Output:

Training file ID: file-0e3aa3f2e81e49a5b8b96166ea214626
Validation file ID: file-8556c3bb41b7416bb7519b47fcd1dd6b

Mulai menyempurnakan

Sekarang setelah file penyempurnaan berhasil diunggah, Anda dapat mengirimkan pekerjaan pelatihan penyempurnaan Anda:

Dalam contoh ini kita juga meneruskan parameter seed. Benih mengontrol reproduksi pekerjaan. Meneruskan seed dan parameter pekerjaan yang sama harus menghasilkan hasil yang sama, tetapi dapat berbeda dalam kasus yang jarang terjadi. Jika benih tidak ditentukan, satu akan dihasilkan untuk Anda.

# Submit fine-tuning training job

response = client.fine_tuning.jobs.create(
    training_file = training_file_id,
    validation_file = validation_file_id,
    model = "gpt-35-turbo-0613", # 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))

Output Python 1.x:

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-35-turbo-0613",
  "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
}

Melacak status pekerjaan pelatihan

Jika Anda ingin melakukan polling status pekerjaan pelatihan hingga selesai, Anda dapat menjalankan:

# 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.')

Output Python 1.x:

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-35-turbo-0613",
  "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
}

Tidak biasa pelatihan membutuhkan waktu lebih dari satu jam untuk diselesaikan. Setelah pelatihan selesai, pesan output akan berubah menjadi sesuatu seperti:

Fine-tuning job ftjob-900fcfc7ea1d4360a9f0cb1697b4eaa6 finished with status: succeeded
Checking other fine-tune jobs for this resource.
Found 4 fine-tune jobs.

Mencantumkan peristiwa penyempurnaan

Versi API: 2024-05-01-preview atau yang lebih baru diperlukan untuk perintah ini.

Meskipun tidak perlu menyelesaikan penyempurnaan, akan sangat membantu untuk memeriksa peristiwa penyempurnaan individu yang dihasilkan selama pelatihan. Hasil pelatihan lengkap juga dapat diperiksa setelah pelatihan selesai dalam file hasil pelatihan.

response = client.fine_tuning.jobs.list_events(fine_tuning_job_id=job_id, limit=10)
print(response.model_dump_json(indent=2))

Output Python 1.x:

{
  "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"
}

Mencantumkan titik pemeriksaan

Versi API: 2024-05-01-preview atau yang lebih baru diperlukan untuk perintah ini.

Ketika setiap epoch pelatihan menyelesaikan titik pemeriksaan dihasilkan. Titik pemeriksaan adalah versi model yang berfungsi penuh yang dapat disebarkan dan digunakan sebagai model target untuk pekerjaan penyempurnaan berikutnya. Titik pemeriksaan dapat sangat berguna, karena dapat memberikan rekam jepret model Anda sebelum overfitting terjadi. Ketika pekerjaan penyempurnaan selesai, Anda akan memiliki tiga versi terbaru dari model yang tersedia untuk disebarkan. Epoch akhir akan diwakili oleh model yang disempurnakan, dua epoch sebelumnya akan tersedia sebagai titik pemeriksaan.

response = client.fine_tuning.jobs.checkpoints.list(job_id)
print(response.model_dump_json(indent=2))

Output Python 1.x:

{
  "data": [
    {
      "id": "ftchkpt-148ab69f0a404cf9ab55a73d51b152de",
      "created_at": 1715743077,
      "fine_tuned_model_checkpoint": "gpt-35-turbo-0613.ft-372c72db22c34e6f9ccb62c26ee0fbd9",
      "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-35-turbo-0613.ft-372c72db22c34e6f9ccb62c26ee0fbd9: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-35-turbo-0613.ft-372c72db22c34e6f9ccb62c26ee0fbd9: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"
}

Hasil eksekusi pelatihan akhir

Untuk mendapatkan hasil akhir, jalankan hal berikut:

# 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

Menyebarkan model yang disempurnakan

Tidak seperti perintah Python SDK sebelumnya dalam tutorial ini, karena pengenalan fitur kuota, penyebaran model harus dilakukan menggunakan REST API, yang memerlukan otorisasi terpisah, jalur API yang berbeda, dan versi API yang berbeda.

Atau, Anda dapat menyebarkan model yang disempurnakan menggunakan salah satu metode penyebaran umum lainnya seperti Azure OpenAI Studio, atau Azure CLI.

variabel Definisi
token Ada beberapa cara untuk menghasilkan token otorisasi. Metode term mudah untuk pengujian awal adalah meluncurkan Cloud Shell dari portal Azure. Kemudian jalankan az account get-access-token. Anda dapat menggunakan token ini sebagai token otorisasi sementara untuk pengujian API. Sebaiknya simpan ini dalam variabel lingkungan baru
langganan ID langganan untuk sumber daya Azure OpenAI terkait
resource_group Nama grup sumber daya untuk sumber daya Azure OpenAI Anda
resource_name Nama sumber daya Azure OpenAI
model_deployment_name Nama kustom untuk penyebaran model baru yang disempurnakan. Ini adalah nama yang akan direferensikan dalam kode Anda saat melakukan panggilan penyelesaian obrolan.
fine_tuned_model Ambil nilai ini dari pekerjaan penyempurnaan Anda menghasilkan langkah sebelumnya. Ini akan terlihat seperti gpt-35-turbo-0613.ft-b044a9d3cf9c4228b5d393567f693b83. Anda harus menambahkan nilai tersebut ke json deploy_data.

Penting

Setelah Anda menyebarkan model yang disesuaikan, jika kapan saja penyebaran tetap tidak aktif selama lebih dari lima belas (15) hari, penyebaran akan dihapus. Penyebaran model yang disesuaikan tidak aktif jika model disebarkan lebih dari lima belas (15) hari yang lalu dan tidak ada penyelesaian atau panggilan penyelesaian obrolan yang dilakukan padanya selama periode 15 hari berkelanjutan.

Penghapusan penyebaran yang tidak aktif tidak menghapus atau memengaruhi model yang dikustomisasi yang mendasar, dan model yang disesuaikan dapat disebarkan ulang kapan saja. Seperti yang dijelaskan dalam harga Azure OpenAI Service, setiap model yang disesuaikan (disempurnakan) yang disebarkan menimbulkan biaya hosting per jam terlepas dari apakah penyelesaian atau panggilan penyelesaian obrolan sedang dilakukan ke model. Untuk mempelajari selengkapnya tentang merencanakan dan mengelola biaya dengan Azure OpenAI, lihat panduan dalam Rencanakan untuk mengelola biaya untuk Azure OpenAI Service.

# 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 = "YOUR_CUSTOM_MODEL_DEPLOYMENT_NAME"

deploy_params = {'api-version': "2023-05-01"}
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-35-turbo-0613.ft-b044a9d3cf9c4228b5d393567f693b83
            "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())

Anda dapat memeriksa kemajuan penyebaran di Azure OpenAI Studio:

Cuplikan layar hasil tabel DataFrame awal dari file CSV.

Tidak jarang proses ini membutuhkan waktu untuk diselesaikan saat berhadapan dengan penyebaran model yang disempurnakan.

Menggunakan model yang disesuaikan yang disebarkan

Setelah model yang disempurnakan disebarkan, Anda dapat menggunakannya seperti model lain yang disebarkan di Chat Playground Azure OpenAI Studio, atau melalui API penyelesaian obrolan. Misalnya, Anda dapat mengirim panggilan penyelesaian obrolan ke model yang disebarkan, seperti yang ditunjukkan dalam contoh Python berikut. Anda dapat terus menggunakan parameter yang sama dengan model yang disesuaikan, seperti suhu dan max_tokens, seperti yang Anda bisa dengan model lain yang disebarkan.

# 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-02-01"
)

response = client.chat.completions.create(
    model = "gpt-35-turbo-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 AI services support this too?"}
    ]
)

print(response.choices[0].message.content)

Menghapus penyebaran

Tidak seperti jenis model Azure OpenAI lainnya, model yang disempurnakan/disesuaikan memiliki biaya hosting per jam yang terkait dengannya setelah disebarkan. Sangat disarankan bahwa setelah Anda selesai dengan tutorial ini dan telah menguji beberapa panggilan penyelesaian obrolan terhadap model yang disempurnakan, anda menghapus penyebaran model.

Menghapus penyebaran tidak akan memengaruhi model itu sendiri, sehingga Anda dapat menyebarkan kembali model yang disempurnakan yang Anda latih untuk tutorial ini kapan saja.

Anda dapat menghapus penyebaran di Azure OpenAI Studio, melalui REST API, Azure CLI, atau metode penyebaran lain yang didukung.

Pemecahan Masalah

Bagaimana cara mengaktifkan penyempurnaan? Membuat model kustom berwarna abu-abu di Azure OpenAI Studio?

Agar berhasil mengakses penyempurnaan, Anda memerlukan Kontributor OpenAI Cognitive Services yang ditetapkan. Bahkan seseorang dengan izin Administrator Layanan tingkat tinggi masih memerlukan akun ini secara eksplisit diatur untuk mengakses penyempurnaan. Untuk informasi selengkapnya, harap tinjau panduan kontrol akses berbasis peran.

Langkah berikutnya