學習分塊如何影響回憶品質、嵌入性能,以及回憶增強生成(RAG)系統的整體有效性.
介紹
在建立使用回憶增強生成(RAG)的AI應用程式時,開發人員通常專注於選擇最佳的LLM或嵌入模型。但有一個基礎步驟經常被低估分塊
分塊
分塊是指將大型文件在生成嵌入並存儲到向量資料庫之前,拆分成更小、更易管理的部分。
分塊不佳可能導致:
- 無關的檢索結果
- 虛假的答案
- 缺失語境
- 更高的推理成本
良好的分段,另一方面,顯著提高檢索精確度和回應品質.
在這篇文章中,我們將探討最常見的分段策略,它們的權衡,以及何時使用每種策略.
分段為何重要
大型語言模型和嵌入模型無法有效地處理無限大的文件。
請考慮一份200頁的PDF文件.
我們不將整個文件作為一個向量嵌入,而是將其拆分成更小的塊:
Large Document
↓
Chunking
↓
Embeddings
↓
Vector Database
↓
Semantic Retrieval
↓
LLM Response
沒有塊分割
單個巨大的嵌入:
- 失去語義粒度
- 檢索無關部分
- 增加token成本
帶有分塊功能
相關文件段落變得可搜尋和可檢索
了解分塊的取捨
分塊大小影響檢索品質
太小:
Missing context
太大:
Noise + irrelevant information
理想的片段平衡:
- 語義意義
- 檢索精確度
- 符號效率
1. 固定大小片段切割
最簡單且最廣泛使用的方法
文件根據固定的字元或符號限制來分割
範例:
- 500 符號
- 1000個字元
它是如何運作的
Document
──────────────────────────
Chunk 1 (500 tokens)
Chunk 2 (500 tokens)
Chunk 3 (500 tokens)
Python範例
使用LangChain:
from langchain.text_splitter import CharacterTextSplitter
splitter = CharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = splitter.split_text(document)
優點
- 容易實現
- 快速處理
- 可預測的片段大小
缺點
- 忽略文件結構
- 可能會在句子中間切斷
- 可能會降低語義含義
適合用於
- 快速原型
- 小型數據集
- 簡單的 RAG 系統
2. 遞歸片段分割
一個更智慧的固定大小分塊版本.
它不會盲目分割,而是嘗試保留結構.
典型層級:
- 段落
- 句子
- 詞
只有當較大的區段超過大小限制時,它才會進一步分割.
工作流程
Paragraph too large?
↓
Split into sentences
↓
Sentence too large?
↓
Split into words
範例
LangChain 遞迴分割器:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = splitter.split_text(document)
優點
- 保留意義
- 提升檢索品質
- 處理混合文件
缺點
- 稍慢
- 可能仍然忽略特定領域的結構
適合對象
大多數 RAG 系統.
這通常是預設建議.
3. 基於句子的分塊
這種策略使分塊與句子邊界對齊.
而不是隨意的 token 數量:
Chunk = Complete Sentences
範例
文件:
AI systems rely on retrieval.
Chunking improves retrieval quality.
Poor chunking hurts accuracy.
可能的片段:
Chunk 1:
AI systems rely on retrieval.
Chunk 2:
Chunking improves retrieval quality.
Chunk 3:
Poor chunking hurts accuracy.
Python 範例
使用 NLTK:
import nltk
from nltk.tokenize import sent_tokenize
sentences = sent_tokenize(document)
優點
- 自然語言邊界
- 更乾淨的嵌入
- 改進的語義完整性
缺點
- 不均勻的片段大小
- 長句子可能超出限制
最適用於
- 對話數據
- 文章
- 問答系統
4. 段落式分塊
段落通常包含一個連貫的概念
這讓它們成為有用的分塊邊界
範例
Paragraph 1 → Chunk 1
Paragraph 2 → Chunk 2
Paragraph 3 → Chunk 3
優點
- 高語義連貫性
- 可讀性分塊
- 適合博客和文件
缺點
- 段落長度不同
- 長段落可能溢出
最佳用於
- 博客
- 文件
- 研究論文
5. 重疊分塊
分塊的主要問題:
邊界處的上下文損失.
範例:
片段 1:
The API authentication uses JWT...
片段 2:
...tokens for secure communication.
重要的意義跨越兩個片段.
重疊解決了這個問題.
重疊如何運作
Chunk 1
──────────────
AAAA BBBB CCCC
Chunk 2
CCCC DDDD EEEE
注意:
CCCC
出現在兩個片段中
程式範例
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=100
)
優點
- 更好的檢索連續性
- 減少邊界問題
- 更高的答案準確性
缺點
- 更多嵌入
- 更大向量儲存空間
- 增加檢索成本
適用於
幾乎所有生產型 RAG 系統
典型重疊率:
- 10–20%
6. 語義分塊
語義分塊使用意義而非大小。
文件會在主題變更時分割.
這顯然更智能.
概念
而不是:
Every 500 tokens
我們分割為:
Meaning shift
範例
文件:
Section A → Databases
Section B → Kubernetes
Section C → Security
語義分塊會建立:
Chunk 1 → Database topic
Chunk 2 → Kubernetes topic
Chunk 3 → Security topic
高階流程
Text
↓
Sentence embeddings
↓
Similarity comparison
↓
Topic boundary detection
↓
Chunks
Python 範例(概念性)
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
句子相似度決定分割點
優點
- 出色的檢索品質
- 主題感知
- 強大的語境相關性
缺點
- 計算成本高
- 實現工作量大
最適用於
- 企業搜尋
- 法律文件
- 知識庫
7. 認識結構的片段化
有些文件已包含結構.
範例:
- HTML標題
- Markdown節段
- 帶標題的PDF
- 程式碼檔案
我們不忽略這點,反而利用它。
範例
Markdown:
# Authentication
JWT details...
# Rate Limiting
API throttling...
分塊:
Authentication section
Rate Limiting section
程式範例
Markdown 標題分割器:
from langchain.text_splitter import MarkdownHeaderTextSplitter
headers = [
("#", "Header1"),
("##", "Header2")
]
優點
- 高語義一致性
- 使用作者意圖
- 適合文件記錄
缺點
- 取決於清晰的格式
- 對原始文本效果較差
最適用於
- 開發者文件
- 維基百科
- 技術文件
8. 代码分塊
來源程式碼需要特殊處理
每500個字元分割可能會破壞邏輯
取而代之的是
根據以下方式分割
- 函數
- 類別
- 模組
- AST節點
壞的塊
def login():
...
中間剪斷.
更好的塊
Entire login() function
使用 Tree-sitter 的範例
import tree_sitter
基於 AST 的解析保留語法。
優點
- 保持邏輯結構
- 更佳的代碼檢索
- 適合AI代碼輔助工具
缺點
- 語言特定的工具
適合對象
- 代碼伴跑器
- 儲存庫搜尋
- 軟體文件
比較分塊策略
| 策略 | 品質 | 複雜性 | 最佳用途 |
|---|---|---|---|
| 固定大小 | 低 | 低 | 原型 |
| 遞迴 | 高 | 低 | 通用RAG |
| 句子 | 中 | 低 | 問答 |
| 段落 | 中 | 低 | 文章 |
| 重疊 | 高 | 低 | 生產 RAG |
| 語義 | 非常高 | 高 | 企業 |
| 結構感知 | 高 | 中 | 文件 |
| 程式碼分塊 | 非常高 | 高 | 程式碼 AI |
一個實用的分塊策略
許多成功的 RAG 系統使用一種混合方法.
範例:
Structure-aware
+
Recursive splitting
+
10–20% overlap
流程:
Document
↓
Heading Split
↓
Recursive Chunking
↓
Overlap
↓
Embeddings
↓
Vector DB
這通常提供最佳的平衡:
- 相關性
- 成本
- 簡易性
結論
分塊不僅僅是預處理。
它直接影響:
- 回撥準確度
- 嵌入品質
- 虛擬現實率
- 使用者體驗
沒有普遍的最佳策略.
一個好規則:
- 從遞迴 + 重疊開始
- 移至語義或結構感知的片段化 隨著複雜性增加
- 使用程式碼感知分塊來進行工程系統
在許多情況下,改善分塊所帶來的收益比改用更大型的LLM還要大。












