Trouver la bonne adéquation : création d’embeddings pour la récupération par IA (RAG) dans les pipelines Zilliz Cloud depuis OSS, VoyageAI et OpenAI
Cet article est rédigé par Christy Bergman et Jiang Chen.
Bienvenue dans notre article de blog sur les modèles d’embedding adaptés aux applications d’IA de Retrieval Augmented Generation (RAG). Voici ce que nous allons couvrir :
Introduction à la façon dont les modèles d’embedding sont utilisés dans RAG (IA générative avec récupération)
Introduction à SBERT, le type de modèle d’embedding le plus courant
Classement MTEB des modèles d’embedding et comment l’utiliser
Six modèles d’embedding automatiquement inclus dans Zilliz Cloud Pipelines
Explication de chaque modèle et conseils pour sélectionner le meilleur modèle d’embedding pour vos besoins
Plongeons-nous dedans !
Ajoutez vos données à l’IA avec Rag : comment les modèles d’embedding + les LLM sont utilisés
Retrieval Augmented Generation (RAG) s’est imposée comme l’approche de référence pour les bots de questions-réponses. Cependant, compte tenu de la date limite d’entraînement des connaissances inhérente à tous les modèles, ils peuvent ne pas connaître les données récentes. La plupart des cas d’utilisation en production complètent leurs modèles avec des connaissances spécifiques afin de combler cette lacune.
Vos réponses d’IA sont-elles coincées dans le passé ? Fatigué des bots qui ne savent que ce sur quoi ils ont été entraînés ?
RAG présente une solution en intégrant vos données dans les connaissances de l’IA. Ce schéma utilise des modèles d’embedding et des grands modèles de langage (LLM). Voici comment cela fonctionne :
Préparation des données à l’aide d’un modèle d’embedding : Lancez RAG en utilisant un modèle d’embedding pour générer des vector embeddings de fragments de texte issus de TOUS vos documents. Cela devient VOTRE espace vectoriel représentant VOS connaissances métier, chaque élément d’information étant représenté comme un vecteur.
Indexation et recherche à l’aide du même modèle d’embedding : Les ordinateurs peuvent exécuter rapidement des recherches vectorielles une fois que vos connaissances sont encodées en vecteurs. L’organisation des vecteurs en structures de données pour les algorithmes de recherche s’appelle l’indexation. Les index sont utilisés dans des bases de données vectorielles comme Milvus. Lorsque vous posez une question, la base de données utilisera l’index pour trouver les vecteurs les plus proches (représentant des phrases ou des paragraphes) dans l’espace vectoriel de vos connaissances métier par rapport au vecteur de votre question. Créez le vecteur de votre question en utilisant le même modèle d’embedding que celui utilisé pour intégrer vos données.
Génération de réponse avec un modèle LLM : C’est la partie « IA générative ». À cette étape, un modèle LLM, tel que ChatGPT, exploite vos connaissances métier pertinentes pour répondre à la question. Les données RAG sont fournies au modèle LLM en injectant les textes Top-K récupérés dans le prompt, qui inclut votre question, le contexte (textes Top-K) et des instructions telles que « Réponds à la question en utilisant uniquement les connaissances dans le contexte de ce prompt ».
Avec RAG, le LLM génère une réponse basée sur vos connaissances métier données, accédant instantanément aux données les plus récentes et comprenant mieux vos questions.
Ce schéma RAG est soutenu par la recherche ; voir l’article Lost in the Middle. L’article montre que la précision du rappel des réponses générées par les LLM diminue avec le nombre de textes récupérés insérés dans le prompt de contexte du modèle. De plus :
Les LLM ont des limites sur la taille du contexte (actuellement, elle est de 128K pour GPT-4 Turbo).
Coût par token, donc il est plus coûteux de transmettre toutes les informations en permanence.
Modèles d’embedding Sentence-BERT
Les modèles d’embedding modernes sont dérivés de la partie encodeur des transformers ; tandis que les modèles LLM (tels que ChatGPT) sont construits à partir de la partie décodeur des transformers. La classe de modèles d’embedding la plus courante est SBERT (Sentence-BERT), qui s’appuie sur BERT mais se spécialise dans la compréhension de phrases complètes. Ainsi, SBERT peut faire la différence entre « The cat sat on the mat » et « The mat sat on the cat » — quelque chose que BERT de base ne ferait pas !
Sémantique désigne le sens qui se cache derrière les mots. C’est particulièrement important dans le contexte des LLM, car les mêmes mots peuvent avoir des significations différentes selon le contexte, l’ordre ou l’usage. Pour plus d’informations sur SBERT, les lecteurs intéressés devraient consulter ces bons articles de référence sur ce modèle ici.
Supposons que vous codiez des applications RAG à partir de zéro. Un excellent point de départ consiste à sélectionner un modèle d’embedding dans le HuggingFace MTEB Leaderboard, trié (par ordre décroissant) selon la colonne « Retrieval Average », car c’est la plus pertinente pour le RAG. Ensuite, choisissez le modèle d’embedding le plus petit et le mieux classé. Le classement change constamment ! Mais changer le modèle d’embedding avec HuggingFace en Python est aussi simple que de modifier une seule variable.
Les performances de retrieval MTEB sont mesurées par le Normalized Discounted Cumulative Gain à 10 (NDCG@10). Cette métrique mesure la qualité des listes top-K en calculant des sommes de ratios où les éléments les mieux classés reçoivent plus de poids que les éléments moins bien classés, tels qu’ils sont renvoyés à un utilisateur, proportionnellement à un ordre de classement idéal.
Source de l’image : HuggingFace MTEB Leaderboard, consulté le 20 février 2024.
Massive Text Embedding Benchmark (MTEB) évalue les modèles d’embedding sur 8 tâches et 58 jeux de données (10 multilingues, 112 langues). Les huit tâches sont l’extraction de bitextes, la classification, le clustering, la classification par paires, le reclassement, la recherche, la similarité textuelle sémantique (STS) et la synthèse.
6 modèles d’embedding clés intégrés à Zilliz Cloud Pipelines
Zilliz Cloud Pipelines a récemment lancé la prise en charge d’un riche ensemble de choix de modèles d’embedding.
| Créateur | Modèle | Dim d’embedding | Longueur du contexte | Tâches de cas d’utilisation | Open Source | *Score MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texte EN général | Oui | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texte ZH général | Oui | 69 |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de haute qualité | Non | Non disponible |
| VoyageAI | voyage-code-2 | 1536 | 16K | Complétion de code à taux de rappel élevé | Non | Non disponible |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots textuels multilingues en temps réel | Non | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots textuels multilingues en temps réel | Non | 65 (3072) 62 (256) |
*HuggingFace MTEB Leaderboard, trié par ordre décroissant selon Retrieval, consulté le 26 février 2024.
Dim d’embedding = longueur du vecteur produit par un modèle ; les vecteurs plus grands peuvent capturer davantage de sens, mais peuvent être moins efficaces en matière de stockage.
Longueur du contexte = nombre maximal de tokens que le modèle peut traiter en une seule fois à un pas de temps unique. Les vecteurs de sortie de la plupart des modèles d’embedding sont normalisés, de sorte que le produit scalaire et la similarité cosinus sont équivalents.
⚠️ Remarque : Même si les benchmarks MTEB offrent des indications précieuses, certains modèles sont connus pour être surajustés ! Effectuez toujours vos propres évaluations !
Avec Zilliz Cloud Pipelines, vous pouvez démarrer gratuitement en vous inscrivant et en créant votre application RAG sans les tracas liés au DevOps ou à l’infrastructure ML.
Source de l’image : Blog annonçant les modèles d’embedding intégrés à Zilliz Cloud Pipelines
Modèles d’embedding BAAI/bge-base-en(ou zh)-v1.5
Ces modèles SBERT open source sont disponibles sur HuggingFace. Quelques avantages de ces petits modèles :
Petits, open source et adaptés au CPU.
C’est un bon choix pour travailler sur un ordinateur portable ou/ou de minuscules ressources cloud.
Les plus rapides pour l’ingestion lors du découpage des données et pour la latence des requêtes chaque fois qu’une question est posée.
Rentables, car les appels API sont gratuits et aucun GPU n’est requis.
Entraînés en chinois et en anglais.
| Créateur | Modèle | Dimension****d’embedding | Longueur du contexte | Tâches de cas d’utilisation | Open Source | *Score MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texte général EN | Oui | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texte général ZH | Oui | 69 |
*Classement MTEB HuggingFace, trié par ordre décroissant de Retrieval, consulté le 26 février 2024.
Modèles d’embedding voyage-2 et voyage-code-2 de VoyageAI
Ces modèles propriétaires sont entraînés à l’aide de l’apprentissage contrastif et du rééchantillonnage par importance sur différentes données et affinés pour différentes tâches. Voyage-2 est entraîné sur des données de dialogue et affiné pour l’intention conversationnelle. Voyage-code-2 est entraîné sur des données de code et affiné pour la complétion de code.
Remarque : Voyage-lite-02-instruct répertorié dans le classement MTEB (trié par ordre décroissant de STS ou de la catégorie « corpus divers ») est différent et ne doit pas être confondu avec les modèles de production voyage-2 et voyage-code-2 décrits ici.
Quelques avantages de ces modèles :
Pour les chatbots RAG de documentation technique, il a été démontré que voyage-01 (obsolète) avait une qualité de récupération supérieure (mesurée en NDCG@10). Voyage-2 est la version la plus récente.
Pour les tâches de code, voyage-code-2 a un taux de rappel supérieur de 14 % pour le texte riche en code.
| Créateur | Modèle | Dimension****d’embedding | Longueur du contexte | Tâches de cas d’utilisation | Open Source | Score MTEB |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de haute qualité | Non | Non disponible |
| VoyageAI | voyage-code-2 | 1536 | 16K | Complétion de code à taux de rappel élevé | Non | Non disponible |
Modèles d’embedding text-embedding-3-small(ou large) d’OpenAI
De la part d’OpenAI, les tout derniers modèles d’embeddings se classent plus haut dans le classement MTEB que leur précédent ada-002. Ces nouveaux modèles d’embeddings offrent également de meilleures performances multilingues (MIRACL) et des prix plus bas.
Selon le blog d’OpenAI, un entraînement sensible à la compression a été utilisé pour créer les embeddings. Les techniques traditionnelles de réduction de dimensionnalité, telles que la quantification, économisent de l’espace, mais au prix d’une énorme perte de précision, car la compression est appliquée « post-hoc » après l’apprentissage des embeddings. L’entraînement sensible à la compression, comme Matryoshka Representation Learning, apprend des embeddings à différentes tailles (dimensions), avec une certaine perte de précision, bien que moins importante qu’avec l’ACP.
De manière impressionnante, les deux modèles prennent en charge des embeddings plus petits sans trop sacrifier la qualité de la récupération. Par exemple, réduire la dimension du vecteur de 3072 à 256 ne fait baisser le score MTEB que de 65 % à 62 %. Cependant, cela représente un besoin en mémoire 12 fois inférieur ! Bien qu’il existe un compromis précision-coût associé à une dimensionnalité plus faible, à l’ère des chatbots alimentés par l’IA, les réponses rapides sont parfois privilégiées par rapport à la précision des réponses.
Quelques avantages de ces modèles :
Capacités multilingues améliorées.
Vecteurs de dimension inférieure avec la plus faible surcharge d’inférence et une perte de précision bien moindre que la quantification binaire ou par produit traditionnelle.
| Créateur | Modèle | Dimension****Embedding | Longueur de contexte | Tâches de cas d’utilisation | Open Source | *Score MTEB |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots textuels multilingues en temps réel | Non | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots textuels multilingues en temps réel | Non | 65 (3072) 62 (256) |
*Classement MTEB HuggingFace, trié par ordre décroissant selon Retrieval, consulté le 26 février 2024.
Vous trouverez ci-dessous un exemple de code pour appeler les nouveaux modèles d’embeddings. Le code complet se trouve dans notre 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,
)
Ensuite, nous spécifions le modèle d’embedding 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
Ensuite, nous créons une collection Milvus sans schéma et spécifions un index.
# 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}`")
# Créez la collection.
mc.create_collection(COLLECTION_NAME,
EMBEDDING_DIM,
consistency_level="Eventually",
auto_id=True,
overwrite=True)
Ensuite, nous lisons les documents techniques LangChain sous forme de fichiers .html téléchargés dans un dossier. Segmentez et intégrez les documents. L’exemple ci-dessous utilise l’analyseur HTML intégré de LangChain comme stratégie de segmentation. Votre stratégie de segmentation pourrait être beaucoup plus simple.
# 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)
Insérez les segments et les embeddings dans 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)
Posez une question à Milvus, qui est maintenant chargé avec les embeddings de la documentation technique 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"]
# Exécutez une recherche vectorielle sémantique en utilisant votre requête et la base de données vectorielle Milvus.
start_time = time.time()
results = mc.search(
COLLECTION_NAME,
data=[query_embeddings],
output_fields=OUTPUT_FIELDS,
limit=2,
consistency_level="Eventually"
)
Générez une réponse en utilisant ChatGPT et les fragments de contexte textuel récupérés.
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 réponse utilisant text-embedding-3-small avec des embeddings réduits dim=256 est parfaite comparée à la même réponse avec dim=1536, au moins pour cet exemple RAG !
Conclusion
Dans ce blog, nous avons présenté comment les modèles d’embedding sont utilisés dans RAG et SBERT, le type de modèle d’embedding le plus courant. Nous avons montré le classement MTEB des modèles d’embedding et expliqué comment l’utiliser. Ensuite, nous avons passé en revue les six différents modèles d’embedding automatiquement inclus dans Zilliz Pipelines. Différents modèles d’embedding sont mieux adaptés à différents cas d’utilisation ; nous avons discuté du moment où choisir tel ou tel modèle. Enfin, nous avons montré du code pour appeler les nouveaux modèles d’embedding d’OpenAI ; et le code complet se trouve dans notre bootcamp github.
Références
Milvus (donnez-nous une étoile !)
Tutoriel sur les parties encodeur-décodeur des transformers
Tutoriel sur les modèles d’embedding encodeur SBERT
Classement MTEB HuggingFace des modèles d’embedding
Fiche de modèle HuggingFace pour BAAI/bg-large-en-v1.5
Modèles d’embedding VoyageAI
Modèles d’embedding OpenAI
Continuer à lire

Introducing Customer-Managed Encryption Keys (CMEK) on Zilliz Cloud
We're announcing the general availability of Customer-Managed Encryption Keys (CMEK) on Zilliz Cloud.

What Exactly Are AI Agents? Why OpenAI and LangChain Are Fighting Over Their Definition?
AI agents are software programs powered by AI that can perceive their environment, make decisions, and take actions to achieve a goal—often autonomously.

Optimizing Embedding Model Selection with TDA Clustering: A Strategic Guide for Vector Databases
Discover how Topological Data Analysis (TDA) reveals hidden embedding model weaknesses and helps optimize vector database performance.



