Utilizar a pesquisa de texto integral com LlamaIndex e Milvus
A pesquisa de texto integral utiliza a correspondência exacta de palavras-chave, recorrendo frequentemente a algoritmos como o BM25 para classificar os documentos por relevância. Nos sistemas RAG (Retrieval-Augmented Generation), este método recupera texto pertinente para melhorar as respostas geradas pela IA.
Entretanto, a pesquisa semântica interpreta o significado contextual para fornecer resultados mais alargados. A combinação de ambas as abordagens cria uma pesquisa híbrida que melhora a recuperação de informações - especialmente nos casos em que um único método não é suficiente.
Com a abordagem Sparse-BM25 do Milvus 2.5, o texto em bruto é automaticamente convertido em vectores esparsos. Isso elimina a necessidade de geração manual de incorporação esparsa e permite uma estratégia de pesquisa híbrida que equilibra a compreensão semântica com a relevância das palavras-chave.
Neste tutorial, aprenderá a utilizar o LlamaIndex e o Milvus para criar um sistema RAG utilizando a pesquisa de texto integral e a pesquisa híbrida. Começaremos por implementar apenas a pesquisa de texto integral e, em seguida, melhorá-la-emos integrando a pesquisa semântica para obter resultados mais abrangentes.
Antes de prosseguir com este tutorial, certifique-se de que está familiarizado com a pesquisa de texto integral e com as noções básicas de utilização do Milvus no LlamaIndex.
Pré-requisitos
Instalar dependências
Antes de começar, certifique-se de que tem as seguintes dependências instaladas:
$ $pip install llama-index-vector-stores-milvus
$ $pip install llama-index-embeddings-openai
$ $pip install llama-index-llms-openai
Se estiver a utilizar o Google Colab, poderá ter de reiniciar o tempo de execução (navegue até ao menu "Tempo de execução" na parte superior da interface e selecione "Reiniciar sessão" no menu pendente).
Configurar contas
Este tutorial usa o OpenAI para incorporação de texto e geração de respostas. É necessário preparar a chave da API do OpenAI.
import openai
openai.api_key = "sk-"
Para utilizar o armazenamento de vectores Milvus, especifique o seu servidor Milvus URI (e, opcionalmente, com o TOKEN). Para iniciar um servidor Milvus, pode configurar um servidor Milvus seguindo o guia de instalação do Milvus ou simplesmente experimentando o Zilliz Cloud gratuitamente.
A pesquisa de texto completo é atualmente suportada no Milvus Standalone, Milvus Distributed e Zilliz Cloud, mas ainda não no Milvus Lite (planeado para implementação futura). Contacte support@zilliz.com para obter mais informações.
URI = "http://localhost:19530"
# TOKEN = ""
Descarregar dados de exemplo
Execute os seguintes comandos para descarregar documentos de exemplo para o diretório "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 com pesquisa de texto integral
A integração da pesquisa de texto integral num sistema RAG equilibra a pesquisa semântica com a recuperação precisa e previsível baseada em palavras-chave. Também pode optar por utilizar apenas a pesquisa em texto integral, embora seja recomendável combinar a pesquisa em texto integral com a pesquisa semântica para obter melhores resultados de pesquisa. Aqui, para efeitos de demonstração, mostraremos apenas a pesquisa de texto integral e a pesquisa híbrida.
Para começar, utilize SimpleDirectoryReaderLoad para carregar o ensaio "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 ...
Pesquisa de texto integral com BM25
O MilvusVectorStore do LlamaIndex suporta a pesquisa de texto integral, permitindo uma recuperação eficiente baseada em palavras-chave. Utilizando uma função incorporada como sparse_embedding_function, aplica a pontuação BM25 para classificar os resultados da pesquisa.
Nesta secção, vamos demonstrar como implementar um sistema RAG usando BM25 para pesquisa de texto integral.
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.
O código acima insere documentos de exemplo no Milvus e cria um índice para permitir a classificação BM25 para pesquisa em texto integral. Desactiva a incorporação densa e utiliza BM25BuiltInFunction com parâmetros predefinidos.
Pode especificar os campos de entrada e saída nos parâmetros BM25BuiltInFunction:
input_field_names (str): O campo de texto de entrada (padrão: "text"). Indica o campo de texto ao qual o algoritmo BM25 é aplicado. Altere isto se utilizar a sua própria coleção com um nome de campo de texto diferente.output_field_names (str): O campo onde as saídas desta função BM25 são armazenadas (predefinição: "sparse_embedding").
Uma vez configurado o armazenamento de vectores, pode efetuar consultas de pesquisa de texto completo utilizando o Milvus com o modo de consulta "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.
Personalizar o analisador de texto
Os analisadores desempenham um papel vital na pesquisa de texto completo, dividindo as frases em tokens e efectuando o processamento lexical, tal como a remoção de palavras-chave e de stop-word. Normalmente, são específicos do idioma. Para mais pormenores, consulte o Milvus Analyzer Guide.
O Milvus suporta dois tipos de analisadores: Analisadores incorporados e Analisadores personalizados. Por padrão, o site BM25BuiltInFunction usa o analisador padrão incorporado, que tokeniza o texto com base na pontuação.
Para usar um analisador diferente ou personalizar o existente, você pode passar um valor para o 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,
)
Pesquisa híbrida com ranqueador
Um sistema de pesquisa híbrido combina a pesquisa semântica e a pesquisa de texto completo, optimizando o desempenho da recuperação num sistema RAG.
O exemplo a seguir usa a incorporação OpenAI para pesquisa semântica e BM25 para pesquisa 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
)
Como funciona
Esta abordagem armazena documentos numa coleção Milvus com ambos os campos vectoriais:
embedding: Embeddings densos gerados pelo modelo de embedding OpenAI para pesquisa semântica.sparse_embedding: Embeddings esparsos calculados com a BM25BuiltInFunction para pesquisa de texto completo.
Além disso, aplicámos uma estratégia de classificação utilizando o "RRFRanker" com os seus parâmetros predefinidos. Para personalizar o reranker, pode configurar hybrid_ranker e hybrid_ranker_params seguindo o Milvus Reranking Guide.
Agora, vamos testar o sistema RAG com uma consulta de amostra:
# 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.
Esta abordagem híbrida garante respostas mais precisas e conscientes do contexto num sistema RAG, aproveitando a recuperação semântica e baseada em palavras-chave.