Bigtable에서 LangChain을 사용하여 최대 한계 관련성 검색 실행
이 페이지에서는 Bigtable 및 Vertex AI를 삽입 서비스로 사용하여 LangChain용 BigtableVectorStore 통합을 통해 최대 주변 관련성 (MMR) 검색을 실행하는 방법을 설명합니다.
MMR은 정보 검색에서 중복을 피하면서 쿼리와 관련성이 높고 다양한 결과 집합을 반환하는 데 사용되는 검색 기법입니다. 표준 벡터 유사성 검색 (예: k-최근접 이웃 방법을 사용하는 검색)은 유사한 항목을 많이 반환할 수 있지만 MMR은 더 다양한 상위 결과를 제공합니다. 이는 벡터 스토어에 중복되거나 중복될 수 있는 데이터가 있는 경우에 유용합니다.
예를 들어 전자상거래 애플리케이션에서 사용자가 '빨간 토마토'를 검색하면 벡터 유사성 검색에서 동일한 유형의 신선한 빨간 토마토 목록을 여러 개 반환할 수 있습니다. MMR 검색은 '신선한 빨간 토마토', '통조림으로 된 잘게 썬 빨간 토마토', '유기농 방울토마토', '토마토 샐러드 레시피'와 같이 더 다양한 결과를 반환하는 것을 목표로 합니다.
이 페이지를 읽기 전에 다음 개념을 알아야 합니다.
- 관련성: 문서가 쿼리와 얼마나 일치하는지를 나타내는 측정값입니다.
- 다양성: 문서가 결과 세트에서 이미 선택된 문서와 얼마나 다른지를 나타내는 측정값입니다.
- 람다 승수: 관련성과 다양성의 균형을 맞추는 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 테이블 식별자를 전달하여 스토어 인스턴스를 만듭니다.
# 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(float): 다양성 조정 매개변수입니다. 다양성을 극대화하려면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}")