Realiza una búsqueda de relevancia marginal máxima con LangChain en Bigtable
En esta página, se describe cómo realizar una búsqueda de relevancia marginal máxima (MMR) con la integración de BigtableVectorStore para LangChain en Bigtable y Vertex AI como el servicio de incorporación.
MMR es una técnica de búsqueda que se usa en la recuperación de información para devolver un conjunto de resultados que sean pertinentes para la búsqueda y diversos, lo que evita la redundancia. Si bien la búsqueda de similitud de vectores estándar (por ejemplo, una búsqueda que usa el método de k vecinos más cercanos) puede devolver muchos elementos similares, la MMR proporciona un conjunto más variado de resultados principales. Esto es útil cuando tienes datos potencialmente superpuestos o duplicados en tu almacén de vectores.
Por ejemplo, en una aplicación de comercio electrónico, si un usuario busca "tomates rojos", una búsqueda de similitud de vectores podría devolver varios anuncios del mismo tipo de tomate rojo fresco. Una búsqueda de MMR tendría como objetivo devolver un conjunto más diverso, como "tomates rojos frescos", "tomates rojos enlatados en cubos", "tomates cherry orgánicos" y, tal vez, incluso "receta de ensalada de tomate".
Antes de leer esta página, es importante que conozcas los siguientes conceptos:
- Relevancia: Es una medida de qué tan bien coincide el documento con la búsqueda.
- Diversidad: Es una medida de qué tan diferente es un documento de los documentos ya seleccionados en el conjunto de resultados.
- Multiplicador de lambda: Es un factor entre 0 y 1 que equilibra la relevancia y la diversidad. Un valor más cercano a 1 prioriza la relevancia, mientras que un valor más cercano a 0 prioriza la diversidad.
La clase BigtableVectorStore para LangChain implementa MMR como un algoritmo de reordenamiento.
Primero, este algoritmo recupera un conjunto más grande de documentos relevantes para la búsqueda y, luego, selecciona los documentos que coinciden con la búsqueda de una manera equilibrada en cuanto a relevancia y diversidad.
Antes de comenzar
En esta guía, se usa Vertex AI como servicio de incorporación. Asegúrate de tener habilitada la API de Vertex AI en tu proyecto.
Roles obligatorios
Para usar Bigtable con LangChain, necesitas los siguientes roles de IAM:
- Usuario de Bigtable (
roles/bigtable.user) en la instancia de Bigtable. - Si inicializas la tabla, también necesitas el rol de administrador de Bigtable (
roles/bigtable.admin).
Configura tu entorno
Instala los paquetes de LangChain necesarios:
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexaiAutentícate en Google Cloud con tu cuenta de usuario.
gcloud auth application-default loginEstablece tu ID del proyecto, el ID de la instancia de Bigtable y el ID de la tabla:
PROJECT_ID = "your-project-id" INSTANCE_ID = "your-instance-id" TABLE_ID = "your-table-id"
Inicializa el servicio de embeddings y crea una tabla
Para usar el almacén de vectores de Bigtable, debes proporcionar embeddings generados por un modelo de IA. En esta guía, usarás el modelo de incorporación de texto gemini-embedding-004 en Vertex AI.
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-004", 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
Instancia BigtableVectorStore
Crea la instancia de la tienda pasando el servicio de incorporación y los identificadores de la tabla de 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.")
Propaga el almacén de vectores
En esta guía, usamos un ejemplo de un servicio de comercio electrónico ficticio en el que los usuarios quieren buscar elementos relacionados con tomates rojos. Primero, debemos agregar algunos productos y descripciones relacionados con el tomate a la tienda de vectores.
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.")
Realiza una búsqueda de MMR
La tienda contiene muchos productos relacionados con el tomate, pero los usuarios solo quieren buscar ofertas asociadas con "tomates rojos". Para obtener un conjunto diverso de resultados, usa la técnica de MMR para realizar la búsqueda.
El método clave que se debe usar es max_marginal_relevance_search, que toma los siguientes argumentos:
query(cadena): Es el texto de búsqueda.k(int): Es la cantidad final de resultados de la búsqueda.fetch_k(int): Es la cantidad inicial de productos similares que se recuperarán antes de aplicar el algoritmo de MMR. Recomendamos que este número sea mayor que el parámetrok.lambda_mult(número de punto flotante): Es el parámetro de ajuste de la diversidad. Usa0.0para obtener la máxima diversidad y1.0para obtener la máxima relevancia.
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}")
Los diferentes valores de lambda_mult producen diferentes conjuntos de resultados, lo que equilibra la similitud con "tomates rojos" y la singularidad de los productos que se muestran.
Cómo usar MMR con un recuperador
Para usar la búsqueda de MMR, también puedes configurar un recuperador de LangChain. El recuperador proporciona una interfaz uniforme que te permite integrar sin problemas métodos de búsqueda especializados, como MMR, directamente en tus cadenas y aplicaciones.
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}")
¿Qué sigue?
- Explora otros tipos de búsqueda y opciones de filtrado disponibles en
BigtableVectorStore. - Obtén más información sobre LangChain en Bigtable.