一篇講透 Chunk 切分:RAG 知識(shí)庫為什么不是“隨便切一刀”?

RAG 知識(shí)庫,很多人第一步就做錯(cuò)了。

他們以為:
把 Word、PDF、網(wǎng)頁、 Markdown 轉(zhuǎn)成文本,然后每 500 字切一段,丟進(jìn)向量庫,就完成了知識(shí)入庫。

但真正上線后會(huì)發(fā)現(xiàn):

用戶問得很具體,系統(tǒng)召回不到;
用戶問一個(gè)流程,答案只拿到中間一步;
用戶問制度條款, 模型 只看到半句話;
用戶問長文檔總結(jié),檢索出來的內(nèi)容前后斷裂;
用戶問“這個(gè)操作怎么做”,模型把第 3 步當(dāng)成第 1 步回答。

問題往往不是模型不行,也不是向量庫不行,而是 Chunk 切分策略太粗糙

Chunk 不是簡單分段,而是 RAG 系統(tǒng)的“知識(shí)顆粒度設(shè)計(jì)”。


一、什么是 Chunk?為什么它這么重要?

Chunk 可以理解為:
把一篇大文檔切成一塊一塊可檢索、可召回、可喂給大模型的小知識(shí)片段。

比如一篇 30 頁的產(chǎn)品手冊(cè),大模型不可能每次都讀全文,向量庫也不適合直接存整篇文章。所以要先切分成多個(gè) Chunk:

原始文檔
 ↓
章節(jié)
 ↓
小節(jié)
 ↓
段落
 ↓
Chunk
 ↓
Embedding
 ↓
向量庫

用戶提問時(shí),系統(tǒng)不是找整篇文檔,而是先找最相關(guān)的 Chunk。

所以 Chunk 切得好不好,直接決定三個(gè)東西:

第一,能不能召回到正確內(nèi)容。
第二,召回內(nèi)容上下文是否完整。
第三,大模型回答時(shí)會(huì)不會(huì)斷章取義。

LangChain 文檔也提到過類似矛盾:檢索時(shí)希望文檔塊足夠小,這樣 Embedding 更精準(zhǔn);但又希望文檔塊足夠大,這樣上下文不丟失。Parent Document Retriever 就是為了解決“小塊精準(zhǔn)召回、大塊恢復(fù)上下文”的問題。


二、為什么不能直接按固定字?jǐn)?shù)切?

很多初學(xué)者會(huì)這樣切:

每 500 字切一塊
每塊重疊 50 字

這確實(shí)簡單,但問題也很明顯。

比如原文是:

一、開戶流程
 
第一步:用戶提交身份證、銀行卡、手機(jī)號(hào)。
第二步:系統(tǒng)進(jìn)行實(shí)名校驗(yàn)。
第三步:風(fēng)控系統(tǒng)判斷用戶是否命中黑名單。
第四步:校驗(yàn)通過后生成賬戶。
第五步:發(fā)送開戶成功通知。

如果機(jī)械切分,可能變成:

Chunk 1:
第一步:用戶提交身份證、銀行卡、手機(jī)號(hào)。
第二步:系統(tǒng)進(jìn)行實(shí)名校驗(yàn)。
 
Chunk 2:
第三步:風(fēng)控系統(tǒng)判斷用戶是否命中黑名單。
第四步:校驗(yàn)通過后生成賬戶。
 
Chunk 3:
第五步:發(fā)送開戶成功通知。

用戶問:“開戶完整流程是什么?”

系統(tǒng)可能只召回 Chunk 2,因?yàn)槔锩嬗小帮L(fēng)控”“賬戶”等關(guān)鍵詞。
大模型拿到的上下文只有第 3 步和第 4 步,于是回答就不完整。

這就是典型的 切分破壞流程結(jié)構(gòu)。

固定長度切分適合兜底,但不適合直接作為企業(yè)級(jí)知識(shí)庫的主策略。


三、Chunk 切分的核心原則:不是按長度切,而是按知識(shí)單元切

好的 Chunk 應(yīng)該滿足四個(gè)要求:

1、語義完整

一個(gè) Chunk 最好表達(dá)一個(gè)完整意思。

比如:

差:
“用戶提交材料后,系統(tǒng)會(huì)進(jìn)行實(shí)名校驗(yàn)。如果校驗(yàn)失敗……”
 
好:
“實(shí)名認(rèn)證規(guī)則:用戶提交身份證、銀行卡、手機(jī)號(hào)后,系統(tǒng)會(huì)校驗(yàn)三要素是否一致。校驗(yàn)失敗時(shí),返回失敗原因,并提示用戶重新提交。”

前者被切斷了,后者是完整知識(shí)點(diǎn)。

2、邊界清晰

Chunk 最好有明確來源:

文檔名稱:開戶操作手冊(cè)
章節(jié):二、開戶注冊(cè)流程
小節(jié):2.1 實(shí)名認(rèn)證
段落:實(shí)名認(rèn)證規(guī)則

這樣召回后,大模型知道這段內(nèi)容來自哪里。

3、顆粒度適中

太?。赫倩鼐珳?zhǔn),但上下文不足。
太大:上下文完整,但 Embedding 語義變稀釋。

所以企業(yè)級(jí)知識(shí)庫通常不會(huì)只保留一種 Chunk,而是會(huì)有:

Small Chunk:用于精準(zhǔn)召回
Parent Chunk:用于上下文恢復(fù)
Section Chunk:用于章節(jié)級(jí)理解
Document Metadata:用于過濾和溯源

4、結(jié)構(gòu)信息不能丟

尤其是流程類、制度類、合同類、產(chǎn)品手冊(cè)類文檔,不能只存純文本,還要存元數(shù)據(jù):

{
  "docId": "doc_001",
  "title": "開戶操作手冊(cè)",
  "sectionTitle": "開戶注冊(cè)流程",
  "chunkType": "process_step",
  "stepNo": 3,
  "totalSteps": 5,
  "parentId": "parent_001"
}

這樣系統(tǒng)才知道:
這是第 3 步,不是孤立的一句話。


四、按語義切分:讓一個(gè) Chunk 表達(dá)一個(gè)完整意思

語義切分的核心是:

不要讓一句話、一段邏輯、一個(gè)規(guī)則被切斷。

比如下面這段制度:

用戶連續(xù)輸錯(cuò)密碼 5 次后,系統(tǒng)會(huì)臨時(shí)鎖定賬戶 30 分鐘。
如果用戶在鎖定期間再次嘗試登錄,系統(tǒng)不會(huì)重新計(jì)算鎖定時(shí)間。
用戶可以通過短信驗(yàn)證碼、人臉識(shí)別或客服人工審核方式解鎖賬戶。

比較好的切法是:

Chunk:
賬戶鎖定規(guī)則:用戶連續(xù)輸錯(cuò)密碼 5 次后,系統(tǒng)會(huì)臨時(shí)鎖定賬戶 30 分鐘。鎖定期間再次嘗試登錄,不會(huì)重新計(jì)算鎖定時(shí)間。用戶可通過短信驗(yàn)證碼、人臉識(shí)別或客服人工審核方式解鎖賬戶。

不要切成:

Chunk 1:
用戶連續(xù)輸錯(cuò)密碼 5 次后,系統(tǒng)會(huì)臨時(shí)鎖定賬戶 30 分鐘。
 
Chunk 2:
如果用戶在鎖定期間再次嘗試登錄,系統(tǒng)不會(huì)重新計(jì)算鎖定時(shí)間。
 
Chunk 3:
用戶可以通過短信驗(yàn)證碼、人臉識(shí)別或客服人工審核方式解鎖賬戶。

因?yàn)橛脩魡枴百~戶被鎖怎么辦”,系統(tǒng)可能只召回 Chunk 3,卻不知道為什么被鎖、鎖多久。

語義切分更適合這些內(nèi)容:

制度條款
業(yè)務(wù)規(guī)則
FAQ 問答
產(chǎn)品說明
異常處理說明
接口字段說明

五、按標(biāo)題切分:標(biāo)題是天然的知識(shí)邊界

很多文檔本身就有標(biāo)題結(jié)構(gòu):

一、賬戶管理
  1.1 開戶
  1.2 銷戶
  1.3 凍結(jié)賬戶
 
二、交易管理
  2.1 轉(zhuǎn)賬
  2.2 充值
  2.3 提現(xiàn)

這類文檔不能只按字?jǐn)?shù)切,而應(yīng)該優(yōu)先按標(biāo)題切。

比如:

標(biāo)題路徑:
賬戶管理 > 開戶 > 實(shí)名認(rèn)證

每個(gè) Chunk 都帶上標(biāo)題路徑:

{
  "docTitle": "賬戶管理手冊(cè)",
  "heading1": "賬戶管理",
  "heading2": "開戶",
  "heading3": "實(shí)名認(rèn)證",
  "content": "用戶開戶時(shí)需要完成三要素實(shí)名認(rèn)證……"
}

這樣用戶問:

開戶時(shí)實(shí)名認(rèn)證失敗怎么辦?

系統(tǒng)不僅能召回正文,還能帶上標(biāo)題上下文:

賬戶管理 > 開戶 > 實(shí)名認(rèn)證

LangChain 的 MarkdownHeaderTextSplitter 就是典型的標(biāo)題切分思路,它會(huì)根據(jù) Markdown 標(biāo)題拆分文檔,并把標(biāo)題作為元數(shù)據(jù)保留下來;拆完后還可以繼續(xù)用其他 splitter 控制 Chunk 大小。


六、按章節(jié)切分:長文檔必須保留章節(jié)結(jié)構(gòu)

長文檔最大的問題是:

局部內(nèi)容有用,但離開章節(jié)背景就容易誤解。

比如一份風(fēng)控規(guī)則文檔:

三、黑名單規(guī)則
 
3.1 命中身份證黑名單
……
3.2 命中手機(jī)號(hào)黑名單
……
3.3 命中設(shè)備指紋黑名單
……

用戶問:

什么情況下會(huì)被風(fēng)控?cái)r截?

如果只召回 3.2,答案就不完整。

所以長文檔一般要設(shè)計(jì)多層結(jié)構(gòu):

Document
 ├── Section:三、黑名單規(guī)則
 │    ├── Chunk:3.1 身份證黑名單
 │    ├── Chunk:3.2 手機(jī)號(hào)黑名單
 │    └── Chunk:3.3 設(shè)備指紋黑名單

小 Chunk 用于精準(zhǔn)召回。
Section 用于恢復(fù)章節(jié)上下文。

這就是 Section Retrieval 的核心思想:

用戶問具體問題時(shí),先召回小 Chunk;
如果發(fā)現(xiàn)多個(gè)小 Chunk 都屬于同一個(gè)章節(jié),就把整個(gè)章節(jié)或章節(jié)摘要一起帶給大模型。


七、按流程切分:流程類文檔必須記錄 stepNo 和 totalSteps

流程類文檔是最容易切壞的。

比如:

一、退款流程
 
第一步:用戶提交退款申請(qǐng)。
第二步:系統(tǒng)校驗(yàn)訂單狀態(tài)。
第三步:判斷是否超過退款期限。
第四步:調(diào)用支付渠道退款。
第五步:更新訂單狀態(tài)。
第六步:發(fā)送退款結(jié)果通知。

如果普通切分,系統(tǒng)只知道每個(gè) Chunk 是一句話。
但它不知道這是流程,也不知道這是第幾步。

企業(yè)級(jí)做法應(yīng)該是:

{
  "chunkType": "process_step",
  "processName": "退款流程",
  "stepNo": 4,
  "totalSteps": 6,
  "stepTitle": "調(diào)用支付渠道退款",
  "content": "第四步:調(diào)用支付渠道退款。系統(tǒng)根據(jù)原支付渠道發(fā)起退款請(qǐng)求,并記錄渠道返回碼。",
  "prevStep": 3,
  "nextStep": 5,
  "parentProcessId": "refund_process_001"
}

這樣用戶問:

退款流程第四步失敗怎么辦?

系統(tǒng)能精準(zhǔn)召回第 4 步。

用戶問:

退款完整流程是什么?

系統(tǒng)可以根據(jù):

processName = 退款流程
stepNo = 1 到 6
totalSteps = 6

把完整流程拼回來。

這就是流程類文檔切分的關(guān)鍵:

流程不是普通文本,流程必須結(jié)構(gòu)化。


八、Small Chunk:用于精準(zhǔn)召回

Small Chunk 的作用是:

讓系統(tǒng)更容易命中用戶問題。

比如用戶問:

退款失敗后訂單狀態(tài)怎么處理?

如果 Chunk 太大,里面同時(shí)包含退款申請(qǐng)、風(fēng)控校驗(yàn)、渠道退款、訂單狀態(tài)、通知等內(nèi)容,Embedding 會(huì)變得很“泛”,不夠精準(zhǔn)。

Small Chunk 可以只保留一個(gè)知識(shí)點(diǎn):

訂單狀態(tài)處理規(guī)則:支付渠道退款失敗時(shí),訂單狀態(tài)保持為“退款處理中”,系統(tǒng)記錄失敗原因,并進(jìn)入重試隊(duì)列。

這種小塊非常適合 向量檢索 。

但 Small Chunk 也有缺點(diǎn):
上下文不完整。

所以不能只用 Small Chunk,還要配合 Parent Chunk。


九、Parent Chunk:用于完整上下文恢復(fù)

Parent Chunk 可以理解為 Small Chunk 的上級(jí)內(nèi)容。

例如:

Parent Chunk:
退款流程完整章節(jié)
 
Small Chunk 1:
用戶提交退款申請(qǐng)
 
Small Chunk 2:
系統(tǒng)校驗(yàn)訂單狀態(tài)
 
Small Chunk 3:
調(diào)用支付渠道退款
 
Small Chunk 4:
退款失敗后的訂單狀態(tài)處理

檢索時(shí)先用 Small Chunk 命中問題:

用戶問題:退款失敗后訂單狀態(tài)怎么處理?
命中 Small Chunk 4

然后系統(tǒng)根據(jù) Small Chunk 里的 parentId 找到 Parent Chunk:

parentId = refund_section_001

最后把 Parent Chunk 或 Parent Chunk 中相關(guān)部分交給大模型。

LangChain 的 ParentDocumentRetriever 就是這個(gè)思路:先檢索小塊,再根據(jù)小塊找到它所屬的父文檔或大塊內(nèi)容并返回,從而平衡精準(zhǔn)召回和上下文完整性。

一句話總結(jié):

Small Chunk 負(fù)責(zé)“找得準(zhǔn)”
Parent Chunk 負(fù)責(zé)“講得全”

十、Window Retrieval:召回命中點(diǎn)附近的上下文

Window Retrieval 適合解決一種常見問題:

召回到的句子是對(duì)的,但前后文不夠。

比如命中句子是:

系統(tǒng)會(huì)進(jìn)入人工審核。

單看這句話,大模型不知道:

為什么進(jìn)入人工審核?
什么情況下進(jìn)入人工審核?
人工審核之后做什么?

所以需要把它前后幾句話一起取出來:

上一句:如果用戶提交的身份證信息與銀行卡信息不一致,系統(tǒng)會(huì)判定為高風(fēng)險(xiǎn)。
命中句:系統(tǒng)會(huì)進(jìn)入人工審核。
下一句:人工審核通過后,用戶可繼續(xù)完成開戶流程。

這就是 Window Retrieval。

LlamaIndex 的 Sentence Window 思路就是:檢索時(shí)可以命中一個(gè)句子,但通過 metadata replacement 把該句子替換成它周圍的上下文窗口,從而讓模型看到更完整的語境。

企業(yè)里可以這樣設(shè)計(jì):

{
  "chunkId": "chunk_1001",
  "content": "系統(tǒng)會(huì)進(jìn)入人工審核。",
  "windowContent": "如果用戶提交的身份證信息與銀行卡信息不一致,系統(tǒng)會(huì)判定為高風(fēng)險(xiǎn)。系統(tǒng)會(huì)進(jìn)入人工審核。人工審核通過后,用戶可繼續(xù)完成開戶流程。",
  "windowSize": 1
}

檢索用 content
生成答案用 windowContent。

這就能做到:

召回精準(zhǔn)
上下文完整
回答不容易斷章取義

十一、Parent Retrieval:小塊召回,大塊回答

Parent Retrieval 和 Window Retrieval 有點(diǎn)像,但范圍更大。

Window Retrieval 通常取命中點(diǎn)前后幾句。
Parent Retrieval 通常取命中 Chunk 所屬的父級(jí)段落、章節(jié)或文檔片段。

比如:

Small Chunk:
支付渠道退款失敗時(shí),訂單狀態(tài)保持為“退款處理中”。
 
Parent Chunk:
退款流程章節(jié),包括退款申請(qǐng)、訂單校驗(yàn)、渠道退款、失敗重試、狀態(tài)更新、通知用戶。

用戶問:

退款失敗后系統(tǒng)怎么處理?

系統(tǒng)流程:

這樣回答會(huì)更完整:

退款失敗后,系統(tǒng)不會(huì)立即關(guān)閉退款單,而是將訂單狀態(tài)保持為“退款處理中”,記錄渠道失敗原因,進(jìn)入重試隊(duì)列。如果多次重試失敗,則轉(zhuǎn)人工處理,并向用戶展示處理中狀態(tài)。

如果只給 Small Chunk,模型可能只能回答一句話。


十二、Section Retrieval:按章節(jié)恢復(fù)完整語境

Section Retrieval 適合處理長文檔。

比如用戶問:

黑名單規(guī)則有哪些?

如果只召回一個(gè) Chunk,可能只看到“手機(jī)號(hào)黑名單”。
但實(shí)際上完整答案應(yīng)該包含:

身份證黑名單
手機(jī)號(hào)黑名單
銀行卡黑名單
設(shè)備指紋黑名單
IP 黑名單
賬戶行為黑名單

Section Retrieval 的做法是:

比如命中結(jié)果:

chunk_01:身份證黑名單
chunk_02:手機(jī)號(hào)黑名單
chunk_03:設(shè)備指紋黑名單

它們都屬于:

sectionId = risk_blacklist_rules
sectionTitle = 黑名單規(guī)則

那系統(tǒng)就可以把整個(gè)“黑名單規(guī)則”章節(jié)拿出來。

這比單純 topK 檢索更穩(wěn)定。


十三、長文檔如何處理?不能一次切到底

長文檔處理要分層。

不要這樣:

一篇 100 頁 PDF
 ↓
每 500 字切一塊
 ↓
全部丟向量庫

更好的方式是:

文檔級(jí)
 ↓
章節(jié)級(jí)
 ↓
段落級(jí)
 ↓
語義 Chunk
 ↓
句子窗口

可以設(shè)計(jì)成:

{
  "docId": "doc_001",
  "docTitle": "風(fēng)控規(guī)則說明書",
  "sectionId": "sec_003",
  "sectionTitle": "黑名單規(guī)則",
  "parentChunkId": "parent_003_001",
  "chunkId": "chunk_003_001_004",
  "chunkType": "rule",
  "content": "手機(jī)號(hào)命中黑名單時(shí),系統(tǒng)會(huì)拒絕開戶申請(qǐng)。",
  "windowContent": "用戶提交開戶申請(qǐng)后,系統(tǒng)會(huì)校驗(yàn)手機(jī)號(hào)。如果手機(jī)號(hào)命中黑名單,系統(tǒng)會(huì)拒絕開戶申請(qǐng),并提示用戶聯(lián)系客服。",
  "metadata": {
    "businessType": "開戶",
    "ruleType": "黑名單",
    "sourcePage": 12
  }
}

這樣每個(gè) Chunk 都不是孤立文本,而是帶著完整身份。


十四、推薦的企業(yè)級(jí) Chunk 入庫流程

一個(gè)比較完整的流程可以這樣做:

1、文檔上傳
 ↓
2、格式解析:Word / PDF / HTML / Markdown
 ↓
3、版面識(shí)別:標(biāo)題、表格、段落、圖片、頁碼
 ↓
4、結(jié)構(gòu)化解析:章節(jié)、標(biāo)題、列表、流程、表格
 ↓
5、清洗:去頁眉頁腳、去重復(fù)、修復(fù)斷行
 ↓
6、標(biāo)題切分:按一級(jí)、二級(jí)、三級(jí)標(biāo)題建立層級(jí)
 ↓
7、語義切分:把章節(jié)內(nèi)容切成完整知識(shí)點(diǎn)
 ↓
8、流程識(shí)別:提取 stepNo、totalSteps、processName
 ↓
9、生成 Small Chunk
 ↓
10、生成 Parent Chunk
 ↓
11、生成 Section Chunk 或章節(jié)摘要
 ↓
12、Embedding 向量化
 ↓
13、寫入向量庫 + 元數(shù)據(jù)索引
 ↓
14、檢索時(shí)執(zhí)行 Small Chunk + Parent / Window / Section 恢復(fù)

這套流程的核心不是“切得越碎越好”,而是:

檢索時(shí)要精準(zhǔn)
回答時(shí)要完整
溯源時(shí)要清楚
流程時(shí)要有順序

十五、Chunk 元數(shù)據(jù)應(yīng)該怎么設(shè)計(jì)?

一個(gè)生產(chǎn)級(jí) Chunk 不應(yīng)該只有 content。

建議至少包含這些字段:

{
  "chunkId": "唯一 Chunk ID",
  "docId": "文檔 ID",
  "docTitle": "文檔標(biāo)題",
  "sectionId": "章節(jié) ID",
  "sectionTitle": "章節(jié)標(biāo)題",
  "headingPath": "一級(jí)標(biāo)題 > 二級(jí)標(biāo)題 > 三級(jí)標(biāo)題",
  "parentChunkId": "父 Chunk ID",
  "chunkType": "rule / faq / process_step / table / paragraph",
  "content": "用于向量化的小塊內(nèi)容",
  "windowContent": "命中點(diǎn)前后窗口內(nèi)容",
  "parentContent": "父級(jí)上下文",
  "pageNo": "來源頁碼",
  "sourceType": "pdf / word / markdown / html",
  "businessTag": "業(yè)務(wù)標(biāo)簽",
  "stepNo": "流程第幾步",
  "totalSteps": "流程總步數(shù)",
  "createdAt": "創(chuàng)建時(shí)間",
  "version": "文檔版本"
}

為什么要這么多字段?

因?yàn)闄z索不只是向量相似度。

真實(shí)業(yè)務(wù)里經(jīng)常需要:

按文檔過濾
按業(yè)務(wù)線過濾
按版本過濾
按章節(jié)過濾
按流程順序恢復(fù)
按頁碼溯源
按 chunkType 做不同策略

沒有元數(shù)據(jù),后面很難做精細(xì)化檢索。


十六、不同類型文檔,切分策略不一樣

1、FAQ 文檔

FAQ 最好按問答對(duì)切:

Q:賬戶被凍結(jié)怎么辦?
A:用戶可以通過 App 提交解凍申請(qǐng)……

不要把多個(gè)問答切在一個(gè) Chunk 里。

推薦:

{
  "chunkType": "faq",
  "question": "賬戶被凍結(jié)怎么辦?",
  "answer": "用戶可以通過 App 提交解凍申請(qǐng)……"
}

2、制度規(guī)則文檔

按規(guī)則點(diǎn)切:

規(guī)則名稱
適用范圍
觸發(fā)條件
處理方式
例外情況

3、流程文檔

按流程步驟切,并記錄:

processName
stepNo
totalSteps
prevStep
nextStep

4、接口文檔

按接口或字段切:

接口名稱
請(qǐng)求參數(shù)
返回參數(shù)
錯(cuò)誤碼
調(diào)用示例

5、表格文檔

表格不能簡單轉(zhuǎn)成一堆文本。

要保留:

表頭
行列關(guān)系
單位
備注
表格標(biāo)題

比如:

產(chǎn)品 | 費(fèi)率 | 生效時(shí)間
A產(chǎn)品 | 0.3% | 2025-01-01
B產(chǎn)品 | 0.5% | 2025-02-01

不能切成:

A產(chǎn)品 0.3%
B產(chǎn)品 0.5%

否則大模型不知道 0.3% 是什么。


十七、Chunk 大小怎么選?

沒有一個(gè)絕對(duì)標(biāo)準(zhǔn),但可以按場景理解。

1、短 FAQ

200~500 字

適合精準(zhǔn)問答。

2、業(yè)務(wù)規(guī)則

300~800 字

保證規(guī)則完整,不要切斷條件和處理方式。

3、流程步驟

每一步一個(gè) Chunk

同時(shí)保留整個(gè)流程的 Parent Chunk。

4、長章節(jié)

Small Chunk:300~600 字
Parent Chunk:1000~2000 字
Section Chunk:整個(gè)章節(jié)或章節(jié)摘要

LlamaIndex 的層級(jí)解析也體現(xiàn)了類似思路:可以把文檔解析成多層節(jié)點(diǎn),比如較大的 2048 級(jí)別、中等的 512 級(jí)別、更小的 128 級(jí)別,子節(jié)點(diǎn)會(huì)關(guān)聯(lián)到父節(jié)點(diǎn)。

重點(diǎn)不是數(shù)字本身,而是層級(jí)思想:

小塊用于檢索
大塊用于上下文
章節(jié)用于完整理解

十八、Overlap 重疊要不要加?

要加,但不能亂加。

Overlap 的作用是防止邊界處信息丟失。

比如:

Chunk 1 結(jié)尾:用戶連續(xù)輸錯(cuò)密碼 5 次后,系統(tǒng)會(huì)鎖定賬戶。
Chunk 2 開頭:鎖定時(shí)間為 30 分鐘。

如果沒有重疊,用戶問“鎖定多久”,可能只召回 Chunk 1,答案不完整。

加一點(diǎn)重疊后:

Chunk 1:
用戶連續(xù)輸錯(cuò)密碼 5 次后,系統(tǒng)會(huì)鎖定賬戶,鎖定時(shí)間為 30 分鐘。
 
Chunk 2:
鎖定時(shí)間為 30 分鐘。用戶可以通過短信驗(yàn)證碼解鎖。

但 Overlap 太大也不好:

存儲(chǔ)變多
召回重復(fù)
上下文浪費(fèi)
答案容易啰嗦

一般建議:

普通段落:10%~20% 重疊
流程步驟:不建議靠 overlap,應(yīng)該靠 stepNo 關(guān)聯(lián)
章節(jié)文檔:靠 parentId 和 sectionId 恢復(fù)上下文

十九、檢索時(shí)應(yīng)該怎么組合?

一個(gè)成熟的檢索鏈路可以這樣設(shè)計(jì):

用戶問題
 ↓
Query Rewrite:問題改寫
 ↓
向量召回 Small Chunk
 ↓
關(guān)鍵詞召回補(bǔ)充
 ↓
元數(shù)據(jù)過濾
 ↓
Rerank 精排
 ↓
判斷 Chunk 類型
 ↓
如果是流程:按 stepNo 補(bǔ)全前后步驟
 ↓
如果是長文檔:走 Parent Retrieval
 ↓
如果是句子命中:走 Window Retrieval
 ↓
如果多個(gè) Chunk 屬于同一章節(jié):走 Section Retrieval
 ↓
組裝上下文
 ↓
大模型生成答案
 ↓
返回答案 + 引用來源

這里的關(guān)鍵是:

召回階段不要給太大內(nèi)容
生成階段不要只給小碎片

二十、一個(gè)完整案例:退款流程文檔怎么切?

原文:

退款流程
 
第一步:用戶提交退款申請(qǐng),填寫退款原因。
第二步:系統(tǒng)校驗(yàn)訂單狀態(tài),只有已支付訂單允許退款。
第三步:系統(tǒng)判斷是否超過退款期限。
第四步:調(diào)用支付渠道發(fā)起退款。
第五步:如果退款成功,更新訂單狀態(tài)為已退款。
第六步:如果退款失敗,訂單狀態(tài)保持退款處理中,并進(jìn)入重試隊(duì)列。
第七步:系統(tǒng)通過短信和站內(nèi)信通知用戶退款結(jié)果。

1、Small Chunk

{
  "chunkType": "process_step",
  "processName": "退款流程",
  "stepNo": 6,
  "totalSteps": 7,
  "content": "第六步:如果退款失敗,訂單狀態(tài)保持退款處理中,并進(jìn)入重試隊(duì)列。"
}

2、Parent Chunk

{
  "chunkType": "process_parent",
  "processName": "退款流程",
  "content": "退款流程包括:用戶提交退款申請(qǐng)、系統(tǒng)校驗(yàn)訂單狀態(tài)、判斷退款期限、調(diào)用支付渠道、成功后更新為已退款、失敗后保持退款處理中并進(jìn)入重試隊(duì)列、通知用戶退款結(jié)果。"
}

3、Window Content

{
  "stepNo": 6,
  "windowContent": "第五步:如果退款成功,更新訂單狀態(tài)為已退款。第六步:如果退款失敗,訂單狀態(tài)保持退款處理中,并進(jìn)入重試隊(duì)列。第七步:系統(tǒng)通過短信和站內(nèi)信通知用戶退款結(jié)果。"
}

4、用戶提問

退款失敗后訂單是什么狀態(tài)?

5、檢索結(jié)果

命中 Small Chunk:

第六步:如果退款失敗,訂單狀態(tài)保持退款處理中,并進(jìn)入重試隊(duì)列。

6、上下文恢復(fù)

補(bǔ)充 Window:

第五步:退款成功更新為已退款。
第六步:退款失敗保持退款處理中并進(jìn)入重試隊(duì)列。
第七步:通知用戶退款結(jié)果。

7、最終回答

退款失敗后,訂單不會(huì)直接變成已退款,也不會(huì)關(guān)閉,而是保持“退款處理中”狀態(tài),并進(jìn)入系統(tǒng)重試隊(duì)列。系統(tǒng)后續(xù)會(huì)繼續(xù)嘗試退款,并通過短信或站內(nèi)信通知用戶結(jié)果。

這個(gè)答案就比單句回答更完整。


二十一、常見錯(cuò)誤:為什么很多 RAG 系統(tǒng)回答不好?

1、只按字?jǐn)?shù)切

結(jié)果:流程斷了,規(guī)則斷了,標(biāo)題丟了。

2、只存 content,不存 metadata

結(jié)果:無法按文檔、章節(jié)、業(yè)務(wù)線、版本過濾。

3、Chunk 太大

結(jié)果:召回不精準(zhǔn),Embedding 表達(dá)變模糊。

4、Chunk 太小

結(jié)果:召回片段太碎,大模型回答缺上下文。

5、流程文檔不記錄步驟

結(jié)果:大模型不知道前后順序,容易亂答。

6、長文檔沒有 Parent / Section

結(jié)果:只能回答局部,不能回答完整章節(jié)問題。

7、表格直接轉(zhuǎn)純文本

結(jié)果:行列關(guān)系丟失,費(fèi)率、時(shí)間、條件對(duì)應(yīng)不上。


二十二、企業(yè)級(jí)推薦方案:多粒度 Chunk + 元數(shù)據(jù) + 上下文恢復(fù)

最終推薦架構(gòu)是:

Small Chunk
負(fù)責(zé)精準(zhǔn)召回
 
Window Chunk
負(fù)責(zé)補(bǔ)充前后文
 
Parent Chunk
負(fù)責(zé)恢復(fù)段落級(jí)上下文
 
Section Chunk
負(fù)責(zé)恢復(fù)章節(jié)級(jí)上下文
 
Metadata
負(fù)責(zé)過濾、排序、溯源、流程恢復(fù)

可以理解為:

Small Chunk 是“搜索命中點(diǎn)”
Parent Chunk 是“上下文說明書”
Section Chunk 是“章節(jié)地圖”
Metadata 是“導(dǎo)航系統(tǒng)”

只要這四層做好,RAG 的準(zhǔn)確率、完整性、可解釋性都會(huì)明顯提升。


二十三、總結(jié)

Chunk 切分不是簡單的文本切割,而是知識(shí)庫建設(shè)里最核心的工程能力之一。

普通系統(tǒng)會(huì)問:

一段切多少字?

成熟系統(tǒng)會(huì)問:

這個(gè)文檔是什么類型?
它的標(biāo)題結(jié)構(gòu)是什么?
它有沒有流程?
它有沒有表格?
它的最小知識(shí)單元是什么?
它的父級(jí)上下文是什么?
用戶問具體問題時(shí)怎么精準(zhǔn)召回?
用戶問完整流程時(shí)怎么恢復(fù)全貌?

真正好用的 RAG 系統(tǒng),一定不是只靠大模型硬答,而是在入庫階段就把知識(shí)結(jié)構(gòu)設(shè)計(jì)好。

最后用一句話總結(jié):

Small Chunk 解決“找得準(zhǔn)”,Parent Chunk 解決“講得全”,Window Retrieval 解決“不斷章取義”,Section Retrieval 解決“長文檔完整理解”,流程類文檔必須記錄 stepNo 和 totalSteps。

Chunk 切分做得越細(xì),RAG 系統(tǒng)上線后越穩(wěn)。切分階段偷懶,后面就只能靠 Prompt、Rerank、模型能力不斷補(bǔ)坑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容