传统 RAG 的困境
如果你用过 RAG(检索增强生成),应该熟悉这套流程:
- 文档切片(chunking)
- 向量化(embedding)
- 存入向量数据库
- 查询时检索 Top-K 相似片段
- 喂给 LLM 生成答案
这套方案有个致命问题:切片粒度很难把握。
切太小,语义不完整;切太大,噪音太多。更麻烦的是,向量相似度检索本质上是模糊匹配——它能找到相关的内容,但不一定能找到精确的内容。
比如你问项目预算在第几章?,向量检索可能返回一堆提到预算的片段,却无法告诉你精确的章节位置。
PageIndex 的思路:给 AI 一张地图
PageIndex 的核心理念很简单:不用向量,用结构。
它把文档解析成一棵层级树:
文档
├── 第一章 概述
│ ├── 1.1 项目背景
│ └── 1.2 目标与范围
├── 第二章 技术方案
│ ├── 2.1 架构设计
│ └── 2.2 技术选型
└── 第三章 实施计划
这棵树直接放在 LLM 的上下文窗口里。检索时,LLM 像人一样读目录找答案:
- 问题:架构设计在哪? → LLM 定位到
第二章 > 2.1 架构设计 - 问题:项目总体目标是什么? → LLM 定位到
第一章 > 1.2 目标与范围
这就是 推理即检索(Reasoning-based Retrieval)。
技术实现:从文档到树状索引
PageIndex 支持 PDF 和 Markdown 两种文档格式。
PDF 处理流程
PDF 是最难处理的格式,因为它的结构往往藏在排版里,而不是代码里。
PageIndex 的处理逻辑:
PDF 输入
↓
Step 1: PDF 解析(提取每页文本,计算 token 数)
↓
Step 2: 目录检测(扫描前 N 页,判断是否有目录)
↓
Step 3: 结构生成
├── 有目录 + 有页码 → 直接解析
├── 有目录 + 无页码 → LLM 匹配章节位置
└── 无目录 → LLM 从文本推断结构
↓
Step 4: 标题验证(检查章节是否真的出现在对应页)
↓
Step 5: 后处理(生成树结构、节点 ID、摘要)
↓
输出 JSON 结构
三种目录场景的智能处理是亮点:
| 场景 | 处理方式 |
|---|---|
| 有目录 + 有页码 | 直接解析,计算物理页码偏移 |
| 有目录 + 无页码 | LLM 遍历文档匹配章节起始位置 |
| 无目录 | 将页面分组,LLM 逐组提取结构 |
Markdown 处理流程
Markdown 天然有层级结构(# 到 ######),处理起来简单得多:
Markdown 输入
↓
Step 1: 读取文件,按行分割
↓
Step 2: 正则提取标题节点(跳过代码块内的标题)
↓
Step 3: 提取每个标题下的文本范围
↓
Step 4: 树瘦身(可选,合并过于细碎的节点)
↓
Step 5: 构建树结构
↓
Step 6: 并发生成节点摘要
↓
输出 JSON 结构
树瘦身(Tree Thinning)
对于层级过深的 Markdown 文档,PageIndex 提供了瘦身功能:
- 计算每个节点的 token 数
- 如果节点 token 数小于阈值,将子节点合并到父节点
- 减少细碎节点,优化检索效果
检索阶段:无向量 RAG 的实现
索引构建完成后,检索就很简单了:
用户提问
↓
Step 1: 加载文档树结构 JSON
↓
Step 2: 构建节点摘要列表
↓
Step 3: LLM 推理,选择最相关的节点(返回 node_id)
↓
Step 4: 提取选中节点的完整文本
↓
Step 5: 基于上下文生成答案
检索 Prompt 示例
你是一个文档检索助手。根据问题,从以下节点中找出最可能包含答案的节点。
问题: {用户的问题}
可用节点:
- 0001: 第一章 概述 - 本文档介绍了项目的整体背景和目标...
- 0002: 第二章 技术方案 - 详细描述了系统架构和技术选型...
- 0003: 第三章 实施计划 - 包含项目的时间节点和里程碑...
请只返回一个 JSON 数组,包含最相关的 node_id(最多3个)
LLM 返回 ["0002"],系统就去提取节点 0002 的完整内容。
与传统向量 RAG 的对比
| 维度 | 传统向量 RAG | PageIndex |
|---|---|---|
| 依赖组件 | 向量数据库(Pinecone、Milvus 等) | 无需额外组件 |
| 切片策略 | 需要精心设计 | 自动结构化 |
| 检索方式 | 向量相似度匹配 | LLM 语义推理 |
| 可解释性 | 较差(返回相似片段,但不知道来自哪) | 好(返回具体节点 ID 和位置) |
| 上下文质量 | 可能包含噪音 | 精准章节定位 |
| 适用场景 | 通用问答 | 结构化文档、专业领域 |
核心优势
1. 降低系统复杂度
不需要部署向量数据库,不需要调切片参数,不需要维护索引。一个 JSON 文件搞定。
2. 精准定位
传统 RAG 返回的是相似片段,PageIndex 返回的是具体章节。后者更接近人类的检索方式。
3. 可解释
每个答案都能追溯到具体的节点 ID。用户可以验证:哦,答案来自第三章 3.2 节。
4. 层级灵活
可以回答概览级问题(这份报告讲什么?),也可以回答细节问题(第三章的实施步骤是什么?)。
快速上手
安装
git clone https://github.com/VectifyAI/PageIndex.git
cd PageIndex
pip install -r requirements.txt
处理 PDF
python run_pageindex.py \
--pdf_path ./documents/report.pdf \
--model qwen3-max \
--if-add-node-summary yes
处理 Markdown
python run_pageindex.py \
--md_path ./documents/readme.md \
--model qwen3-max \
--if-thinning yes
执行 RAG 查询
python pageindex_rag_simple.py \
--structure ./results/doc_structure.json \
--query "文档主要内容是什么?"
局限性
PageIndex 不是银弹:
- 依赖文档结构:如果文档本身没有清晰的结构(比如小说、散文),效果会打折扣
- LLM 成本:构建索引和检索都需要调用 LLM,成本比纯向量检索高
- 语言限制:目录检测和结构推断对中文 PDF 的效果可能不如英文
- 超长文档:如果文档结构树太大,超出上下文窗口,需要额外的分片策略
总结
PageIndex 代表了一种新的 RAG 范式:用结构化索引替代向量切片,用 LLM 推理替代相似度匹配。
它不是要取代向量 RAG,而是提供了一个更适合结构化文档的方案。如果你的场景是处理技术文档、研究报告、法律合同这类有清晰层级的内容,PageIndex 值得一试。
GitHub: https://github.com/VectifyAI/PageIndex
参考资源:
- PageIndex 官方文档: https://pageindex.ai/
- FinanceBench 评测: 98.7% 准确率