news 2026/9/12 19:13:46

RAG 分块策略实测:固定窗口 vs 递归切分 vs 结构感知,用 100 道题说话

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RAG 分块策略实测:固定窗口 vs 递归切分 vs 结构感知,用 100 道题说话

RAG(检索增强生成)落地时,分块(chunking,把长文档切成喂给向量库的小段)大概是工程师踩的第一个参数坑。怎么切、切多大,网上的答案是清一色的理论推演:“语义完整性”、“粒度平衡”、“建议 512”。这些建议有没有数字撑腰?我把自己的 10 篇技术长文切了,跑了个对照实验。

一、实验怎么搭的

语料:2026 年本人写的 10 篇实测长文(DeepSeek Harness 系列 4 篇、ARC-AGI-3 harness 实测、DseWiki 数据实拉、SkillSpector 扫描、两篇模型对比、一篇 Code Review 规范重写),其中 7 篇已发在本账号,3 篇是没发的稿子——语料按域选齐,不看发布状态。共 74,727 字符,清洗掉导航行和状态注记,代码块和表格原样保留——中文技术文,带代码、带表格,是分块策略最容易出事故的文体。

测试集:100 道题。每篇文章出 10 题,分两档——A 档 30 道主题级(问文章主线话题),B 档 70 道细节级(必须读到正文里的具体数字、命令、报错才能答,比如"DSH 用 npm 发了多少个版本")。题目按真实搜索口吻写,不允许出现"这篇文章"这种元指涉。ground truth(标准答案)标到文章级。

变量与固定量:被测的是三种分块策略 × 三种粒度——

固定窗口递归切分结构感知
实现字符滑窗LangChainRecursiveCharacterTextSplitter,中文分隔符自建,按 Markdown 标题分节,代码块不切断
粒度256 / 512 / 1024 字符同左同左

嵌入模型固定 bge-small-zh-v1.5,向量库 Chroma,top-k=5,重叠(overlap)固定 50 字符。3×3 共 9 组配置,每组 100 题全量检索,共 900 次。CPU 跑完一组 10~15 秒。

二、主结果:总体差异小得意外

配置块数Hit@1A 档 Hit@1B 档 Hit@1MRR@5代码块切断次数
固定-2563660.8300.7670.8570.87723
固定-5121650.8300.7670.8570.87710
固定-1024800.8300.8670.8140.8857
递归-2564710.8200.7670.8430.87512
递归-5122030.8200.7670.8430.8754
递归-1024900.8100.7670.8290.8652
结构-2563470.8100.7670.8290.86710
结构-5121880.8100.7670.8290.8678
结构-1024970.8200.7670.8430.8722

九组配置的 Hit@1 全挤在 0.81~0.83。选错分块策略的代价,比网上说的小得多——至少在万字级语料、文章级 ground truth 这个口径下,策略之间拉不开数量级差距。

但 A/B 分层看,结论才站得住。

三、A/B 档方向相反

A 档(主题级)只有固定-1024 突出:0.867,其余八组齐刷刷 0.767。大窗口把整篇文章的主题语境塞进一个块里,主题级查询的语义匹配更稳。

B 档(细节级)反过来:固定-1024 掉到 0.814,是三种策略的 1024 粒度里最差的;256 和 512 粒度下三策略的差距压在 2 题以内(0.829~0.857)。细节事实分散在全文各处,窗口越大,单块里被"稀释"掉的上下文越多。

说直白点:如果你的 RAG 主要答"这份文档讲了什么"级别的问题,大窗口是免费收益;如果答细节,大窗口开始亏。

四、1024 字符组藏着截断伪影

实验里最反直觉的一组数字:bge-small-zh-v1.5 的输入窗口是 512 token,我用 tokenizer 逐块实测——固定-1024 有 90% 的块超长被模型静默截断,递归-1024 是 72%,结构-1024 是 61%。也就是说,1024 粒度组测的根本不是"1024 字符的分块效果",而是"1024 字符的块被截成前半段的效果"。

那固定-1024 的 A 档优势是真的吗?我补了个对照:同样的分块,一组保留前 510 token(模型默认行为),一组保留后 510 token——

截断方向A 档 Hit@1B 档 Hit@1
保头(默认)0.8670.814
保尾0.8330.729

保尾让 B 档掉了 8.5 个百分点。细节事实散布在块的全文,截掉哪头都丢内容;而主题词天然集中在块的开头,静默截断"恰好"护住了主题信号——固定-1024 的 A 档领先,一部分是截断方向的运气,不是大窗口本身的功劳。顺带一个实操提醒:选大 chunk 前先查嵌入模型的 max_seq_length,否则你在测一个自己没意识到的混合体。

五、结构感知的真实价值在代码块

结构感知策略在命中率上没赢,但它赢了另一张表:代码块被切断的次数

同样是 256 字符,固定窗口切了 23 次代码块,结构感知只切 10 次;拉到 1024,结构感知和递归都只剩 2 次,固定窗口还有 7 次。切断的代码块在检索层看不出来——数字上它照样命中——但下游生成层拿到半截package.json或半条命令,就是幻觉的直接原料。如果 RAG 检索结果要喂给模型生成答案,代码完整性比 2 个点的命中率值钱。

六、5 道题,9 组配置全部失手

有 5 道题在所有配置下 Hit@1 全军覆没。一个个拆开看,死法几乎一样:全死在跨文章语义重叠。“dsh 启动后 web 界面默认开在哪个端口”,答案在 DSH 上手实录,top1 却是 197 包架构解读;"dsh 官方自带哪几个预设模式"问的也是上手实录,被插件市场文抢走;"dsh 的 patch 文件里空数组后面能追加条目吗"指向插件市场文,top1 是上手实录;"DSH 的 197 个包按功能分成了哪几大类"问 197 包文,还是被上手实录压过去;"只读沙箱里的 agent 怎么把 wiki 页面改掉的"指向 DseWiki 数据实拉,top1 是 DSH 插件开发——沙箱执行语境强重叠。五道题里四道死在 DSH 系列内部互抢:同一个系列写多了,篇与篇的检索边界自然糊掉。

这不是分块的锅。任何 chunking 配置都救不回语义层的歧义,这个锅在下游——重排序(rerank,拿原查询对候选块精排)或元数据过滤。这也是系列第 2 篇的入口:chunking 榨不出来的分,得去重排序那层取。

七、工程结论

  1. 别为分块策略焦虑:9 组配置的差距被普遍高估,先把嵌入模型、测试集和 top-k 调明白,收益更大;
  2. 按问题类型选粒度:答主题选大窗口,答细节选 256~512;两种都要,就上父子分块(粗粒度检索、细粒度喂给模型);
  3. 大 chunk 先查嵌入窗口:超窗的截断是静默的,必要时把 chunk 控制在模型 max_seq_length 的 token 数内;
  4. 带代码的语料优先结构感知:命中率没赢,代码完整性完胜,生成质量的钱在这省;
  5. 分块解决不了语义歧义:留预算给重排序。

数据核验说明

  • 语料 10 篇共 74,727 字符,清洗规则与文件清单见 rag-lab 仓库corpus/
  • 测试集 100 题(A 档 30 / B 档 70),LLM 按篇生成、人工全检,元指涉与 schema 错误均为 0;跨篇撞题用 6 字滑窗初筛后人工复核为 0;
  • 全实验 900 次检索为单次运行(无重复),CPU 每组 10~15 秒;嵌入模型 bge-small-zh-v1.5(512 维),向量库 chromadb 1.5.9,递归切分为 langchain-text-splitters 实现;
  • ground truth 标文章级,top-k 命中目标文章即记 hit,是宽松口径——数字只用于 9 组横向对比,不代表端到端问答质量;
  • 语料 10 篇全部为本人原创的中文技术文(AI 实测域,已发布 7 篇、未发稿 3 篇),Java 老文尚未混入,跨域干扰指标本期为 0、留待语料扩充后补测;结论不外推英文语料与其他文体;
  • 截断对照只覆盖固定-1024 的头/尾两方向,未做 3×2 全因子;n=100 报分层观察,不做显著性检验。

一条命令复现

gitclone https://github.com/ethanliang2016/rag-lab&&cdrag-lab pipinstall-rrequirements.txt python src/run_eval.py

模型自动从 hf-mirror 下载,全部结果(含 100 题逐题命中记录、5 道顽固题明细、截断对照数据)在results/目录。


留个问题:你们的 RAG 里 chunk 大小是怎么定的,是拍的还是测的?评论区聊聊,下一篇我拿重排序来救那 5 道顽固题。


相关实测

  • 《RAG 重排序实测:双编码召回 + CrossEncoder 精排,500 条真实查询上的收益与代价》—— 分块撞墙之后往下游要,精排能救回多少
  • 《RAG 生成层实测:把答案递到模型嘴边,7B 还是漏掉一半》—— 检索修到 0.506 之后,生成层还漏多少

完整导航:博客导航|agent 安全 / RAG 实测 / AI 代码治理,都在这

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 19:13:39

Matlab实现BP神经网络时间序列预测实战指南

1. 项目概述:BP神经网络与时间序列预测的完美结合时间序列预测一直是数据分析领域的核心课题之一,从股票价格走势到气象预报,从设备故障预警到销售趋势分析,无不依赖高效准确的预测模型。在众多预测方法中,BP神经网络因…

作者头像 李华
网站建设 2026/9/12 19:13:27

垂直AI软件实战:从通用大模型到细分场景的选型避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 19:11:56

驰宇微TFT-LCD选型与定制开发实战指南

1. 为什么“驰宇微”液晶屏的选型不是查参数表那么简单“驰宇微”这三个字在工业显示领域里,不是品牌名,而是行业里对深圳驰宇微电子有限公司及其TFT-LCD模组产品的习惯性简称。我第一次接触这个厂牌是在2019年做一款手持式电力巡检终端时——客户明确要…

作者头像 李华
网站建设 2026/9/12 19:11:55

ThinkPHP+Vue前后端分离选课成绩管理系统设计与实现全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华