milvus-logo
LFAI
Casa
  • Integrazioni

Milvus Hybrid Search Retriever

Panoramica

Milvus è un database vettoriale open-source costruito per alimentare le applicazioni di ricerca per similarità e AI. Milvus rende la ricerca di dati non strutturati più accessibile e fornisce un'esperienza utente coerente indipendentemente dall'ambiente di distribuzione.

Questo vi aiuterà a iniziare con il retriever Milvus Hybrid Search, che combina i punti di forza della ricerca vettoriale densa e rada. Per una documentazione dettagliata di tutte le funzioni e le configurazioni di MilvusCollectionHybridSearchRetriever, consultare il riferimento API.

Si veda anche la documentazione sulla ricerca multivettoriale di Milvus.

Dettagli dell'integrazione

RecuperoSelf-hostOfferta cloudPacchetto
MilvusCollectionHybridSearchRetrieverlangchain_milvus

Configurazione

Se si desidera ottenere il tracciamento automatico delle singole query, è possibile impostare la chiave API di LangSmith decommentando qui sotto:

# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"

Installazione

Questo retriever si trova nel pacchetto langchain-milvus. Questa guida richiede le seguenti dipendenze:

%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,
)

Avviare il servizio Milvus

Fare riferimento alla documentazione di Milvus per avviare il servizio Milvus.

Dopo aver avviato Milvus, è necessario specificare l'URI di connessione di Milvus.

CONNECTION_URI = "http://localhost:19530"

Preparare la chiave API OpenAI

Fare riferimento alla documentazione di OpenAI per ottenere la chiave API di OpenAI e impostarla come variabile d'ambiente.

export OPENAI_API_KEY=<your_api_key>

Preparare le funzioni di incorporamento dense e rade

Finanziamo 10 descrizioni false di romanzi. Nella produzione reale, potrebbe trattarsi di una grande quantità di dati testuali.

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.",
]

Utilizzeremo OpenAI Embedding per generare vettori densi e l'algoritmo BM25 per generare vettori sparsi.

Inizializzare la funzione di incorporamento denso e ottenere la dimensione

dense_embedding_func = OpenAIEmbeddings()
dense_dim = len(dense_embedding_func.embed_query(texts[1]))
dense_dim
1536

Inizializzare la funzione di incorporamento rado.

Si noti che l'output di sparse embedding è un insieme di vettori sparsi, che rappresentano l'indice e il peso delle parole chiave del testo in ingresso.

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}

Creare la raccolta Milvus e caricare i dati

Inizializzare l'URI di connessione e stabilire la connessione

connections.connect(uri=CONNECTION_URI)

Definire i nomi dei campi e i loro tipi di dati

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),
]

Creare una collezione con lo schema definito

schema = CollectionSchema(fields=fields, enable_dynamic_field=False)
collection = Collection(
    name="IntroductionToTheNovels", schema=schema, consistency_level="Strong"
)

Definire l'indice per i vettori densi e radi

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()

Inserire le entità nella collezione e caricare la collezione

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()

Istanziazione

Ora possiamo istanziare il nostro retriever, definendo i parametri di ricerca per i campi sparsi e densi:

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,
)

Nei parametri di input di questo Retriever, utilizziamo un embedding denso e un embedding sparso per eseguire una ricerca ibrida sui due campi di questa raccolta e utilizziamo WeightedRanker per il reranking. Infine, verranno restituiti i 3 documenti top-K.

Uso

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'})]

Utilizzo all'interno di una catena

Inizializzare ChatOpenAI e definire un modello di prompt

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"]
)

Definire una funzione per la formattazione dei documenti

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

Definire una catena utilizzando il retriever e altri componenti

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

Eseguire una query utilizzando la catena definita

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."

Eliminare la raccolta

collection.drop()

Riferimento API

Per una documentazione dettagliata di tutte le funzioni e le configurazioni di MilvusCollectionHybridSearchRetriever, consultare il riferimento API.

Tradotto daDeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

Questa pagina è stata utile?