Realize uma pesquisa de relevância marginal máxima com o LangChain no Bigtable
Esta página descreve como realizar uma pesquisa de relevância marginal máxima (MMR)
usando a integração BigtableVectorStore para o LangChain no
Bigtable e na Vertex AI como o serviço de incorporação.
A MMR é uma técnica de pesquisa usada na obtenção de informações para devolver um conjunto de resultados relevantes para a consulta e diversificados, evitando a redundância. Embora a pesquisa de similaridade vetorial padrão (por exemplo, uma pesquisa que usa o método dos k-vizinhos mais próximos) possa devolver muitos itens semelhantes, a MMR oferece um conjunto mais variado de principais resultados. Isto é útil quando tem dados potencialmente sobrepostos ou duplicados na sua base de dados vetorial.
Por exemplo, numa aplicação de comércio eletrónico, se um utilizador pesquisar "tomates vermelhos", uma pesquisa de semelhança vetorial pode devolver várias fichas do mesmo tipo de tomate vermelho fresco. Uma pesquisa de MMR tem como objetivo devolver um conjunto mais diversificado, como "tomates vermelhos frescos", "tomates vermelhos picados em lata", "tomates cereja biológicos" e, talvez, até "receita de salada de tomate".
Antes de ler esta página, é importante que conheça os seguintes conceitos:
- Relevância: uma medida da correspondência entre o documento e a consulta.
- Diversidade: uma medida da diferença de um documento em relação aos documentos já selecionados no conjunto de resultados.
- Multiplicador lambda: um fator entre 0 e 1 que equilibra a relevância e a diversidade. Um valor mais próximo de 1 dá prioridade à relevância, enquanto um valor mais próximo de 0 dá prioridade à diversidade.
A classe BigtableVectorStore para o LangChain
implementa o MMR como um algoritmo de reclassificação.
Este algoritmo obtém primeiro um conjunto maior de documentos relevantes para a consulta e seleciona os documentos que correspondem à consulta de uma forma equilibrada para a relevância e a diversidade.
Antes de começar
Este guia usa o Vertex AI como o serviço de incorporação. Certifique-se de que tem a API Vertex AI ativada no seu projeto.
Funções necessárias
Para usar o Bigtable com o LangChain, precisa das seguintes funções do IAM:
- Utilizador do Bigtable
(
roles/bigtable.user) na instância do Bigtable. - Se estiver a inicializar a tabela, também precisa da função Bigtable
Administrator
(
roles/bigtable.admin).
Configure o seu ambiente
Instale os pacotes LangChain necessários:
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexaiFaça a autenticação no Google Cloud com a sua conta de utilizador.
gcloud auth application-default loginDefina o ID do projeto, o ID da instância do Bigtable e o ID da tabela:
PROJECT_ID = "your-project-id" INSTANCE_ID = "your-instance-id" TABLE_ID = "your-table-id"
Inicialize o serviço de incorporação e crie uma tabela
Para usar o arquivo vetorial do Bigtable, tem de fornecer incorporações geradas por um modelo de IA. Neste guia, vai usar o modelo de incorporação de texto gemini-embedding-004 noVertex 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
Instancie BigtableVectorStore
Crie a instância de armazenamento transmitindo o serviço de incorporação e os identificadores da tabela do 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.")
Preencha o banco de dados vetorial
Neste guia, usamos um cenário de exemplo de um serviço de comércio eletrónico fictício onde os utilizadores querem pesquisar itens relacionados com tomates vermelhos. Primeiro, temos de adicionar alguns produtos e descrições relacionados com tomate à base de dados vetorial.
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.")
Realizar pesquisa de MMR
A loja contém muitos produtos relacionados com tomate, mas os utilizadores querem pesquisar ofertas associadas apenas a "tomates vermelhos". Para obter um conjunto diversificado de resultados, use a técnica de MMR para realizar a pesquisa.
O método de chave a usar é o
max_marginal_relevance_search
que usa os seguintes argumentos:
query(str): o texto de pesquisa.k(int): o número final de resultados da pesquisa.fetch_k(int): o número inicial de produtos semelhantes a obter antes de aplicar o algoritmo MMR. Recomendamos que este número seja superior ao parâmetrok.lambda_mult(float): o parâmetro de ajuste da diversidade. Use0.0para a máxima diversidade e1.0para a máxima relevância.
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}")
Os diferentes valores de lambda_mult geram diferentes conjuntos de resultados, equilibrando a semelhança com "tomates vermelhos" com a singularidade dos produtos apresentados.
Usar o MMR com um recuperador
Para usar a pesquisa MMR, também pode configurar um recuperador LangChain. O motor de obtenção fornece uma interface uniforme que lhe permite integrar perfeitamente métodos de pesquisa especializados, como MMR, diretamente nas suas cadeias e aplicações.
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}")
O que se segue?
- Explore outros tipos de pesquisa e opções de filtragem disponíveis em
BigtableVectorStore. - Saiba mais sobre o LangChain no Bigtable.