Fine-tune EmbeddingGemma

عرض على ai.google.dev التشغيل في Google Colab التشغيل في Kaggle الفتح في Vertex AI عرض المصدر على GitHub

يساعد الضبط الدقيق في تقليل الفجوة بين الفهم العام للنموذج والدقة المتخصصة وعالية الأداء التي يتطلّبها تطبيقك. بما أنّه لا يوجد نموذج واحد مثالي لكل مهمة، فإنّ عملية الضبط الدقيق تعمل على تكييف النموذج مع مجال عملك المحدّد.

لنفترض أنّ شركتك "شيبويا المالية" تقدّم منتجات مالية معقّدة مختلفة، مثل صناديق الاستثمار وحسابات NISA (حساب توفير معفى من الضرائب) وقروض الإسكان. يستخدم فريق دعم العملاء قاعدة معلومات داخلية للعثور بسرعة على إجابات عن أسئلة العملاء.

الإعداد

قبل البدء في هذا البرنامج التعليمي، أكمِل الخطوات التالية:

  • يمكنك الوصول إلى EmbeddingGemma من خلال تسجيل الدخول إلى Hugging Face والنقر على أوافق على الترخيص لنموذج Gemma.
  • أنشئ رمز دخول في Hugging Face واستخدِمه لتسجيل الدخول من Colab.

سيتم تشغيل ورقة الملاحظات هذه على وحدة المعالجة المركزية أو وحدة معالجة الرسومات.

تثبيت حِزم Python

ثبِّت المكتبات المطلوبة لتشغيل نموذج EmbeddingGemma وإنشاء عمليات التضمين. ‫Sentence Transformers هو إطار عمل Python لعمليات التضمين في النصوص والصور. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات Sentence Transformers.

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

بعد قبول الترخيص، تحتاج إلى رمز مميّز صالح من Hugging Face للوصول إلى النموذج.

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

تحميل النموذج

استخدِم مكتبات sentence-transformers لإنشاء مثيل لفئة نموذج باستخدام 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

تجهيز مجموعة بيانات الضبط الدقيق

هذا هو الجزء الأكثر أهمية. عليك إنشاء مجموعة بيانات تعلّم النموذج معنى "مشابه" في سياقك المحدّد. غالبًا ما تكون هذه البيانات منظَّمة على شكل ثلاثيات: (نص الرابط، إيجابي، سلبي)

  • العبارة الأساسية: الاستعلام أو الجملة الأصلية
  • إيجابي: جملة مشابهة جدًا أو مطابقة للجملة الأساسية من الناحية الدلالية
  • سلبية: جملة تتناول موضوعًا ذا صلة ولكنها مختلفة من الناحية الدلالية.

في هذا المثال، أعددنا 3 مجموعات ثلاثية فقط، ولكن في تطبيق حقيقي، ستحتاج إلى مجموعة بيانات أكبر بكثير لتحقيق أداء جيد.

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

قبل الضبط الدقيق

قد يؤدي البحث عن "استثمار معفى من الضرائب" إلى ظهور النتائج التالية مع درجات التشابه:

  1. المستند: فتح حساب NISA (النتيجة: 0.51)
  2. المستند: فتح حساب توفير عادي (النتيجة: 0.50) <- نتيجة مشابهة، قد تكون مربكة
  3. المستند: دليل طلب القرض السكني (النتيجة: 0.44)
task_name = "STS"

def get_scores(query, documents):
  # Calculate embeddings by calling model.encode()
  query_embeddings = model.encode(query, prompt_name=task_name)
  doc_embeddings = model.encode(documents, prompt_name=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.51571906
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.5035889
Document:  Home Loan Application Guide -> 🤖 Score:  0.4406476

التدريب

باستخدام إطار عمل مثل sentence-transformers في لغة Python، يتعلّم النموذج الأساسي تدريجيًا الفروق الدقيقة في مفرداتك المالية.

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.6459116
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.42690125
Document:  Home Loan Application Guide -> 🤖 Score:  0.40419024
Step 6 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.68530923
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.3611964
Document:  Home Loan Application Guide -> 🤖 Score:  0.40812016
Step 9 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.7168733
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.3449782
Document:  Home Loan Application Guide -> 🤖 Score:  0.44477722
Step 12 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.73008573
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.34124148
Document:  Home Loan Application Guide -> 🤖 Score:  0.4676212
Step 15 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.73378766
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.34055778
Document:  Home Loan Application Guide -> 🤖 Score:  0.47503752
Step 15 finished. Running evaluation:
Document:  Opening a NISA Account -> 🤖 Score:  0.73378766
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.34055778
Document:  Home Loan Application Guide -> 🤖 Score:  0.47503752
TrainOutput(global_step=15, training_loss=0.009651267528511198, metrics={'train_runtime': 195.3004, 'train_samples_per_second': 0.077, 'train_steps_per_second': 0.077, 'total_flos': 0.0, 'train_loss': 0.009651267528511198, 'epoch': 5.0})

بعد الضبط الدقيق

يؤدي طلب البحث نفسه الآن إلى عرض نتائج أكثر وضوحًا:

  1. المستند: فتح حساب NISA (نتيجة المطابقة: 0.73) <- أكثر ثقة
  2. المستند: فتح حساب توفير عادي (النتيجة: 0.34) <- أقل صلة بشكل واضح
  3. المستند: دليل طلب القرض السكني (النتيجة: 0.47)
get_scores(query, documents)
Document:  Opening a NISA Account -> 🤖 Score:  0.73378766
Document:  Opening a Regular Savings Account -> 🤖 Score:  0.34055778
Document:  Home Loan Application Guide -> 🤖 Score:  0.47503752

لتحميل النموذج إلى Hugging Face Hub، يمكنك استخدام طريقة push_to_hub من مكتبة Sentence Transformers.

يسهّل تحميل النموذج الوصول إليه للاستدلال مباشرةً من Hub، ومشاركته مع الآخرين، وتحديد إصدار عملك. بعد التحميل، يمكن لأي شخص تحميل النموذج باستخدام سطر واحد من الرمز البرمجي، وذلك ببساطة عن طريق الإشارة إلى معرّف النموذج الفريد <username>/my-embedding-gemma

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

الملخّص والخطوات التالية

لقد تعرّفت الآن على كيفية تعديل نموذج EmbeddingGemma ليناسب مجالاً معيّنًا من خلال ضبطه بدقة باستخدام مكتبة Sentence Transformers.

في ما يلي بعض الإجراءات الأخرى التي يمكنك تنفيذها باستخدام EmbeddingGemma: