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. 使用方式

  1. 上传 .txt.md 文件(UTF-8/GBK)。
  2. 可调参数:
    • base_max_size
    • key_content_max_size
    • overlap
  3. 页面会展示:
    • 分片统计摘要
    • 每个 chunk 的文本
    • 元数据(chunk_id、section_path、is_key_content、weight、prev/next)
    • 文档结构评分、结构质量和切分方式

4. 分片规则

本项目的分片策略不是“固定长度硬切”,而是按“先识别结构,再决定是否切分”的顺序执行。

4.1 标题识别规则

分片前会先扫描文本,识别章节边界。当前支持的标题格式包括:

  • Markdown 标题:#######
  • 中文章节标题:第X章第X节第X条
  • 中文编号标题:一、二、三、
  • 数字编号标题:11.21.2.3 等后接正文的行
  • 中文括号标题:(一)(二)

为了减少误判,以下内容不会被当作标题:

  • 日期和时间行,例如 2026年10月18日 08:30 - 16:30
  • 全数字或数字密集的行
  • 明显属于数据内容、表格内容、列表内容的行

4.2 章节优先策略

chunk_document() 采用“章节优先”原则:

  1. 先按标题把文档拆成 section。
  2. 统计每个 section 的 token 长度。
  3. 如果 section 长度 <= max_size,则直接保留为一个完整 chunk,不再继续切分。
  4. 只有当 section 超过阈值时,才进入递归切分。

这意味着:

  • 小章节会尽量保持完整,不会被过度打散。
  • 大章节才会继续细分,避免一次性产生太多碎片。
  • base_max_sizekey_content_max_size 会共同影响实际切分阈值。
  • 长章节会继续进入更细粒度的递归切分;短章节会直接保留为完整 chunk。

4.3 超长 section 的递归切分

当 section 超过阈值时,会按以下顺序继续处理:

  1. 先尝试列表保护:如果内容是“前导句 + 列表”,会把前导句和列表项绑定在一起。
  2. 再判断是否为表格块:如果是表格,则按行切分,并在每个 chunk 中复制表头。
  3. 如果既不是列表块也不是表格块,则先按段落拆分,段落仍超长时再进入句子级切分。
  4. 句子级切分是最后的回退手段,由 sentence_chunk() 负责。
  5. 递归切分时会保留句子级 overlap,增强上下文连续性;当 overlap=0 时不会回带上一句。

4.4 列表保护规则

对于这类内容:

1
2
3
4
以下内容为报名要求:
1. 按时提交材料
2. 保持联系方式畅通
3. 遵守现场安排

系统会尽量把前导句和列表项视作一个整体,而不是把前导句单独切出去。这样可以避免列表失去说明上下文。

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:来自哪个章节
  • typetexttable
  • start_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