Effectuer une recherche de pertinence marginale maximale avec LangChain sur Bigtable
Cette page explique comment effectuer une recherche de pertinence marginale maximale (MMR) à l'aide de l'intégration BigtableVectorStore pour LangChain dans Bigtable et de Gemini Enterprise Agent Platform comme service d'embedding.
La MMR est une technique de recherche utilisée dans la recherche d'informations pour renvoyer un ensemble de résultats à la fois pertinents pour la requête et diversifiés, en évitant la redondance. Alors que la recherche de similarité vectorielle standard (par exemple, une recherche qui utilise la méthode des k-plus proches voisins) peut renvoyer de nombreux éléments similaires, la MMR fournit un ensemble plus varié de résultats principaux. Cela est utile lorsque vous avez des données potentiellement chevauchantes ou en double dans votre magasin de vecteurs.
Par exemple, dans une application de commerce électronique, si un utilisateur recherche "tomates rouges", une recherche de similarité vectorielle peut renvoyer plusieurs fiches du même type de tomates rouges fraîches. Une recherche MMR vise à renvoyer un ensemble plus diversifié, tel que "tomates rouges fraîches", "tomates rouges en dés en conserve", "tomates cerises bio" et peut-être même "recette de salade de tomates".
Avant de lire cette page, il est important de connaître les concepts suivants :
- Pertinence : mesure de la correspondance entre le document et la requête.
- Diversité : mesure de la différence entre un document et les documents déjà sélectionnés dans l'ensemble de résultats.
- Multiplicateur lambda : facteur compris entre 0 et 1 qui équilibre la pertinence et la diversité. Une valeur plus proche de 1 donne la priorité à la pertinence, tandis qu'une valeur plus proche de 0 donne la priorité à la diversité.
La classe BigtableVectorStore pour LangChain
implémente la MMR en tant qu'algorithme de reclassement.
Cet algorithme récupère d'abord un ensemble plus important de documents pertinents pour la requête, puis sélectionne les documents qui correspondent à la requête d'une manière équilibrée pour la pertinence et la diversité.
Avant de commencer
Ce guide utilise Agent Platform comme service d'embedding. Assurez-vous que l'API Agent Platform est activée dans votre projet.
Rôles requis
Pour utiliser Bigtable avec LangChain, vous avez besoin des rôles IAM suivants :
- Utilisateur Bigtable
(
roles/bigtable.user) sur l'instance Bigtable. - Si vous initialisez la table, vous avez également besoin du rôle Administrateur
Bigtable
(
roles/bigtable.admin).
Configurer votre environnement
Installez les packages LangChain requis :
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexaiAuthentifiez-vous auprès de Google Cloud avec votre compte utilisateur.
gcloud auth application-default loginDéfinissez l'ID de votre projet, l'ID de votre instance Bigtable et l'ID de votre table :
PROJECT_ID = "your-project-id" INSTANCE_ID = "your-instance-id" TABLE_ID = "your-table-id"
Initialiser le service d'embedding et créer une table
Pour utiliser le magasin de vecteurs Bigtable, vous devez fournir des embeddings générés par un modèle d'IA. Dans ce guide, vous allez utiliser le modèle d'embedding textuel
gemini-embedding-001 sur
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
Instancier BigtableVectorStore
Créez l'instance de magasin en transmettant le service d'embedding et les identifiants de table 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.")
Remplir le magasin de vecteurs
Dans ce guide, nous utilisons un exemple de scénario d'un service d'e-commerce fictif dans lequel les utilisateurs souhaitent rechercher des articles liés aux tomates rouges. Nous devons d'abord ajouter des produits et des descriptions liés aux tomates au magasin de vecteurs.
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.")
Effectuer une recherche MMR
Le magasin contient de nombreux produits liés aux tomates, mais les utilisateurs ne souhaitent rechercher que les offres associées aux "tomates rouges". Pour obtenir un ensemble de résultats diversifié, utilisez la technique MMR pour effectuer la recherche.
La méthode clé à utiliser est la
max_marginal_relevance_search
qui accepte les arguments suivants :
query(str) : texte de recherche.k(int) : nombre final de résultats de recherche.fetch_k(int) : nombre initial de produits similaires à récupérer avant d'appliquer l'algorithme MMR. Nous vous recommandons que ce nombre soit supérieur au paramètrek.lambda_mult(float) : paramètre de réglage de la diversité. Utilisez0.0pour une diversité maximale et1.0pour une pertinence maximale.
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}")
Différentes valeurs lambda_mult génèrent différents ensembles de résultats, en équilibrant la similarité avec "tomates rouges" et l'unicité des produits affichés.
Utiliser la MMR avec un récupérateur
Pour utiliser la recherche MMR, vous pouvez également configurer un récupérateur LangChain. Le récupérateur fournit une interface uniforme qui vous permet d'intégrer de manière transparente des méthodes de recherche spécialisées, telles que la MMR, directement dans vos chaînes et applications.
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}")
Étape suivante
- Découvrez d'autres types de recherche et options de filtrage disponibles dans
BigtableVectorStore. - En savoir plus sur LangChain dans Bigtable.