LangChain-RAG必備:向量數據庫如何CRUD
今天我將帶領大家,以最為基礎的CRUD入手來看看向量數據庫應該如何使用。考慮到目前市面上的向量數據庫眾多,每個數據庫的操作方式也無統一標準。「本文將基于LangChain提供的VectorStore類中的統一操作方法,以chroma向量數據庫作為示例進行演示。」
向量數據庫-新增
LangChain的VectorStore類是一個通用的向量數據庫的接口,它可以對接不同的底層向量數據庫,如chroma、faiss、annoy等,實現統一的操作方法和API。VectorStore類還提供了一些高級的功能,如語義檢索、最大邊際相關性(MMR)等,可以幫助我們更好地利用向量數據庫的能力。
要想向向量數據庫中新增數據,我們首先需要創建一個VectorStore對象,并在創建時配置好embedding function,即用于將原始數據轉換為向量的函數。如下所示:
# 通過HuggingFace創建embedding_function
embeddings = HuggingFaceEmbeddings(model_name=model)
# 創建VectorStore的具體實現類Chroma對象,并指定collection_name和持久化目錄
vector = Chroma(collection_name = 'cname', embedding_functinotallow=embeddings,persist_directory='/vs')
創建好VectorStore對象后,我們就可以使用insert方法來向向量數據庫中插入數據了。insert方法接受一個doc對象作為參數,doc對象可以是一個字符串或一個字典,如果是一個字典,那么必須包含一個名為text的鍵,其值為要插入的文本內容,同時,我們還可以在doc對象中添加一些其他的元數據,用于后續的查詢或過濾。例如,我們可以向向量數據庫中插入以下三個doc對象:
# 先將文本拆分并轉化為doc
loader = TextLoader(url,autodetect_encoding = True)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 插入向量數據庫
vector.add_documents(documents=splits)
add_documents方法會返回一個id列表,這個id是doc的索引,用于唯一標識插入的doc對象。我們可以根據需要記錄這個id,并與原始文件關聯,一般來說,一個file對應多個doc,例如,我們可以將一個長文本拆分為多個段落,然后將每個段落作為一個doc插入到向量數據庫中,這樣可以提高檢索的效率和精度。
向量數據庫-刪除
要想從向量數據庫中刪除數據,我們可以使用delete方法,delete方法接受一個id或一個id列表作為參數,然后根據id來刪除對應的doc對象。例如,我們可以使用以下代碼來刪除id為1的doc對象:
# 刪除id為1的doc對象
vector.delete('1')
如果我們不知道要刪除的doc對象的id,但是知道它的一些元數據,我們可以先使用metadata中的字段來查詢到id,然后再使用delete方法來批量刪除。例如,我們可以使用以下代碼來刪除所有category為功能的doc對象:
# 根據file_id的條件,查詢到所有符合的doc對象的id
reuslt = vector.get(where={"file_id":file_id})
# 使用delete方法,批量刪除這些id對應的doc對象
if reuslt['ids'] :
vector.delete(reuslt['ids'])
向量數據庫-更新
VectorStore類沒有提供專門的更新方法,因為更新一個doc對象相當于先刪除它,然后再插入一個新的doc對象。因此,我們可以使用delete和insert方法來實現文檔的更新。例如,我們可以使用以下代碼來更新id為2的doc對象,將它的source從文檔改為官網:
# 刪除id為2的doc對象
vector.delete('2')
# 插入新的doc對象
vector.add_documents(new_doc)
向量數據庫-查詢
VectorStore類提供了多種查詢方法,用于根據不同的需求和場景來檢索向量數據庫中的數據。查詢方法主要分為兩種類型:similarity和mmr。similarity類型的查詢方法是基于向量之間的相似度來進行檢索的,它可以接受一個字符串或一個向量作為查詢,然后返回最相似的doc對象以及相似度。mmr類型的查詢方法是基于最大邊際相關性(MMR)來進行檢索的,它可以接受一個字符串或一個向量作為查詢,然后返回一個多樣化的doc對象列表,這些doc對象既與查詢相關,又盡量不相似。
接下來,我們將介紹以下四個查詢方法:
- similarity_search:這個方法是最基本的相似度查詢方法,它接受一個字符串作為查詢,以及一個可選的top_n參數,用于指定返回的doc對象的數量,默認為4,然后返回最相似的doc對象或它們的id。例如,我們可以使用以下代碼來查詢與“語義檢索”最相似的doc對象:
# 查詢與“語義檢索”最相似的doc對象
docs = vector.similarity_search("語義檢索")
# 打印查詢結果
for doc in docs:
print(doc)
- similarity_search_with_score:這個方法與similarity_search類似,但是它會同時返回向量之間的距離,距離越小表示越相似。例如,我們可以使用以下代碼來查詢與“語義檢索”最相似的doc對象,并打印它們的分數:
# 查詢與“語義檢索”最相似的doc對象,并返回分數
docs_with_score = vector.similarity_search_with_score("語義檢索")
# 打印查詢結果和分數
for doc_with_score in docs_with_score:
print(doc_with_score[0], doc_with_score[1])
- similarity_search_with_relevance_scores:這個方法與similarity_search_with_score類似,但是它會將分數轉換為一個介于0和1之間的相關度評分,這個評分表示查詢和doc對象之間的語義相關程度,評分越高越相似。代碼與similarity_search_with_score類似,不再額外示例
- max_marginal_relevance_search:這個方法是基于最大邊際相關性(MMR)來進行查詢的,最大邊際相關性(MMR)是一種用于檢索或摘要的方法,它既考慮了查詢和文檔之間的相似度,又考慮了文檔之間的多樣性,從而避免返回重復或冗余的結果。它接受一個字符串或一個向量作為查詢,以及一個可選的top_n參數,用于指定返回的doc對象的數量,默認為10,然后返回一個多樣化的doc對象列表,這些doc對象既與查詢相關,又盡量不相似。這個方法可以用于生成摘要、提取關鍵信息、避免重復內容等場景。例如,我們可以使用以下代碼來查詢與“LangChain”相關的但不相似的doc對象:
# 查詢與“LangChain”相關的但不相似的doc對象
docs = vector.max_marginal_relevance_search("LangChain")
# 打印查詢結果
for doc in docs:
print(doc)
結語
「CRUD只是操作向量數據庫的基礎手段,想要用好RAG必須在CRUD的基礎上掌握語義檢索的相關原理。」比如文檔拆分時需要按語義盡可能的拆分為小的單元,而在召回時,則需要基于召回的單元盡可能的補充完整的窗口上下文,才能在最終使用LLM時得到盡可能好的結果。
本文轉載自 ??AI小智??,作者: AI小智
