Eseguire la ricerca di massima rilevanza marginale con LangChain su Bigtable
Questa pagina descrive come eseguire una ricerca di massima rilevanza marginale (MMR) utilizzando l'integrazione BigtableVectorStore per LangChain in Bigtable e Gemini Enterprise Agent Platform come servizio di embedding.
MMR è una tecnica di ricerca utilizzata nel recupero delle informazioni per restituire un insieme di risultati pertinenti alla query e diversi, evitando la ridondanza. Mentre la ricerca standard di similarità vettoriale (ad esempio, una ricerca che utilizza il metodo dei k-vicini più prossimi) potrebbe restituire molti elementi simili, MMR fornisce un insieme più vario di risultati principali. Questa funzionalità è utile quando hai dati potenzialmente sovrapposti o duplicati nel datastore vettoriale.
Ad esempio, in un'applicazione di e-commerce, se un utente cerca "pomodori rossi", una ricerca di similarità vettoriale potrebbe restituire più schede dello stesso tipo di pomodoro rosso fresco. Una ricerca MMR mirerebbe a restituire un insieme più vario, ad esempio "pomodori rossi freschi", "pomodori rossi a cubetti in scatola", "pomodorini biologici" e magari anche "ricetta di insalata di pomodori".
Prima di leggere questa pagina, è importante conoscere i seguenti concetti:
- Pertinenza: una misura di quanto il documento corrisponde alla query.
- Diversità: una misura di quanto un documento è diverso dai documenti già selezionati nel set di risultati.
- Moltiplicatore lambda: un fattore compreso tra 0 e 1 che bilancia pertinenza e diversità. Un valore più vicino a 1 dà la priorità alla pertinenza, mentre un valore più vicino a 0 dà la priorità alla diversità.
La classe BigtableVectorStore per LangChain
implementa MMR come algoritmo di riordinamento.
Questo algoritmo recupera prima un insieme più ampio di documenti pertinenti alla query e seleziona i documenti che corrispondono alla query in modo bilanciato per pertinenza e diversità.
Prima di iniziare
Questa guida utilizza Agent Platform come servizio di embedding. Assicurati di aver abilitato l'API Agent Platform nel tuo progetto.
Ruoli obbligatori
Per utilizzare Bigtable con LangChain, devi disporre dei seguenti ruoli IAM:
- Utente Bigtable
(
roles/bigtable.user) sull' istanza Bigtable. - Se stai inizializzando la tabella, devi disporre anche del ruolo Bigtable
Administrator
(
roles/bigtable.admin).
Configura l'ambiente
Installa i pacchetti LangChain richiesti:
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexaiEsegui l'autenticazione a Google Cloud con il tuo account utente.
gcloud auth application-default loginImposta l'ID progetto, l'ID istanza Bigtable e l'ID tabella:
PROJECT_ID = "your-project-id" INSTANCE_ID = "your-instance-id" TABLE_ID = "your-table-id"
Inizializza il servizio di embedding e crea una tabella
Per utilizzare il datastore vettoriale Bigtable, devi fornire gli embedding generati da un modello di AI. In questa guida, utilizzi il modello di text embedding
gemini-embedding-001 su
Agent Platform.
from langchain_google_vertexai import VertexAIEmbeddings
from langchain_google_bigtable.vector_store import init_vector_store_table, BigtableVectorStore, ColumnConfig
# Initialize an embedding service
embedding_service = VertexAIEmbeddings(model_name="text-embedding-001", project=PROJECT_ID)
# Define column families
DATA_COLUMN_FAMILY = "product_data"
# Initialize the table (if it doesn't exist)
try:
init_vector_store_table(
project_id=PROJECT_ID,
instance_id=INSTANCE_ID,
table_id=TABLE_ID,
content_column_family=DATA_COLUMN_FAMILY,
embedding_column_family=DATA_COLUMN_FAMILY,
)
print(f"Table {TABLE_ID} created successfully.")
except ValueError as e:
print(e) # Table likely already exists
Crea un'istanza di BigtableVectorStore
Crea l'istanza del datastore passando il servizio di embedding e gli identificatori della tabella Bigtable.
# Configure columns
content_column = ColumnConfig(
column_family=DATA_COLUMN_FAMILY, column_qualifier="product_description"
)
embedding_column = ColumnConfig(
column_family=DATA_COLUMN_FAMILY, column_qualifier="embedding"
)
# Create the vector store instance
vector_store = BigtableVectorStore.create_sync(
project_id=PROJECT_ID,
instance_id=INSTANCE_ID,
table_id=TABLE_ID,
embedding_service=embedding_service,
collection="ecommerce_products",
content_column=content_column,
embedding_column=embedding_column,
)
print("BigtableVectorStore instantiated.")
Popola il datastore vettoriale
In questa guida, utilizziamo uno scenario di esempio di un servizio di e-commerce fittizio in cui gli utenti vogliono cercare articoli correlati ai pomodori rossi. Innanzitutto, dobbiamo aggiungere alcuni prodotti e descrizioni relativi ai pomodori al datastore vettoriale.
from langchain_core.documents import Document
products = [
Document(page_content="Fresh organic red tomatoes, great for salads.", metadata={"type": "fresh produce", "color": "red", "name": "Organic Vine Tomatoes"}),
Document(page_content="Ripe red tomatoes on the vine.", metadata={"type": "fresh", "color": "red", "name": "Tomatoes on Vine"}),
Document(page_content="Sweet cherry tomatoes, red and juicy.", metadata={"type": "fresh", "color": "red", "name": "Cherry Tomatoes"}),
Document(page_content="Canned diced red tomatoes in juice.", metadata={"type": "canned", "color": "red", "name": "Diced Tomatoes"}),
Document(page_content="Sun-dried tomatoes in oil.", metadata={"type": "preserved", "color": "red", "name": "Sun-Dried Tomatoes"}),
Document(page_content="Green tomatoes, perfect for frying.", metadata={"type": "fresh", "color": "green", "name": "Green Tomatoes"}),
Document(page_content="Tomato paste, concentrated flavor.", metadata={"type": "canned", "color": "red", "name": "Tomato Paste"}),
Document(page_content="Mixed salad greens with cherry tomatoes.", metadata={"type": "prepared", "color": "mixed", "name": "Salad Mix with Tomatoes"}),
Document(page_content="Yellow pear tomatoes, mild flavor.", metadata={"type": "fresh", "color": "yellow", "name": "Yellow Pear Tomatoes"}),
Document(page_content="Heirloom tomatoes, various colors.", metadata={"type": "fresh", "color": "various", "name": "Heirloom Tomatoes"}),
]
vector_store.add_documents(products)
print(f"Added {len(products)} products to the vector store.")
Esegui la ricerca MMR
Il datastore contiene molti prodotti correlati ai pomodori, ma gli utenti vogliono cercare solo le offerte associate a "pomodori rossi". Per ottenere un insieme diversificato di risultati, utilizza la tecnica MMR per eseguire la ricerca.
Il metodo chiave da utilizzare è il
max_marginal_relevance_search
che accetta i seguenti argomenti:
query(str): il testo di ricerca.k(int): il numero finale di risultati di ricerca.fetch_k(int): il numero iniziale di prodotti simili da recuperare prima di applicare l'algoritmo MMR. Ti consigliamo di scegliere un numero maggiore rispetto al parametrok.lambda_mult(float): il parametro di ottimizzazione della diversità. Utilizza0.0per la massima diversità,1.0per la massima pertinenza.
user_query = "red tomatoes"
k_results = 4
fetch_k_candidates = 10
print(f"Performing MMR search for: '{user_query}'")
# Example 1: Balanced relevance and diversity
mmr_results_balanced = vector_store.max_marginal_relevance_search(
user_query, k=k_results, fetch_k=fetch_k_candidates, lambda_mult=0.5
)
print(f"MMR Results (lambda=0.5, k={k_results}, fetch_k={fetch_k_candidates}):")
for doc in mmr_results_balanced:
print(f" - {doc.metadata['name']}: {doc.page_content}")
print("\n")
# Example 2: Prioritizing Diversity
mmr_results_diverse = vector_store.max_marginal_relevance_search(
user_query, k=k_results, fetch_k=fetch_k_candidates, lambda_mult=0.1
)
print(f"MMR Results (lambda=0.1, k={k_results}, fetch_k={fetch_k_candidates}):")
for doc in mmr_results_diverse:
print(f" - {doc.metadata['name']}: {doc.page_content}")
print("\n")
# Example 3: Prioritizing Relevance
mmr_results_relevant = vector_store.max_marginal_relevance_search(
user_query, k=k_results, fetch_k=fetch_k_candidates, lambda_mult=0.9
)
print(f"MMR Results (lambda=0.9, k={k_results}, fetch_k={fetch_k_candidates}):")
for doc in mmr_results_relevant:
print(f" - {doc.metadata['name']}: {doc.page_content}")
Valori lambda_mult diversi producono insiemi di risultati diversi, bilanciando la similarità con "pomodori rossi" con l'unicità dei prodotti mostrati.
Utilizzare MMR con un recuperatore
Per utilizzare la ricerca MMR, puoi anche configurare un recuperatore LangChain. Il recuperatore fornisce un'interfaccia uniforme che ti consente di integrare senza problemi metodi di ricerca specializzati, come MMR, direttamente nelle tue catene e applicazioni.
retriever = vector_store.as_retriever(
search_type="mmr",
search_kwargs={
"k": 3,
"fetch_k": 10,
"lambda_mult": 0.3,
}
)
retrieved_docs = retriever.invoke(user_query)
print(f"\nRetriever MMR Results for '{user_query}':")
for doc in retrieved_docs:
print(f" - {doc.metadata['name']}: {doc.page_content}")
Passaggi successivi
- Esplora altri tipi di ricerca e opzioni di filtro disponibili in
BigtableVectorStore. - Scopri di più su LangChain in Bigtable.