Realizar pesquisa de relevância marginal máxima com LangChain no Bigtable
Nesta página, descrevemos como realizar uma pesquisa de relevância marginal máxima (MMR)
usando a integração BigtableVectorStore para LangChain no
Bigtable e na Vertex AI como o serviço de incorporação.
O MMR é uma técnica de pesquisa usada na recuperação de informações para retornar um conjunto de resultados relevantes e diversos para a consulta, evitando redundância. Enquanto a pesquisa padrão de similaridade vetorial (por exemplo, uma pesquisa que usa o método dos k-vizinhos mais próximos) pode retornar muitos itens semelhantes, o MMR oferece um conjunto mais variado de resultados principais. Isso é útil quando você tem dados potencialmente sobrepostos ou duplicados no seu repositório de vetores.
Por exemplo, em um aplicativo de e-commerce, se um usuário pesquisar "tomates vermelhos", uma pesquisa de similaridade de vetor poderá retornar várias listagens do mesmo tipo de tomate vermelho fresco. Uma pesquisa de MMR retornaria um conjunto mais diversificado, como "tomates vermelhos frescos", "tomates vermelhos picados em lata", "tomates cereja orgânicos" e talvez até "receita de salada de tomate".
Antes de ler esta página, é importante conhecer os seguintes conceitos:
- Relevância: uma medida de quão bem o documento corresponde à consulta.
- Diversidade: uma medida de como um documento é diferente dos documentos já selecionados no conjunto de resultados.
- Multiplicador lambda: um fator entre 0 e 1 que equilibra relevância e diversidade. Um valor mais próximo de 1 prioriza a relevância, enquanto um valor mais próximo de 0 prioriza a diversidade.
A classe BigtableVectorStore para LangChain
implementa o MMR como um algoritmo de reclassificação.
Primeiro, esse algoritmo busca um conjunto maior de documentos relevantes para a consulta e seleciona aqueles que correspondem à consulta de maneira equilibrada para relevância e diversidade.
Antes de começar
Este guia usa a Vertex AI como o serviço de incorporação. Verifique se a API Vertex AI está ativada no seu projeto.
Funções exigidas
Para usar o Bigtable com o LangChain, você precisa dos seguintes papéis do IAM:
- Usuário do Bigtable
(
roles/bigtable.user) na instância do Bigtable. - Se você estiver inicializando a tabela, também precisará do papel de Administrador do Bigtable (
roles/bigtable.admin).
Configurar o ambiente
Instale os pacotes LangChain necessários:
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexaiAutentique-se no Google Cloud com sua conta de usuário.
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"
Inicializar o serviço de embedding e criar uma tabela
Para usar o repositório de vetores do Bigtable, você precisa fornecer embeddings
gerados por um modelo de IA. Neste guia, você vai usar o modelo de embedding de texto
gemini-embedding-004 na
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
Instanciar BigtableVectorStore
Crie a instância de repositório transmitindo o serviço de incorporação e os identificadores de 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.")
Preencher o repositório de vetores
Neste guia, usamos um cenário de exemplo de um serviço de e-commerce fictício em que os usuários querem pesquisar itens relacionados a tomates vermelhos. Primeiro, precisamos adicionar alguns produtos e descrições relacionados a tomate ao banco de dados de vetores.
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.")
Fazer uma pesquisa de MMR
A loja tem muitos produtos relacionados a tomate, mas os usuários querem pesquisar apenas ofertas associadas a "tomates vermelhos". Para ter um conjunto diversificado de resultados, use a técnica de MMR para fazer a pesquisa.
O método principal a ser usado é o
max_marginal_relevance_search
que recebe os seguintes argumentos:
query(str): o texto da pesquisa.k(int): o número final de resultados da pesquisa.fetch_k(int): o número inicial de produtos semelhantes a serem recuperados antes de aplicar o algoritmo MMR. Recomendamos que esse número seja maior que o parâmetrok.lambda_mult(float): o parâmetro de ajuste de diversidade. Use0.0para diversidade máxima e1.0para relevância máxima.
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}")
Valores de lambda_mult diferentes geram conjuntos de resultados diferentes, equilibrando a semelhança com "tomates vermelhos" e a exclusividade dos produtos mostrados.
Como usar a MMR com um extrator
Para usar a pesquisa de MMR, também é possível configurar um recuperador do LangChain. O extrator fornece uma interface uniforme que permite integrar perfeitamente métodos de pesquisa especializados, como MMR, diretamente nas suas cadeias e aplicativos.
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}")
A seguir
- Conheça outros tipos de pesquisa e opções de filtragem disponíveis no
BigtableVectorStore. - Saiba mais sobre o LangChain no Bigtable.