|
|
הרצה ב-Google Colab
|
|
|
צפייה במקור ב-GitHub
|
Gemma Embedding הוא מודל קל משקל ופתוח להטמעה, שנועד לאחזור מהיר ואיכותי במכשירים יומיומיים כמו טלפונים ניידים. עם 308 מיליון פרמטרים בלבד, הוא יעיל מספיק כדי להריץ טכניקות מתקדמות של AI, כמו Retrieval Augmented Generation (יצירה משולבת-אחזור, RAG), ישירות במחשב המקומי שלכם, בלי צורך בחיבור לאינטרנט.
הגדרה
לפני שמתחילים את המדריך הזה, צריך לבצע את השלבים הבאים:
- כדי לקבל גישה ל-Gemma, צריך להתחבר ל-Hugging Face ולבחור באפשרות אישור הרישיון עבור מודל Gemma.
- יוצרים אסימון גישה ל-Hugging Face ומשתמשים בו כדי להתחבר מ-Colab.
ה-notebook הזה יפעל ב-CPU או ב-GPU.
התקנת חבילות 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
יצירת הטמעה
הטמעה היא ייצוג מספרי של טקסט, כמו מילה או משפט, שמשקף את המשמעות הסמנטית שלו. בעצם, זהו וקטור (רשימה של מספרים) שמאפשר למחשבים להבין את הקשרים וההקשר של מילים.
עכשיו נראה איך EmbeddingGemma מעבד שלוש מילים שונות ["apple", "banana", "car"].
EmbeddingGemma אומן על כמויות עצומות של טקסט ולמד את הקשרים בין מילים ומושגים.
words = ["apple", "banana", "car"]
# Calculate embeddings by calling model.encode()
embeddings = model.encode(words)
print(embeddings)
for idx, embedding in enumerate(embeddings):
print(f"Embedding {idx+1} (shape): {embedding.shape}")
[[-0.18476306 0.00167681 0.03773484 ... -0.07996225 -0.02348064 0.00976741] [-0.21189538 -0.02657359 0.02513712 ... -0.08042689 -0.01999852 0.00512146] [-0.18924113 -0.02551468 0.04486253 ... -0.06377774 -0.03699806 0.03973572]] Embedding 1: (768,) Embedding 2: (768,) Embedding 3: (768,)
המודל מחזיר וקטור מספרי לכל משפט. הווקטורים בפועל ארוכים מאוד (768), אבל כדי לפשט את ההסבר, הם מוצגים עם כמה ממדים.
המפתח הוא לא המספרים עצמם, אלא המרחק בין הווקטורים. אם נשרטט את הווקטורים האלה במרחב רב-ממדי, הווקטורים של apple ושל banana יהיו קרובים מאוד זה לזה. הווקטור של car יהיה רחוק מאוד משני הווקטורים האחרים.
קביעת מידת הדמיון
בקטע הזה נשתמש בהטמעות כדי לקבוע עד כמה משפטים שונים דומים מבחינה סמנטית. כאן מוצגות דוגמאות עם ציוני דמיון גבוהים, בינוניים ונמוכים.
דמיון גבוה:
- משפט א': "השף הכין ארוחה טעימה לאורחים".
- משפט ב': "ארוחת ערב טעימה בושלה על ידי השף בשביל המבקרים".
- הסבר: שני המשפטים מתארים את אותו אירוע במילים שונות ובמבנים דקדוקיים שונים (ניסוח פעיל לעומת ניסוח סביל). המשמעות הבסיסית שלהם זהה.
דמיון בינוני:
- משפט א': "היא מומחית ללמידת מכונה".
- משפט ב': "יש לו עניין רב בבינה מלאכותית".
- הסבר: המשפטים קשורים זה לזה כי למידת מכונה היא תחום משנה של בינה מלאכותית. עם זאת, הם מדברים על אנשים שונים עם רמות שונות של מעורבות (מומחה לעומת מתעניין).
דמיון נמוך:
- משפט א': "The weather in Tokyo is sunny today".
- משפט ב': "אני צריך לקנות מצרכים לשבוע".
- הסבר: שני המשפטים עוסקים בנושאים שונים לחלוטין, ואין ביניהם חפיפה סמנטית.
# The sentences to encode
sentence_high = [
"The chef prepared a delicious meal for the guests.",
"A tasty dinner was cooked by the chef for the visitors."
]
sentence_medium = [
"She is an expert in machine learning.",
"He has a deep interest in artificial intelligence."
]
sentence_low = [
"The weather in Tokyo is sunny today.",
"I need to buy groceries for the week."
]
for sentence in [sentence_high, sentence_medium, sentence_low]:
print("🙋♂️")
print(sentence)
embeddings = model.encode(sentence)
similarities = model.similarity(embeddings[0], embeddings[1])
print("`-> 🤖 score: ", similarities.numpy()[0][0])
🙋♂️ ['The chef prepared a delicious meal for the guests.', 'A tasty dinner was cooked by the chef for the visitors.'] `-> 🤖 score: 0.8002148 🙋♂️ ['She is an expert in machine learning.', 'He has a deep interest in artificial intelligence.'] `-> 🤖 score: 0.45417833 🙋♂️ ['The weather in Tokyo is sunny today.', 'I need to buy groceries for the week.'] `-> 🤖 score: 0.22262995
שימוש בהנחיות עם EmbeddingGemma
כדי ליצור את ההטמעות הכי טובות באמצעות EmbeddingGemma, צריך להוסיף 'הנחיה' או 'משימה' לתחילת טקסט הקלט. הפרומפטים האלה מבצעים אופטימיזציה של ההטמעות למשימות ספציפיות, כמו אחזור מסמכים או מענה לשאלות, ועוזרים למודל להבחין בין סוגים שונים של קלט, כמו שאילתת חיפוש לעומת מסמך.
איך משתמשים בהנחיות
יש שלוש דרכים להשתמש בפרומפט במהלך ההסקה.
שימוש בארגומנט
prompt
מעבירים את מחרוזת ההנחיה המלאה ישירות לשיטהencode. כך יש לכם שליטה מדויקת.embeddings = model.encode( sentence, prompt="task: sentence similarity | query: " )שימוש בארגומנט
prompt_name
בוחרים הנחיה מוגדרת מראש לפי השם שלה. ההנחיות האלה נטענות מההגדרות של המודל או במהלך האתחול שלו.embeddings = model.encode(sentence, prompt_name="STS")שימוש בהנחיה שמוגדרת כברירת מחדל
אם לא מציינים אתpromptאו אתprompt_name, המערכת תשתמש אוטומטית בהנחיה שמוגדרת כdefault_prompt_name. אם לא מוגדרת ברירת מחדל, לא תופעל הנחיה.embeddings = model.encode(sentence)
print("Available tasks:")
for name, prefix in model.prompts.items():
print(f" {name}: \"{prefix}\"")
print("-"*80)
for sentence in [sentence_high, sentence_medium, sentence_low]:
print("🙋♂️")
print(sentence)
embeddings = model.encode(sentence, prompt_name="STS")
similarities = model.similarity(embeddings[0], embeddings[1])
print("`-> 🤖 score: ", similarities.numpy()[0][0])
Available tasks: query: "task: search result | query: " document: "title: none | text: " BitextMining: "task: search result | query: " Clustering: "task: clustering | query: " Classification: "task: classification | query: " InstructionRetrieval: "task: code retrieval | query: " MultilabelClassification: "task: classification | query: " PairClassification: "task: sentence similarity | query: " Reranking: "task: search result | query: " Retrieval: "task: search result | query: " Retrieval-query: "task: search result | query: " Retrieval-document: "title: none | text: " STS: "task: sentence similarity | query: " Summarization: "task: summarization | query: " -------------------------------------------------------------------------------- 🙋♂️ ['The chef prepared a delicious meal for the guests.', 'A tasty dinner was cooked by the chef for the visitors.'] `-> 🤖 score: 0.9363755 🙋♂️ ['She is an expert in machine learning.', 'He has a deep interest in artificial intelligence.'] `-> 🤖 score: 0.6425841 🙋♂️ ['The weather in Tokyo is sunny today.', 'I need to buy groceries for the week.'] `-> 🤖 score: 0.38587403
תרחיש שימוש: Retrieval-Augmented Generation (יצירה משולבת-אחזור, RAG)
במערכות RAG, משתמשים בערכים הבאים של prompt_name כדי ליצור הטמעות מיוחדות לשאילתות ולמסמכים:
לשאילתות: משתמשים ב-
prompt_name="Retrieval-query".query_embedding = model.encode( "How do I use prompts with this model?", prompt_name="Retrieval-query" )במסמכים: משתמשים ב-
prompt_name="Retrieval-document". כדי לשפר עוד יותר את ההטמעות של המסמכים, אפשר גם לכלול כותרת באמצעות הארגומנטpromptישירות:- עם כותרת:
doc_embedding = model.encode( "The document text...", prompt="title: Using Prompts in RAG | text: " )- בלי כותרת:
doc_embedding = model.encode( "The document text...", prompt="title: none | text: " )- עם כותרת:
קריאה נוספת
- פרטים על כל ההנחיות הזמינות של EmbeddingGemma מופיעים בכרטיס המודל.
- מידע כללי על תבניות של הנחיות זמין במסמכי התיעוד של Sentence Transformer.
- דוגמה ל-RAG אפשר לראות בדוגמה פשוטה ל-RAG ב-Gemma Cookbook.
סיווג
סיווג הוא המשימה של הקצאת קטע טקסט לקטגוריה או לתווית מוגדרות מראש. זו אחת המשימות הבסיסיות ביותר בעיבוד שפה טבעית (NLP).
יישום מעשי של סיווג טקסט הוא ניתוב של כרטיסים לתמיכה בלקוחות. התהליך הזה מפנה אוטומטית את פניות הלקוחות למחלקה הנכונה, וכך חוסך זמן ומצמצם את העבודה הידנית.
labels = ["Billing Issue", "Technical Support", "Sales Inquiry"]
sentence = [
"Excuse me, the app freezes on the login screen. It won't work even when I try to reset my password.",
"I would like to inquire about your enterprise plan pricing and features for a team of 50 people.",
]
# Calculate embeddings by calling model.encode()
label_embeddings = model.encode(labels, prompt_name="Classification")
embeddings = model.encode(sentence, prompt_name="Classification")
# Calculate the embedding similarities
similarities = model.similarity(embeddings, label_embeddings)
print(similarities)
idx = similarities.argmax(1)
print(idx)
for example in sentence:
print("🙋♂️", example, "-> 🤖", labels[idx[sentence.index(example)]])
tensor([[0.4673, 0.5145, 0.3604],
[0.4191, 0.5010, 0.5966]])
tensor([1, 2])
🙋♂️ Excuse me, the app freezes on the login screen. It won't work even when I try to reset my password. -> 🤖 Technical Support
🙋♂️ I would like to inquire about your enterprise plan pricing and features for a team of 50 people. -> 🤖 Sales Inquiry
למידת ייצוגים של בבושקה (MRL)
מודל EmbeddingGemma משתמש ב-MRL כדי לספק כמה גדלים של הטמעה ממודל אחד. זו שיטת אימון חכמה שיוצרת הטמעה יחידה באיכות גבוהה, שבה המידע הכי חשוב מרוכז בתחילת הווקטור.
המשמעות היא שאפשר לקבל הטמעה קטנה יותר אבל עדיין שימושית מאוד, פשוט על ידי שימוש ב-N המאפיינים הראשונים של ההטמעה המלאה. אחסון של הטמעות קטנות יותר וקצרות יותר זול משמעותית, והעיבוד שלהן מהיר יותר, אבל היעילות הזו באה על חשבון האיכות הפוטנציאלית של ההטמעות. ה-MRL מאפשר לכם לבחור את האיזון האופטימלי בין המהירות הזו לבין הדיוק, בהתאם לצרכים הספציפיים של האפליקציה שלכם.
נשתמש בשלוש מילים ["apple", "banana", "car"] וניצור הטמעות פשוטות כדי לראות איך MRL עובד.
def check_word_similarities():
# Calculate the embedding similarities
print("similarity function: ", model.similarity_fn_name)
similarities = model.similarity(embeddings[0], embeddings[1:])
print(similarities)
for idx, word in enumerate(words[1:]):
print("🙋♂️ apple vs.", word, "-> 🤖 score: ", similarities.numpy()[0][idx])
# Calculate embeddings by calling model.encode()
embeddings = model.encode(words, prompt_name="STS")
check_word_similarities()
similarity function: cosine tensor([[0.7510, 0.6685]]) 🙋♂️ apple vs. banana -> 🤖 score: 0.75102395 🙋♂️ apple vs. car -> 🤖 score: 0.6684626
עכשיו, כדי להגיש בקשה מהר יותר, לא צריך ליצור מודל חדש. פשוט חורצים את ההטמעות המלאות ל-512 המאפיינים הראשונים. כדי לקבל תוצאות אופטימליות, מומלץ גם להגדיר את normalize_embeddings=True, שמשנה את קנה המידה של הווקטורים לאורך יחידה של 1.
embeddings = model.encode(words, truncate_dim=512, normalize_embeddings=True)
for idx, embedding in enumerate(embeddings):
print(f"Embedding {idx+1}: {embedding.shape}")
print("-"*80)
check_word_similarities()
Embedding 1: (512,) Embedding 2: (512,) Embedding 3: (512,) -------------------------------------------------------------------------------- similarity function: cosine tensor([[0.7674, 0.7041]]) 🙋♂️ apple vs. banana -> 🤖 score: 0.767427 🙋♂️ apple vs. car -> 🤖 score: 0.7040509
בסביבות מוגבלות מאוד, אפשר לקצר עוד יותר את ההטמעות ל-256 מימדים בלבד. אפשר גם להשתמש במכפלה סקלרית, שהיא יעילה יותר, לחישובים של דמיון במקום בקוסינוס סטנדרטי של דמיון.
model = SentenceTransformer(model_id, truncate_dim=256, similarity_fn_name="dot").to(device=device)
embeddings = model.encode(words, prompt_name="STS", normalize_embeddings=True)
for idx, embedding in enumerate(embeddings):
print(f"Embedding {idx+1}: {embedding.shape}")
print("-"*80)
check_word_similarities()
Embedding 1: (256,) Embedding 2: (256,) Embedding 3: (256,) -------------------------------------------------------------------------------- similarity function: dot tensor([[0.7855, 0.7382]]) 🙋♂️ apple vs. banana -> 🤖 score: 0.7854644 🙋♂️ apple vs. car -> 🤖 score: 0.7382126
סיכום והשלבים הבאים
עכשיו יש לכם את כל מה שצריך כדי ליצור הטמעות טקסט באיכות גבוהה באמצעות EmbeddingGemma וספריית Sentence Transformers. אפשר להשתמש במיומנויות האלה כדי ליצור תכונות עוצמתיות כמו דמיון סמנטי, סיווג טקסט ומערכות Retrieval-Augmented Generation (יצירה משולבת-אחזור, RAG), ולהמשיך לחקור את האפשרויות של מודלים מסוג Gemma.
כדאי לעיין במסמכים הבאים:
- Fine-tune EmbeddingGemma
- דוגמה פשוטה ל-RAG ב-Gemma Cookbook
הרצה ב-Google Colab
צפייה במקור ב-GitHub