在 Bigtable 上使用 LangChain 執行最大邊際關聯性搜尋
本頁面說明如何使用 BigtableVectorStore 整合功能,在 Bigtable 和 Vertex AI 中執行 Maximal Marginal Relevance (MMR) 搜尋,並將 Vertex AI 做為嵌入服務。
MMR 是資訊檢索中使用的搜尋技術,可傳回一組與查詢相關且多樣化的結果,避免重複。標準向量相似度搜尋 (例如使用 k-最鄰近方法進行的搜尋) 可能會傳回許多相似項目,但 MMR 會提供更多樣化的熱門結果。如果向量儲存空間中可能出現重疊或重複的資料,這項功能就非常實用。
舉例來說,在電子商務應用程式中,如果使用者搜尋「紅番茄」,向量相似度搜尋可能會傳回多個相同類型的新鮮紅番茄商品。MMR 搜尋會盡量傳回更多樣的結果,例如「新鮮紅番茄」、「罐頭紅番茄丁」、「有機櫻桃番茄」,甚至可能包括「番茄沙拉食譜」。
閱讀本頁面之前,請務必瞭解下列概念:
- 關聯性:文件與查詢的相符程度。
- 多樣性:衡量文件與結果集中已選取文件的差異程度。
- Lambda 乘數:介於 0 和 1 之間的係數,可平衡相關性和多樣性。值越接近 1,系統越會優先顯示相關性高的結果;值越接近 0,系統越會優先顯示多樣性高的結果。
LangChain 的 BigtableVectorStore 類別會將 MMR 實作為重新排序演算法。這項演算法會先擷取與查詢相關的一組較大的文件,然後以兼顧相關性和多元性的方式,選取符合查詢的文件。
事前準備
本指南使用 Vertex AI 做為嵌入服務。確認您已在專案中啟用 Vertex AI API。
必要的角色
如要搭配 LangChain 使用 Bigtable,您需要下列 IAM 角色:
- Bigtable 執行個體的 Bigtable 使用者 (
roles/bigtable.user)。 - 如果您要初始化表格,還需要 Bigtable 系統管理員 (
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 資料表 ID,建立商店執行個體。
# 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}")