【LangChain 速遞】Parent Document Retriever
很喜歡?LangChain 父文檔檢索(Parent Document Retriever)的理念,以及 @clusteredbytes 制作的很酷的手繪圖。所以周末花了一些時(shí)間重構(gòu)了一個(gè)序列圖來(lái)處理內(nèi)部工作流程,希望它能幫助大家更好的了解這個(gè)檢索器~?
原推:https://twitter.com/zhanghaili0610/status/1692887244745388125?s=20

Parent Document Retriever 的實(shí)現(xiàn)流程如下:
使用兩個(gè)文本分割器將原始文本分割成較大的塊(父塊)和較小的塊(子塊)
在向量存儲(chǔ)(Vector Store)中僅存儲(chǔ)較小的子塊,因?yàn)樵谇度牒笏鼈兡芨鼫?zhǔn)確地反映語(yǔ)義含義
在內(nèi)存存儲(chǔ)(Memory Store)中存儲(chǔ)較大的父塊,鍵是每個(gè)父塊的唯一 ID,值是對(duì)應(yīng)的文本內(nèi)容
對(duì)每個(gè)子塊的向量嵌入,將其對(duì)應(yīng)的父塊的唯一 ID 存儲(chǔ)為元數(shù)據(jù)(metadata)
創(chuàng)建 ParentDocumentRetriever,傳入上面創(chuàng)建的向量存儲(chǔ)、內(nèi)存存儲(chǔ)和兩個(gè)分割器
調(diào)用 add_documents 方法將文檔添加到檢索器中時(shí),執(zhí)行以下操作:
? ?使用父分割器拆分文檔成父塊,為每個(gè)父塊生成唯一 ID
? ?將父塊及其 ID 存入內(nèi)存存儲(chǔ)
? ?使用子分割器進(jìn)一步拆分父塊成子塊
? ?將所有子塊存入向量存儲(chǔ),并將每個(gè)子塊的父 ID 作為元數(shù)據(jù)
當(dāng)調(diào)用 get_relevant_documents 方法時(shí),首先從向量存儲(chǔ)中獲取相關(guān)的子塊,然后取出其父 ID,再?gòu)膬?nèi)存存儲(chǔ)中獲取對(duì)應(yīng)的父塊并返回
這樣我們使用子塊進(jìn)行相似性匹配,但返回包含更多上下文的父塊給下游任務(wù)使用。
Parent Document Retriever 的核心價(jià)值在于它結(jié)合了小塊和大塊的優(yōu)勢(shì):
小塊在向量嵌入后可以更準(zhǔn)確地反映語(yǔ)義含義,這有利于后續(xù)的相似性檢索
而大塊提供了更完整的上下文信息,這對(duì)下游的語(yǔ)言生成任務(wù)很重要,可以幫助模型更好地理解查詢(xún)的語(yǔ)義
Parent Document Retriever 通過(guò)使用小塊進(jìn)行相似性匹配,但返回大塊作為結(jié)果,巧妙地利用了兩者的優(yōu)勢(shì)
這樣可以避免僅使用小塊時(shí)可能出現(xiàn)的斷章取義的問(wèn)題,也避免了僅使用大塊時(shí)嵌入語(yǔ)義損失的問(wèn)題
使得后續(xù)的檢索增強(qiáng)生成模型可以基于語(yǔ)義相關(guān)且上下文完整的文檔來(lái)產(chǎn)生更加連貫和符合邏輯的回復(fù)
通過(guò)調(diào)整兩個(gè)分割器的粒度,可以平衡語(yǔ)義精確度和上下文完整度,靈活適應(yīng)不同的任務(wù)需求
相比直接使用一種策略,Parent Document Retriever 提供了一種更聰明、更有效的文檔存儲(chǔ)和檢索機(jī)制