Couchbase
Couchbase 是一個屢獲殊榮的分散式 NoSQL 雲端資料庫,為您所有的雲端、行動、人工智慧和邊緣運算應用程式提供無與倫比的多功能性、效能、可擴展性和財務價值。 Couchbase 透過開發人員的程式碼輔助和應用程式的向量搜尋來擁抱人工智慧。
向量搜尋是 Couchbase 中全文檢索服務(搜尋服務)的一部分。
本教學課程說明如何在 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["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_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_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
的不同搜尋/查詢可能性,可以在此處找到。
建立多樣化的 Metadata 以進行混合搜尋
為了模擬混合搜尋,讓我們從現有的文件中建立一些隨機的 metadata。我們統一地向 metadata 添加三個欄位:date
在 2010 年到 2020 年之間、rating
在 1 到 5 之間,以及 author
設定為 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
物件中,像 author 這樣的文字欄位的精確匹配。
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 (conjuncts) 或 OR (disjuncts) 運算符結合不同的搜尋查詢。
在此範例中,我們正在檢查 rating 在 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
參數中使用任何支援的 Query 方法,例如 Geo Distance、Polygon Search、Wildcard、Regular Expressions 等。有關可用查詢方法及其語法的更多詳細信息,請參閱文檔。
通過轉換為檢索器進行查詢
您也可以將向量儲存轉換為檢索器,以便在您的鏈中使用。
以下是如何將您的向量儲存轉換為檢索器,然後使用簡單的查詢和篩選器調用檢索器。
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 中,您需要進入“高級模式”,然後在人字形“常規設置”下,您可以選中“[X] 儲存動態欄位”或“[X] 索引動態欄位”。
- 在 Couchbase Server 中,在索引編輯器(而非快速編輯器)中,在人字形“高級”下,您可以選中“[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