通用 RAG 的“能回答”并不等于科研场景的“回答可信”。光学资料中常见中英混排、 公式、参数表、光路图和跨文档对比;一次看似合理的回答,可能缺少关键证据,甚至引用 错误页面。
OptiRAG 因此同时建设两条链路:
- 应用链路:解析 PDF、Word、表格与图片,检索证据,并通过 Agent 完成规格查询和实验方案设计;
- 评测链路:用人工复核题集测量召回、排序、答案、引用、幻觉、延迟及成本,基于失败案例进行可验证优化。
当前最可靠的正式 Test 结论是:纯向量检索整体最佳,Recall@5 为 0.927; 查询拆分与保守合并主要改善跨文档问题,不应表述为“知识图谱全面优于向量检索”。
| 模块 | 能力 |
|---|---|
| 多模态文档解析 | 基于 RAG-Anything / MinerU 处理 PDF、DOCX、XLSX、PPTX、图片、Markdown 等资料,保留文本、表格、图片和公式信息 |
| 用户 Query 改写 | 对复杂科研问题进行意图识别和子查询拆分,同时保留原始问题的主要召回结果,避免改写后语义漂移 |
| 检索召回 | 提供 BM25、向量、BM25 + 向量 RRF、文档邻接图 + 混合检索,以及面向跨文档问题的保守合并策略 |
| 记忆与上下文工程 | 使用 LangGraph SqliteSaver 持久化会话状态;对 Top-K 证据进行排序、去重、引用约束和上下文组装 |
| Agent 工作流 | Plan → Execute → Replan,支持普通问答与流式实验方案设计,前端实时展示计划和执行步骤 |
| RAG 效果评估 | 100 条人工复核光学问答,覆盖检索指标、答案正确率、引用 F1、幻觉率、P50/P95 延迟和调用成本字段 |
flowchart LR
subgraph Input["知识输入"]
D["PDF / Word / Excel / PPT"]
M["图片 / 表格 / 公式"]
end
subgraph Index["解析与索引"]
P["RAG-Anything + MinerU"]
C["切片与元数据"]
V["向量索引"]
G["文档结构图"]
end
subgraph Runtime["问答运行时"]
Q["用户 Query"]
R["Query 改写 / 子问题拆分"]
H["混合召回与保守合并"]
X["证据上下文"]
A["LangGraph Agent"]
O["答案 / 引用 / 实验方案"]
end
subgraph Eval["可复现评测"]
DS["100 条人工复核问答"]
E["Recall · MRR · nDCG\n正确率 · 引用 · 幻觉 · 延迟"]
F["失败归因与回归验证"]
end
D --> P
M --> P
P --> C
C --> V
C --> G
Q --> R
R --> H
V --> H
G --> H
H --> X
X --> A
A --> O
DS --> E
O --> E
E --> F
F -.优化.-> R
F -.优化.-> H
sequenceDiagram
participant U as 用户
participant API as FastAPI
participant R as RAG Engine
participant A as LangGraph Agent
participant DB as SQLite Checkpoint
alt 同步知识问答
U->>API: POST /api/chat
API->>R: 检索 Top-K 证据
R-->>API: 引用片段
API-->>U: 答案 + 来源
else 流式实验方案设计
U->>API: POST /api/chat/stream
API->>A: Plan → Execute → Replan
A->>R: 分步骤检索
A->>DB: 保存计划与上下文
A-->>U: SSE 计划 / 步骤 / 报告
end
评测集由 12 份 MIT OpenCourseWare 与 NIST 光学资料、577 个语料切片和 100 条问答组成;其中 Dev 20 条、冻结 Test 80 条。每题包含参考答案、引用文档、 相关 chunk、证据 span、实体、难度和复核信息。
冻结 Test 的 80 题均参与运行;Recall、MRR 和 nDCG 统计其中 75 道可回答题。
| 检索方案 | Recall@5 | MRR@5 | nDCG@5 | P95 |
|---|---|---|---|---|
| BM25 | 0.487 | 0.376 | 0.386 | 0.7 ms |
| 纯向量 | 0.927 | 0.803 | 0.817 | 297.4 ms |
| BM25 + 向量 RRF | 0.893 | 0.775 | 0.785 | 271.2 ms |
| 文档邻接图 + 混合检索 | 0.720 | 0.499 | 0.539 | 297.7 ms |
错误分析发现,Top 5 容易集中在同一文档,导致多跳问题只召回部分事实。项目在独立
CrossDoc Dev 上确定“保留原始 Top 3 + 子查询竞争两个补充槽位”策略,再固定参数
验证冻结 Test 中的 10 道 multi_document 题:
| 指标 | 原始向量 | 保守合并 v2 | 变化 |
|---|---|---|---|
| Recall@5 | 0.600 | 0.700 | +0.100 |
| 完整证据覆盖率 | 0.500 | 0.700 | +0.200 |
| 答案正确率 | 0.630 | 0.710 | +0.080 |
| 引用 F1 | 0.540 | 0.660 | +0.120 |
| 检索 P95 | 361.4 ms | 519.3 ms | +157.9 ms |
| 混合幻觉率 | 0.200 | 0.220 | +0.020 |
该优化提高了证据覆盖与下游答案质量,但增加了延迟,且没有降低幻觉率。完整实验边界、 失败方案和逐题归因请阅读:
- Python 3.11–3.13
- 可用的 OpenAI 兼容 LLM;多模态解析还需要 VLM 和 Embedding 服务
- 可选:Docker / Docker Compose,用于启动 Milvus 或完整容器环境
git clone <your-repository-url>
cd OptiRAG
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
make dev打开:
- Web 工作台:http://127.0.0.1:9900
- API 文档:http://127.0.0.1:9900/docs
- 评测标注台:http://127.0.0.1:9900/static/annotation.html
页面右上角的“模型设置”可以填写 LLM Key 与 Embedding Key。浏览器提供的 Key 仅随
当前请求发送,不写入服务端配置;VLM Key 仍应通过环境变量配置。不要直接用
file:// 打开 HTML,否则 API 请求与模块加载可能无法正常工作。
.env.example 已包含完整说明。开发阶段可让用户在页面输入 LLM / Embedding Key:
DEBUG=True
HOST=0.0.0.0
PORT=9900
LLM_API_BASE=https://api.deepseek.com
LLM_MODEL=deepseek-chat
LLM_API_KEY=
VLM_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
VISION_MODEL=qwen-vl-max
VLM_API_KEY=your-vlm-key
EMBEDDING_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
EMBEDDING_MODEL=text-embedding-v4
EMBEDDING_API_KEY=生产环境不应依赖浏览器临时 Key,并应将 DEBUG=False;评测与标注接口只在开发模式
开放。
cp .env.example .env
# 编辑 .env,补全生产所需配置,并设置 MILVUS_HOST=milvus
docker compose up -d --build
docker compose logs -f app容器编排包含 OptiRAG、Milvus、etcd 和 MinIO。更完整的反向代理、持久化与备份说明见 部署指南。
- 在“模型设置”中配置当前开发会话使用的模型 Key;
- 上传光学教材、论文或设备规格书,等待解析和索引完成;
- 直接提问参数、原理和对比问题,或输入复杂实验目标;
- 查看回答引用、Agent 计划与执行步骤;
- 在开发模式下运行检索/生成评测,比较指标并检查失败案例。
浏览器 Key 对应的请求头为 X-DashScope-API-Key;独立 Embedding Key 使用
X-Embedding-API-Key。
# 上传文档
curl -X POST http://127.0.0.1:9900/api/upload \
-F "file=@optics-notes.pdf"
# 同步问答:也可省略请求头,改用服务端 LLM_API_KEY
curl -X POST http://127.0.0.1:9900/api/chat \
-H "Content-Type: application/json" \
-H "X-DashScope-API-Key: $LLM_API_KEY" \
-d '{"question":"比较两种干涉仪的适用场景"}'
# 流式实验方案设计
curl -N -X POST http://127.0.0.1:9900/api/chat/stream \
-H "Content-Type: application/json" \
-H "X-DashScope-API-Key: $LLM_API_KEY" \
-d '{"question":"设计测量非线性晶体的 Z-scan 实验方案"}'数据协议、语料构建和命令说明见 data/evaluation/README.md。 下面是最常用的本地命令:
# 校验冻结数据
python -m app.evaluation.validate \
--corpus data/evaluation/generated/corpus.jsonl \
--questions data/evaluation/optics_qa_test_v1.jsonl \
--expected-questions 80 \
--require-reviewed
# BM25:不需要外部 Embedding 服务
python -m app.evaluation.run_retrieval \
--retriever bm25 \
--questions data/evaluation/optics_qa_test_v1.jsonl \
--output artifacts/evaluation/test-bm25
# 向量或混合检索:读取 .env 中的 Embedding 配置
python -m app.evaluation.run_retrieval \
--retriever vector \
--questions data/evaluation/optics_qa_test_v1.jsonl \
--output artifacts/evaluation/test-vector评测产物写入 artifacts/evaluation/,API Key 不进入运行配置、缓存或响应。端到端成本
只有在配置 LLM_INPUT_COST_PER_MILLION_USD 和
LLM_OUTPUT_COST_PER_MILLION_USD 后才会计算,否则保持 null。
| 功能 | 方法 | 路径 |
|---|---|---|
| 健康检查 | GET | /health |
| 文档上传 | POST | /api/upload |
| 文档列表 / 详情 / 删除 | GET / DELETE | /api/documents... |
| 同步问答 | POST | /api/chat |
| SSE 流式 Agent | POST | /api/chat/stream |
| 会话读取 / 清除 | GET / DELETE | /api/chat/session/{session_id} |
| 标注工作台 API(仅 Debug) | GET / PATCH | /api/evaluation/annotations... |
| 检索与生成评测(仅 Debug) | POST | /api/evaluation/... |
OptiRAG/
├── app/
│ ├── agent/ # Plan-Execute-Replan、工具与状态
│ ├── api/ # 问答、上传、知识库、标注与评测接口
│ ├── engine/ # RAG-Anything 封装与文档生命周期
│ ├── evaluation/ # 数据构建、四类检索、生成评测与重评分
│ ├── models/ # 请求、响应和文档模型
│ ├── services/ # 浏览器临时 Key 解析
│ └── main.py # FastAPI 入口
├── data/evaluation/ # manifest 与冻结题集
├── docs/evaluation/ # 协议、基线、失败分析和最终报告
├── static/ # 原生 JS 工作台与标注页面
├── tests/ # API、Agent、前端和评测测试
├── docker-compose.yml # OptiRAG + Milvus + etcd + MinIO
└── pyproject.toml
make dev # 热重载开发服务
make test # pytest + coverage
make lint # Ruff
make format # Ruff / Black
make clean # 清理测试与 Python 缓存前端使用原生 JavaScript ES Modules,并集成 KaTeX 与 Mermaid。MCP 示例扩展位于
mcp_servers/。
- 正式 Test 上最佳整体基线是纯向量检索;当前文档邻接图不是完整实体关系知识图谱。
- 跨文档提升来自固定的 10 题 Test 切片;参数在独立 CrossDoc Dev 上选择,但该切片 曾参与问题诊断,不等同于完全独立的外部测试集。
- 答案正确率和大部分幻觉指标来自模型裁判;跨文档优化后的 0.220 幻觉率为 “2 个风险案例人工确认 + 其余 8 题自动评分”的混合口径。
- RAG-Anything 不可用时会进入有限降级模式,多模态解析能力随之不可用。