项目概览
CitedRAG 将文档导入、检索、问答和评测放在一个工作区里。用户先建立知识库,再提出问题;答案中的 [N] 对应具体来源、页码和原文片段。没有足够证据时,系统应拒答或说明缺失信息。
项目定位
技术资料问答的难点不只是生成一段通顺文字,而是让读者能确认答案从哪里来、资料是否覆盖问题,以及哪些结论仍然缺少依据。CitedRAG 把证据放在交互中心:回答旁边可以展开原文、查看来源页码,再进入对应文档。
它面向论文阅读、技术方案核对和内部文档研究等场景,当前真实应用是本地单用户工作台。工作区用于分开管理不同资料集合,不等同于已经实现企业多租户认证或文档访问控制。
| 对象 | 保存什么 | 在问答中的作用 |
|---|---|---|
| 工作区 | 文档、会话、运行与索引的范围 | 决定本次可以检索哪些资料 |
| 文档与片段 | 来源、页码、原文及索引状态 | 构成可追溯证据 |
| 会话 | 用户问题与已提交回答 | 保留多轮上下文 |
| 运行 | 一次问答的状态、计划、证据和轨迹 | 支持审批、取消、恢复和排查 |
| 文献条目 | 来源元数据与附件关联 | 将外部资料按需引入工作区 |
| 评测案例与批次 | 期望、配置快照与逐题结果 | 判断一次变更影响了哪些问题 |
从资料到回答
flowchart TD
A[文档与可选文献来源] --> B[解析与页面感知切片]
B --> C[工作区索引]
C --> D[混合召回与重排]
D --> E[直接回答或研究计划]
E --> F[引用与逐句支持校验]
F --> G[答案、证据与执行轨迹]
真实项目使用 FastAPI 提供接口,SQLite 保存工作区、文档、运行与评测记录,FAISS 与词法索引组织检索,LangGraph 协调 direct、planner、researcher 和 writer。React 工作台展示同一套接口下的任务状态与证据。
从一个问题看完整体验
用户先上传资料并等索引就绪,再问“某个方法为什么采用混合检索”。检索器从当前工作区取出候选,经融合和可选重排组织上下文;简单问题直接回答,证据不足的复杂问题可以拆成多个研究任务。
研究计划成本较高时先展示审批,用户可删改任务、批准或取消。生成答案后,系统检查引用编号和结论支持,再把答案、实际使用的证据与执行轨迹提交到会话。拒答也是一种有效业务结果:它表示当前资料或校验结果不足以支撑回答,不能与网络失败混为一谈。
用户看见的证据可以沿“答案编号 → 原文片段 → 来源与页码 → 文档”逐步核对。检索到了某篇论文,只说明候选包含这篇资料;是否支持答案里的具体结论,还需要下一层检查。
为什么采用自适应编排
每个问题都先规划、再多轮调用工具,会给简单查询增加不必要的成本。固定直接问答又难以覆盖需要多角度比较的问题。项目先尝试较短路径,在确有证据缺口时升级,并用任务状态、迭代与调用预算约束后续研究。
这种设计把路径选择变成可观察状态,而不是只写在提示词里。轨迹用于解释如何得到结果,预算用于限制执行,引用用于核对答案;三者解决不同问题,不能互相替代。
演示可操作的内容
演示复用项目当前的 React 前端,使用浏览器本地数据代替服务端。预置两份技术笔记和一个空工作区:
| 操作 | 可以观察的结果 |
|---|---|
| 问“RRF 如何融合 BM25 与向量检索?” | 流式返回匹配原文,点击引用查看证据,再打开来源文档 |
| 问“明天巴黎的天气是多少?” | 没有相应资料,返回证据不足的拒答 |
| 问“深入比较混合检索与证据校验” | 等待研究计划审批,可以修改任务、批准或取消 |
| 上传 Markdown 或文本 | 任务完成后,当前工作区可检索新内容;可重新索引、替换或删除 |
| 启用文献来源 | 浏览明确标注为模拟的文献条目,按需导入、重复导入去重 |
| 运行评估案例 | 现场计算关键词、来源与回答行为检查,查看历史并导出 |
问答、文档、工作区与评测保存在当前浏览器。“重置演示”恢复初始样本。运行中刷新会留下可恢复状态;停止则取消当前轮。
演示边界
演示执行的是本地词项检索与原文摘录,没有 FAISS、embedding、CrossEncoder、LLM 或语义支持判分。研究计划和来源连接是模拟流程,不会连接真实 Zotero、下载论文、执行 MCP 命令或读取服务器路径。提供商表单不会连接用户填写的地址,也不保存输入的密钥。
浏览器仅解析不超过 2 MB 的 .md、.txt 和 .json。真实后端的多格式解析、向量计算、检查点和并行研究由 Python 服务实现,不能把这里的响应速度或小样本分数理解为真实后端性能。
技术栈与工程组织
FastAPI 负责接口和 SSE,LangGraph 负责状态图与检查点,SQLite 记录业务对象,FAISS 与词法通道负责检索;embedding 和 CrossEncoder 来自检索模型。前端使用 React、TypeScript、Ant Design、TanStack Query 与 Zustand,分别承担界面、类型、请求缓存和交互状态。
文档任务、问答运行和来源导入具有不同生命周期。前端不能因为上传请求返回成功就显示“可问答”,也不能因为流连接结束就把运行标为完成;最终状态需要从对应任务或运行记录确认。
![CitedRAG 对话页:回答的每个结论后面带 [1][2] 引用编号,下方展开证据](/covers/citedrag-art.webp)