【AI面试临阵磨枪-40】文本切块(Chunking)策略:固定长度、语义切块、递归切块、重叠设计

一、面试题目

请详细介绍 RAG 中文本切块(Chunking)四大核心策略:固定长度切块、语义切块、递归字符切块、切块重叠设计,分别原理、优缺点、适用场景、工程选型建议。

二、知识储备

1. 基础概念

Chunking 文本切块 把长文档切分成小块,用于向量化入库、检索召回,是 RAG 影响召回精度最重要的前置环节 。切块核心矛盾:块太小丢上下文、块太大语义混杂

2. 四种切块策略详解

(一)固定长度切块(Fixed-size Chunking)

原理

固定字符 / Token 长度一刀切,比如每 512 Token 切一块,顺序截取,不考虑句子、段落、语义边界。

优点

  • 实现最简单、速度最快、成本最低
  • 适合海量文档批量处理
  • 可控性强、容易做容量预估

缺点

  • 容易截断句子、割裂语义
  • 一块内可能包含多个无关主题
  • 边界破碎严重,检索精度低

适用场景

  • 结构化不强、口语化、网文、杂乱文档
  • 低成本快速搭建 RAG、原型验证
  • 对召回精度要求不高的场景

工程要点

常用:512 / 1024 Token 固定长度。

(二)递归字符切块(Recursive Character Text Splitter)

原理

分层递归切割 ,按优先级从大到小分隔符依次切:段落换行 \n\n单行换行 \n句号。逗号,空格 → 单个字符 `先按大分隔符切,若仍超长度,再用下一级更细分隔符递归切。

优点

  • 尽量保留段落、句子完整性
  • 不强行截断语义边界
  • 效果远好于固定长度,实现简单
  • 工业级默认首选切块方案

缺点

  • 仍不理解深层语义,只靠符号规则
  • 特殊无标点文档效果一般

适用场景

  • 技术文档、PDF、知识库、手册、书籍
  • 绝大多数企业 RAG 落地首选
  • 有标准标点、段落结构的正式文本

(三)语义切块(Semantic Chunking)

原理

  1. 先按短句 / 小片段粗切
  2. 对每个片段做 Embedding 向量化
  3. 计算相邻片段语义相似度
  4. 相似度低于阈值 → 判定语义边界,从此处切分

优点

  • 按语义主题自然切分,不割裂上下文
  • 每块内部主题单一、纯度高
  • RAG 召回准确率最高

缺点

  • 要多次调用 Embedding,成本高、速度慢
  • 阈值调优依赖经验
  • 长文档处理耗时明显增加

适用场景

  • 高精度知识库、法律合同、医疗文档、专业论文
  • 对问答精准度要求极高、允许一定成本开销
  • 主题边界清晰的正式文稿

(四)切块重叠设计(Chunk Overlap / 滑动重叠)

原理

相邻两个 Chunk 之间保留一段重复文本,例如块长 1024,重叠 128。后一块开头复用前一块末尾一段内容,形成上下文平滑过渡。

核心作用

  • 解决关键信息落在两块边界被拆分、检索漏召
  • 保持跨块上下文连续性
  • 提升问答连贯性,避免断章取义

优点

  • 极低成本大幅提升召回效果
  • 兼容所有切块策略(固定 / 递归 / 语义都可加重叠)

缺点

  • 增加少量 Token、向量数量变多、存储略增

工程经验值

  • 块长 512 → 重叠 64~128
  • 块长 1024 → 重叠 128~256
  • 重叠不宜过大:超过块长 20% 收益边际递减

适用场景

所有生产级 RAG 都必须开启重叠,是标配设计。

3. 四种策略横向对比总结

|----------|---------------|------------|----------|-----------------|
| 切块方式 | 核心原理 | 精度 | 速度成本 | 工程推荐 |
| 固定长度 | 按固定字符硬切 | 低 | 最快、最低 | 原型、杂乱文本 |
| 递归切块 | 按换行 / 句号分层递归切 | 中高 | 快、低成本 | 企业 RAG 默认首选 |
| 语义切块 | 向量相似度识别语义边界 | 最高 | 慢、高成本 | 高精度专业场景 |
| 重叠设计 | 块间保留重复上下文 | 提升 5%~15% | 微增成本 | 全部场景必开 |


4. 工程落地最佳选型(面试直接背)

  1. 通用企业 RAG:递归字符切块 + 固定重叠(10%~20%)
  2. 高精度专业场景:语义切块 + 适度重叠
  3. 快速原型 / 杂乱网文:固定长度切块 + 小重叠
  4. 任何生产环境不允许无重叠切块,必须加 Overlap

5. 常见踩坑

  • 只固定长度不做递归:语义割裂严重、问答乱答
  • 不开重叠:边界关键信息丢失、召回漏缺
  • 语义切块阈值乱设:块过碎或块过大
  • 切块统一尺寸不做自适应:长句被硬截断

三、破局之道

面试高阶总结:文本切块不是简单切字符串,而是在语义完整性、块大小、速度成本、检索召回率之间做平衡。固定长度最简单但精度最差;递归切块靠分隔符分层切割,是工业级性价比首选;语义切块通过向量相似度识别主题边界,精度最高但成本高;重叠设计是所有生产级 RAG 的标配,用极小成本解决边界信息丢失问题。

落地最优组合:递归切块 + 合理重叠做通用基线,高精度业务再叠加语义切块。

四、极简代码实现

Python

python 复制代码
# 1. 固定长度切块 + 重叠
def fixedChunk(text, chunkSize=512, overlap=128):
    chunks = []
    start = 0
    textLen = len(text)
    while start < textLen:
        end = start + chunkSize
        chunks.append(text[start:end])
        # 滑动步进 = 块长 - 重叠
        start += chunkSize - overlap
    return chunks

# 2. 递归字符切块 + 重叠
def recursiveChunk(text, chunkSize=1024, overlap=128):
    # 切割分隔符优先级
    separators = ["\n\n", "\n", "。", ",", " "]

    def splitRecurse(content, sepIdx):
        # 不能再分 或 已经小于块长,直接返回
        if sepIdx >= len(separators) or len(content) <= chunkSize:
            return [content]
        # 按当前分隔符切割
        parts = content.split(separators[sepIdx])
        res = []
        for p in parts:
            res.extend(splitRecurse(p, sepIdx + 1))
        return res

    # 先递归切分
    rawChunks = splitRecurse(text, 0)
    # 加相邻重叠
    final = []
    for i in range(len(rawChunks)):
        if i > 0:
            # 前一块末尾 + 当前块
            merge = rawChunks[i-1][-overlap:] + rawChunks[i]
            final.append(merge)
        else:
            final.append(rawChunks[i])
    return final

JavaScript

javascript 复制代码
// 1. 固定长度切块 + 重叠
function fixedChunk(text, chunkSize = 512, overlap = 128) {
  const chunks = [];
  let start = 0;
  const textLen = text.length;
  while (start < textLen) {
    const end = start + chunkSize;
    chunks.push(text.slice(start, end));
    start += chunkSize - overlap;
  }
  return chunks;
}

// 2. 递归字符切块 + 重叠
function recursiveChunk(text, chunkSize = 1024, overlap = 128) {
  const separators = ["\n\n", "\n", "。", ",", " "];

  function splitRecurse(content, sepIdx) {
    if (sepIdx >= separators.length || content.length <= chunkSize) {
      return [content];
    }
    const parts = content.split(separators[sepIdx]);
    let res = [];
    for (let p of parts) {
      res = res.concat(splitRecurse(p, sepIdx + 1));
    }
    return res;
  }

  // 递归原始切块
  const rawChunks = splitRecurse(text, 0);
  // 叠加重叠
  const final = [];
  for (let i = 0; i < rawChunks.length; i++) {
    if (i > 0) {
      const merge = rawChunks[i-1].slice(-overlap) + rawChunks[i];
      final.push(merge);
    } else {
      final.push(rawChunks[i]);
    }
  }
  return final;
}
相关推荐
techdashen1 小时前
p99 延迟从 9.5 毫秒降到 18 微秒:Cloudflare 机器学习基础设施重构全记录
人工智能·机器学习·重构
AI服务老曹1 小时前
架构师视角:如何构建支持GB28181/RTSP的异构AI视频平台?从Docker部署到源码交付的深度实践
人工智能·docker·音视频
IT_陈寒2 小时前
Vite热更新失效?你可能漏了这个小细节
前端·人工智能·后端
机器之心2 小时前
今天起,Claude正式接入Office全家桶,跨应用还能共享记忆
人工智能·openai
机器之心2 小时前
破案了!为啥ChatGPT老想着「稳稳地接住你」
人工智能·openai
二哈赛车手2 小时前
新人笔记---Spring AI的Advisor以及其底层机制讲解(涉及源码),包含一些遇见的Spring AI的Advisor缺陷问题的解决方案
java·人工智能·spring boot·笔记·spring
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章66-直线夹角
图像处理·人工智能·opencv·算法·计算机视觉
不背八股的AI选手2 小时前
《别再“喂prompt赌运气”了:我的AI开发工程化管理实践》
人工智能
AC赳赳老秦2 小时前
接口测试自动化:用 OpenClaw 对接 Postman,实现批量回归测试、测试报告自动生成与推送
java·人工智能·python·算法·elasticsearch·deepseek·openclaw