Sentence Transformers की मदद से एम्बेडिंग जनरेट करना

ai.google.dev पर देखें Google Colab में चलाएं Kaggle में चलाएं Vertex AI में खोलें GitHub पर सोर्स देखें

EmbeddingGemma एक लाइटवेट और ओपन एम्बेडिंग मॉडल है. इसे मोबाइल फ़ोन जैसे रोज़मर्रा के डिवाइसों पर, तेज़ी से और बेहतर क्वालिटी में जानकारी पाने के लिए डिज़ाइन किया गया है. इसमें सिर्फ़ 30.8 करोड़ पैरामीटर हैं. इसलिए, यह ऐडवांस एआई तकनीकों को चलाने के लिए काफ़ी असरदार है. जैसे, सीधे तौर पर आपकी लोकल मशीन पर इंटरनेट कनेक्शन की ज़रूरत के बिना, रीट्रिवल ऑगमेंटेड जनरेशन (आरएजी) को चलाया जा सकता है.

सेटअप

इस ट्यूटोरियल को शुरू करने से पहले, यह तरीका अपनाएं:

  • Gemma को ऐक्सेस करने के लिए, 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()

मॉडल लोड करें

EmbeddingGemma की मदद से मॉडल क्लास का इंस्टेंस बनाने के लिए, sentence-transformers लाइब्रेरी का इस्तेमाल करें.

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

Embedding जनरेट की जा रही है

एम्बेडिंग, टेक्स्ट का संख्यात्मक प्रतिनिधित्व होता है. जैसे, कोई शब्द या वाक्य. इससे टेक्स्ट का सिमैंटिक मतलब पता चलता है. असल में, यह संख्याओं की एक सूची (वेक्टर) होती है. इससे कंप्यूटर को शब्दों के बीच के संबंध और उनके संदर्भ को समझने में मदद मिलती है.

आइए, देखते हैं कि 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 का वेक्टर अन्य दो वेक्टर से काफ़ी दूर होगा.

मिलते-जुलते कॉन्टेंट का पता लगाना

इस सेक्शन में, हम यह तय करने के लिए एम्बेडिंग का इस्तेमाल करते हैं कि अलग-अलग वाक्य, सिमेंटिक तौर पर कितने मिलते-जुलते हैं. यहां हमने ज़्यादा, सामान्य, और कम मिलते-जुलते स्कोर वाले उदाहरण दिखाए हैं.

  • मिलते-जुलते डिज़ाइन:

    • वाक्य A: "शेफ़ ने मेहमानों के लिए स्वादिष्ट खाना बनाया."
    • वाक्य B: "शेफ़ ने मेहमानों के लिए स्वादिष्ट डिनर बनाया."
    • वजह: दोनों वाक्यों में एक ही इवेंट के बारे में बताया गया है. हालांकि, इसके लिए अलग-अलग शब्दों और व्याकरण के नियमों (ऐक्टिव और पैसिव वॉइस) का इस्तेमाल किया गया है. इन दोनों का मुख्य मतलब एक ही है.
  • कुछ हद तक मिलते-जुलते डिज़ाइन:

    • वाक्य A: "वह मशीन लर्निंग की विशेषज्ञ है."
    • वाक्य B: "उसे आर्टिफ़िशियल इंटेलिजेंस में काफ़ी दिलचस्पी है."
    • वजह: दोनों वाक्य एक-दूसरे से जुड़े हैं, क्योंकि मशीन लर्निंग, आर्टिफ़िशियल इंटेलिजेंस का एक उपक्षेत्र है. हालांकि, इनमें अलग-अलग लोगों के बारे में बात की गई है. साथ ही, इनमें लोगों की दिलचस्पी के लेवल (एक्सपर्ट बनाम दिलचस्पी) के बारे में भी बताया गया है.
  • मिलते-जुलते कॉन्टेंट का कम होना:

    • वाक्य A: "टोक्यो में आज धूप खिली है."
    • वाक्य B: "मुझे इस हफ़्ते के लिए किराने का सामान खरीदना है."
    • वजह: दोनों वाक्य पूरी तरह से अलग-अलग विषयों पर हैं और इनमें कोई भी सिमैंटिक ओवरलैप नहीं है.
# 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 की मदद से सबसे अच्छे एम्बेडिंग जनरेट करने के लिए, आपको अपने इनपुट टेक्स्ट की शुरुआत में "निर्देश वाला प्रॉम्प्ट" या "टास्क" जोड़ना चाहिए. ये प्रॉम्प्ट, दस्तावेज़ खोजने या सवालों के जवाब देने जैसे खास टास्क के लिए एम्बेडिंग को ऑप्टिमाइज़ करते हैं. साथ ही, मॉडल को अलग-अलग तरह के इनपुट के बीच अंतर करने में मदद करते हैं. जैसे, खोज क्वेरी बनाम दस्तावेज़.

प्रॉम्प्ट लागू करने का तरीका

अनुमान लगाने के दौरान, तीन तरीकों से प्रॉम्प्ट लागू किया जा सकता है.

  1. prompt आर्ग्युमेंट का इस्तेमाल करना
    पूरी प्रॉम्प्ट स्ट्रिंग को सीधे तौर पर encode तरीके से पास करें. इससे आपको सटीक कंट्रोल मिलता है.

    embeddings = model.encode(
        sentence,
        prompt="task: sentence similarity | query: "
    )
    
  2. prompt_name आर्ग्युमेंट का इस्तेमाल करना
    पहले से तय किए गए किसी प्रॉम्प्ट को उसके नाम से चुनें. इन प्रॉम्प्ट को मॉडल के कॉन्फ़िगरेशन से या मॉडल के शुरू होने के दौरान लोड किया जाता है.

    embeddings = model.encode(sentence, prompt_name="STS")
    
  3. डिफ़ॉल्ट प्रॉम्प्ट का इस्तेमाल करना
    अगर आपने 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

इस्तेमाल का उदाहरण: जानकारी को फिर से पाने के लिए जनरेटिव एआई का इस्तेमाल करना (आरएजी)

आरएजी सिस्टम के लिए, अपनी क्वेरी और दस्तावेज़ों के लिए खास एम्बेडिंग बनाने के लिए, यहां दी गई 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: "
    )
    

इस बारे में और पढ़ें

कैटगरी

क्लासिफ़िकेशन का मतलब है, किसी टेक्स्ट को पहले से तय की गई एक या उससे ज़्यादा कैटगरी या लेबल में असाइन करना. यह नैचुरल लैंग्वेज प्रोसेसिंग (एनएलपी) के सबसे बुनियादी कामों में से एक है.

टेक्स्ट क्लासिफ़िकेशन का एक व्यावहारिक उदाहरण, ग्राहक सहायता टिकट की रूटिंग है. इस प्रोसेस के ज़रिए, ग्राहक की क्वेरी अपने-आप सही विभाग को भेज दी जाती हैं. इससे समय बचता है और मैन्युअल तरीके से किए जाने वाले काम में कमी आती है.

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

मैट्र्योश्का रिप्रेजेंटेशन लर्निंग (एमआरएल)

EmbeddingGemma, MRL का इस्तेमाल करता है, ताकि एक मॉडल से कई एम्बेडिंग साइज़ उपलब्ध कराए जा सकें. यह ट्रेनिंग का एक बेहतरीन तरीका है. इससे एक ही, अच्छी क्वालिटी वाली एंबेडिंग बनती है. इसमें सबसे ज़रूरी जानकारी, वेक्टर की शुरुआत में होती है.

इसका मतलब है कि पूरी एम्बेडिंग के पहले N डाइमेंशन लेकर, छोटी लेकिन काम की एम्बेडिंग बनाई जा सकती है. छोटे और काटे गए एम्बेडिंग को सेव करने में कम खर्च आता है और इन्हें प्रोसेस करने में कम समय लगता है. हालांकि, इससे एम्बेडिंग की क्वालिटी कम हो सकती है. एमआरएल की मदद से, अपने ऐप्लिकेशन की खास ज़रूरतों के हिसाब से, स्पीड और सटीक नतीजे के बीच सही संतुलन बनाया जा सकता है.

आइए, तीन शब्दों ["apple", "banana", "car"] का इस्तेमाल करके, आसान एम्बेडिंग बनाते हैं. इससे यह पता चलेगा कि एमआरएल कैसे काम करता है.

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 लाइब्रेरी का इस्तेमाल करके, अच्छी क्वालिटी की टेक्स्ट एम्बेडिंग जनरेट करने की सुविधा है. इन स्किल का इस्तेमाल करके, सेमैंटिक सिमिलैरिटी, टेक्स्ट क्लासिफ़िकेशन, और रीट्रिवल-ऑगमेंटेड जनरेशन (आरएजी) सिस्टम जैसी बेहतरीन सुविधाएँ बनाएँ. साथ ही, यह एक्सप्लोर करना जारी रखें कि Gemma मॉडल की मदद से क्या-क्या किया जा सकता है.

इसके बाद, यहां दिए गए दस्तावेज़ पढ़ें: