分块(chunking)没什么玄的,就是把文档切成模型能一口咽下去的小块。玄的是"哪种分块好"。所有人都在比召回、比切得准不准,可这张评估表底下压着一格几乎没人画:文档改一次,你得重新嵌多少东西。
我第一版画这一格,画错了,还挺得意。先说这个。
我以为是这样:
旧版 [ 块1 ][ 块2 ][ 块3 ][ 块4 ]
↑ 块2 里删了半句话
新版 [ 块1 ][ 块2'][ 块3 ][ 块4 ]
↑ 只重算这一块
改哪块就重算哪块。增量更新,天经地义。我画完还欣赏了一会儿,觉得自己把这事儿想通了。
然后去翻论文:arXiv:2610.31019,十月二十二号挂出来的,五个人。看完才发现自己漏了一整个东西:边界。
再画一张:
旧版 |---块1---|---块2---|---块3---|
新版 |---块1---|---块2-------|---块3---|
↑ 块2 短了,块3 的起点往前挪
块3 的内容一个字没动。可它被切的位置变了,切出来的那串字符跟着变,嵌入就得重算。而且这个位移会顺着往后一路传,越靠后的块越容易被前面的一次编辑推走。
我盯着第二张图看了半天,才把"内容没变但位置变了"和"位置变了所以字符序列变了"这两件事接上。第一张图不是错在方向,是错在它把块当成一个个独立的抽屉——其实它们是一条绳上剪出来的段。
等等等等,先别急着说"那我把块切得稳一点不就行了"。稳一点是有代价的,往下看。
论文比了三种无状态分块器:不重叠固定大小、递归段落优先、内容定义。规则卡得很死:120 对相邻的中英文维基百科修订版本,只有字节完全相同才允许复用旧嵌入,编码器冻结。说白了,能省的地方它一点没漏,省不下来的都是真省不下来。
116 篇进了共同成功池,长度校准后的参数下:
| 分块器 | 重算的新版本嵌入输入占比 |
|---|---|
| 不重叠固定大小 | 57% – 68% |
| 递归段落优先 | 38% – 56% |
| 内容定义 | 43% – 54% |
我第一反应是内容定义应该最省——它不就是按内容找边界的吗?结果跟递归基本同档,中文 62 篇里还有 4 篇压根没切成能用的样子,掉出共同池。行吧,又挨一下。
那 4 篇为什么失败,论文只说失败了,没给原因。我的猜测是中文没有空格,内容定义的边界靠特征判断,特征一飘就切不动。这是猜的,别当结论。
插一句我自己的判断:静态快照上做的检索评估,有一半是在自娱自乐。论文那个数最能说明问题——固定 2048 token 的检索预算下,同一语言内部,三种分块的平均证据召回率差不到 2 个百分点。重算成本差 20 到 30 个点,召回差 2 个点。那我过去在分块策略上纠结半天,纠结的是哪一头?
咔哒一下扣上了:这一格量的不是"切得准不准",是"你的知识库活着要花多少钱"。
打个比方。把一篇文章裁成一叠等宽的纸条,你在中间某个字上改一笔,所有纸条的折痕都得重折——因为折痕是拿尺子量着宽度打的,不是量着意思打的。
旧: |----|----|----|----|----|
↑ 这儿删掉两个字
新: |----|---|----|----|----|----|
↑ 后面每一条折痕都跟着挪了
这个比喻挺顺手,但它漏风,我得标出来:它能解释固定大小为什么最贵,解释不了递归和内容定义为什么也没便宜到哪去,也有三四成。后者得回到机制本身。每个 chunk 是独立嵌入的,彼此没有共享坐标,这是分块这个设计的地基,不是能随手去掉的装饰。地基不动,边界一动,重算就躲不掉。比喻负责把你送到"边界"这个门口,进门之后还得看真实机制。
还有一层我得老实说:内容定义"更省"这结论别急着抄下来。论文的成本参数网格显示,递归和内容定义这两种内容感知分块器的成本排序,会随着 chunk 长度设置翻转。这句话离开参数就是空的。长度匹配的所有条件下唯一站得住的,是不重叠固定大小最贵,这一条稳。
我以前更新知识库的做法是整批重跑,图省事。看完这些数才反应过来,我每次重跑都在替"边界漂移"买单,而且买了很久。
反过来,那个"字节完全相同才复用"的死规则,其实给了我一个偏乐观的信号。真实工程里没人会傻到按字节比,你按段落做哈希、或者给每个 chunk 存一份源区间,能省的比论文里这个下限多得多。这是我的推论,论文没测,别拿它当论文结论。
至于"边界漂移就是重算的成因"这个判断,论文不是从数据里反推出来的,还做了受控编辑和逐字存在诊断来撑。这点我信。
画到这儿。自检一句:现在你能不能给一个没碰过分块的人讲明白,改一个错别字为什么会让六成的嵌入重算?如果讲到"块3 内容没变凭什么重算"那里卡住,那多半是边界这一格没画清楚,回来我们补。
下期想画开哪个,你说了算。我这儿压着两个候选:一个是"embedding 模型换一版为什么就得全量重建",另一个是"chunk 重叠到底在救什么"。哪个更想看?
