RAG 语义分片演示项目
RAG Chunk Demo (FastAPI)
这是一个可运行的 RAG 分片演示项目,包含:
- 文档结构识别(标题/层级)
- 章节优先切分
- 超长内容递归切分
- 列表前导句保护
- 表格按行切分并复制表头
- 句子级 overlap
- 真实 token 计数(tiktoken)
- 文档结构评分(doc_structure_score)
- 切分方式展示(split_strategy)
- chunk 元数据(section_path、prev/next、is_key_content、weight)
完整项目可以在Github获取。
1. 安装依赖(uv)
1 | uv sync |
2. 启动
1 | uv run uvicorn app.main:app --reload --port 8000 |
浏览器打开:
3. 使用方式
- 上传
.txt或.md文件(UTF-8/GBK)。 - 可调参数:
base_max_sizekey_content_max_sizeoverlap
- 页面会展示:
- 分片统计摘要
- 每个 chunk 的文本
- 元数据(chunk_id、section_path、is_key_content、weight、prev/next)
- 文档结构评分、结构质量和切分方式
4. 分片规则
本项目的分片策略不是“固定长度硬切”,而是按“先识别结构,再决定是否切分”的顺序执行。
4.1 标题识别规则
分片前会先扫描文本,识别章节边界。当前支持的标题格式包括:
- Markdown 标题:
#到###### - 中文章节标题:
第X章、第X节、第X条 - 中文编号标题:
一、、二、、三、等 - 数字编号标题:
1、1.2、1.2.3等后接正文的行 - 中文括号标题:
(一)、(二)等
为了减少误判,以下内容不会被当作标题:
- 日期和时间行,例如
2026年10月18日 08:30 - 16:30 - 全数字或数字密集的行
- 明显属于数据内容、表格内容、列表内容的行
4.2 章节优先策略
chunk_document() 采用“章节优先”原则:
- 先按标题把文档拆成 section。
- 统计每个 section 的 token 长度。
- 如果 section 长度
<= max_size,则直接保留为一个完整 chunk,不再继续切分。 - 只有当 section 超过阈值时,才进入递归切分。
这意味着:
- 小章节会尽量保持完整,不会被过度打散。
- 大章节才会继续细分,避免一次性产生太多碎片。
base_max_size和key_content_max_size会共同影响实际切分阈值。- 长章节会继续进入更细粒度的递归切分;短章节会直接保留为完整 chunk。
4.3 超长 section 的递归切分
当 section 超过阈值时,会按以下顺序继续处理:
- 先尝试列表保护:如果内容是“前导句 + 列表”,会把前导句和列表项绑定在一起。
- 再判断是否为表格块:如果是表格,则按行切分,并在每个 chunk 中复制表头。
- 如果既不是列表块也不是表格块,则先按段落拆分,段落仍超长时再进入句子级切分。
- 句子级切分是最后的回退手段,由
sentence_chunk()负责。 - 递归切分时会保留句子级 overlap,增强上下文连续性;当
overlap=0时不会回带上一句。
4.4 列表保护规则
对于这类内容:
1 | 以下内容为报名要求: |
系统会尽量把前导句和列表项视作一个整体,而不是把前导句单独切出去。这样可以避免列表失去说明上下文。
4.5 表格切分规则
如果文本被识别为表格块,切分时会采用“表头复制 + 按行分段”的方式:
- Markdown 表格会保留表头和分隔行。
- 后续行按长度上限分配到不同 chunk 中。
- 每个 chunk 都尽量保持可读、可单独理解。
4.6 overlap 规则
超长文本按句子切分时,会保留一定长度的 overlap:
- overlap 以句子为单位回退,而不是按字符盲切。
- 这样可以保留上下文衔接,减少 chunk 边界处的信息丢失。
- overlap 的实际长度由页面参数
overlap控制。 - 当
overlap=0时,不会保留上一句上下文。
4.7 文档结构评分
分片结果里会返回 doc_structure_score,用于描述文档结构是否清晰:
- 标题数量越多,得分越高
- 标题层级越完整,得分越高
- 列表和表格越丰富,得分会有额外加分
评分结果会显示在 summary 中,并附带 structure_quality:
high:结构清晰,适合按章节组织medium:结构尚可low:标题较少,结构偏弱
4.8 切分方式展示
摘要区还会显示 split_strategy,用于说明当前文档实际用了哪些切分路径:
章节优先:所有文档都会经过的首层策略表格切分:文档中包含表格块时出现递归切分:章节超长,需要继续拆分时出现句子级 overlap:递归切分且overlap > 0时出现
如果文档很短,通常只会看到 章节优先。
4.9 输出结果里会看到什么
每个 chunk 通常会带上这些信息:
chunk_id:分片唯一编号section/section_path:来自哪个章节type:text或tablestart_char/end_char:在原文中的字符位置prev_chunk_id/next_chunk_id:前后 chunk 关系is_key_content:是否为重点内容weight:重点内容权重更高
4.10 典型效果
- 结构清晰、但篇幅较短的通知或说明文档:通常会保留为少量完整 chunk。
- 超长制度、FAQ、研究指南:会在章节内继续递归切分。
- 表格、清单、带前导说明的列表:会优先保持可读性和上下文完整。
- 页面摘要会同时显示分片统计、文档结构评分、结构质量和切分方式,方便快速判断当前文档走了哪条路径。
4. 主要文件
app/chunker.py:分片核心逻辑app/main.py:FastAPI 路由templates/index.html:页面模板static/style.css:样式static/app.js:前端交互
5. 可继续升级
- embedding 语义断点切分
- PDF 版面信息(字体/坐标)融合
- 接入向量库并演示检索效果
6. 兼容说明
- 当前仓库仍保留
requirements.txt,用于兼容非 uv 场景。 - 推荐默认使用 uv:
uv sync+uv run ...。 - 若系统中没有全局
uv命令,可先安装:pip install uv。 - 若仅安装在项目虚拟环境,可使用:
./.venv/Scripts/uv.exe sync与./.venv/Scripts/uv.exe run uvicorn app.main:app --reload --port 8000。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 沃特陌 | Wotemo!
评论


