Trovare la soluzione giusta: creazione di embedding per il recupero AI (RAG) nelle pipeline Zilliz Cloud da OSS, VoyageAI e OpenAI
Questo post è scritto da Christy Bergman e Jiang Chen.
Benvenuti nel nostro post del blog sui modelli di embedding pensati per applicazioni di AI Retrieval Augmented Generation (RAG). Ecco cosa tratteremo:
Introduzione a come i modelli di embedding vengono utilizzati in RAG (AI generativa con retrieval)
Introduzione a SBERT, il tipo più comune di modello di embedding
Classifica MTEB dei modelli di embedding e come usarla
Sei modelli di embedding inclusi automaticamente in Zilliz Cloud Pipelines
Spiegazione di ciascun modello e suggerimenti su come scegliere il miglior modello di embedding per le tue esigenze
Iniziamo!
Aggiungi i tuoi dati all'AI con Rag: come vengono usati i modelli di embedding + LLM
Retrieval Augmented Generation (RAG) è emerso come l'approccio di riferimento per i bot di domande e risposte. Tuttavia, data la data limite di training della conoscenza intrinseca a tutti i modelli, potrebbero non avere consapevolezza dei dati recenti. La maggior parte dei casi d'uso in produzione integra i propri modelli con conoscenze specifiche per colmare questa lacuna.
Le risposte della tua AI sono bloccate nel passato? Stanco dei bot che conoscono solo ciò su cui sono stati addestrati?
RAG presenta una soluzione integrando i tuoi dati nella conoscenza dell'AI. Questo modello utilizza modelli di embedding e Large Language Models (LLM). Ecco come funziona:
Preparazione dei dati usando un modello di embedding: Avvia RAG usando un modello di embedding per generare vector embeddings di blocchi di testo da TUTTI i tuoi documenti. Questo diventa IL TUO spazio vettoriale che rappresenta LA TUA conoscenza di dominio, con ogni informazione rappresentata come un vettore.
Indicizzazione e ricerca usando lo stesso modello di embedding: I computer possono eseguire rapidamente ricerche vettoriali una volta che la tua conoscenza è codificata in vettori. Organizzare i vettori in strutture dati per gli algoritmi di ricerca si chiama indicizzazione. Gli indici sono usati in database vettoriali come Milvus. Quando fai una domanda, il database userà l'indice per trovare i vettori più vicini (che rappresentano frasi o paragrafi) nel tuo spazio vettoriale di conoscenza di dominio rispetto al vettore della tua domanda. Crea il vettore della tua domanda usando lo stesso modello di embedding usato per incorporare i tuoi dati.
Generazione della risposta con un modello LLM: Questa è la parte di “AI generativa”. In questo passaggio, un modello LLM, come ChatGPT, sfrutta la tua conoscenza di dominio pertinente per rispondere alla domanda. I dati RAG vengono forniti al modello LLM inserendo i testi top-K recuperati nel prompt, che include la tua domanda, il contesto (testi Top-K) e istruzioni come “Rispondi alla domanda usando solo la conoscenza nel contesto di questo prompt”.
Con RAG, l'LLM genera una risposta basata sulla tua conoscenza di dominio fornita, accedendo istantaneamente ai dati più recenti e comprendendo meglio le tue domande.
Questo modello RAG è supportato dalla ricerca; vedi l'articolo Lost in the Middle. L'articolo mostra che l'accuratezza del Recall delle risposte generate dagli LLM diminuisce con il numero di testi recuperati inseriti nel prompt di contesto del modello. Inoltre:
Gli LLM hanno limiti sulla dimensione del contesto (al momento, è 128K per GPT-4 Turbo).
Costo per token, quindi è più costoso passare tutte le informazioni tutto il tempo.
Modelli di embedding Sentence-BERT
I modelli di embedding moderni derivano dalla parte Encoder dei transformer; mentre i modelli LLM (come ChatGPT) sono costruiti dalla parte Decoder dei transformer. La classe di modelli di embedding più comune è SBERT (Sentence-BERT), che si basa su BERT ma è specializzata nella comprensione di frasi complete. Quindi, SBERT può distinguere tra "The cat sat on the mat" e "The mat sat on the cat" - cosa che il BERT di base non saprebbe fare!
Semantica si riferisce al significato dietro le parole. Questo è particolarmente importante nel contesto degli LLM perché le stesse parole possono avere significati diversi in base al contesto, all’ordine o all’uso. Per ulteriori informazioni su SBERT, i lettori interessati dovrebbero consultare questi validi articoli introduttivi su quel modello qui.
Supponiamo che tu stia sviluppando applicazioni RAG da zero. Un ottimo punto di partenza è selezionare un modello di embedding dalla HuggingFace MTEB Leaderboard, ordinata (in modo decrescente) in base alla colonna "Retrieval Average'' poiché è la più rilevante per RAG. Quindi, scegli il modello di embedding più piccolo e con il ranking più alto. La classifica cambia costantemente! Ma cambiare il modello di embedding con HuggingFace in Python è semplice quanto modificare una singola variabile.
Le prestazioni di Retrieval MTEB sono misurate dal Normalized Discounted Cumulative Gain at 10 (NDCG@10). Questa metrica misura la qualità delle liste top-K calcolando somme di rapporti in cui agli elementi con ranking più alto viene assegnato un peso maggiore rispetto agli elementi con ranking più basso, così come restituiti a un utente in proporzione a un ordine classificato ideale.
Fonte immagine: HuggingFace MTEB Leaderboard, accesso effettuato il 20 febbraio 2024.
Massive Text Embedding Benchmark (MTEB) valuta i modelli di embedding su 8 attività e 58 dataset (10 multilingue, 112 lingue). Le otto attività sono bitext mining, classificazione, clustering, classificazione di coppie, reranking, retrieval, similarità testuale semantica (STS) e riassunto.
6 modelli di embedding chiave integrati in Zilliz Cloud Pipelines
Zilliz Cloud Pipelines ha recentemente lanciato il supporto per un ricco insieme di scelte di modelli di embedding.
| Creatore | Modello | Dim embedding | Lunghezza contesto | Attività dei casi d’uso | Open Source | *Punteggio MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Testo EN generale | Sì | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Testo ZH generale | Sì | 69 |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbot RAG di alta qualità | No | Non disponibile |
| VoyageAI | voyage-code-2 | 1536 | 16K | Completamento del codice ad alto tasso di richiamo | No | Non disponibile |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbot testuali multilingue in tempo reale | No | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbot testuali multilingue in tempo reale | No | 65 (3072) 62 (256) |
*HuggingFace MTEB Leaderboard, ordinata in ordine decrescente per Retrieval, accesso effettuato il 26 febbraio 2024.
Dim embedding = lunghezza del vettore prodotto da un modello; vettori più grandi potrebbero catturare più significato, ma potrebbero essere meno efficienti in termini di archiviazione.
Lunghezza contesto = numero massimo di token che il modello può elaborare contemporaneamente in un singolo passo temporale. I vettori di output della maggior parte dei modelli di embedding sono normalizzati, quindi prodotto scalare e similarità coseno sono equivalenti.
⚠️ Nota: Anche se i benchmark MTEB offrono indicazioni preziose, è noto che alcuni modelli sono soggetti a overfitting! Esegui sempre le tue valutazioni!
Con Zilliz Cloud Pipelines, puoi iniziare gratuitamente registrandoti e costruendo la tua applicazione RAG senza le complicazioni di DevOps o dell’infrastruttura ML.
Fonte immagine: Blog che annuncia i modelli di embedding integrati in Zilliz Cloud Pipelines
Modelli di embedding BAAI/bge-base-en(or zh)-v1.5
Questi modelli SBERT open-source sono disponibili su HuggingFace. Alcuni vantaggi di questi piccoli modelli:
Piccoli, open source e adatti alla CPU.
Sono una buona scelta per lavorare su un laptop e/o con risorse cloud minime.
I più veloci per l’ingestion durante il chunking dei dati e per la latenza delle query ogni volta che viene posta una domanda.
Convenienti poiché le chiamate API sono gratuite e non è richiesta una GPU.
Addestrati sia in lingua cinese sia in lingua inglese.
| Creator | Model | Embedding****Dim | Context Length | Use Case Tasks | Open Source | *MTEB Score |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Testo EN generale | Sì | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Testo ZH generale | Sì | 69 |
*HuggingFace MTEB Leaderboard, ordinata in ordine decrescente per Retrieval, consultata il 26 febbraio 2024.
Modelli di embedding voyage-2 e voyage-code-2 di VoyageAI
Questi modelli proprietari sono addestrati utilizzando contrastive learning e importance resampling su dati diversi e ottimizzati per compiti diversi. Voyage-2 è addestrato su dati di dialogo e ottimizzato per l’intento conversazionale. Voyage-code-2 è addestrato su dati di codice e ottimizzato per il completamento del codice.
Nota: Voyage-lite-02-instruct elencato nella leaderboard MTEB (ordinata in ordine decrescente per STS o categoria “diverse corpora”) è diverso e non va confuso con i modelli di produzione voyage-2 e voyage-code-2 descritti qui.
Alcuni vantaggi di questi modelli:
Per chatbot RAG di documentazione tecnica, è stato dimostrato che voyage-01 (deprecato) ha una qualità di retrieval più elevata (misurata come NDCG@10). Voyage-2 è la versione più recente.
Per attività di codice, voyage-code-2 ha un tasso di recall superiore del 14% per testi ad alta intensità di codice.
| Creator | Model | Embedding****Dim | Context Length | Use Case Tasks | Open Source | MTEB Score |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbot RAG di alta qualità | No | Non disponibile |
| VoyageAI | voyage-code-2 | 1536 | 16K | Completamento codice con alto tasso di recall | No | Non disponibile |
Modelli di embedding text-embedding-3-small(or large) di OpenAI
Da OpenAI, i modelli di embedding più recenti si posizionano più in alto nella classifica MTEB rispetto al loro precedente ada-002. Questi nuovi modelli di embedding hanno anche prestazioni multilingue più elevate (MIRACL) e prezzi più bassi.
Secondo il blog di OpenAI, per creare gli embedding è stato utilizzato un addestramento consapevole della compressione. Le tecniche tradizionali di riduzione della dimensionalità, come la quantizzazione, fanno risparmiare spazio ma comportano un’enorme perdita di accuratezza perché la compressione viene applicata “post-hoc” dopo che gli embedding sono stati appresi. L’addestramento consapevole della compressione, come Matryoshka Representation Learning, apprende embedding di dimensioni diverse (dimensioni), con una certa perdita di accuratezza, sebbene non significativa come con la PCA.
In modo impressionante, entrambi i modelli supportano embedding più piccoli senza sacrificare molto la qualità del recupero. Ad esempio, ridurre la dimensione vettoriale da 3072 a 256 riduce il punteggio MTEB solo dal 65% al 62%. Tuttavia, questo significa un requisito di memoria 12 volte inferiore! Sebbene esista un compromesso tra accuratezza e costo associato a una dimensionalità inferiore, nell’era dei chatbot alimentati dall’IA, le risposte rapide a volte hanno la priorità sull’accuratezza delle risposte.
Alcuni vantaggi di questi modelli:
Capacità multilingue migliorate.
Vettori a dimensione inferiore con il minimo overhead di inferenza e una perdita di accuratezza molto inferiore rispetto alla quantizzazione binaria o di prodotto tradizionale.
| Creatore | Modello | Dim****Embedding | Lunghezza contesto | Attività dei casi d’uso | Open Source | *Punteggio MTEB |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbot di testo multilingue in tempo reale | No | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbot di testo multilingue in tempo reale | No | 65 (3072) 62 (256) |
*Classifica MTEB di HuggingFace, ordinata in modo decrescente per Retrieval, consultata il 26 febbraio 2024.
Di seguito è riportato un esempio di codice per chiamare i nuovi modelli di embedding. Il codice completo si trova nel nostro bootcamp github.
# STEP 1. CONNECT TO MILVUS
# !pip install pymilvus
from pymilvus import connections, utility
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv("ZILLIZ_API_KEY")
# Connect to Zilliz cloud using endpoint URI and API key TOKEN.
CLUSTER_ENDPOINT="https://in03-xxxx.api.gcp-us-west1.zillizcloud.com:443"
connections.connect(
alias='default',
uri=CLUSTER_ENDPOINT,
token=TOKEN,
)
Successivamente, specifichiamo il modello di embedding di OpenAI.
# STEP 2. EMBEDDING MODEL.
import openai, pprint
from openai import OpenAI
# OpenAI embedding model name, `text-embedding-3-large` or `ext-embedding-3-small`.
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIM = 512
Successivamente, creiamo una collection Milvus senza schema e specifichiamo un indice.
# STEP 3. CREATE A NO-SCHEMA MILVUS COLLECTION AND USE AUTOINDEX.
from pymilvus import MilvusClient
COLLECTION_NAME = "MilvusDocs_text_embedding_3_small"
# https://milvus.io/docs/using_milvusclient.md
mc = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN)
# Check if collection already exists, if so drop it.
has = utility.has_collection(COLLECTION_NAME)
if has:
drop_result = utility.drop_collection(COLLECTION_NAME)
print(f"Successfully dropped collection: `{COLLECTION_NAME}`")
# Crea la raccolta.
mc.create_collection(COLLECTION_NAME,
EMBEDDING_DIM,
consistency_level="Eventually",
auto_id=True,
overwrite=True)
Successivamente, leggiamo i documenti tecnici di LangChain come file .html scaricati in una cartella. Suddividi e incorpora i documenti. L’esempio seguente utilizza il parser HTML integrato di LangChain come strategia di suddivisione. La tua strategia di suddivisione potrebbe essere molto più semplice.
# STEP 4. PREPARE DATA: CHUNK AND EMBED
# Read docs into LangChain.
from langchain.document_loaders import DirectoryLoader
path = "../RAG/rtdocs/pymilvus.readthedocs.io/en/latest/"
loader = DirectoryLoader(path, glob='*.html')
docs = loader.load()
from langchain.text_splitter import HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter
from bs4 import BeautifulSoup
# Define the headers to split on for the HTMLHeaderTextSplitter
headers_to_split_on = [
("h1", "Header 1"),
("h2", "Header 2"),
]
# Create an instance of the HTMLHeaderTextSplitter
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# Specify chunk size and overlap.
chunk_size = 511
chunk_overlap = np.round(chunk_size * 0.10, 0)
print(f"chunk_size: {chunk_size}, chunk_overlap: {chunk_overlap}")
# Create an instance of the RecursiveCharacterTextSplitter
child_splitter = RecursiveCharacterTextSplitter(
chunk_size = chunk_size,
chunk_overlap = chunk_overlap,
length_function = len,
)
# Split the HTML text using the HTMLHeaderTextSplitter.
start_time = time.time()
html_header_splits = []
for doc in docs:
soup = BeautifulSoup(doc.page_content, 'html.parser')
splits = html_splitter.split_text(str(soup))
for split in splits:
# Add the source URL and header values to the metadata
metadata = {}
new_text = split.page_content
for header_name, metadata_header_name in headers_to_split_on:
# Handle exceptions if h1 does not exist.
try:
header_value = new_text.split("¶ ")[0].strip()[:100]
metadata[header_name] = header_value
except:
break
split.metadata = {
**metadata,
"source": doc.metadata["source"]
}
# Add the header to the text
split.page_content = split.page_content
html_header_splits.extend(splits)
# Split the documents further into smaller, recursive chunks.
chunks = child_splitter.split_documents(html_header_splits)
Inserisci i frammenti e gli embedding in Milvus.
# STEP 5. INSERT CHUNKS AND EMBEDDINGS IN ZILLIZ.
# Convert chunks to a list of dictionaries.
chunk_list = []
for chunk in chunks:
# Generate the embeddings.
response = openai_client.embeddings.create(
input=chunk.page_content,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
embeddings = response.data[0].embedding
# Assemble embedding vector, original text chunk, metadata.
chunk_dict = {
'vector': embeddings,
'chunk': chunk.page_content,
'source': chunk.metadata['source'],
'h1': chunk.metadata['h1'][:50],
}
chunk_list.append(chunk_dict)
# Insert data into the Milvus collection.
insert_result = mc.insert(
COLLECTION_NAME,
data=chunk_list,
progress_bar=True)
# After the final entity is inserted, call flush to stop growing segments left in memory.
mc.flush(COLLECTION_NAME)
Poni una domanda a Milvus, che ora è caricato con gli embedding della documentazione tecnica di Milvus.
# Define a sample question about your data.
SAMPLE_QUESTION = "What do the parameters for HNSW mean?"
# Embed the question using the same encoder.
response = openai_client.embeddings.create(
input=SAMPLE_QUESTION,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
query_embeddings = response.data[0].embedding
# Define output fields to return.
OUTPUT_FIELDS = ["h1", "h2", "source", "chunk"]
# Esegui una ricerca vettoriale semantica usando la tua query e il database vettoriale Milvus.
start_time = time.time()
results = mc.search(
COLLECTION_NAME,
data=[query_embeddings],
output_fields=OUTPUT_FIELDS,
limit=2,
consistency_level="Eventually"
)
Genera una risposta usando ChatGPT e i blocchi di contesto testuale recuperati.
LLM_NAME = "gpt-3.5-turbo"
TEMPERATURE = 0.1
RANDOM_SEED = 415
# Separate all the context together by space.
contexts_combined = ' '.join(context)
SYSTEM_PROMPT = f"""Use the Context below to answer the user's question. Be clear, factual, complete, concise.
If the answer is not in the Context, say "I don't know".
Otherwise answer with fewer than 4 sentences and cite the grounding sources.
Context: contexts_combined
Answer: The answer to the question.
Grounding sources: {context_metadata[0]['source']}
"""
# Generate response using the OpenAI API.
response = openai_client.chat.completions.create(
messages=[
{"role": "system", "content": SYSTEM_PROMPT,},
{"role": "user", "content": f"question: {SAMPLE_QUESTION}",}
],
model=LLM_NAME,
temperature=TEMPERATURE,
seed=RANDOM_SEED,
)
# Print the question and answer along with grounding sources and citations.
print(f"Question: {SAMPLE_QUESTION}")
for i, choice in enumerate(response.choices, 1):
pprint.pprint(f"Answer: {choice.message.content}")
print("\n")
La risposta usando text-embedding-3-small con embedding ridotti dim=256 è perfetta rispetto alla stessa risposta con dim=1536, almeno per questo esempio RAG!
Conclusione
In questo blog, abbiamo introdotto come i modelli di embedding vengono usati in RAG e SBERT, il tipo più comune di modello di embedding. Abbiamo mostrato la classifica MTEB dei modelli di embedding e spiegato come usarla. Poi, abbiamo esaminato i sei diversi modelli di embedding inclusi automaticamente in Zilliz Pipelines. Diversi modelli di embedding sono più adatti a diversi casi d'uso; abbiamo discusso quando scegliere quale modello. Infine, abbiamo mostrato il codice per chiamare i nuovi modelli di embedding OpenAI; e il codice completo si trova nel nostro bootcamp github.
Riferimenti
Milvus (lasciaci una star!)
Tutorial sulle parti Encoder-Decoder dei transformer
Tutorial sui modelli di embedding SBERT Encoder
HuggingFace MTEB Leaderboard dei modelli di embedding
Scheda modello HuggingFace per BAAI/bg-large-en-v1.5
Modelli di embedding VoyageAI
Modelli di embedding OpenAI
Continua a leggere

Context Engineering Strategies for AI Agents: A Developer’s Guide
Learn practical context engineering strategies for AI agents. Explore frameworks, tools, and techniques to improve reliability, efficiency, and cost.

Vector Databases vs. Time Series Databases
Use a vector database for similarity search and semantic relationships; use a time series database for tracking value changes over time.

What is the K-Nearest Neighbors (KNN) Algorithm in Machine Learning?
KNN is a supervised machine learning technique and algorithm for classification and regression. This post is the ultimate guide to KNN.



