Gjenero integrimet me Sentence Transformers

Shiko në ai.google.dev Ekzekuto në Google Colab Ekzekuto në Kaggle Hape në Vertex AI Shiko burimin në GitHub

EmbeddingGemma është një model i lehtë dhe i hapur i përfaqësimeve të tekstit i krijuar për marrje të shpejtë dhe me cilësi të lartë në pajisjet e përditshme si telefonat celularë. Me vetëm 308 milionë parametra, ai është mjaftueshëm efikas për të ekzekutuar teknika të përparuara të IA-së, si p.sh. Retrieval Augmented Generation (RAG), drejtpërdrejt në makinën tënde lokale pa pasur nevojë për lidhje interneti.

Konfigurimi

Para se të fillosh këtë udhëzues, përfundo hapat e mëposhtëm:

  • Merr qasje te Gemma duke u identifikuar në Hugging Face dhe duke zgjedhur Prano licencën për një model të Gemma.
  • Gjenero një token qasjeje të Hugging Face dhe përdore atë për t'u identifikuar nga Colab.

Ky bllok shënimesh do të ekzekutohet në CPU ose GPU.

Instalo paketat e Python

Instalo bibliotekat e nevojshme për ekzekutimin e modelit EmbeddingGemma dhe gjenerimin e përfaqësimeve. Sentence Transformers është një kuadër i Python për përfaqësimet e tekstit dhe imazheve. Për më shumë informacion, shiko dokumentacionin e Sentence Transformers.

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

Pasi të kesh pranuar licencën, të duhet një kod i vlefshëm i Hugging Face për t'u qasur te modeli.

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

Ngarko modelin

Përdor bibliotekat e sentence-transformers për të krijuar një shembull të një klase modeli me 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

Integrimi po gjenerohet

Një integrim është një përfaqësim numerik i tekstit, si p.sh. një fjalë ose fjali, që kap kuptimin e tij semantik. Në thelb, është një listë numrash (një vektor) që i lejon kompjuterët të kuptojnë marrëdhëniet dhe kontekstin e fjalëve.

Le të shikojmë se si EmbeddingGemma do të përpunojë tri fjalë të ndryshme ["apple", "banana", "car"].

EmbeddingGemma është trajnuar me sasi të mëdha teksti dhe ka mësuar marrëdhëniet midis fjalëve dhe koncepteve.

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

Modeli nxjerr një vektor numerik për çdo fjali. Vectorët aktualë janë shumë të gjatë (768), por për thjeshtësi, ato paraqiten me disa dimensione.

Çelësi nuk janë numrat individualë në vetvete, por distanca midis vektorëve. Nëse do t'i paraqisnim këta vektorë në një hapësirë shumëdimensionale, vektorët për apple dhe banana do të ishin shumë afër njëri-tjetrit. Dhe vektori për car do të jetë shumë larg dy të tjerëve.

Po përcaktohet ngjashmëria

Në këtë seksion, ne përdorim integrimet për të përcaktuar se sa të ngjashme janë në mënyrë semantike fjali të ndryshme. Këtu tregojmë shembuj me rezultate të ngjashmërisë të lartë, mesatare dhe të ulët.

  • Ngjashmëri e lartë:

    • Fjali A: "Kryekuzhinieri përgatiti një vakt të shijshëm për mysafirët."
    • Fjali B: "Një darkë e shijshme u gatuar nga shefi i kuzhinës për vizitorët."
    • Arsyetimi: Të dyja fjalitë përshkruajnë të njëjtin ngjarje duke përdorur fjalë dhe struktura gramatikore të ndryshme (forma veprore kundrejt formës joveprore). Ato përcjellin të njëjtin kuptim thelbësor.
  • Ngjashmëri mesatare:

    • Fjalia A: "Ajo është një eksperte në të mësuarit automatik."
    • Fjali B: "Ai ka një interes të madh për inteligjencën artificiale."
    • Arsyetimi: Fjalitë janë të lidhura pasi të mësuarit automatik është një nënfushë e inteligjencës artificiale. Megjithatë, ato flasin për persona të ndryshëm me nivele të ndryshme angazhimi (ekspert kundrejt interesit).
  • Ngjashmëri e ulët:

    • Fjali A: "Sot moti në Tokio është me diell."
    • Fjali B: "Duhet të blej ushqime për javën."
    • Arsyetimi: Dy fjalitë janë për tema krejtësisht të palidhura dhe nuk kanë asnjë mbivendosje semantike.
# 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

Përdorimi i kërkesave me EmbeddingGemma

Për të gjeneruar përfaqësimet më të mira me EmbeddingGemma, duhet të shtosh një "kërkesë udhëzuese" ose "detyrë" në fillim të tekstit tënd të hyrjes. Këto kërkesa optimizojnë integrimet për detyra specifike, si p.sh. marrja e dokumenteve ose përgjigjja e pyetjeve, dhe e ndihmojnë modelin të dallojë midis llojeve të ndryshme të hyrjeve, si p.sh. një kërkesë kërkimi kundrejt një dokumenti.

Si të zbatosh kërkesat

Mund të zbatosh një kërkesë gjatë përfundimit në tri mënyra.

  1. Duke përdorur argumentin prompt
    Kaloni vargun e plotë të kërkesës drejtpërdrejt në metodën encode. Kjo të jep kontroll të saktë.

    embeddings = model.encode(
        sentence,
        prompt="task: sentence similarity | query: "
    )
    
  2. Duke përdorur argumentin prompt_name
    Zgjidh një kërkesë të paracaktuar me emrin e saj. Këto kërkesa ngarkohen nga konfigurimi i modelit ose gjatë inicializimit të tij.

    embeddings = model.encode(sentence, prompt_name="STS")
    
  3. Përdorimi i kërkesës së parazgjedhur
    Nëse nuk specifikon as prompt dhe as prompt_name, sistemi do të përdorë automatikisht kërkesën e caktuar si default_prompt_name. Nëse nuk është caktuar asnjë e parazgjedhur, atëherë nuk zbatohet asnjë kërkesë.

    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

Rasti i përdorimit: Gjenerimi i përmirësuar i informacionit (RAG)

Për sistemet RAG, përdor vlerat e mëposhtme të prompt_name për të krijuar integrime të specializuara për pyetjet dhe dokumentet e tua:

  • Për pyetjet: Përdor prompt_name="Retrieval-query".

    query_embedding = model.encode(
        "How do I use prompts with this model?",
        prompt_name="Retrieval-query"
    )
    
  • Për "Dokumentet": Përdor prompt_name="Retrieval-document". Për të përmirësuar më tej integrimet e dokumenteve, mund të përfshish gjithashtu një titull duke përdorur argumentin prompt drejtpërdrejt:

    • Me një titull:
    doc_embedding = model.encode(
        "The document text...",
        prompt="title: Using Prompts in RAG | text: "
    )
    
    • Pa titull:
    doc_embedding = model.encode(
        "The document text...",
        prompt="title: none | text: "
    )
    

Lexim i mëtejshëm

Klasifikimi

Klasifikimi është detyra e caktimit të një pjese teksti në një ose disa kategori ose etiketa të paracaktuara. Është një nga detyrat më themelore në përpunimin e gjuhës natyrore (NLP).

Një zbatim praktik i klasifikimit të tekstit është ridrejtimi i biletave të mbështetjes për klientët. Ky proces i drejton automatikisht pyetjet e klientëve te departamenti i duhur, duke kursyer kohë dhe duke zvogëluar punën manuale.

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

Matryoshka Representation Learning (MRL)

EmbeddingGemma shfrytëzon MRL-në për të ofruar disa madhësi të vektorizimit nga një model i vetëm. Është një metodë e zgjuar trajnimi që krijon një integrim të vetëm me cilësi të lartë ku informacionet më të rëndësishme janë të përqendruara në fillim të vektorit.

Kjo do të thotë që mund të marrësh një integrim më të vogël, por përsëri shumë të dobishëm, thjesht duke marrë N dimensionet e para të integrimit të plotë. Përdorimi i përfshirjeve më të vogla dhe të shkurtuara është dukshëm më i lirë për t'u ruajtur dhe më i shpejtë për t'u përpunuar, por ky efikasitet vjen me koston e cilësisë së mundshme më të ulët të përfshirjeve. MRL-ja të jep mundësinë të zgjedhësh balancën optimale mes shpejtësisë dhe saktësisë për nevojat specifike të aplikacionit tënd.

Le të përdorim tri fjalë ["apple", "banana", "car"] dhe të krijojmë integrime të thjeshtuara për të parë se si funksionon 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

Tani, për një aplikim më të shpejtë, nuk të duhet një model i ri. Thjesht shkurto mbivendosjet e plota në 512 dimensionet e para. Për rezultate optimale, rekomandohet gjithashtu të caktosh normalize_embeddings=True, i cili i shkallëzon vektorët në një gjatësi njësi prej 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

Në mjedise jashtëzakonisht të kufizuara, mund t'i shkurtosh më tej përfaqësimet në vetëm 256 dimensione. Mund të përdorësh gjithashtu prodhimin e brendshëm më efikas për llogaritjet e ngjashmërisë në vend të ngjashmërisë standarde kosinus.

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

Përmbledhja dhe hapat e radhës

Tani je i pajisur për të gjeneruar integrime të tekstit me cilësi të lartë duke përdorur EmbeddingGemma dhe bibliotekën e Sentence Transformers. Zbatoji këto aftësi për të ndërtuar veçori të fuqishme si ngjashmëria semantike, klasifikimi i tekstit dhe sistemet e gjenerimit të përmirësuar të informacionit (RAG) dhe vazhdo të eksplorosh se çfarë është e mundur me modelet Gemma.

Shiko dokumentet e mëposhtme më pas: