Chuyển đến nội dung chính

Tinh chỉnh GPT-4o Mini: Hướng dẫn từng bước

Tùy biến mô hình GPT-4o Mini để phân loại bài đăng từ Reddit thành nhãn "gây căng thẳng" và "không căng thẳng".
· 13 phút đọc

Khám phá cùng AI

Trước khi bắt đầu tinh chỉnh mô hình GPT-4o Mini, chúng tôi khuyến nghị bạn tìm hiểu về kỹ thuật tạo prompt, xâu chuỗi prompt và gọi hàm để tùy biến phản hồi của mô hình và nhận được câu trả lời theo lĩnh vực cụ thể.

Tinh chỉnh là cần thiết khi bạn muốn điều chỉnh phong cách, giọng điệu hoặc định dạng. Nó được dùng để cải thiện độ tin cậy và độ chính xác, xử lý các prompt phức tạp, hoặc thực hiện một tác vụ mới mà kỹ sư prompt không đạt được.

Trong hướng dẫn này, chúng ta sẽ tinh chỉnh mô hình GPT-4o Mini để phân loại văn bản thành nhãn "căng thẳng" và "không căng thẳng". Sau đó, chúng ta sẽ truy cập mô hình đã tinh chỉnh bằng OpenAI API và playground của OpenAI. Cuối cùng, chúng ta sẽ đánh giá mô hình đã tinh chỉnh bằng cách so sánh hiệu năng trước và sau khi tinh chỉnh bằng các chỉ số phân loại khác nhau.

Fine-tuning GPT-4o Mini feature image

Hình ảnh: Tác giả

Giới thiệu GPT-4o Mini

GPT-4o Mini là mô hình ngôn ngữ lớn đa năng tiết kiệm chi phí nhất hiện có. Mô hình đạt 82% trên MMLU và hiện vượt trội hơn Claude 3.5 Sonnet về sở thích trò chuyện trên bảng xếp hạng LMSYS. Giá là 15 cent cho mỗi triệu token đầu vào và 60 cent cho mỗi triệu token đầu ra, rẻ hơn 60% so với GPT-3.5 Turbo.

Hiện GPT-4o mini hỗ trợ văn bản và hình ảnh làm đầu vào. Mô hình có cửa sổ ngữ cảnh 128K token, hỗ trợ tối đa 16K token đầu ra cho mỗi yêu cầu và có kiến thức đến tháng 10/2023. GPT-4o Mini có thể xử lý văn bản phi tiếng Anh vì sử dụng bộ tokenizer của GPT-4o. Chúng ta có được lợi thế kép với chi phí thấp.

Tìm hiểu trường hợp sử dụng, API hoàn thành hội thoại và các điểm chuẩn chi tiết của GPT-4o Mini bằng cách đọc blog của chúng tôi, GPT-4o Mini là gì?

Thiết lập OpenAI API

Truy cập trang web OpenAI và tạo tài khoản. Tinh chỉnh khá tốn kém, và việc sử dụng GPT-4o Mini qua API yêu cầu bạn gắn phương thức thanh toán vào tài khoản. Để tránh gián đoạn, hãy đảm bảo bạn có ít nhất 10 USD tín dụng trong tài khoản trước khi thử tinh chỉnh mô hình.

Vào bảng điều khiển chính, nhấp tab “API keys” và tạo khóa bí mật OpenAI API.

generating the OpenAI API key

Chúng tôi sử dụng DataLab của DataCamp làm trình soạn thảo mã. Để thiết lập biến môi trường khóa OpenAI API, vào tab môi trường và nhấp tùy chọn biến môi trường. Sau đó, thêm biến môi trường cho khóa API và kích hoạt như minh họa dưới đây.

Setting the environment variable in DataLab

Cài đặt gói OpenAI Python để truy cập GPT-4o Mini.

%%capture
%pip install openai

Tạo client bằng khóa OpenAI API và tạo phản hồi bằng prompt mẫu. Hàm hoàn thành hội thoại yêu cầu tên mô hình và danh sách messages theo định dạng từ điển.

from IPython.display import Markdown, display
from openai import OpenAI
import os

openai_api_key = os.environ["OPENAI_API_KEY"]

client = OpenAI(api_key=openai_api_key)

response = client.chat.completions.create(
  model="gpt-4o-mini",
  messages=[
    {"role": "system", "content": "You are a great philosopher."},
    {"role": "user", "content": "What is the meaning of life?"}
  ]
)
display(Markdown(response.choices[0].message.content))

OpenAI API của chúng ta đã thiết lập xong và sẵn sàng khởi chạy tác vụ tinh chỉnh.

Generating the response using the GPT-4o-mini

Mới dùng API của OpenAI? Bạn có thể theo dõi hướng dẫn chi tiết, dễ hiểu Hướng dẫn API GPT-4o: Bắt đầu với API của OpenAI để hiểu cách viết vài dòng mã truy cập các mô hình tối tân.

Tinh chỉnh GPT-4o Mini

Trong phần này, chúng ta sẽ tinh chỉnh mô hình GPT-4o Mini trên bộ dữ liệu Stress Detection from the Social Media Articles từ Kaggle. Bộ dữ liệu chứa các bài đăng từ Reddit và Twitter, phân loại thành các nhãn căng thẳng và không căng thẳng.

Tạo bộ dữ liệu

Giờ chúng ta sẽ nạp và xử lý bộ dữ liệu.

  1. Nạp 200 hàng đầu từ bộ dữ liệu bài đăng Reddit.
  2. Loại bỏ tất cả cột trừ 'title' và 'label'.
  3. Ánh xạ cột nhãn để chuyển 0 và 1 thành nhãn "không căng thẳng" và "căng thẳng".
  4. Chia bộ dữ liệu thành tập huấn luyện và tập xác thực.
  5. Lưu cả hai tập huấn luyện và xác thực ở định dạng JSONL.

Lưu ý: Đảm bảo đúng định dạng bộ dữ liệu, gồm có system prompt, truy vấn của người dùng và phản hồi. Phản hồi sẽ là nhãn.

import pandas as pd
import json
from sklearn.model_selection import train_test_split

# Load the CSV file with the correct delimiter
file_path = 'Reddit_Title.csv'  # Change this to your local path
data = pd.read_csv(file_path, sep=';')

# Clean up and drop unnecessary columns, and select the top 200 rows
data_cleaned = data[['title', 'label']].head(200)

# Mapping the 'label' column to more human-readable text
label_mapping = {0: "non-stress", 1: "stress"}
data_cleaned['label'] = data_cleaned['label'].map(label_mapping)

# Split the data into training and validation sets (80% train, 20% validation)
train_data, validation_data = train_test_split(data_cleaned, test_size=0.2, random_state=42)

def save_to_jsonl(data, output_file_path):
    jsonl_data = []
    for index, row in data.iterrows():
        jsonl_data.append({
            "messages": [
                {"role": "system", "content": "Given a social media post, classify whether it indicates 'stress' or 'non-stress'."},
                {"role": "user", "content": row['title']},
                {"role": "assistant", "content": f"\"{row['label']}\""}
            ]
        })

    # Save to JSONL format
    with open(output_file_path, 'w') as f:
        for item in jsonl_data:
            f.write(json.dumps(item) + '\n')

# Save the training and validation sets to separate JSONL files
train_output_file_path = 'stress_detection_train.jsonl' 
validation_output_file_path = 'stress_detection_validation.jsonl'

save_to_jsonl(train_data, train_output_file_path)
save_to_jsonl(validation_data, validation_output_file_path)

print(f"Training dataset save to {train_output_file_path}")
print(f"Validation dataset save to {validation_output_file_path}")

Đầu ra: 

Training dataset save to stress_detection_train.jsonl
Validation dataset save to stress_detection_validation.jsonl

Tải lên bộ dữ liệu

Giờ chúng ta sẽ dùng client OpenAI để tải cả hai tập huấn luyện và xác thực lên phục vụ tinh chỉnh.

train_file = client.files.create(
  file=open(train_output_file_path, "rb"),
  purpose="fine-tune"
)

valid_file = client.files.create(
  file=open(validation_output_file_path, "rb"),
  purpose="fine-tune"
)

print(f"Training file Info: {train_file}")
print(f"Validation file Info: {valid_file}")

OpenAI API sẽ kiểm tra hợp lệ bộ dữ liệu trước, sau đó tải lên và tạo metadata để chúng ta dùng tinh chỉnh mô hình. 

Training file Info: FileObject(id='file-b2lo2chod6xuMhYg9JcEsnp6', bytes=48563, created_at=1727133513, filename='stress_detection_train.jsonl', object='file', purpose='fine-tune', status='processed', status_details=None)
Validation file Info: FileObject(id='file-Fae0AVSUhTGr49qhQz8d2yyp', bytes=12284, created_at=1727133514, filename='stress_detection_validation.jsonl', object='file', purpose='fine-tune', status='processed', status_details=None)

Để kiểm tra việc đẩy dữ liệu lên đám mây đã thành công chưa, vào Dashboard và nhấp tab “Storage”. Sẽ có hai tệp sẵn sàng để sử dụng.

Uploading the traning and validation dataset.

Bắt đầu tác vụ tinh chỉnh

Tạo tác vụ tinh chỉnh bằng client API. Hàm tinh chỉnh yêu cầu ID tệp dữ liệu huấn luyện, ID tệp dữ liệu xác thực, tên mô hình và siêu tham số. Chúng ta sẽ tinh chỉnh mô hình trong ba epoch. Để cải thiện hiệu năng, bạn có thể huấn luyện trên toàn bộ bộ dữ liệu với ít nhất 5 epoch. 

model = client.fine_tuning.jobs.create(
  training_file=train_file.id, 
  validation_file=valid_file.id,
  model="gpt-4o-mini-2024-07-18", 
  hyperparameters={
    "n_epochs": 3,
	"batch_size": 3,
	"learning_rate_multiplier": 0.3
  }
)
job_id = model.id
status = model.status

print(f'Fine-tuning model with jobID: {job_id}.')
print(f"Training Response: {model}")
print(f"Training Status: {status}")

Khi chạy hàm, tác vụ tinh chỉnh sẽ bắt đầu và hiển thị log. 

Fine-tuning model with jobID: ftjob-rgIMFxZSsWDqCNfOev54e4Jq.
Training Response: FineTuningJob(id='ftjob-rgIMFxZSsWDqCNfOev54e4Jq', created_at=1727135628, error=Error(code=None, message=None, param=None), fine_tuned_model=None, finished_at=None, hyperparameters=Hyperparameters(n_epochs=3, batch_size=3, learning_rate_multiplier=0.3), model='gpt-4o-mini-2024-07-18', object='fine_tuning.job', organization_id='org-jLXWbL5JssIxj9KNgoFBK7Qi', result_files=[], seed=748607710, status='validating_files', trained_tokens=None, training_file='file-b2lo2chod6xuMhYg9JcEsnp6', validation_file='file-Fae0AVSUhTGr49qhQz8d2yyp', estimated_finish=None, integrations=[], user_provided_suffix=None)
Training Status: validating_files

Bạn có thể xem trạng thái tác vụ tinh chỉnh trên bảng điều khiển bằng cách nhấp tab “Fine-tuning” và nhấp vào job ID.

Model fine-tuneing

Hoặc kiểm tra trạng thái tác vụ tinh chỉnh bằng hàm jobs.retrieve. 

# Retrieve the state of a fine-tune
client.fine_tuning.jobs.retrieve(job_id)

Đầu ra: 

FineTuningJob(id='ftjob-rgIMFxZSsWDqCNfOev54e4Jq', created_at=1727135628, error=Error(code=None, message=None, param=None), fine_tuned_model=None, finished_at=None, hyperparameters=Hyperparameters(n_epochs=3, batch_size=3, learning_rate_multiplier=0.3), model='gpt-4o-mini-2024-07-18', object='fine_tuning.job', organization_id='org-jLXWbL5JssIxj9KNgoFBK7Qi', result_files=[], seed=748607710, status='running', trained_tokens=None, training_file='file-b2lo2chod6xuMhYg9JcEsnp6', validation_file='file-Fae0AVSUhTGr49qhQz8d2yyp', estimated_finish=1727135943, integrations=[], user_provided_suffix=None)

Nếu bạn thấy loss không giảm, bạn luôn có thể hủy tác vụ bằng hàm jobs.cancel.

# Cancel a job
client.fine_tuning.jobs.cancel(job_id)

Khi tác vụ tinh chỉnh hoàn tất, bạn sẽ nhận email thông báo mô hình đã sẵn sàng sử dụng.

Receiving the email about fine-tuning the job status.

Truy cập mô hình đã tinh chỉnh bằng API

Để truy cập mô hình đã tinh chỉnh, chúng ta cần lấy tên mô hình đã tinh chỉnh. Để làm vậy, chúng ta sẽ lấy thông tin tất cả tác vụ tinh chỉnh, chọn tác vụ gần nhất, rồi chọn tên mô hình.

result = client.fine_tuning.jobs.list()

# Retrieve the fine tuned model
fine_tuned_model = result.data[0].fine_tuned_model
print(fine_tuned_model)

Đây là tên mô hình đã tinh chỉnh của chúng ta. 

ft:gpt-4o-mini-2024-07-18:personal::AAnFfX5q

Tạo phản hồi bằng cách cung cấp cho hàm hoàn thành hội thoại tên mô hình đã tinh chỉnh, messages với system prompt đúng và một mẫu từ bộ dữ liệu.

completion = client.chat.completions.create(
  model = fine_tuned_model,
  messages=[
    {"role": "system", "content": "Given a social media post, classify whether it indicates 'stress' or 'non-stress'."},
    {"role": "user", "content": "Just went to my first homecoming, and they played a song I've always wanted to dance to at an official dance. Sorry for the terrible quality, but my happiness in this moment couldn't be exaggerated!"}
  ]
)
print(completion.choices[0].message.content)

Thành công! Tôi đã dự đoán đúng nhãn.

"non-stress"

Nếu bạn không hài lòng với mô hình, bạn luôn có thể xóa nó bằng lệnh sau. Chúng tôi sẽ không làm điều đó vì cần chạy thêm đánh giá mô hình trước.

# Delete a fine-tuned model (must be an owner of the org the model was created in)
client.models.delete(fine_tuned_model)

Truy cập mô hình đã tinh chỉnh bằng Playground

Có một cách khác để truy cập mô hình đã tinh chỉnh và thử nghiệm với nhiều prompt hiệu quả hơn.

Vào bảng điều khiển OpenAI, nhấp tab "Fine-tuning", chọn tác vụ vừa chạy gần đây, rồi nhấp nút "Playground" ở góc dưới bên phải.

Accessing the fine-tuned model using playground.

Bạn sẽ được đưa đến ứng dụng chatbot. Tại đây, bạn có thể cung cấp system prompt và bắt đầu nhập các mẫu bài đăng Reddit. 

Trying out fine-tuned model.

Bạn thậm chí có thể chạy cùng một prompt và so sánh với mô hình khác để phân tích tốt hơn. 

Đánh giá mô hình

Chúng ta đã tinh chỉnh mô hình và thấy rằng khá ổn. Nhưng bạn đã cân nhắc liệu ban đầu nó vốn đã tốt hơn chưa? Chúng ta vẫn chưa so sánh chi tiết trước và sau khi tinh chỉnh. 

Trong phần này, chúng ta sẽ dùng dữ liệu xác thực để dự đoán nhãn bằng mô hình gốc rồi so sánh với mô hình đã tinh chỉnh. Chúng ta sẽ so sánh dựa trên độ chính xác, báo cáo phân loại và ma trận nhầm lẫn. 

Đánh giá mô hình trước khi tinh chỉnh

Tạo hàm predict nhận đầu vào là bộ dữ liệu và tên mô hình để sinh danh sách nhãn dự đoán. Hàm dùng cùng system message và tiêu đề bài đăng từ bộ dữ liệu.

def predict(test, model):
    y_pred = []
    categories = ["non-stress", "stress"]

    for index, row in test.iterrows():
        response = client.chat.completions.create(
            model=model,
            messages=[
                {
                    "role": "system",
                    "content": "Given a social media post, classify whether it indicates 'stress' or 'non-stress'.",
                },
                {"role": "user", "content": row["title"]},
            ],
        )

        answer = response.choices[0].message.content

        # Determine the predicted category

        for category in categories:
            if category.lower() in answer.lower():
                y_pred.append(category)
                break
        else:
            y_pred.append("none")
    return y_pred

Sau đó, tạo hàm evaluate, hàm này sẽ dùng nhãn dự đoán và nhãn thực để tạo điểm chính xác, báo cáo phân loại và ma trận nhầm lẫn.

from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import numpy as np


def evaluate(y_true, y_pred):
    labels = ["non-stress", "stress"]
    mapping = {label: idx for idx, label in enumerate(labels)}

    def map_func(x):
        return mapping.get(
            x, -1
        )  # Map to -1 if not found, but should not occur with correct data

    y_true_mapped = np.vectorize(map_func)(y_true)
    y_pred_mapped = np.vectorize(map_func)(y_pred)

    # Calculate accuracy

    accuracy = accuracy_score(y_true=y_true_mapped, y_pred=y_pred_mapped)
    print(f"Accuracy: {accuracy:.3f}")

    # Generate accuracy report

    unique_labels = set(y_true_mapped)  # Get unique labels

    for label in unique_labels:
        label_indices = [
            i for i in range(len(y_true_mapped)) if y_true_mapped[i] == label
        ]
        label_y_true = [y_true_mapped[i] for i in label_indices]
        label_y_pred = [y_pred_mapped[i] for i in label_indices]
        label_accuracy = accuracy_score(label_y_true, label_y_pred)
        print(f"Accuracy for label {labels[label]}: {label_accuracy:.3f}")
    # Generate classification report

    class_report = classification_report(
        y_true=y_true_mapped,
        y_pred=y_pred_mapped,
        target_names=labels,
        labels=list(range(len(labels))),
    )
    print("\nClassification Report:")
    print(class_report)

    # Generate confusion matrix

    conf_matrix = confusion_matrix(
        y_true=y_true_mapped, y_pred=y_pred_mapped, labels=list(range(len(labels)))
    )
    print("\nConfusion Matrix:")
    print(conf_matrix)

Cung cấp hàm predict với bộ dữ liệu xác thực và tên mô hình gốc. Sau đó, truyền nhãn dự đoán và nhãn thực vào hàm evaluate để tạo báo cáo đánh giá mô hình.

y_pred = predict(validation_data, "gpt-4o-mini-2024-07-18")
y_true = validation_data["label"]
evaluate(y_true, y_pred)

Mô hình gốc khá tốt trong phân loại văn bản. Chúng ta đạt 92,5% độ chính xác.

Accuracy: 0.925
Accuracy for label non-stress: 0.947
Accuracy for label stress: 0.905

Classification Report:
              precision    recall  f1-score   support

  non-stress       0.90      0.95      0.92        19
      stress       0.95      0.90      0.93        21

    accuracy                           0.93        40
   macro avg       0.93      0.93      0.92        40
weighted avg       0.93      0.93      0.93        40


Confusion Matrix:
[[18  1]
 [ 2 19]]

Đánh giá mô hình sau khi tinh chỉnh

Hãy dùng hàm predict với tên mô hình đã tinh chỉnh để tạo nhãn căng thẳng. Sau đó, dùng nhãn dự đoán và nhãn thực để tạo báo cáo đánh giá mô hình chi tiết.

fine_tuned_model = "ft:gpt-4o-mini-2024-07-18:personal::AAnFfX5q"

y_pred = predict(validation_data,fine_tuned_model)
evaluate(y_true, y_pred)

Hiệu năng mô hình đã cải thiện. Chúng ta đạt 97,5% độ chính xác, một mức cải thiện đáng kể.

Accuracy: 0.975
Accuracy for label non-stress: 1.000
Accuracy for label stress: 0.952

Classification Report:
              precision    recall  f1-score   support

  non-stress       0.95      1.00      0.97        19
      stress       1.00      0.95      0.98        21

    accuracy                           0.97        40
   macro avg       0.97      0.98      0.97        40
weighted avg       0.98      0.97      0.98        40


Confusion Matrix:
[[19  0]
 [ 1 20]]

Tinh chỉnh cho một số tác vụ có thể cải thiện đáng kể độ chính xác. Đây chỉ là bài thử mẫu, nhưng trong dự án thực tế, tinh chỉnh cải thiện độ chính xác và hiệu năng của mô hình trên các tác vụ phân loại, định kiểu và đầu ra có cấu trúc.

Nếu bạn gặp sự cố khi chạy mã trên, vui lòng tham khảo không gian làm việc DataLab: Tinh chỉnh GPT-4 Mini.

Bước tiếp theo trong hành trình của bạn là dùng mô hình đã tinh chỉnh này để tạo một ứng dụng AI hoàn chỉnh. Bạn có thể tìm hiểu bằng cách theo dõi code along: Tạo trợ lý AI với GPT-4o.

Kết luận

Trong hướng dẫn này, chúng ta đã tinh chỉnh thành công mô hình GPT-4o mini để phân loại văn bản thành nhãn "căng thẳng" và "không căng thẳng". Sau đó, chúng ta truy cập mô hình đã tinh chỉnh bằng OpenAI API và playground của OpenAI, cho phép áp dụng thực tế và thử nghiệm thêm.

Việc đánh giá mô hình đã tinh chỉnh cho kết quả đáng chú ý, cho thấy cải thiện hiệu năng phân loại trên nhiều chỉ số so với mô hình gốc. Quy trình này nhấn mạnh giá trị của tinh chỉnh trong việc đạt đầu ra đáng tin cậy và chính xác hơn, đặc biệt với các tác vụ như phân loại văn bản.

Nếu bạn muốn dùng mô hình miễn phí, mã nguồn mở, chúng tôi có một hướng dẫn xuất sắc mang tên Tinh chỉnh Llama 3.2 và dùng cục bộ: Hướng dẫn từng bước. Trong hướng dẫn này, chúng tôi sẽ chỉ bạn cách tinh chỉnh phiên bản Llama mới nhất và chuyển đổi sang định dạng GGUF để dùng cục bộ trên laptop của bạn.

Abid Ali Awan

Tác giả

Abid Ali Awan

Là một nhà khoa học dữ liệu được chứng nhận, tôi đam mê tận dụng công nghệ tiên tiến để tạo ra các ứng dụng học máy đổi mới. Với nền tảng vững chắc về nhận dạng giọng nói, phân tích và báo cáo dữ liệu, MLOps, AI hội thoại và NLP, tôi đã rèn giũa kỹ năng phát triển các hệ thống thông minh có thể tạo ra tác động thực sự. Bên cạnh chuyên môn kỹ thuật, tôi cũng là một người truyền đạt tốt, có khả năng chắt lọc các khái niệm phức tạp thành ngôn ngữ rõ ràng, súc tích. Nhờ đó, tôi trở thành một blogger được nhiều người quan tâm trong lĩnh vực khoa học dữ liệu, chia sẻ góc nhìn và kinh nghiệm với cộng đồng các chuyên gia dữ liệu ngày càng lớn. Hiện tại, tôi tập trung vào sáng tạo và biên tập nội dung, làm việc với các mô hình ngôn ngữ lớn để phát triển nội dung mạnh mẽ và hấp dẫn, giúp doanh nghiệp và cá nhân tận dụng tối đa dữ liệu của mình.

Chủ đề

Liên quan