Milvus Hybrid Retriever de recherche
Vue d'ensemble
Milvus est une base de données vectorielle open-source conçue pour alimenter les applications de recherche de similarité et d'intelligence artificielle. Milvus rend la recherche de données non structurées plus accessible et offre une expérience utilisateur cohérente quel que soit l'environnement de déploiement.
Ceci vous aidera à démarrer avec le récupérateur Milvus Hybrid Search, qui combine les forces de la recherche vectorielle dense et de la recherche vectorielle clairsemée. Pour une documentation détaillée de toutes les fonctionnalités et configurations de MilvusCollectionHybridSearchRetriever
, consultez la référence API.
Voir également la documentation sur la recherche multivectorielle Milvus.
Détails de l'intégration
Récupérateur | Auto-hébergement | Offre en nuage | Paquet |
---|---|---|---|
MilvusCollectionHybridSearchRetriever | ✅ | ❌ | langchain_milvus |
Mise en place
Si vous souhaitez obtenir un traçage automatisé à partir de requêtes individuelles, vous pouvez également définir votre clé API LangSmith en décommentant ci-dessous :
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"
Installation
Ce récupérateur se trouve dans le paquet langchain-milvus
. Ce guide nécessite les dépendances suivantes :
%pip install --upgrade --quiet pymilvus[model] langchain-milvus langchain-openai
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_milvus.retrievers import MilvusCollectionHybridSearchRetriever
from langchain_milvus.utils.sparse import BM25SparseEmbedding
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from pymilvus import (
Collection,
CollectionSchema,
DataType,
FieldSchema,
WeightedRanker,
connections,
)
Démarrer le service Milvus
Veuillez vous référer à la documentation Milvus pour démarrer le service Milvus.
Après avoir démarré milvus, vous devez spécifier votre URI de connexion milvus.
CONNECTION_URI = "http://localhost:19530"
Préparer la clé API OpenAI
Veuillez vous référer à la documentation OpenAI pour obtenir votre clé API OpenAI et la définir comme variable d'environnement.
export OPENAI_API_KEY=<your_api_key>
Préparer les fonctions d'intégration denses et éparses
Imaginons 10 fausses descriptions de romans. Dans la production réelle, il peut s'agir d'une grande quantité de données textuelles.
texts = [
"In 'The Whispering Walls' by Ava Moreno, a young journalist named Sophia uncovers a decades-old conspiracy hidden within the crumbling walls of an ancient mansion, where the whispers of the past threaten to destroy her own sanity.",
"In 'The Last Refuge' by Ethan Blackwood, a group of survivors must band together to escape a post-apocalyptic wasteland, where the last remnants of humanity cling to life in a desperate bid for survival.",
"In 'The Memory Thief' by Lila Rose, a charismatic thief with the ability to steal and manipulate memories is hired by a mysterious client to pull off a daring heist, but soon finds themselves trapped in a web of deceit and betrayal.",
"In 'The City of Echoes' by Julian Saint Clair, a brilliant detective must navigate a labyrinthine metropolis where time is currency, and the rich can live forever, but at a terrible cost to the poor.",
"In 'The Starlight Serenade' by Ruby Flynn, a shy astronomer discovers a mysterious melody emanating from a distant star, which leads her on a journey to uncover the secrets of the universe and her own heart.",
"In 'The Shadow Weaver' by Piper Redding, a young orphan discovers she has the ability to weave powerful illusions, but soon finds herself at the center of a deadly game of cat and mouse between rival factions vying for control of the mystical arts.",
"In 'The Lost Expedition' by Caspian Grey, a team of explorers ventures into the heart of the Amazon rainforest in search of a lost city, but soon finds themselves hunted by a ruthless treasure hunter and the treacherous jungle itself.",
"In 'The Clockwork Kingdom' by Augusta Wynter, a brilliant inventor discovers a hidden world of clockwork machines and ancient magic, where a rebellion is brewing against the tyrannical ruler of the land.",
"In 'The Phantom Pilgrim' by Rowan Welles, a charismatic smuggler is hired by a mysterious organization to transport a valuable artifact across a war-torn continent, but soon finds themselves pursued by deadly assassins and rival factions.",
"In 'The Dreamwalker's Journey' by Lyra Snow, a young dreamwalker discovers she has the ability to enter people's dreams, but soon finds herself trapped in a surreal world of nightmares and illusions, where the boundaries between reality and fantasy blur.",
]
Nous utiliserons l'OpenAI Embedding pour générer des vecteurs denses, et l'algorithme BM25 pour générer des vecteurs épars.
Initialisation de la fonction d'intégration dense et obtention de la dimension
dense_embedding_func = OpenAIEmbeddings()
dense_dim = len(dense_embedding_func.embed_query(texts[1]))
dense_dim
1536
Initialiser la fonction d'incorporation éparse.
Notez que la sortie de l'incorporation éparse est un ensemble de vecteurs épars, qui représentent l'index et le poids des mots-clés du texte d'entrée.
sparse_embedding_func = BM25SparseEmbedding(corpus=texts)
sparse_embedding_func.embed_query(texts[1])
{0: 0.4270424944042204,
21: 1.845826690498331,
22: 1.845826690498331,
23: 1.845826690498331,
24: 1.845826690498331,
25: 1.845826690498331,
26: 1.845826690498331,
27: 1.2237754316221157,
28: 1.845826690498331,
29: 1.845826690498331,
30: 1.845826690498331,
31: 1.845826690498331,
32: 1.845826690498331,
33: 1.845826690498331,
34: 1.845826690498331,
35: 1.845826690498331,
36: 1.845826690498331,
37: 1.845826690498331,
38: 1.845826690498331,
39: 1.845826690498331}
Création de la collection Milvus et chargement des données
Initialiser l'URI de connexion et établir la connexion
connections.connect(uri=CONNECTION_URI)
Définir les noms des champs et leurs types de données
pk_field = "doc_id"
dense_field = "dense_vector"
sparse_field = "sparse_vector"
text_field = "text"
fields = [
FieldSchema(
name=pk_field,
dtype=DataType.VARCHAR,
is_primary=True,
auto_id=True,
max_length=100,
),
FieldSchema(name=dense_field, dtype=DataType.FLOAT_VECTOR, dim=dense_dim),
FieldSchema(name=sparse_field, dtype=DataType.SPARSE_FLOAT_VECTOR),
FieldSchema(name=text_field, dtype=DataType.VARCHAR, max_length=65_535),
]
Créer une collection avec le schéma défini
schema = CollectionSchema(fields=fields, enable_dynamic_field=False)
collection = Collection(
name="IntroductionToTheNovels", schema=schema, consistency_level="Strong"
)
Définir l'index pour les vecteurs denses et épars
dense_index = {"index_type": "FLAT", "metric_type": "IP"}
collection.create_index("dense_vector", dense_index)
sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"}
collection.create_index("sparse_vector", sparse_index)
collection.flush()
Insérer des entités dans la collection et charger la collection
entities = []
for text in texts:
entity = {
dense_field: dense_embedding_func.embed_documents([text])[0],
sparse_field: sparse_embedding_func.embed_documents([text])[0],
text_field: text,
}
entities.append(entity)
collection.insert(entities)
collection.load()
Instanciation
Nous pouvons maintenant instancier notre récupérateur, en définissant les paramètres de recherche pour les champs denses et épars :
sparse_search_params = {"metric_type": "IP"}
dense_search_params = {"metric_type": "IP", "params": {}}
retriever = MilvusCollectionHybridSearchRetriever(
collection=collection,
rerank=WeightedRanker(0.5, 0.5),
anns_fields=[dense_field, sparse_field],
field_embeddings=[dense_embedding_func, sparse_embedding_func],
field_search_params=[dense_search_params, sparse_search_params],
top_k=3,
text_field=text_field,
)
Dans les paramètres d'entrée de ce récupérateur, nous utilisons un encapsulage dense et un encapsulage clairsemé pour effectuer une recherche hybride sur les deux champs de cette collection, et nous utilisons WeightedRanker pour le reranking. Enfin, 3 documents top-K seront retournés.
Utilisation
retriever.invoke("What are the story about ventures?")
[Document(page_content="In 'The Lost Expedition' by Caspian Grey, a team of explorers ventures into the heart of the Amazon rainforest in search of a lost city, but soon finds themselves hunted by a ruthless treasure hunter and the treacherous jungle itself.", metadata={'doc_id': '449281835035545843'}),
Document(page_content="In 'The Phantom Pilgrim' by Rowan Welles, a charismatic smuggler is hired by a mysterious organization to transport a valuable artifact across a war-torn continent, but soon finds themselves pursued by deadly assassins and rival factions.", metadata={'doc_id': '449281835035545845'}),
Document(page_content="In 'The Dreamwalker's Journey' by Lyra Snow, a young dreamwalker discovers she has the ability to enter people's dreams, but soon finds herself trapped in a surreal world of nightmares and illusions, where the boundaries between reality and fantasy blur.", metadata={'doc_id': '449281835035545846'})]
Utilisation au sein d'une chaîne
Initialiser ChatOpenAI et définir un modèle d'invite
llm = ChatOpenAI()
PROMPT_TEMPLATE = """
Human: You are an AI assistant, and provides answers to questions by using fact based and statistical information when possible.
Use the following pieces of information to provide a concise answer to the question enclosed in <question> tags.
<context>
{context}
</context>
<question>
{question}
</question>
Assistant:"""
prompt = PromptTemplate(
template=PROMPT_TEMPLATE, input_variables=["context", "question"]
)
Définir une fonction pour formater les documents
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
Définir une chaîne utilisant le récupérateur et d'autres composants
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
Effectuer une requête à l'aide de la chaîne définie
rag_chain.invoke("What novels has Lila written and what are their contents?")
"Lila Rose has written 'The Memory Thief,' which follows a charismatic thief with the ability to steal and manipulate memories as they navigate a daring heist and a web of deceit and betrayal."
Déposer la collection
collection.drop()
Référence API
Pour une documentation détaillée de toutes les fonctionnalités et configurations de MilvusCollectionHybridSearchRetriever
, consultez la référence API.