在 Bigtable 上使用 LangChain 执行最大边际相关性搜索
本页面介绍了如何使用 BigtableVectorStore 集成在 Bigtable 和 Vertex AI 中执行最大边际相关性 (MMR) 搜索,并将 Vertex AI 用作嵌入服务。
MMR 是一种信息检索中使用的搜索技术,用于返回一组与查询相关且多样化的结果,避免冗余。虽然标准向量相似度搜索(例如,使用 k-最近邻方法的搜索)可能会返回许多相似的项,但 MMR 会提供一组更多样化的热门结果。当向量存储区中可能存在重叠或重复数据时,此功能非常有用。
例如,在电子商务应用中,如果用户搜索“红番茄”,则向量相似性搜索可能会返回多个相同类型的新鲜红番茄商品详情。MMR 搜索旨在返回更多样化的结果,例如“新鲜的红番茄”“罐装红番茄丁”“有机樱桃番茄”,甚至可能包括“番茄沙拉食谱”。
在阅读本页面内容之前,请务必了解以下概念:
- 相关性:衡量文档与查询的匹配程度。
- 多样性:衡量文档与结果集中已选择的文档之间的差异程度。
- Lambda 乘数:介于 0 到 1 之间的一个系数,用于平衡相关性和多样性。值越接近 1,相关性就越重要;值越接近 0,多样性就越重要。
LangChain 的 BigtableVectorStore 类将 MMR 实现为重新排名算法。此算法首先会提取与查询相关的一组较大规模的文档,然后以平衡相关性和多样性的方式选择与查询匹配的文档。
准备工作
本指南使用 Vertex AI 作为嵌入服务。确保已在项目中启用了 Vertex AI API。
所需的角色
如需将 Bigtable 与 LangChain 搭配使用,您需要具备以下 IAM 角色:
- Bigtable 实例上的 Bigtable User (
roles/bigtable.user)。 - 如果您要初始化表,还需要 Bigtable Administrator (
roles/bigtable.admin) 角色。
设置环境
安装所需的 LangChain 软件包:
pip install --upgrade --quiet langchain-google-bigtable langchain-google-vertexai使用您的用户账号向 Google Cloud 进行身份验证。
gcloud auth application-default login设置项目 ID、Bigtable 实例 ID 和表 ID:
PROJECT_ID = "your-project-id" INSTANCE_ID = "your-instance-id" TABLE_ID = "your-table-id"
初始化嵌入服务并创建表
如需使用 Bigtable 向量存储区,您需要提供由 AI 模型生成的嵌入。在本指南中,您将使用 Vertex AI 上的文本嵌入 gemini-embedding-004 模型。
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
实例化 BigtableVectorStore
通过传递嵌入服务和 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.")
填充向量存储区
在本指南中,我们将使用一个虚构的电子商务服务示例场景,其中用户想要搜索与红番茄相关的商品。首先,我们需要向向量存储区添加一些与番茄相关的产品和说明。
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.")
执行 MMR 搜索
该商店包含许多与番茄相关的商品,但用户只想搜索与“红番茄”相关的商品。如需获得多样化的结果,请使用 MMR 技术执行搜索。
要使用的关键方法是 max_marginal_relevance_search,该方法接受以下实参:
query(str):搜索文本。k(整数):最终搜索结果数。fetch_k(int):在应用 MMR 算法之前要检索的初始类似商品数量。建议此数字大于k参数。lambda_mult(浮点):多样性调整形参。使用0.0可实现最大程度的多样性,使用1.0可实现最大程度的相关性。
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}")
不同的 lambda_mult 值会产生不同的结果集,从而在“红番茄”的相似性与所显示商品的独特性之间取得平衡。
将 MMR 与检索器搭配使用
如需使用 MMR 搜索,您还可以配置 LangChain 检索器。检索器提供了一个统一的接口,可让您将 MMR 等专业搜索方法直接无缝集成到链和应用中。
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}")
后续步骤
- 探索
BigtableVectorStore中提供的其他搜索类型和过滤选项。 - 详细了解 Bigtable 中的 LangChain。