Couchbase
Couchbase 是一個獲獎的 NoSQL 分散式雲端資料庫,為您的所有雲端、行動、人工智慧和邊緣運算應用程式提供無與倫比的多功能性、效能、可擴展性和財務價值。 Couchbase 透過為開發人員提供程式碼輔助和為其應用程式提供向量搜尋來擁抱人工智慧。
向量搜尋是 Couchbase 中 全文檢索服務(Search Service)的一部分。
本教學說明如何在 Couchbase 中使用向量搜尋。您可以使用 Couchbase Capella 或您自行管理的 Couchbase Server。
設定
若要存取 CouchbaseVectorStore
,您首先需要安裝 langchain-couchbase
合作夥伴套件
pip install -qU langchain-couchbase
憑證
前往 Couchbase 網站 並建立新的連線,請務必儲存您的資料庫使用者名稱和密碼
import getpass
COUCHBASE_CONNECTION_STRING = getpass.getpass(
"Enter the connection string for the Couchbase cluster: "
)
DB_USERNAME = getpass.getpass("Enter the username for the Couchbase cluster: ")
DB_PASSWORD = getpass.getpass("Enter the password for the Couchbase cluster: ")
如果您想要獲得一流的模型呼叫自動追蹤功能,您也可以取消註解下方內容來設定您的 LangSmith API 金鑰
# os.environ["LANGSMITH_TRACING"] = "true"
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass()
初始化
在實例化之前,我們需要建立連線。
建立 Couchbase 連線物件
我們首先建立與 Couchbase 叢集的連線,然後將叢集物件傳遞給向量資料庫。
在此,我們使用上述的使用者名稱和密碼進行連線。您也可以使用任何其他支援的方式連線到您的叢集。
有關連線到 Couchbase 叢集的更多資訊,請查看 文件。
from datetime import timedelta
from couchbase.auth import PasswordAuthenticator
from couchbase.cluster import Cluster
from couchbase.options import ClusterOptions
auth = PasswordAuthenticator(DB_USERNAME, DB_PASSWORD)
options = ClusterOptions(auth)
cluster = Cluster(COUCHBASE_CONNECTION_STRING, options)
# Wait until the cluster is ready for use.
cluster.wait_until_ready(timedelta(seconds=5))
我們現在將設定 Couchbase 叢集中我們要用於向量搜尋的 bucket、scope 和 collection 名稱。
在此範例中,我們使用預設的 scope 和 collection。
BUCKET_NAME = "langchain_bucket"
SCOPE_NAME = "_default"
COLLECTION_NAME = "default"
SEARCH_INDEX_NAME = "langchain-test-index"
有關如何建立支援向量欄位的搜尋索引的詳細資訊,請參閱文件。
簡單實例化
下面,我們使用叢集資訊和搜尋索引名稱建立向量資料庫物件。
pip install -qU langchain-openai
import getpass
import os
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
from langchain_couchbase.vectorstores import CouchbaseVectorStore
vector_store = CouchbaseVectorStore(
cluster=cluster,
bucket_name=BUCKET_NAME,
scope_name=SCOPE_NAME,
collection_name=COLLECTION_NAME,
embedding=embeddings,
index_name=SEARCH_INDEX_NAME,
)
指定文字和嵌入欄位
您可以選擇性地使用 text_key
和 embedding_key
欄位來指定文件的文字和嵌入欄位。
vector_store_specific = CouchbaseVectorStore(
cluster=cluster,
bucket_name=BUCKET_NAME,
scope_name=SCOPE_NAME,
collection_name=COLLECTION_NAME,
embedding=embeddings,
index_name=SEARCH_INDEX_NAME,
text_key="text",
embedding_key="embedding",
)
管理向量資料庫
建立向量資料庫後,我們可以透過新增和刪除不同的項目來與其互動。
將項目新增至向量資料庫
我們可以使用 add_documents
函數將項目新增至我們的向量資料庫。
from uuid import uuid4
from langchain_core.documents import Document
document_1 = Document(
page_content="I had chocalate chip pancakes and scrambled eggs for breakfast this morning.",
metadata={"source": "tweet"},
)
document_2 = Document(
page_content="The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees.",
metadata={"source": "news"},
)
document_3 = Document(
page_content="Building an exciting new project with LangChain - come check it out!",
metadata={"source": "tweet"},
)
document_4 = Document(
page_content="Robbers broke into the city bank and stole $1 million in cash.",
metadata={"source": "news"},
)
document_5 = Document(
page_content="Wow! That was an amazing movie. I can't wait to see it again.",
metadata={"source": "tweet"},
)
document_6 = Document(
page_content="Is the new iPhone worth the price? Read this review to find out.",
metadata={"source": "website"},
)
document_7 = Document(
page_content="The top 10 soccer players in the world right now.",
metadata={"source": "website"},
)
document_8 = Document(
page_content="LangGraph is the best framework for building stateful, agentic applications!",
metadata={"source": "tweet"},
)
document_9 = Document(
page_content="The stock market is down 500 points today due to fears of a recession.",
metadata={"source": "news"},
)
document_10 = Document(
page_content="I have a bad feeling I am going to get deleted :(",
metadata={"source": "tweet"},
)
documents = [
document_1,
document_2,
document_3,
document_4,
document_5,
document_6,
document_7,
document_8,
document_9,
document_10,
]
uuids = [str(uuid4()) for _ in range(len(documents))]
vector_store.add_documents(documents=documents, ids=uuids)
從向量資料庫刪除項目
vector_store.delete(ids=[uuids[-1]])
查詢向量資料庫
建立向量資料庫並新增相關文件後,您很可能會希望在執行您的鏈或代理程式期間查詢它。
直接查詢
相似度搜尋
執行簡單的相似度搜尋可以如下進行
results = vector_store.similarity_search(
"LangChain provides abstractions to make working with LLMs easy",
k=2,
)
for res in results:
print(f"* {res.page_content} [{res.metadata}]")
帶分數的相似度搜尋
您也可以透過呼叫 similarity_search_with_score
方法來取得結果的分數。
results = vector_store.similarity_search_with_score("Will it be hot tomorrow?", k=1)
for res, score in results:
print(f"* [SIM={score:3f}] {res.page_content} [{res.metadata}]")
指定要傳回的欄位
您可以使用搜尋中的 fields
參數來指定要從文件中傳回的欄位。這些欄位會作為傳回的 Document 中 metadata
物件的一部分傳回。您可以取得儲存在搜尋索引中的任何欄位。文件的 text_key
會作為文件的 page_content
的一部分傳回。
如果您未指定要取得的任何欄位,則會傳回索引中儲存的所有欄位。
如果您想要取得 metadata
中的其中一個欄位,您需要使用 .
來指定它。
例如,若要取得 metadata
中的 source
欄位,您需要指定 metadata.source
。
query = "What did I eat for breakfast today?"
results = vector_store.similarity_search(query, fields=["metadata.source"])
print(results[0])
混合查詢
Couchbase 允許您透過將向量搜尋結果與對文件的非向量欄位(如 metadata
物件)的搜尋結合來執行混合搜尋。
結果將基於向量搜尋和搜尋服務支援的搜尋的結果組合。每個組件搜尋的分數會加總以獲得結果的總分。
若要執行混合搜尋,有一個可選參數 search_options
可以傳遞給所有相似度搜尋。
search_options
的不同搜尋/查詢可能性可以在 這裡 找到。
為混合搜尋建立多樣化的元數據
為了模擬混合搜尋,讓我們從現有文件建立一些隨機元數據。我們統一在元數據中新增三個欄位,date
介於 2010 年到 2020 年之間,rating
介於 1 到 5 之間,作者設定為 John Doe 或 Jane Doe。
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
loader = TextLoader("../../how_to/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# Adding metadata to documents
for i, doc in enumerate(docs):
doc.metadata["date"] = f"{range(2010, 2020)[i % 10]}-01-01"
doc.metadata["rating"] = range(1, 6)[i % 5]
doc.metadata["author"] = ["John Doe", "Jane Doe"][i % 2]
vector_store.add_documents(docs)
query = "What did the president say about Ketanji Brown Jackson"
results = vector_store.similarity_search(query)
print(results[0].metadata)
依精確值查詢
我們可以在 metadata
物件中搜尋文字欄位的精確匹配,例如作者。
query = "What did the president say about Ketanji Brown Jackson"
results = vector_store.similarity_search(
query,
search_options={"query": {"field": "metadata.author", "match": "John Doe"}},
fields=["metadata.author"],
)
print(results[0])
依部分匹配查詢
我們可以透過為搜尋指定模糊度來搜尋部分匹配。當您想要搜尋搜尋查詢的輕微變化或拼字錯誤時,這非常有用。
在此,「Jae」與「Jane」接近(模糊度為 1)。
query = "What did the president say about Ketanji Brown Jackson"
results = vector_store.similarity_search(
query,
search_options={
"query": {"field": "metadata.author", "match": "Jae", "fuzziness": 1}
},
fields=["metadata.author"],
)
print(results[0])
依日期範圍查詢
我們可以在日期欄位(如 metadata.date
)上搜尋日期範圍查詢內的文件。
query = "Any mention about independence?"
results = vector_store.similarity_search(
query,
search_options={
"query": {
"start": "2016-12-31",
"end": "2017-01-02",
"inclusive_start": True,
"inclusive_end": False,
"field": "metadata.date",
}
},
)
print(results[0])
依數值範圍查詢
我們可以在數值欄位(如 metadata.rating
)的範圍內搜尋文件。
query = "Any mention about independence?"
results = vector_store.similarity_search_with_score(
query,
search_options={
"query": {
"min": 3,
"max": 5,
"inclusive_min": True,
"inclusive_max": True,
"field": "metadata.rating",
}
},
)
print(results[0])
結合多個搜尋查詢
可以使用 AND(連接詞)或 OR(分離詞)運算符組合不同的搜尋查詢。
在此範例中,我們正在檢查評分介於 3 到 4 之間且日期介於 2015 年到 2018 年之間的文件。
query = "Any mention about independence?"
results = vector_store.similarity_search_with_score(
query,
search_options={
"query": {
"conjuncts": [
{"min": 3, "max": 4, "inclusive_max": True, "field": "metadata.rating"},
{"start": "2016-12-31", "end": "2017-01-02", "field": "metadata.date"},
]
}
},
)
print(results[0])
其他查詢
同樣地,您可以在 search_options
參數中使用任何支援的查詢方法,例如地理距離、多邊形搜尋、萬用字元、正規表示式等。有關可用查詢方法及其語法的更多詳細資訊,請參閱文件。
透過轉換為檢索器來查詢
您也可以將向量資料庫轉換為檢索器,以便在您的鏈中更輕鬆地使用。
以下是如何將您的向量資料庫轉換為檢索器,然後使用簡單的查詢和篩選器調用檢索器。
retriever = vector_store.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"k": 1, "score_threshold": 0.5},
)
retriever.invoke("Stealing from the bank is a crime", filter={"source": "news"})
用於檢索增強生成的使用方法
有關如何將此向量資料庫用於檢索增強生成 (RAG) 的指南,請參閱以下章節
常見問題
問題:我應該在建立 CouchbaseVectorStore 物件之前建立搜尋索引嗎?
是的,目前您需要在建立 CouchbaseVectoreStore
物件之前建立搜尋索引。
問題:我沒有在搜尋結果中看到我指定的所有欄位。
在 Couchbase 中,我們只能傳回儲存在搜尋索引中的欄位。請確保您嘗試在搜尋結果中存取的欄位是搜尋索引的一部分。
一種處理方法是在索引中動態地索引和儲存文件的欄位。
- 在 Capella 中,您需要前往「進階模式」,然後在「一般設定」的 chevron 下,您可以勾選「[X] 儲存動態欄位」或「[X] 索引動態欄位」
- 在 Couchbase Server 中,在索引編輯器(非快速編輯器)中,在「進階」的 chevron 下,您可以勾選「[X] 儲存動態欄位」或「[X] 索引動態欄位」
請注意,這些選項會增加索引的大小。
有關動態映射的更多詳細資訊,請參閱 文件。
問題:我無法在搜尋結果中看到 metadata 物件。
這很可能是由於文件中的 metadata
欄位未被 Couchbase 搜尋索引索引和/或儲存。為了在文件中索引 metadata
欄位,您需要將其作為子映射新增至索引。
如果您選擇映射映射中的所有欄位,您將能夠按所有 metadata 欄位進行搜尋。或者,為了優化索引,您可以選擇 metadata
物件內要索引的特定欄位。您可以參考 文件 以了解有關索引子映射的更多資訊。
建立子映射
API 參考
有關所有 CouchbaseVectorStore
功能和配置的詳細文件,請前往 API 參考: https://langchain-python.dev.org.tw/api_reference/couchbase/vectorstores/langchain_couchbase.vectorstores.CouchbaseVectorStore.html