![]() |
![]() |
![]() |
|
![]() |
L'ottimizzazione contribuisce a colmare il divario tra la comprensione generica di un modello e l'accuratezza specializzata e ad alte prestazioni richiesta dalla tua applicazione. Poiché nessun modello è perfetto per ogni attività, il perfezionamento lo adatta al tuo dominio specifico.
Immagina che la tua azienda, "Shibuya Financial", offra vari prodotti finanziari complessi come fondi di investimento, conti NISA (un conto di risparmio con agevolazioni fiscali) e mutui per la casa. Il tuo team di assistenza clienti utilizza una knowledge base interna per trovare rapidamente le risposte alle domande dei clienti.
Configurazione
Prima di iniziare questo tutorial, completa i seguenti passaggi:
- Accedi a EmbeddingGemma effettuando l'accesso a Hugging Face e selezionando Accetta licenza per un modello Gemma.
- Genera un token di accesso Hugging Face e utilizzalo per accedere da Colab.
Questo notebook verrà eseguito su CPU o GPU.
Installa i pacchetti Python
Installa le librerie necessarie per eseguire il modello EmbeddingGemma e generare gli embedding. Sentence Transformers è un framework Python per gli incorporamenti di testo e immagini. Per saperne di più, consulta la documentazione di Sentence Transformers.
pip install -U sentence-transformers git+https://github.com/huggingface/transformers@v4.56.0-Embedding-Gemma-preview
Dopo aver accettato la licenza, è necessario un token Hugging Face valido per accedere al modello.
# Login into Hugging Face Hub
from huggingface_hub import login
login()
Carica modello
Utilizza le librerie sentence-transformers
per creare un'istanza di una classe di modello con 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
Preparare il set di dati di fine tuning
Questa è la parte più importante. Devi creare un set di dati che insegni al modello cosa significa "simile" nel tuo contesto specifico. Questi dati sono spesso strutturati come triplette: (ancora, positivo, negativo)
- Ancora: la query o la frase originale.
- Positivo: una frase semanticamente molto simile o identica all'ancora.
- Negativa: una frase che riguarda un argomento correlato, ma semanticamente distinto.
In questo esempio, abbiamo preparato solo 3 triplette, ma per un'applicazione reale avresti bisogno di un set di dati molto più grande per ottenere buoni risultati.
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 })
Prima dell'ottimizzazione
Una ricerca di "investimento esentasse" potrebbe aver restituito i seguenti risultati, con i punteggi di similarità:
- Documento: Apertura di un conto NISA (punteggio: 0,45)
- Documento: Apertura di un conto di risparmio ordinario (punteggio: 0,48) <- Punteggio simile, potenzialmente fuorviante
- Documento: Guida alla richiesta di mutuo per la casa (punteggio: 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
Formazione
Utilizzando un framework come sentence-transformers
in Python, il modello di base apprende gradualmente le sottili distinzioni nel tuo vocabolario finanziario.
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})
Dopo l'ottimizzazione
La stessa ricerca ora produce risultati molto più chiari:
- Documento: Apertura di un conto NISA (punteggio: 0,72) <- Molto più sicuro
- Documento: Apertura di un conto di risparmio ordinario (punteggio: 0,28) <- Chiaramente meno pertinente
- Documento: Guida alla richiesta di mutuo per la casa (punteggio: 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
Per caricare il modello su Hugging Face Hub, puoi utilizzare il metodo push_to_hub
della libreria Sentence Transformers.
Il caricamento del modello semplifica l'accesso per l'inferenza direttamente dall'hub, la condivisione con altri e il controllo delle versioni del tuo lavoro. Una volta caricato, chiunque può caricare il tuo modello con una sola riga di codice, semplicemente facendo riferimento al suo ID modello univoco <username>/my-embedding-gemma
# Push to Hub
model.push_to_hub("my-embedding-gemma")
Riepilogo e passaggi successivi
Ora hai imparato ad adattare un modello EmbeddingGemma per un dominio specifico eseguendo l'ottimizzazione con la libreria Sentence Transformers.
Scopri cos'altro puoi fare con EmbeddingGemma:
- Training Overview nella documentazione di Sentence Transformers
- Generare incorporamenti con Sentence Transformers
- Esempio semplice di RAG nel cookbook di Gemma