PageIndex 入门指南
PageIndex: 无向量、基于推理的 RAG 系统
什么是 PageIndex?
传统向量数据库 RAG 依赖语义相似度而非真正的相关性。但相似度 ≠ 相关性 —— 检索真正需要的是相关性,这需要推理能力。
PageIndex 是一个无向量、基于推理的 RAG 系统,它从长文档构建层次化树索引,并使用 LLM 在索引上进行推理实现智能、上下文感知的检索。
它模拟人类专家如何通过树搜索导航和提取复杂文档中的知识,让 LLM 能够思考和推理找到最相关的文档部分。
核心特性
相比传统向量 RAG,PageIndex 的优势:
| 特性 | 传统向量 RAG | PageIndex |
|---|---|---|
| 向量数据库 | ✅ 需要 | ❌ 不需要 |
| 分块 | ✅ 人工切分 | ❌ 自然章节 |
| 可解释性 | ❌ 黑盒 | ✅ 基于推理,可追踪 |
| 上下文感知 | ❌ 有限 | ✅ 完整上下文 |
| 人类式检索 | ❌ 相似度匹配 | ✅ 树搜索推理 |
工作原理
PageIndex 分两步执行检索:
1. 生成树结构索引
将长文档转换为类似"目录"的树结构索引,但针对 LLM 优化:
{
"title": "Financial Stability",
"node_id": "0006",
"start_index": 21,
"end_index": 22,
"summary": "The Federal Reserve ...",
"nodes": [
{
"title": "Monitoring Financial Vulnerabilities",
"node_id": "0007",
"start_index": 22,
"end_index": 28,
"summary": "The Federal Reserve's monitoring ..."
},
{
"title": "Domestic and International Cooperation",
"node_id": "0008",
"start_index": 28,
"end_index": 31,
"summary": "In 2023, the Federal Reserve collaborated ..."
}
]
}
2. 基于树的推理检索
通过树搜索进行推理检索,LLM 能够:
- 理解文档层次结构
- 根据问题定位相关章节
- 获取具体内容进行回答
适用场景
PageIndex 特别适合:
- 📊 财务报告 - 10-K、10-Q、年报
- 📜 监管文件 - SEC filings、合规文档
- 📚 学术教材 - 教科书、研究论文
- ⚖️ 法律文档 - 合同、法律手册
- 🔧 技术手册 - API 文档、产品手册
任何超过 LLM 上下文限制的长文档都适合使用 PageIndex。
性能表现
PageIndex 在 FinanceBench 基准测试中达到了 98.7% 的准确率,显著优于传统向量 RAG 系统。
快速开始
1. 安装依赖
pip install -r requirements.txt
核心依赖:
litellm- LLM 调用(支持多模型)pymupdf- PDF 解析PyPDF2- PDF 文本提取python-dotenv- 环境变量管理pyyaml- 配置文件
2. 设置 API Key
创建 .env 文件:
OPENAI_API_KEY=your_openai_key_here
支持多模型(通过 LiteLLM):
# OpenAI
OPENAI_API_KEY=sk-xxx
# Anthropic
ANTHROPIC_API_KEY=xxx
# 其他模型
# 参考:https://docs.litellm.ai/docs/providers
3. 生成 PageIndex 树结构
PDF 文档:
python run_pageindex.py --pdf_path /path/to/document.pdf
Markdown 文档:
python run_pageindex.py --md_path /path/to/document.md
输出结果保存到 ./results/ 目录。
可选参数
# 模型选择
--model gpt-4o-2024-11-20
# PDF 参数
--toc-check-pages 20 # 检查目录的前 20 页
--max-pages-per-node 10 # 每个节点最大页数
--max-tokens-per-node 20000 # 每个节点最大 token 数
# 输出选项
--if-add-node-id yes # 添加节点 ID
--if-add-node-summary yes # 添加节点摘要
--if-add-doc-description yes # 添加文档描述
--if-add-node-text yes # 添加节点文本
# Markdown 参数
--if-thinning yes # 树剪枝(减少冗余节点)
--thinning-threshold 5000 # 剪枝最小 token 阈值
--summary-token-threshold 200 # 摘要 token 阈值
使用 PageIndexClient
初始化客户端
from pageindex import PageIndexClient
# 创建客户端(指定工作空间)
client = PageIndexClient(workspace="~/pageindex_workspace")
# 或者直接使用 API Key
client = PageIndexClient(api_key="sk-xxx")
索引文档
# 索引 PDF
doc_id = client.index("document.pdf")
# 索引 Markdown
doc_id = client.index("document.md", mode="md")
获取文档信息
# 获取元数据
metadata = client.get_document(doc_id)
# 返回:doc_id, doc_name, doc_description, type, status, page_count
# 获取树结构
structure = client.get_document_structure(doc_id)
# 返回:JSON 树结构(不含文本,节省 token)
# 获取页面内容
content = client.get_page_content(doc_id, pages="5-7")
# 返回:指定页面的文本内容
示例:Agentic Vectorless RAG
使用 OpenAI Agents SDK 构建文档问答 Agent:
from agents import Agent, Runner, function_tool
from pageindex import PageIndexClient
# 初始化客户端
client = PageIndexClient(workspace="./workspace")
doc_id = client.index("report.pdf")
# 定义工具
@function_tool
def get_document() -> str:
"""获取文档元数据"""
return client.get_document(doc_id)
@function_tool
def get_document_structure() -> str:
"""获取文档树结构"""
return client.get_document_structure(doc_id)
@function_tool
def get_page_content(pages: str) -> str:
"""获取指定页面内容"""
return client.get_page_content(doc_id, pages)
# 创建 Agent
agent = Agent(
name="Document QA",
instructions="你是一个文档问答助手。使用工具检索文档内容。",
tools=[get_document, get_document_structure, get_page_content],
)
# 运行查询
result = Runner.run(agent, "第 5 页的财务数据是什么?")
print(result.final_output)
完整示例:参见 examples/agentic_vectorless_rag_demo.py
工作流示例
完整流程
from pageindex import PageIndexClient
import json
# 1. 初始化客户端
client = PageIndexClient(workspace="./my_workspace")
# 2. 索引文档
doc_id = client.index("financial_report_2025.pdf")
print(f"文档 ID: {doc_id}")
# 3. 查看文档元数据
metadata = json.loads(client.get_document(doc_id))
print(f"文档名称:{metadata['doc_name']}")
print(f"总页数:{metadata['page_count']}")
# 4. 查看树结构
structure = json.loads(client.get_document_structure(doc_id))
utils.print_tree(structure) # 打印树结构
# 5. 获取特定页面内容
content = json.loads(client.get_page_content(doc_id, "5-7"))
for page in content:
print(f"=== 第 {page['page']} 页 ===")
print(page['content'])
工作空间持久化
# 使用工作空间,文档会持久化保存
client = PageIndexClient(workspace="~/pageindex_workspace")
# 索引文档(保存到工作空间)
doc_id = client.index("document.pdf")
# 重启后自动加载已索引的文档
client2 = PageIndexClient(workspace="~/pageindex_workspace")
print(client2.documents.keys()) # 包含之前索引的文档
配置说明
config.yaml 配置项
model: "gpt-4o-2024-11-20" # 用于构建索引的模型
retrieve_model: "gpt-5.4" # 用于检索的模型(默认使用 model)
toc_check_page_num: 20 # 检查目录的前 20 页
max_page_num_each_node: 10 # 每个节点最大页数
max_token_num_each_node: 20000 # 每个节点最大 token 数
if_add_node_id: "yes" # 添加节点 ID
if_add_node_summary: "yes" # 添加节点摘要
if_add_doc_description: "no" # 添加文档描述
if_add_node_text: "no" # 添加节点文本
命令行覆盖配置
# 覆盖模型
python run_pageindex.py --pdf_path doc.pdf --model gpt-4o
# 覆盖其他参数
python run_pageindex.py --pdf_path doc.pdf \
--toc-check-pages 30 \
--max-pages-per-node 15 \
--max-tokens-per-node 30000
常见问题
Q: 为什么不需要向量数据库?
A: PageIndex 使用文档的结构信息和 LLM 的推理能力进行检索,而不是向量相似度搜索。这带来了:
- 更好的可解释性
- 更精确的检索
- 不需要维护向量索引
Q: 支持哪些模型?
A: 通过 LiteLLM 支持多种模型:
- OpenAI: gpt-4o, gpt-4o-mini
- Anthropic: claude-sonnet-4, claude-opus
- 其他:参考 LiteLLM 文档
Q: 如何处理超大文档?
A: PageIndex 的树结构天然支持超大文档:
- 每个节点限制 token 数(默认 20000)
- 树结构可以很深,支持多层级
- 检索时只获取相关节点,不会加载全文
Q: Markdown 和 PDF 有什么区别?
A:
- PDF: 需要解析页面,支持物理页码
- Markdown: 基于行号,使用
#判断层级 - 推荐: PDF 使用 PageIndex OCR 获得更好的解析效果
Q: 如何优化检索效果?
A:
- 使用更强的模型(如 gpt-4o)
- 调整
max_token_num_each_node(增加节点内容) - 使用云服务的增强 OCR 和树构建流水线
- 在 Agent 提示词中明确工具使用规则
相关资源
下一步
- PageIndex 快速入门 - 30 分钟上手
- PageIndex 实战案例 - 实际应用场景
- 无向量 RAG 详解 - 深入原理
相关文档
文档来源:VectifyAI/PageIndex