在 Bigtable 上使用 LangChain 执行最大边际相关性搜索
本页面介绍了如何在 Bigtable 中使用 BigtableVectorStore 集成来执行最大边际相关性 (MMR) 搜索,并将 Gemini Enterprise Agent Platform 用作嵌入服务。
MMR 是一种信息检索中使用的搜索技术,用于返回一组与查询相关且多样的结果,避免冗余。虽然标准向量相似性搜索(例如,使用 k- 最近邻方法的搜索)可能会返回许多相似的项,但 MMR 会提供更多样化的热门结果。当向量存储区中可能存在重叠或重复数据时,此功能非常有用。
例如,在电子商务应用中,如果用户搜索“红番茄”,则向量相似性搜索可能会返回多个相同类型的新鲜红番茄商品信息。MMR 搜索的目标是返回更多样化的结果,例如“新鲜红番茄”“罐装红番茄丁”“有机樱桃番茄”,甚至可能是“番茄沙拉食谱”。
在阅读本页面之前,请务必了解以下概念:
- 相关性:衡量文档与查询的匹配程度。
- 多样性:衡量文档与结果集中已选择的文档的差异程度。
- Lambda 乘数:介于 0 和 1 之间的因子,用于 平衡相关性和多样性。值越接近 1,相关性优先级越高;值越接近 0,多样性优先级越高。
LangChain 的 BigtableVectorStore 类 将 MMR 实现为重排序算法。此算法首先提取与查询相关的一组较大文档,然后选择与查询匹配的文档,并以平衡相关性和多样性的方式进行选择。
准备工作
本指南使用 Agent Platform 作为嵌入服务。确保已在项目中启用 Agent Platform 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 模型生成的嵌入。在本指南中,您将使用 Agent Platform 上的文本嵌入
gemini-embedding-001 模型。
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
实例化 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(int):搜索结果的最终数量。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}")