RAG 系统的幕后黑手:如何科学地对长文本切片 (Text Chunking)?

0 阅读3分钟

当你决定用 LangChain、LlamaIndex 或是原生的向量数据库(如 ChromaDB)给自己搭建一个私有的知识库搜索问答系统(RAG)时,你很快就会碰到第一个卡脖子的大头疼:文本分块(Chunking)

为什么要做切片? 因为大多数大模型有上下文长度限制,更重要的是,向量模型(Embedding)把太长的文章揉成一个向量的话,会严重丢失细节(也就是所谓的“稀释”)。为了准确,我们需要把一篇 1 万字的技术 PDF,切成一块块 300 到 500 字的小豆腐块。

但怎么切,大有讲究!今天分享三种最主流的切分策略。

第一层级:基于固定字符数量 (Character Splitter)

顾名思义:暴力一刀切。比如设定每块长度为 500 个字母/汉字,且允许前后块有 50 个字重叠 (Overlap) 防止一句话被从中间物理切断。

  • 优点:极其简单、速度最快,不需要引入复杂的计算。
  • 缺点:不带大脑。它很可能会把一行极其关键的代码:public static void main(...) 从中间咔嚓劈开,导致这段代码的两半分别被存了进去,搜索结果惨不忍睹。

第二层级:基于 Token 的切分 (Token Splitter)

因为大模型都是按 Token 计费和限制长度的,所以很多系统会用诸如 tiktoken 这样的库,先把文本转成 Token 再来切。比如规定每块是 512 个 Token。

  • 适用场景:适用于你需要精准控制送给大语言模型的令牌长度,防止超限报错。
  • 评价:属于工程上的稳妥选择,但从“找对意图”的角度来说,它还是盲目的。

第三层级:基于语义 / Markdown 层级的智能切片

这是真正能在实战中拉开差距的地方! 如果你切的是一篇文章,为什么不根据 \n\n(段落符号)来切?如果你切的是代码,为啥不借助树结构的解析器,把一个个完整的 function 或者 class 整体剥离出来?

  • Markdown 切片器:聪明的系统会识别 # 章节一## 子章节。它会努力保证属于同一个 # 标签下的内容待在同一个块里。这保证了局部上下文的完整性。只有块大意完整,Embedding 获取出的向量才是纯粹的。

核心忠告

在 RAG 中,切片策略一旦选错,后面的所有向量搜索都会被污染。 实战中最常用的策略是:“优先以 Markdown 标题或空行切割(保证语义),如果某个自然段实在太长,再用 Token 作为后备切分底线”。


本文是个人学习大模型方向时的实战小记,希望对准备入门 AI 开发的大家有所启发。

感谢关注,我会持续更新,欢迎查看相关源码实现与学习记录:
github.com/start007-sm…