> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/context_engineering_guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/context_engineering_guide/di-er-bu-fen-he-xin-ji-shu-yu-ce-le/05_select/5.2_chunking.md).

# 5.2 文档分块策略

## 5.2.1 分块的重要性

**分块**（Chunking）是将大文档切分为小片段的过程，是 [RAG](/context_engineering_guide/di-er-bu-fen-he-xin-ji-shu-yu-ce-le/05_select/5.1_rag_principles.md) 系统的关键步骤。分块质量直接影响：

* 检索精度：能否找到最相关的内容
* 上下文完整性：检索到的内容是否包含完整语义
* Token 效率：是否高效利用上下文空间

## 5.2.2 分块的基本原则

**原则一：语义完整性**

每个块应该是一个语义完整的单元，能够独立表达完整的含义。

**原则二：大小适中**

块不能太大（占用过多上下文空间），也不能太小（缺失必要上下文）。

**原则三：信息自包含**

块应该包含理解其内容所需的必要背景信息。

## 5.2.3 常见分块方法

```mermaid
graph TB
    subgraph "分块方法层级"
        A["固定大小分块"]
        B["基于分隔符分块"]
        C["递归分块"]
        D["语义分块"]
        E["基于 LLM 分块"]
    end

    A --> |"简单"| F["复杂度"]
    E --> |"复杂"| F
```

图 5-2：分块方法层级

### 固定大小分块

按固定的字符数或 Token 数切分。

```
优点：实现简单、结果可预测
缺点：可能破坏语义完整性
适用：快速原型、对质量要求不高
```

参数：块大小（通常 500-2000 字符）、重叠大小（10-20%）

### 基于分隔符分块

按自然分隔符（段落、句子、换行）切分。

```
优点：保持自然边界
缺点：块大小不一致
适用：结构清晰的文档
```

常用分隔符：`\n\n`、`\n`、`.`、`。`

### 递归分块

尝试按多级分隔符切分，自动适应文档结构。

```
优点：平衡完整性和一致性
缺点：实现较复杂
适用：大多数文档类型
```

典型分隔符序列：`["\n\n", "\n", " ", ""]`

### 语义分块

基于语义相似度切分，保持语义单元完整。

```
优点：语义完整性最好
缺点：计算成本高
适用：对质量要求高的场景
```

实现方式：计算相邻句子的嵌入相似度，在相似度低谷处切分。

### 基于 LLM 分块

使用语言模型理解内容结构进行切分。

```
优点：理解能力最强
缺点：成本高、延迟大
适用：高价值内容、复杂文档
```

## 5.2.4 分块策略对比实验（示意）

为了说明不同分块策略可能带来的差异，下面给出一个 **示意性的对比图**（不同数据集、检索器、嵌入模型与评测口径会导致结果差异很大）：

```mermaid
xychart-beta
    title "不同分块策略的检索效果对比 (Recall@10)"
    x-axis ["固定大小(200)", "固定大小(500)", "语义分块", "递归分块"]
    y-axis "Recall@10 (%)" 40 --> 90
    bar [65.2, 72.5, 85.8, 81.3]
```

图 5-3：不同分块策略检索效果示意

*注：数值仅用于说明趋势，不应被视为可复现的通用结论。*

* **语义分块** 通常能获得最佳的检索效果，因为其保持了语义单元的完整性。
* **递归分块** 在效果与成本之间取得了较好的平衡。
* **过小的固定分块** 容易破坏语义，导致召回率下降。

## 5.2.5 分块参数调优

**块大小选择**

| 场景    | 推荐大小            | 理由      |
| ----- | --------------- | ------- |
| 精确问答  | 200-500 Token   | 聚焦单一信息点 |
| 综合理解  | 500-1000 Token  | 更多上下文   |
| 长文档摘要 | 1000-2000 Token | 涵盖更多内容  |

**重叠设置**

重叠可以防止信息被切断在边界处，典型设置为块大小的 10-20%。

**元数据保留**

为每个块附加元数据：

* 来源文档
* 位置信息（第几章、第几节）
* 标题层级
* 时间戳

## 5.2.6 特殊文档类型处理

**代码文档**

按函数、类等逻辑结构切分，而非按行数。

**表格数据**

保持行完整性，必要时将表头附加到每个块。

**对话记录**

按对话轮次切分，保持问答对完整。

**技术文档**

尊重标题层级结构，将标题作为块的上下文前缀。

## 5.2.7 分块质量评估

评估分块效果的方法：

1. **边界检查**：人工检查切分边界是否合理
2. **检索测试**：测试典型查询能否检索到相关块
3. **下游效果**：观察最终任务效果

## 5.2.8 最佳实践

1. **从递归分块开始**：适用于大多数场景
2. **根据内容调整**：不同类型文档使用不同策略
3. **保留结构信息**：将标题等信息附加到块中
4. **测试和迭代**：持续评估和优化分块效果

## 5.2.9 实战案例：三种场景的分块对比

以下是三种典型场景的分块策略对比，展示如何根据内容特点选择合适的方法。

### 案例一：产品规格表

**场景**：用户问“这款手机支持 5G 吗？”需要从产品说明书中检索答案。

**错误做法**：

```
# 按 500 字符固定分块

第一块: "...4800万像素主摄像头，支持光学防抖。5G 网络..."  ← 5G信息被切断
第二块: "...支持 SA/NSA 双模。电池容量 5000mAh..."
```

**正确做法**：

```
# 按产品规格表的属性分块

块-网络: "网络制式: 5G SA/NSA 双模，支持 n1/n28/n41/n78 频段"
块-相机: "摄像头: 4800万像素主摄，支持光学防抖"
块-电池: "电池: 5000mAh，支持 67W 快充"
```

**踩坑经验**：规格表按固定字符数分块会把相关属性切断，导致模型无法完整回答。应按语义属性分块，每个块对应一个完整的产品特性。

***

### 案例二：法律合同

**场景**：找出合同中的“不可抗力”免责条款。

**错误做法**：

```
# 按段落分块，但切断了条款

第一块: "...第八条 不可抗力 如因战争、地震、洪水等不可..."
第二块: "...抗力事件导致合同无法履行，双方均不承担违约责任。"
```

**正确做法**：

```
# 按条款层级分块，保持完整

块-第八条: "第八条 不可抗力
如因战争、地震、洪水等不可抗力事件导致合同无法履行，双方均不承担违约责任。
不可抗力事件发生后，受影响方应在 7 日内书面通知对方。"
```

**踩坑经验**：法律文本的完整性至关重要。曾因分块切断句子导致法律含义改变（“不承担”变成“承担”）。必须按条款结构分块，宁可块大一点也不能破坏语义完整性。

***

### 案例三：代码库

**场景**：开发者问“这个函数是怎么实现的？”

**错误做法**：

```
# 按 50 行固定分块

第一块: "def calculate_price(items):
    total = 0
    for item in items:
        if item.discount:"  ← 函数被切断

第二块: "            price = item.price * 0.8
        else:
            price = item.price
        total += price
    return total"  ← 缺少函数开头
```

**正确做法**：

```
# 按函数/类为单位分块

块-calculate_price: "# 位置: pricing.py:45-62
def calculate_price(items):
    '''计算购物车总价，支持折扣'''
    total = 0
    for item in items:
        if item.discount:
            price = item.price * 0.8
        else:
            price = item.price
        total += price
    return total

调用方: checkout.py:process_order()"

```

**踩坑经验**：代码按行数分块会切断函数逻辑，模型无法理解完整实现。应按 AST（抽象语法树）提取函数/类为单位，并附带调用关系元数据。
