Utilización de la búsqueda de texto completo con LlamaIndex y Milvus
Labúsqueda de texto completo utiliza la concordancia exacta de palabras clave, a menudo aprovechando algoritmos como BM25 para clasificar los documentos por relevancia. En los sistemas de Recuperación-Generación Mejorada (RAG ), este método recupera el texto pertinente para mejorar las respuestas generadas por la IA.
Por su parte, la búsqueda semántica interpreta el significado contextual para ofrecer resultados más amplios. La combinación de ambos enfoques crea una búsqueda híbrida que mejora la recuperación de información, especialmente en los casos en los que un solo método se queda corto.
Con el enfoque Sparse-BM25 de Milvus 2.5, el texto en bruto se convierte automáticamente en vectores dispersos. Esto elimina la necesidad de la generación manual de incrustaciones dispersas y permite una estrategia de búsqueda híbrida que equilibra la comprensión semántica con la relevancia de las palabras clave.
En este tutorial, aprenderá a utilizar LlamaIndex y Milvus para construir un sistema RAG utilizando la búsqueda de texto completo y la búsqueda híbrida. Comenzaremos implementando sólo la búsqueda de texto completo y luego la mejoraremos integrando la búsqueda semántica para obtener resultados más completos.
Antes de continuar con este tutorial, asegúrese de que está familiarizado con la búsqueda de texto completo y con los conceptos básicos del uso de Milvus en LlamaIndex.
Requisitos previos
Instalar dependencias
Antes de empezar, asegúrate de tener instaladas las siguientes dependencias:
$ $pip install llama-index-vector-stores-milvus
$ $pip install llama-index-embeddings-openai
$ $pip install llama-index-llms-openai
Si utilizas Google Colab, es posible que tengas que reiniciar el tiempo de ejecución (ve al menú "Tiempo de ejecución" en la parte superior de la interfaz y selecciona "Reiniciar sesión" en el menú desplegable).
Configurar cuentas
Este tutorial utiliza OpenAI para la incrustación de texto y la generación de respuestas. Es necesario preparar la clave API de OpenAI.
import openai
openai.api_key = "sk-"
Para utilizar el almacén vectorial Milvus, especifique su servidor Milvus URI (y opcionalmente con el TOKEN). Para iniciar un servidor Milvus, puede configurar un servidor Milvus siguiendo la guía de instalación de Milvus o simplemente probando Zilliz Cloud de forma gratuita.
La búsqueda de texto completo está actualmente soportada en Milvus Standalone, Milvus Distributed y Zilliz Cloud, pero todavía no en Milvus Lite (prevista para una futura implementación). Póngase en contacto con support@zilliz.com para obtener más información.
URI = "http://localhost:19530"
# TOKEN = ""
Descargar datos de ejemplo
Ejecute los siguientes comandos para descargar documentos de ejemplo en el directorio "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 con búsqueda de texto completo
La integración de la búsqueda de texto completo en un sistema RAG equilibra la búsqueda semántica con una recuperación precisa y predecible basada en palabras clave. También puede optar por utilizar únicamente la búsqueda de texto completo, aunque se recomienda combinarla con la búsqueda semántica para obtener mejores resultados. A modo de demostración, mostraremos la búsqueda de texto completo sola y la búsqueda híbrida.
Para empezar, utilice SimpleDirectoryReaderLoad para cargar el ensayo "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 ...
Búsqueda de texto completo con BM25
MilvusVectorStore de LlamaIndex admite la búsqueda de texto completo, lo que permite una recuperación eficaz basada en palabras clave. Utilizando una función incorporada como sparse_embedding_function, aplica la puntuación BM25 para clasificar los resultados de la búsqueda.
En esta sección, demostraremos cómo implementar un sistema RAG utilizando BM25 para la búsqueda de texto completo.
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.
El código anterior inserta documentos de ejemplo en Milvus y construye un índice para permitir la clasificación BM25 para la búsqueda de texto completo. Desactiva la incrustación densa y utiliza BM25BuiltInFunction con parámetros por defecto.
Puede especificar los campos de entrada y salida en los parámetros BM25BuiltInFunction:
input_field_names (str): El campo de texto de entrada (por defecto: "text"). Indica a qué campo de texto se aplica el algoritmo BM25. Modifíquelo si utiliza su propia colección con un nombre de campo de texto diferente.output_field_names (str): El campo donde se almacenan las salidas de esta función BM25 (por defecto: "sparse_embedding").
Una vez configurado el almacén de vectores, puede realizar consultas de búsqueda de texto completo utilizando Milvus con el modo de consulta "sparse" o "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.
Personalizar el analizador de texto
Los analizadores desempeñan un papel fundamental en la búsqueda de texto completo, ya que descomponen las frases en tokens y realizan el procesamiento léxico, como la eliminación de palabras vacías y de palabras clave. Suelen ser específicos de cada idioma. Para más detalles, consulte la Guía de analizadores de Milvus.
Milvus admite dos tipos de analizadores: Analizadores incorporados y Analizadores personalizados. Por defecto, BM25BuiltInFunction utiliza el analizador incorporado estándar, que tokeniza el texto basándose en la puntuación.
Para utilizar un analizador diferente o personalizar el existente, puede pasar un valor al argumento 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,
)
Búsqueda híbrida con Reranker
Un sistema de búsqueda híbrido combina la búsqueda semántica y la búsqueda de texto completo, optimizando el rendimiento de la recuperación en un sistema RAG.
El siguiente ejemplo utiliza la incrustación OpenAI para la búsqueda semántica y BM25 para la búsqueda de texto completo:
# 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
)
Funcionamiento
Este enfoque almacena los documentos en una colección Milvus con ambos campos vectoriales:
embedding: Incrustaciones densas generadas por el modelo de incrustación OpenAI para la búsqueda semántica.sparse_embedding: Incrustaciones dispersas calculadas mediante BM25BuiltInFunction para la búsqueda de texto completo.
Además, hemos aplicado una estrategia de reranking utilizando "RRFRanker" con sus parámetros por defecto. Para personalizar el reranker, puede configurar hybrid_ranker y hybrid_ranker_params siguiendo la Milvus Reranking Guide.
Ahora, probemos el sistema RAG con una consulta de ejemplo:
# 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.
Este enfoque híbrido garantiza respuestas más precisas y conscientes del contexto en un sistema RAG al aprovechar tanto la recuperación semántica como la basada en palabras clave.