RAG 中的語義分塊:實現(xiàn)更優(yōu)的上下文檢索
檢索增強生成(RAG)技術(shù)異軍突起,席卷了整個大語言模型領(lǐng)域。通過將大語言模型(LLMs)的強大能力與外部知識檢索相結(jié)合,RAG使得模型能夠生成準(zhǔn)確且有依據(jù)的回復(fù),即便在專業(yè)領(lǐng)域也不例外。在每一個表現(xiàn)卓越的RAG流程背后,都有一個默默發(fā)揮關(guān)鍵作用的 “英雄”:分塊技術(shù),尤其是語義分塊。
RAG生態(tài)系統(tǒng)與分塊的作用
RAG代表了人工智能系統(tǒng)獲取和利用知識方式的重大變革。傳統(tǒng)的大語言模型僅依賴于其預(yù)先訓(xùn)練的知識,這可能存在局限性或時效性問題。RAG通過在生成過程中從外部資源(如數(shù)據(jù)庫、文檔或互聯(lián)網(wǎng))檢索相關(guān)信息,很好地解決了這一局限性。這些外部知識就像補充彈藥,極大地擴展了模型的知識邊界,使其能夠應(yīng)對各種復(fù)雜問題。
在RAG流程中,分塊是至關(guān)重要的一環(huán)。分塊指的是在對文檔進行嵌入和索引之前,將其分割成較小單元的過程。這些分塊在查詢時被檢索出來,并輸入到大語言模型中用于生成回復(fù)。然而,分塊并非簡單的切割操作,其方式直接影響著RAG系統(tǒng)的性能。如果分塊過大,它們可能無法適配模型的上下文窗口,導(dǎo)致信息丟失;而如果分塊過小或分割不當(dāng),語義信息會被破壞,使模型難以理解和處理,進而影響最終回復(fù)的質(zhì)量。
分塊面臨的挑戰(zhàn)
以一段醫(yī)學(xué)文章為例,假設(shè)內(nèi)容如下:“蝙蝠俠主要在哥譚市活動,這是一個犯罪猖獗、腐敗橫行的大都市。他的宿敵小丑在混亂和不可預(yù)測中如魚得水。盡管布魯斯·韋恩資助了哥譚市的許多社會項目,但他仍在為自己作為億萬富翁和義警的雙重身份而苦苦掙扎。” 如果使用簡單的分塊方法,可能會將其分割為:
- 分塊1:“蝙蝠俠主要在哥譚市活動,這是一個犯罪猖獗的”
- 分塊2:“大都市,腐敗橫行。他的宿敵小丑,”
- 分塊3:“在混亂和不可預(yù)測中如魚得水。盡管布魯斯·韋恩”
- 分塊4:“資助了哥譚市的許多社會項目,但他仍在為......”
此時,若用戶提問:“是什么讓蝙蝠俠的生活如此矛盾?” 檢索器可能會隨機獲取到句子中間的某個分塊,或者遺漏關(guān)于他雙重身份的關(guān)鍵信息,進而導(dǎo)致給出的答案籠統(tǒng)或錯誤。這清晰地展現(xiàn)了不恰當(dāng)分塊帶來的問題,突出了語義分塊的重要性和必要性。
語義分塊詳解
語義分塊旨在以一種保留每個單元有意義、自包含上下文的方式分割文檔。它尊重自然的邊界,比如段落、句子或主題,確保每個分塊都能獨立回答相關(guān)的查詢。實現(xiàn)語義分塊通常涉及以下幾個關(guān)鍵步驟:
- 句子邊界檢測
準(zhǔn)確識別句子的起止位置,這是保留語義完整性的基礎(chǔ)。因為句子是表達完整思想的基本語言單位,正確劃分句子邊界有助于將相關(guān)信息歸為一組。
- 主題建?;蚧谇度氲姆指?/span>
主題建??梢苑治鑫臋n內(nèi)容,將具有相似主題的部分劃分為一個分塊?;谇度氲姆指顒t利用詞或句子的嵌入向量,通過計算向量之間的相似度來確定分割點,在語義發(fā)生變化的地方進行分割,使每個分塊內(nèi)的語義更加連貫。
- 使用重疊窗口保留上下文
為了避免在分割過程中丟失上下文信息,通常會采用重疊窗口的方法。即相鄰分塊之間有一定比例的重疊內(nèi)容,這樣可以確保在檢索和處理分塊時,前后信息能夠相互關(guān)聯(lián),增強模型對上下文的理解。
分塊策略對比
常見的分塊策略有多種,從簡單到語義化程度高依次介紹如下:
- 固定大小分塊(簡單方法)
在Python的LangChain庫中,可以使用 CharacterTextSplitter
進行固定大小分塊。示例代碼如下:
from langchain.text_splitter import CharacterTextSplitter
splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_text(document)
這種方法的優(yōu)點是簡單直接,易于實現(xiàn)。但它存在明顯的缺陷,可能會在句子中間進行分割,破壞句子的完整性和上下文連貫性,影響語義的表達。
- 基于句子的分塊
借助 NLTKTextSplitter
可以實現(xiàn)基于句子的分塊,示例代碼為:
from langchain.text_splitter import NLTKTextSplitter
splitter = NLTKTextSplitter(chunk_size=3, chunk_overlap=1)
chunks = splitter.split_text(document)
- 該方法能夠保留句子邊界,一定程度上保證了語義的完整性。然而,它可能仍然會在分塊過程中分割主題,導(dǎo)致一個主題被分散到多個分塊中,不利于模型對完整主題的理解和處理。
- 遞歸分塊
RecursiveCharacterTextSplitter
提供了遞歸分塊的功能,代碼如下:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "\n", ".", " ", ""],
chunk_size=500,
chunk_overlap=100
)
chunks = splitter.split_text(document)
遞歸分塊嘗試在較大的邊界(如段落、句子、單詞)上進行分割,能夠在分塊長度和語義保持之間取得較好的平衡。不過,它可能仍然需要根據(jù)具體應(yīng)用場景進行微調(diào),以達到最佳效果。
- 基于嵌入的語義分塊(高級方法)
這種技術(shù)利用句子嵌入來在語義發(fā)生變化的地方分割文本。示例代碼如下:
from sentence_transformers import SentenceTransformer, util
import nltk
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = nltk.sent_tokenize(document)
embeddings = model.encode(sentences)
similarities = [util.cos_sim(embeddings[i], embeddings[i+1]) for i in range(len(embeddings)-1)]
chunks = []
chunk = [sentences[0]]
for i, score in enumerate(similarities):
if score < 0.6: # 可根據(jù)需要調(diào)整閾值
chunks.append(" ".join(chunk))
chunk = []
chunk.append(sentences[i+1])
if chunk:
chunks.append(" ".join(chunk))
基于嵌入的語義分塊能夠真正實現(xiàn)語義層面的分割,對于包含豐富主題的文檔效果顯著。但它的計算復(fù)雜度較高,處理速度相對較慢,實現(xiàn)過程也更為復(fù)雜。
評估分塊質(zhì)量
分塊策略的優(yōu)劣直接影響RAG系統(tǒng)下游的各個環(huán)節(jié),因此評估分塊質(zhì)量至關(guān)重要??梢詮囊韵聨讉€方面進行評估:
指標(biāo)
- 與真實情況的分塊重疊度(如使用Recall@k指標(biāo))通過計算分塊與理想分塊(真實情況)的重疊比例,衡量分塊的準(zhǔn)確性。重疊度越高,說明分塊結(jié)果越接近理想狀態(tài),能夠更好地保留相關(guān)信息。
- 嵌入一致性(分塊內(nèi)相似度應(yīng)較高)評估分塊內(nèi)文本的嵌入向量之間的相似度。如果分塊內(nèi)的文本相似度高,意味著分塊內(nèi)的語義連貫性好,模型更容易理解和處理。
- 模型回答準(zhǔn)確率(端到端RAG評估)通過實際輸入查詢,觀察模型基于分塊生成的回答的準(zhǔn)確率。這是最直接評估分塊策略對RAG系統(tǒng)整體性能影響的指標(biāo)。
工具
- LangChain RAG評估器LangChain庫提供的評估器可以方便地對RAG系統(tǒng)進行評估,包括對分塊效果的評估。
- Ragas這是一個專門用于評估RAG系統(tǒng)的工具包,能夠從多個維度對分塊質(zhì)量進行分析。
- 帶有真實相關(guān)性標(biāo)簽的自定義問答對通過創(chuàng)建自定義的問答對,并標(biāo)注問題與答案之間的相關(guān)性,可以針對性地評估分塊策略在特定任務(wù)上的表現(xiàn)。
最佳實踐
為了實現(xiàn)有效的語義分塊,需要遵循以下最佳實踐:
- 優(yōu)先選擇基于句子或語義感知的分塊方式
這種方式能夠更好地保留語義信息,提高模型對上下文的理解能力。
- 合理使用分塊重疊
通常,50 - 100個標(biāo)記的重疊是比較合適的。分塊重疊可以確保相鄰分塊之間的信息連貫性,避免因分割導(dǎo)致的上下文丟失。
- 根據(jù)具體應(yīng)用場景調(diào)整分塊大小
不同類型的文檔(如法律文檔和推文)對分塊大小的要求不同。法律文檔通常內(nèi)容復(fù)雜、信息量大,可能需要較大的分塊;而推文內(nèi)容簡短,分塊大小應(yīng)相應(yīng)減小。
- 利用元數(shù)據(jù)(如標(biāo)題、副標(biāo)題)進行層次感知分塊
元數(shù)據(jù)可以提供文檔的結(jié)構(gòu)信息,幫助在分塊時更好地考慮文檔的層次結(jié)構(gòu),使分塊結(jié)果更符合邏輯。
- 持續(xù)評估、迭代和重新訓(xùn)練檢索器
隨著數(shù)據(jù)的變化和應(yīng)用場景的調(diào)整,分塊策略可能需要不斷優(yōu)化。通過持續(xù)評估分塊質(zhì)量,對檢索器進行迭代和重新訓(xùn)練,可以確保RAG系統(tǒng)始終保持良好的性能。
語義分塊在現(xiàn)實中的巨大影響
語義分塊對于實際的RAG系統(tǒng)來說至關(guān)重要,甚至可以決定系統(tǒng)的成敗。以一個企業(yè)應(yīng)用案例(法律合同問答機器人)為例,從簡單分塊切換到遞歸 + 語義分塊后,取得了顯著的效果:
- 答案準(zhǔn)確率提高23%
語義分塊使得機器人能夠更準(zhǔn)確地理解問題的上下文,從合同文檔中檢索到更相關(guān)的信息,從而生成更準(zhǔn)確的答案。
- 幻覺現(xiàn)象減少41%
在生成式模型中,幻覺是一個常見問題,即模型生成看似合理但實際上錯誤的信息。語義分塊通過提供更準(zhǔn)確的上下文,有效減少了這種現(xiàn)象的發(fā)生。
- 檢索器命中率從62% 提升到87%
語義分塊優(yōu)化了分塊的內(nèi)容和結(jié)構(gòu),使檢索器能夠更精準(zhǔn)地匹配用戶的查詢,大大提高了命中率。
語義分塊是RAG技術(shù)中不可或缺的關(guān)鍵環(huán)節(jié)。它通過優(yōu)化文檔的分割方式,提升了上下文檢索的效果,進而顯著提高了RAG系統(tǒng)的性能。隨著人工智能技術(shù)的不斷發(fā)展,語義分塊技術(shù)也將不斷演進和完善,為更多領(lǐng)域的應(yīng)用提供有力支持。無論是開發(fā)內(nèi)部知識機器人,還是構(gòu)建特定領(lǐng)域的智能助手,深入理解和應(yīng)用語義分塊技術(shù)都將帶來巨大的優(yōu)勢,推動人工智能應(yīng)用向更加智能、高效的方向發(fā)展。