Utilisation de la recherche plein texte avec LlamaIndex et Milvus
Larecherche plein texte utilise la correspondance exacte des mots-clés, en s'appuyant souvent sur des algorithmes tels que BM25 pour classer les documents en fonction de leur pertinence. Dans les systèmes RAG (Retrieval-Augmented Generation), cette méthode permet d'extraire du texte pertinent afin d'améliorer les réponses générées par l'IA.
Parallèlement, la recherche sémantique interprète le sens du contexte pour fournir des résultats plus larges. La combinaison des deux approches crée une recherche hybride qui améliore la recherche d'informations, en particulier dans les cas où une seule méthode ne suffit pas.
Avec l'approche Sparse-BM25 de Milvus 2.5, le texte brut est automatiquement converti en vecteurs épars. Cela élimine la nécessité de générer manuellement des vecteurs épars et permet une stratégie de recherche hybride qui équilibre la compréhension sémantique et la pertinence des mots clés.
Dans ce tutoriel, vous apprendrez à utiliser LlamaIndex et Milvus pour construire un système RAG utilisant la recherche plein texte et la recherche hybride. Nous commencerons par mettre en œuvre la recherche en texte intégral seule, puis nous l'améliorerons en intégrant la recherche sémantique pour obtenir des résultats plus complets.
Avant de poursuivre ce tutoriel, assurez-vous d'être familier avec la recherche plein texte et les bases de l'utilisation de Milvus dans LlamaIndex.
Conditions préalables
Installer les dépendances
Avant de commencer, assurez-vous que les dépendances suivantes sont installées :
$ $pip install llama-index-vector-stores-milvus
$ $pip install llama-index-embeddings-openai
$ $pip install llama-index-llms-openai
Si vous utilisez Google Colab, il se peut que vous deviez redémarrer le runtime (Naviguez vers le menu "Runtime" en haut de l'interface, et sélectionnez "Restart session" dans le menu déroulant).
Configurer les comptes
Ce tutoriel utilise OpenAI pour l'intégration de texte et la génération de réponses. Vous devez préparer la clé API OpenAI.
import openai
openai.api_key = "sk-"
Pour utiliser le magasin de vecteurs Milvus, indiquez votre serveur Milvus URI (et éventuellement TOKEN). Pour démarrer un serveur Milvus, vous pouvez le configurer en suivant le guide d'installation Milvus ou en essayant simplement Zilliz Cloud gratuitement.
La recherche en texte intégral est actuellement prise en charge dans Milvus Standalone, Milvus Distributed et Zilliz Cloud, mais pas encore dans Milvus Lite (prévu pour une mise en œuvre future). Contactez support@zilliz.com pour plus d'informations.
URI = "http://localhost:19530"
# TOKEN = ""
Télécharger des données d'exemple
Exécutez les commandes suivantes pour télécharger des exemples de documents dans le répertoire "data/paul_graham" :
$ mkdir -p 'data/paul_graham/'
$ $wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
--2025-03-27 07:49:01-- https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 75042 (73K) [text/plain]
Saving to: ‘data/paul_graham/paul_graham_essay.txt’
data/paul_graham/pa 100%[===================>] 73.28K --.-KB/s in 0.07s
2025-03-27 07:49:01 (1.01 MB/s) - ‘data/paul_graham/paul_graham_essay.txt’ saved [75042/75042]
RAG avec recherche en texte intégral
L'intégration de la recherche plein texte dans un système RAG permet d'équilibrer la recherche sémantique et la recherche précise et prévisible par mot-clé. Vous pouvez également choisir de n'utiliser que la recherche plein texte, bien qu'il soit recommandé de combiner la recherche plein texte avec la recherche sémantique pour obtenir de meilleurs résultats de recherche. À des fins de démonstration, nous présenterons ici la recherche en texte intégral seule et la recherche hybride.
Pour commencer, utilisez SimpleDirectoryReaderLoad pour charger l'essai "What I Worked On" de Paul Graham :
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
# Let's take a look at the first document
print("Example document:\n", documents[0])
Example document:
Doc ID: 16b7942f-bf1a-4197-85e1-f31d51ea25a9
Text: What I Worked On February 2021 Before college the two main
things I worked on, outside of school, were writing and programming. I
didn't write essays. I wrote what beginning writers were supposed to
write then, and probably still are: short stories. My stories were
awful. They had hardly any plot, just characters with strong feelings,
which I ...
Recherche plein texte avec BM25
Le site MilvusVectorStore de LlamaIndex prend en charge la recherche plein texte, ce qui permet une recherche efficace par mot-clé. En utilisant une fonction intégrée comme sparse_embedding_function, il applique la notation BM25 pour classer les résultats de la recherche.
Dans cette section, nous allons montrer comment mettre en œuvre un système RAG utilisant BM25 pour la recherche en texte intégral.
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.vector_stores.milvus.utils import BM25BuiltInFunction
from llama_index.core import Settings
# Skip dense embedding model
Settings.embed_model = None
# Build Milvus vector store creating a new collection
vector_store = MilvusVectorStore(
uri=URI,
# token=TOKEN,
enable_dense=False,
enable_sparse=True, # Only enable sparse to demo full text search
sparse_embedding_function=BM25BuiltInFunction(),
overwrite=True,
)
# Store documents in Milvus
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
Embeddings have been explicitly disabled. Using MockEmbedding.
Le code ci-dessus insère des documents d'exemple dans Milvus et construit un index pour permettre le classement BM25 pour la recherche en texte intégral. Il désactive l'intégration dense et utilise BM25BuiltInFunction avec les paramètres par défaut.
Vous pouvez spécifier les champs d'entrée et de sortie dans les paramètres BM25BuiltInFunction:
input_field_names (str): Le champ texte d'entrée (par défaut : "text"). Il indique le champ de texte auquel l'algorithme BM25 s'applique. Modifiez ce paramètre si vous utilisez votre propre collection avec un nom de champ de texte différent.output_field_names (str): Le champ dans lequel les sorties de cette fonction BM25 sont stockées (par défaut : "sparse_embedding").
Une fois le magasin de vecteurs configuré, vous pouvez effectuer des recherches en texte intégral à l'aide de Milvus avec le mode de requête "sparse" ou "text_search" :
import textwrap
query_engine = index.as_query_engine(
vector_store_query_mode="sparse", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. They learned about the importance of growth
rate as the ultimate test of a startup, the value of building stores for users to understand retail
and software usability, and the significance of being the "entry level" option in a market.
Additionally, they discovered the accidental success of making Viaweb inexpensive, the challenges of
hiring too many people, and the relief felt when the company was acquired by Yahoo.
Personnaliser l'analyseur de texte
Les analyseurs jouent un rôle essentiel dans la recherche en texte intégral en décomposant les phrases en tokens et en effectuant un traitement lexical, tel que le stemming et la suppression des mots vides. Ils sont généralement spécifiques à une langue. Pour plus de détails, voir le Guide de l'analyseur Milvus.
Milvus prend en charge deux types d'analyseurs : Les analyseurs intégrés et les analyseurs personnalisés. Par défaut, le site BM25BuiltInFunction utilise l'analyseur intégré standard, qui génère des jetons dans le texte en fonction de la ponctuation.
Pour utiliser un autre analyseur ou personnaliser l'analyseur existant, vous pouvez donner une valeur à l'argument analyzer_params:
bm25_function = BM25BuiltInFunction(
analyzer_params={
"tokenizer": "standard",
"filter": [
"lowercase", # Built-in filter
{"type": "length", "max": 40}, # Custom cap size of a single token
{"type": "stop", "stop_words": ["of", "to"]}, # Custom stopwords
],
},
enable_match=True,
)
Recherche hybride avec Reranker
Un système de recherche hybride combine la recherche sémantique et la recherche en texte intégral, optimisant ainsi les performances de recherche dans un système RAG.
L'exemple suivant utilise l'intégration OpenAI pour la recherche sémantique et BM25 pour la recherche en texte intégral :
# Create index over the documnts
vector_store = MilvusVectorStore(
uri=URI,
# token=TOKEN,
# enable_dense=True, # enable_dense defaults to True
dim=1536,
enable_sparse=True,
sparse_embedding_function=BM25BuiltInFunction(),
overwrite=True,
# hybrid_ranker="RRFRanker", # hybrid_ranker defaults to "RRFRanker"
# hybrid_ranker_params={}, # hybrid_ranker_params defaults to {}
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
embed_model="default", # "default" will use OpenAI embedding
)
Fonctionnement
Cette approche stocke les documents dans une collection Milvus avec les deux champs vectoriels :
embedding: les encastrements denses générés par le modèle d'encastrement d'OpenAI pour la recherche sémantique.sparse_embedding: les encastrements épars calculés à l'aide de BM25BuiltInFunction pour la recherche en texte intégral.
En outre, nous avons appliqué une stratégie de reranking en utilisant "RRFRanker" avec ses paramètres par défaut. Pour personnaliser le reranker, vous pouvez configurer hybrid_ranker et hybrid_ranker_params en suivant le Milvus Reranking Guide.
Testons maintenant le système RAG avec un exemple de requête :
# Query
query_engine = index.as_query_engine(
vector_store_query_mode="hybrid", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. These included the importance of
understanding growth rate as the ultimate test of a startup, the impact of hiring too many people,
the challenges of being at the mercy of investors, and the relief experienced when Yahoo bought the
company. Additionally, the author learned about the significance of user feedback, the value of
building stores for users, and the realization that growth rate is crucial for the long-term success
of a startup.
Cette approche hybride garantit des réponses plus précises et contextuelles dans un système RAG en tirant parti de la recherche sémantique et de la recherche par mot-clé.