Tinh chỉnh EmbeddingGemma

Xem trên ai.google.dev Chạy trong Google Colab Chạy trong Kaggle Mở trong Vertex AI Xem nguồn trên GitHub

Tinh chỉnh giúp thu hẹp khoảng cách giữa kiến thức chung của mô hình và độ chính xác chuyên biệt, hiệu suất cao mà ứng dụng của bạn yêu cầu. Vì không có mô hình nào hoàn hảo cho mọi nhiệm vụ, nên việc tinh chỉnh sẽ điều chỉnh mô hình cho phù hợp với miền cụ thể của bạn.

Giả sử công ty của bạn ("Shibuya Financial") cung cấp nhiều sản phẩm tài chính phức tạp như quỹ đầu tư, tài khoản NISA (tài khoản tiết kiệm được ưu đãi thuế) và khoản vay mua nhà. Nhóm hỗ trợ khách hàng của bạn sử dụng một cơ sở kiến thức nội bộ để nhanh chóng tìm ra câu trả lời cho các câu hỏi của khách hàng.

Thiết lập

Trước khi bắt đầu hướng dẫn này, hãy hoàn tất các bước sau:

  • Truy cập vào EmbeddingGemma bằng cách đăng nhập vào Hugging Face rồi chọn Acknowledge license (Chấp nhận giấy phép) cho một mô hình Gemma.
  • Tạo Mã truy cập Hugging Face và dùng mã này để đăng nhập từ Colab.

Sổ tay này sẽ chạy trên CPU hoặc GPU.

Cài đặt các gói Python

Cài đặt các thư viện cần thiết để chạy mô hình EmbeddingGemma và tạo các vectơ nhúng. Sentence Transformers là một khung Python để nhúng văn bản và hình ảnh. Để biết thêm thông tin, hãy xem tài liệu về Sentence Transformers.

pip install -U sentence-transformers git+https://github.com/huggingface/transformers@v4.56.0-Embedding-Gemma-preview

Sau khi chấp nhận giấy phép, bạn cần có một mã thông báo Hugging Face hợp lệ để truy cập vào mô hình.

# Login into Hugging Face Hub
from huggingface_hub import login
login()

Tải mô hình

Sử dụng các thư viện sentence-transformers để tạo một thực thể của lớp mô hình bằng EmbeddingGemma.

import torch
from sentence_transformers import SentenceTransformer

device = "cuda" if torch.cuda.is_available() else "cpu"

model_id = "google/embeddinggemma-300M"
model = SentenceTransformer(model_id).to(device=device)

print(f"Device: {model.device}")
print(model)
print("Total number of parameters in the model:", sum([p.numel() for _, p in model.named_parameters()]))
Device: cuda:0
SentenceTransformer(
  (0): Transformer({'max_seq_length': 2048, 'do_lower_case': False, 'architecture': 'Gemma3TextModel'})
  (1): Pooling({'word_embedding_dimension': 768, 'pooling_mode_cls_token': False, 'pooling_mode_mean_tokens': True, 'pooling_mode_max_tokens': False, 'pooling_mode_mean_sqrt_len_tokens': False, 'pooling_mode_weightedmean_tokens': False, 'pooling_mode_lasttoken': False, 'include_prompt': True})
  (2): Dense({'in_features': 768, 'out_features': 3072, 'bias': False, 'activation_function': 'torch.nn.modules.linear.Identity'})
  (3): Dense({'in_features': 3072, 'out_features': 768, 'bias': False, 'activation_function': 'torch.nn.modules.linear.Identity'})
  (4): Normalize()
)
Total number of parameters in the model: 307581696

Chuẩn bị tập dữ liệu tinh chỉnh

Đây là phần quan trọng nhất. Bạn cần tạo một tập dữ liệu để dạy mô hình biết "tương tự" có nghĩa là gì trong ngữ cảnh cụ thể của bạn. Dữ liệu này thường được cấu trúc dưới dạng bộ ba: (anchor, positive, negative)

  • Anchor: Cụm từ hoặc câu hỏi ban đầu.
  • Tích cực: Một câu có ngữ nghĩa rất giống hoặc giống hệt với câu gốc.
  • Tiêu cực: Một câu có chủ đề liên quan nhưng khác biệt về ngữ nghĩa.

Trong ví dụ này, chúng ta chỉ chuẩn bị 3 bộ ba, nhưng đối với một ứng dụng thực tế, bạn sẽ cần một tập dữ liệu lớn hơn nhiều để hoạt động hiệu quả.

from datasets import Dataset

dataset = [
    ["How do I open a NISA account?", "What is the procedure for starting a new tax-free investment account?", "I want to check the balance of my regular savings account."],
    ["Are there fees for making an early repayment on a home loan?", "If I pay back my house loan early, will there be any costs?", "What is the management fee for this investment trust?"],
    ["What is the coverage for medical insurance?", "Tell me about the benefits of the health insurance plan.", "What is the cancellation policy for my life insurance?"],
]

# Convert the list-based dataset into a list of dictionaries.
data_as_dicts = [ {"anchor": row[0], "positive": row[1], "negative": row[2]} for row in dataset ]

# Create a Hugging Face `Dataset` object from the list of dictionaries.
train_dataset = Dataset.from_list(data_as_dicts)
print(train_dataset)
Dataset({
    features: ['anchor', 'positive', 'negative'],
    num_rows: 3
})

Trước khi tinh chỉnh

Một cụm từ tìm kiếm "đầu tư miễn thuế" có thể đã cho ra các kết quả sau, kèm theo điểm tương đồng:

  1. Tài liệu: Mở tài khoản NISA (Điểm: 0,45)
  2. Tài liệu: Mở tài khoản tiết kiệm thông thường (Điểm: 0,48) <- Điểm tương tự, có thể gây nhầm lẫn
  3. Tài liệu: Hướng dẫn nộp đơn vay mua nhà (Điểm: 0,42)
task_name = "STS"

def get_scores(query, documents):
  # Calculate embeddings by calling model.encode()
  query_embeddings = model.encode(query, prompt=task_name)
  doc_embeddings = model.encode(documents, prompt=task_name)

  # Calculate the embedding similarities
  similarities = model.similarity(query_embeddings, doc_embeddings)

  for idx, doc in enumerate(documents):
    print("Document: ", doc, "-> 🤖 Score: ", similarities.numpy()[0][idx])

query = "I want to start a tax-free installment investment, what should I do?"
documents = ["Opening a NISA Account", "Opening a Regular Savings Account", "Home Loan Application Guide"]

get_scores(query, documents)
Document:  Opening a NISA Account -> 🤖 Score:  0.45698774
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.48092696
Document:  Home Loan Application Guide -> 🤖 Score:  0.42127067

Đào tạo

Khi sử dụng một khung như sentence-transformers trong Python, mô hình cơ sở sẽ dần học được những điểm khác biệt tinh tế trong từ vựng tài chính của bạn.

from sentence_transformers import SentenceTransformerTrainer, SentenceTransformerTrainingArguments
from sentence_transformers.losses import MultipleNegativesRankingLoss
from transformers import TrainerCallback

loss = MultipleNegativesRankingLoss(model)

args = SentenceTransformerTrainingArguments(
    # Required parameter:
    output_dir="my-embedding-gemma",
    # Optional training parameters:
    prompts=model.prompts[task_name],    # use model's prompt to train
    num_train_epochs=5,
    per_device_train_batch_size=1,
    learning_rate=2e-5,
    warmup_ratio=0.1,
    # Optional tracking/debugging parameters:
    logging_steps=train_dataset.num_rows,
    report_to="none",
)

class MyCallback(TrainerCallback):
    "A callback that evaluates the model at the end of eopch"
    def __init__(self, evaluate):
        self.evaluate = evaluate # evaluate function

    def on_log(self, args, state, control, **kwargs):
        # Evaluate the model using text generation
        print(f"Step {state.global_step} finished. Running evaluation:")
        self.evaluate()

def evaluate():
  get_scores(query, documents)

trainer = SentenceTransformerTrainer(
    model=model,
    args=args,
    train_dataset=train_dataset,
    loss=loss,
    callbacks=[MyCallback(evaluate)]
)
trainer.train()
Step 3 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.6449194
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.44123
Document:  Home Loan Application Guide -> 🤖 Score:  0.46752414
Step 6 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.68873787
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.34069622
Document:  Home Loan Application Guide -> 🤖 Score:  0.50065553
Step 9 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.7148906
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.30480516
Document:  Home Loan Application Guide -> 🤖 Score:  0.52454984
Step 12 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.72614634
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.29255486
Document:  Home Loan Application Guide -> 🤖 Score:  0.5370023
Step 15 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.7294032
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.2893038
Document:  Home Loan Application Guide -> 🤖 Score:  0.54087913
Step 15 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.7294032
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.2893038
Document:  Home Loan Application Guide -> 🤖 Score:  0.54087913
TrainOutput(global_step=15, training_loss=0.009651281436261646, metrics={'train_runtime': 63.2486, 'train_samples_per_second': 0.237, 'train_steps_per_second': 0.237, 'total_flos': 0.0, 'train_loss': 0.009651281436261646, 'epoch': 5.0})

Sau khi tinh chỉnh

Cùng một nội dung tìm kiếm nhưng giờ đây sẽ cho ra kết quả rõ ràng hơn nhiều:

  1. Document: Opening a NISA account (Score: 0.72) <- Much more confident
  2. Tài liệu: Mở tài khoản tiết kiệm thông thường (Điểm: 0,28) <- Ít liên quan hơn rõ ràng
  3. Tài liệu: Hướng dẫn nộp đơn vay mua nhà (Điểm: 0,54)
get_scores(query, documents)
Document:  Opening a NISA Account -> 🤖 Score:  0.7294032
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.2893038
Document:  Home Loan Application Guide -> 🤖 Score:  0.54087913

Để tải mô hình lên Hugging Face Hub, bạn có thể sử dụng phương thức push_to_hub trong thư viện Sentence Transformers.

Việc tải mô hình lên giúp bạn dễ dàng truy cập để suy luận trực tiếp từ Hub, chia sẻ với người khác và quản lý phiên bản cho công việc của mình. Sau khi tải lên, bất kỳ ai cũng có thể tải mô hình của bạn chỉ bằng một dòng mã, chỉ cần tham chiếu đến mã nhận dạng mô hình duy nhất <username>/my-embedding-gemma

# Push to Hub
model.push_to_hub("my-embedding-gemma")

Tóm tắt và các bước tiếp theo

Giờ đây, bạn đã tìm hiểu cách điều chỉnh một mô hình EmbeddingGemma cho một miền cụ thể bằng cách tinh chỉnh mô hình đó bằng thư viện Sentence Transformers.

Khám phá những việc khác bạn có thể làm với EmbeddingGemma: