Skip to content

About

面向私有论文库的可复现、证据可追溯研究 Agent:双语图文检索、事实级证据编译、主 Agent 自适应编排、可恢复事件流与受控工具审批。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

论文研究 Agent

一个面向私有、高质量论文集合的可复现、证据可追溯研究 Agent 工程。

项目重点不是让模型自由拼接论文结论,而是把论文发现、双语混合检索、最小事实编译、 引用验证、跨轮状态恢复和高风险工具审批收敛到可测试的确定性边界。当前已经形成从冻结语料、 图文检索和记忆,到主 Agent 自适应编排、受控执行子图、事实级证据台账、可恢复事件流与 私有研究界面的本地闭环。

核心工程亮点

  • 可信检索与引用:围绕 80 篇、2,286 页英文论文形成 6,252 个检索块和 806 张图表语义,融合中文 BM25 / BGE 与英文科研检索式,经路内和跨语言 RRF、CrossEncoder 重排后生成回答;引用必须命中本轮真实 chunk 白名单。
  • 事实级证据编译:多论文比较由代码确定性解析目标与维度,模型只提出受契约约束的最小事实需求;每个“论文 × 维度”网格单元独立检索、编译和提交,失败单元可精确重试,最终答案再由已验证事实确定性渲染,不让答案模型重新改写证据关系。
  • 自适应三图编排:跨轮次主 Agent 先恢复上下文,再以保守分类器选择无模型快路或完整规划;清晰的单一论文任务可直接物化,复杂或模糊任务继续走完整规划。固定证据图与动态工具图只执行受控任务,不修改主目标与计划。
  • 受控 Agent Runtime:LangGraph ReAct 工作流覆盖规划、工具执行、证据充分性反思、提前终止和有限重规划;18 项扩展研究工具全部受严格 Schema、总时长、调用次数、重复调用和信任等级约束,不注册任意 Shell、Python 或文件系统能力。
  • 状态、安全与审批:SQLite Checkpoint 恢复 thread;笔记、报告和长期记忆写入使用与工具名、参数哈希绑定的一次性审批令牌,避免旧确认复用到新参数。
  • 并行混合研究:前端提交问题、附件和明确的 rag_mode(disabled / preferred / required);preferred 遇到“本地论文 + 外部核验”意图时,确定性建立同组 local_rag 与 dynamic_tools 两个只读证据任务并同时启动。两支汇合后由大模型使用自身知识、推理和两类证据综合回答,不创建第三个 direct_chat 分支,也不会因启用 RAG 或外部检索而关闭模型原有知识。
  • 隐私可观测性:可恢复产品事件流按游标持久化阶段、任务、工具、路由和安全原因码,支持刷新续传、历史回放、暂停、继续与取消;事件账本和安全遥测均不记录问题、证据正文或 Provider 原始载荷。
  • 本机资源调度:面向 16 逻辑线程的单用户工作站采用单进程共享索引、六路比较检索和有界本地模型线程池;远端模型 I/O 与本地检索分层限流,避免用多 worker 重复加载模型。最近一次全量工程门禁为 999 项测试、171 个子测试全部通过。

当前里程碑

  • 冻结语料论文级数据契约
  • 语料清单校验器
  • 全 2286 页确定性结构化解析与元素 ID
  • 可追溯语义片段与稳定 chunk ID
  • 基线 A:纯向量检索
  • 30 条单审阅者银标诊断查询
  • 基线 B:BM25 + 向量混合检索
  • 基线 C:混合检索 + 重排模型
  • 分层、预算受控且可引用的 RAG 上下文组装
  • 图片信息契约、806 张图表裁剪与图文混合检索链路
  • 806 张图表的视觉模型摘要与图文混合索引重建
  • 中文问题到英文科研检索式的双路在线检索编排
  • 私人研究模式下的结构化回答生成与严格引用验证
  • 24 小时、按 session 隔离的本地短期记忆与多轮追问上下文
  • 框架无关的只读论文搜索与证据读取工具
  • LangChain 工具适配与受控 LangGraph ReAct 研究工作流
  • 可选启用、带 SQLite State Checkpoint 的受控多步研究 Agent Runtime
  • 证据充分性反思、提前终止、重复查询防护与有界重新规划
  • 不保存问题、查询和证据正文的 Agent 节点、工具、耗时与 Runtime 拦截日志
  • 多论文比较最小事实契约、确定性证据投影与逐单元事务式重试
  • 精确金标块、同论文替代块和语义事实三级证据血缘归因
  • 20 题开发集与 10 题封存集的完整多论文比较端到端评测
  • 主 Agent 自适应快路与复杂任务完整规划分流
  • 六路并发比较检索、事实级 Compiler 与确定性答案渲染
  • 非比较研究的独立检索两步批次与批后评估(默认单步,启用须通过质量门禁;见执行规则)
  • 可刷新续传、历史回放和运行控制的持久化事件流
  • 可选、默认关闭且受静态准入控制的 MCP 只读工具接入
  • 本地 RAG 与外部学术检索的计划级分组、真实并行执行和原子汇合
  • 外部学术 Provider 就绪状态、只读双白名单和部分失败降级

详细安排见RAG 检索基线实施计划。

最新评测快照

在代码版本 0d32441 上,固定 Top 4 的五题 v2 门禁取得 5/5 成功;15/15 条强制事实全部完成 检索、水化、Compiler 可见、编译、确定性答案输入、表达和正确引用链路,30/30 个请求单元通过, 最终失败单元为 0。五题真实主 Agent 运行中,两题命中确定性快路,三题因复杂或模糊而保守进入 完整规划;快路的主路由加任务物化 p50 约 15 ms,加上下文水化后的主编排前奏 p50 约 63 ms。

这是一组固定五题开发门禁,不能外推为全量生产分布结论;v2 金标也仍待人工双审与仲裁。 较早的 30 题全量快照位于代码版本 66810d5,取得 27/30 成功、0 超时和 99.1% 的已表达事实 引用正确率。最新自适应编排、事实链路、模型裁判方差和回滚边界见 主 Agent 自适应编排与比较规划维度修复复测, 旧全量口径见多论文比较最小证据编译器 v2 评测摘要。

主 Agent 统一编排

生产启动首先进入跨轮次主 Agent 主体图(paper_research_main_v1),不是先 进入某个执行子图。主图先恢复最近历史、滚动摘要、活动目标、会话任务计划、 远距会话召回与长期记忆,再解释本轮变化、对齐目标和规划任务;长期记忆最多 召回 5 条并受 5,000 字符预算约束,读取失败时降级为空而不阻断请求。只有完成这些 步骤后,才按能力把受控任务派发给普通聊天、本地论文、动态工具、附件问答或 文件编辑执行器。本地论文研究图与动态工具图都是 child executor(子执行器), 不能自行修改主目标、任务计划或会话版本。

当用户同时要求本地论文依据与最新外部核验时,主图将两个任务标记为同一个 parallel_group_id,通过结构化并发同时派发并在批次边界汇合。并行分支只负责获取证据; 大模型仍负责问题理解、规划、概念背景、推论和最终综合。模型自身背景知识不会被伪装成引用, 本地引用只来自本轮通过白名单校验的论文 chunk,时效性结论只有在外部学术分支成功时才标记为 已核验。

浏览器只使用以下统一接口:

  • POST /paper-research/api/agent/runs:提交带稳定 request_id、message、 rag_mode 和附件 ID 的请求,返回统一 NDJSON 事件流。
  • GET /paper-research/api/agent/runs/{request_id}:断流后查询终态或等待状态。
  • GET /paper-research/api/agent/runs/{request_id}/events?after_event_id=N:从持久化游标 继续读取运行事件;刷新页面不会重新提交原问题或重复执行工具。
  • POST /paper-research/api/agent/runs/{request_id}/approval:批准或拒绝原写任务, 只恢复暂停的 child,不重新解释、对齐目标或规划。
  • POST /paper-research/api/agent/runs/{request_id}/control:请求暂停、继续或取消运行; 浏览器只通过这一显式控制入口改变运行状态。

同一 request_id 重试会返回持久化结果和 run_reused,不会新增 turn 或重复副作用。 旧 /ask、/chat/stream、/tools/run 与 /tools/approval 在 primary 模式只作为 兼容代理保留,浏览器不得调用;legacy 模式则可在紧急回滚时恢复旧实现。

生产命令 scripts/serve_web.py 默认使用 PRA_MAIN_AGENT_MODE=primary。显式配置 PRA_MAIN_AGENT_MODE=legacy 并重启即可回滚;已废弃的 PRA_MAIN_AGENT_ENABLED 只为旧部署读取兼容,不应继续写入新环境文件。

实时运行轨迹

主 Agent 使用 main-agent-stream-v2 事件协议。事件在主图和子执行器运行期间实时发布, 先写入独立的 SQLite 产品事件账本,再通知当前浏览器;慢客户端或网络中断可按同一 run 内 单调递增的 event_id 补齐。浏览器只在本地保存 request_id、conversation_id 和 last_event_id 三个续传字段,不缓存问题、回答事件、工具结果或论文证据。历史会话也从同一 账本恢复,因此实时视图、刷新续传和历史回放使用相同的对话节点。

回答事件会明确标注 delivery mode(交付模式):

  • provider_live:直接转发模型提供方的实时文本增量。
  • validated_replay:本地 RAG 或结构化回答完成引用验证后再分块输出,不宣称是模型首 token。
  • event_only:本轮只有状态、工具或交互事件,没有回答文本增量。

产品事件只允许公开阶段名、任务标题、工具名、状态、计数、耗时、固定原因码和安全附件 ID。 原始问题、system prompt(系统提示词)、隐藏 chain-of-thought(思维链)、工具参数、Provider 原始载荷、论文正文与召回正文均不会进入事件账本或 DOM;原有安全遥测库继续独立存在,前端 不会直接读取它。

界面把研究过程放回当前对话:思考摘要、计划、工具、检索、回答和本轮统计按稳定节点原位更新, 完成节点默认折叠;“详情”抽屉默认关闭。桌面会话导航可收起,移动端改为遮罩抽屉。附件和 RAG 模式保留在紧凑输入区;等待工具审批时,输入区会切换为“拒绝/允许”,处理后恢复原输入框。 运行中的暂停、继续、取消以及暂停后的计划编辑均按当前状态显示,不再依赖常驻右栏。

数据边界

原始 PDF、生成索引、运行数据库和密钥不进入 Git。仓库通过环境变量引用本地冻结语料:

Copy-Item .env.example .env
$env:PRA_CORPUS_DIR = 'D:\path\to\research_collection'

当前冻结版本:

llm-eval-reliability-v1.0.0-2026-07-26
80 篇论文:核心集 60,挑战集 20

本地验证

$env:PYTHONPATH = 'src'
python -m unittest discover -s tests -v
python scripts/validate_corpus.py --corpus-dir D:\path\to\research_collection
python scripts/parse_corpus.py --corpus-dir D:\path\to\research_collection

# 以下 BUILD_DIR 替换为本地最新解析产物目录
python scripts/build_chunks.py `
  --elements "$env:BUILD_DIR\elements.jsonl" `
  --sections "$env:BUILD_DIR\sections.jsonl"
python scripts/build_retrieval_index.py `
  --chunks data/processed/chunks/chunks.jsonl
python scripts/search.py "How is hallucination evaluated?" `
  --variant C --chunks data/processed/chunks/chunks.jsonl
python scripts/evaluate_retrieval.py `
  --chunks data/processed/chunks/chunks.jsonl

PDF 解析默认启用 OCR(光学字符识别)降级:普通数字版页面继续使用 pdfplumber,仅当 页面含栅格图像且原生文本少于 24 个字符,或原生页面提取失败时,才渲染该页并调用 Tesseract。OCR 文字会标记为 generated,同时记录引擎、语言模型和版本;扫描页需要 OCR 但运行时不可用时会明确记为失败,不会静默作为空白页进入索引。

先安装摄取依赖和 Tesseract 5,并安装 eng、chi_sim 语言包:

python -m pip install -e ".[ingestion]"
# Windows 示例;也可通过 PRA_TESSERACT_CMD 指向已有 tesseract.exe
winget install --id UB-Mannheim.TesseractOCR

Linux 可安装 tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim。相关参数见 .env.example;只有明确不处理扫描件时才将 PRA_OCR_ENABLED 设为 false。

持续知识库更新使用以下命令;它会检查冻结清单,仅解析新增 PDF,将旧产物原样合并到新的 不可变构建,重新生成 chunk 与向量索引,并且只在全部成功后原子切换 data/processed/current_knowledge_base.json。已存在的来源哈希、页面/元素/chunk ID 和父构建 都不会被改写;删除既有来源、为既有来源重分配 corpus_id、或更改解析/OCR 配置都会被拒绝。 新增文件仍须先经过现有冻结清单校验,并在清单中提供未使用的 corpus_id、内容哈希和版权 元数据;更新器不从文件名猜测论文身份,避免破坏可追溯性。

python scripts/update_knowledge_base.py `
  --corpus-dir D:\path\to\research_collection

# 持续轮询冻结清单;生产服务在下一次重启时读取已切换的完整构建。
python scripts/update_knowledge_base.py `
  --corpus-dir D:\path\to\research_collection `
  --watch-interval-seconds 60

证据有两层置信度:原生 PDF 文本为 high;OCR 结果为 low。默认检索只使用高置信度 证据;若确需使用 OCR,调用方必须显式设置 include_low_confidence=True,且该层级会随检索 命中、上下文和引用元数据一同保留,供回答策略或人工复核使用。

中文生产查询使用独立的双路入口,不改变原有 A/B/C 基线,也不需要重新分块或生成向量:

$env:DASHSCOPE_API_KEY = '<本机 Key>'
$env:PRA_CORPUS_DIR = 'D:\path\to\research_collection'
python scripts/search.py "哪些方法能降低 RAG 在 TruthfulQA 上的幻觉?" `
  --bilingual `
  --chunks data/processed/chunks/chunks.jsonl

完整问答可以用一条命令串起查询改写、双路检索、上下文组装、回答生成和引用验证:

python scripts/rag.py "哪些方法能降低 RAG 在 TruthfulQA 上的幻觉?" `
  --chunks data/processed/chunks/chunks.jsonl `
  --corpus-dir "$env:PRA_CORPUS_DIR" `
  --output data/runtime/example-answer.json

连续追问需要显式复用同一个安全 session_id;不传该参数时仍是完全无状态的单轮问答:

python scripts/rag.py "BEIR 基准包含哪些检索任务?" `
  --session-id beir-review-01 `
  --chunks data/processed/chunks/chunks.jsonl `
  --corpus-dir "$env:PRA_CORPUS_DIR"

python scripts/rag.py "它和 MTEB 有什么区别?" `
  --session-id beir-review-01 `
  --chunks data/processed/chunks/chunks.jsonl `
  --corpus-dir "$env:PRA_CORPUS_DIR"

系统里的“记忆/上下文”不是四套同义数据库:最近消息窗口用于保持当前对话连贯, 远距会话召回用于找回较早轮次,下面的短期 RAG 记忆用于 24 小时内的追问改写, 长期记忆则保存经明确意图和审批确认的偏好、项目背景或已确认结论。Conversation Store 中的滚动摘要、目标和任务计划属于主 Agent 工作区状态,也会参与水合,但不是长期记忆。

短期记忆不是整份模型上下文。它只在本地 SQLite 中保存最近问题、通过引用验证的 claims.text、来源 chunk ID 和版权分类;不会保存论文证据正文、旧的 [E1] 标签、完整 回答、模型请求或原始响应。默认 24 小时过期、每个 session 最多 20 轮,每次最多选 6 轮 且不超过 1200 个保守估算 Token。配置见 configs/memory/short-term-v1.json。

Web 研究台另由编排层维护统一的 Conversation Store:普通聊天、本地 RAG、附件、外部学术研究 和动态工具共享同一 conversation ID。每轮无条件准备最近窗口、主题 Episode 与远距用户问题 候选,再由一次结构化 Turn Interpreter 同时判断历史依赖、生成独立问题并规划研究能力;规则 只校验真实 turn ID、会话隔离、能力开关和低置信度澄清。只有独立问题进入中英文论文查询改写。 “自动使用本地论文知识库”表示由来源意图选择本地论文,并可与动态研究组合;“仅依据本地论文回答” 则禁止外部研究。显式模式与“使用/不要使用知识库、联网”等语言要求冲突时,请求在执行前返回 可操作的 422,不会静默覆盖。检查器显示最近窗口、远距候选、采用 turn ID/相关度、能力计划和实际检索路径。 清空会话会同时清除共享账本及其 Episode 索引。

模型上下文是每次调用临时重新组装的快照:可信 system 规则、筛选后的低信任记忆、当前 问题、本轮新检索证据和输出约束。记忆只帮助解析“它、上述方法、前者”等指代,不能充当 事实证据;当前回答仍必须引用本轮重新检索到的论文 chunk。memory-aware 查询的改写缓存和 查询审计明文也被限制为最多 1 天,并在读取或打开数据库时物理清理过期记录。

收到查询后,中文 BM25 + BGE 召回会与 Qwen 英文科研检索式改写并行启动;中英文 各自先做一次路内 RRF,再做跨语言 RRF,最后只使用英文改写查询执行一次英文 Reranker。改写总截止时间默认 2 秒,超时、网络错误、限流或无效 JSON 均返回中文混合 召回结果,不经过英文 Reranker;没有配置 Key 时同样安全降级。配置见 configs/retrieval/bilingual-qwen-v1.json。

改写缓存和查询审计分别保存在 data/runtime/query-rewrite-v2.sqlite3 与 data/runtime/query-audit-v1.sqlite3,不与索引元数据共库。成功改写 90 天内直接命中, 365 天内只在 API 失败时作为过期缓存降级;审计中的中英文查询明文保留 30 天,之后仅 保留查询哈希、模型/提示词版本、各阶段排名、分数和延迟。审计不写证据正文、图注、 figure_json、绝对路径、请求/响应体或密钥。

查询改写请求只包含固定改写提示词和当前用户问题,不上传论文正文、图片摘要或命中证据。 传入 --corpus-dir(或设置 PRA_CORPUS_DIR)后,结果会附带命中论文的 storage_class。双路结果若没有加载版权映射,可以在本地查看排名,但后续上下文组装会 拒绝继续,避免把 internal_research_only 边界默认为可公开。

首版研究工具位于 paper_research_agent.agent。ResearchToolService 提供框架无关的 search_corpus 和 get_evidence:前者只返回排名、稳定 ID、页码、哈希和版权分类,后者 只按显式 chunk ID 从本地不可变语料读取正文。搜索结果会再次经过现有血缘适配器校验; 检索元数据与源 chunk 不一致、版权映射缺失或请求越界时关闭失败。

安装 agent 可选依赖后,build_langchain_tools 将这两个方法包装为固定名称和 Pydantic 参数契约的 LangChain 工具;build_research_graph 通过这些工具执行受控 plan -> reason -> execute_tools -> assess_evidence -> reason/finalize 循环。Planner 最多产生 6 个只读检索子问题;结构化 Evidence Reasoner 可在证据充分时提前结束,或在证据不足时 提出一条新的本地检索,但不能扩展工具白名单。Graph 同时限制每步证据数、总工具调用次数、 重规划次数和重复查询,并按 chunk ID 去重。

ResearchAgentRuntime 负责总超时、session_id -> thread_id 映射,并重新核对终态中的动作 序列、工具计数、重规划计数、终止原因,以及正文、哈希、页码和版权分类。通过后,证据才会进入现有 assemble_context -> answer_context、引用白名单和回答验证器。SQLite Checkpoint 只保存在 data/runtime/,其中可能包含研究 State 和内部证据正文,禁止提交或公开。

python -m pip install -e ".[retrieval,web,agent]"
$env:PRA_RESEARCH_AGENT_ENABLED = 'true'
$env:PRA_RESEARCH_AGENT_MAX_STEPS = '4'
$env:PRA_RESEARCH_AGENT_EVIDENCE_PER_STEP = '3'
$env:PRA_RESEARCH_AGENT_MAX_TOOL_CALLS = '12'
$env:PRA_RESEARCH_AGENT_TIMEOUT_SECONDS = '90'
# 可选:让目录、表格、图片和公式工具读取当前解析产物
$env:PRA_SECTIONS_PATH = 'data/processed/<current-build>/sections.jsonl'
$env:PRA_ELEMENTS_PATH = 'data/processed/<current-build>/elements.jsonl'

默认不开启 Agent,原单次 RAG 路径保持不变。完整 Agent 架构由一层主编排图和两条执行子图 组成:主图统一维护跨轮次目标、任务计划和路由;固定证据子图只用 search_corpus / get_evidence 形成可验证引用;动态工具子图才允许模型在固定 18 项扩展工具中 逐步选择。两条执行子图都不是自由工具 Agent;Shell、任意 Python 和任意网络/文件能力均未注册, 写工具必须经过 Runtime 审批。

Agent 启用后,结构化事件默认写入与 State Checkpoint 同目录的 data/runtime/agent-events-v1.sqlite3。每次运行生成独立 run_id,覆盖运行开始/完成/失败、 每个 Graph 节点开始/完成/失败、工具调用开始/完成/失败、总超时、工具白名单/预算拦截和 终态输出拒绝。事件只保存组件名、状态、耗时、数量、预算、错误类型、固定原因码,以及问题、 查询、步骤和 thread 的 SHA-256 指纹;不保存 API Key、问题正文、查询正文、chunk ID、证据 正文、Provider 请求/响应或自由文本异常消息。日志写入采用 best-effort,SQLite 暂时不可写 不会改变研究结果或放宽 fail-closed 安全策略。

可按一次运行查看安全轨迹:

SELECT event_id, event_type, component, name, status, duration_ms, reason_code
FROM agent_events
WHERE run_id = '<run_id>'
ORDER BY event_id;

扩展研究工具平台

生产 Agent Runtime 现在除核心 search_corpus / get_evidence 外,还注册 18 项严格 Schema 工具。核心可引用证据循环仍用原两工具关闭失败;扩展工具通过 ResearchAgentRuntime.execute_tool 或完整 LangChain registry 调用,结果不会绕过现有引用验证。

  • 本地证据:get_adjacent_chunks、get_paper_metadata、trace_evidence_source、 get_paper_outline
  • 学术网络:search_scholarly_sources、resolve_paper_identifier、get_citation_graph、 check_paper_status
  • 非文本理解:extract_table、inspect_figure、extract_equation
  • 计算核验:calculate、analyze_experiment_data、verify_claim、 check_reproducibility
  • 成果管理:save_research_note、export_research_report、manage_long_term_memory

多论文比较不属于动态工具。主路由会把带有多个本地论文 ID 的学术比较交给固定研究图;规划器将 每篇论文与比较维度拆成独立步骤,search_corpus 用对应 corpus_id 同时约束 BM25 和向量召回。 证据编译模型只返回最小事实、片段 ID、事实需求 ID 和限定词;本地代码再校验论文范围、事实需求、 必要限定词和覆盖状态,确定性生成事实 ID 与最终台账。单元失败时只重试失败 requirement,已提交 单元继续保留;连续编译失败以独立 compiler_failed 状态终止,不回退为空台账或证据不足。 最终回答上下文不再携带原始证据正文,而是按计划 requirement 顺序投影经过验证的事实台账与引用。 当前编译器可见性严格隔离不同论文,但同一论文内的证据仍可被该论文的多个维度复用;这是后续按 缺失事实自适应水化并收紧到同维度范围的明确优化项。普通单篇问答仍保持原有全局检索 rank 顺序。 升级前若有尚未完成、下一步仍指向 compare_papers 的动态 Graph checkpoint,应新建任务重新执行; 该旧工具名已从严格目录移除,恢复时会按未知工具关闭失败。

工具目录为每项能力固定风险级别、默认超时和最大结果数。本地读取直接执行;学术网络只向 Crossref、arXiv 或 Semantic Scholar 发送当前检索式/论文标识符,不发送本地 chunk 或论文正文; 计算器只解释算术 AST,实验分析只支持最多 1000 行、20 列和固定统计白名单。 长期记忆会在主 Agent 解释本轮请求前由现有 manage_long_term_memory(search) 只读召回, 解释器只能从实际召回 ID 中选择。被选中的记忆可进入普通聊天、本地 RAG 或动态工具三条 执行路径;本地 RAG 将其装配为独立的低信任 JSON 层,记忆 ID 永远不会进入 citation(引用) 集合,confirmed_conclusion 仍须由本轮论文证据重新核验。水合观测只记录各阶段耗时、数量、 最终字符数和保守 Token 估算,不记录问题、记忆正文、记忆 ID 或 Provider 原始载荷。

长期记忆新增、更新、删除必须使用与工具名、参数哈希绑定的 5 分钟一次性审批令牌;搜索和 列举是只读操作,无需审批。记录按作用域隔离,支持内容去重、版本替代、软删除和可选过期; 所有文件和 SQLite 只写入 data/runtime/,默认拒绝路径逃逸与静默覆盖。

动态工具 Graph 会先执行只读记忆召回,再进入 recall_memory -> route -> execute -> route/propose_memory/finalize;记忆写入路径为 propose_memory -> execute(仅生成请求) -> interrupt -> 用户批准/拒绝 -> execute/finalize。只有 用户明确表达“记住、更新记忆、忘记”等意图时才会生成结构化候选,普通问答不会自动写入。 模型只负责 返回结构化 ToolDecision,Runtime 再校验工具名、参数 Schema、风险策略、超时、重复调用和 初始计划、重复调用、连续无新证据、工具次数与总时长预算。观察结果额外标注四类信任等级:citation_evidence、research_context、 computed_result、side_effect,长期记忆始终属于低信任 research_context,只有第一类可作为 论文事实的引用候选;确认结论还必须绑定当前语料中真实存在的不可变 chunk ID。

Owner Web API 提供 POST /paper-research/api/tools/run 与 POST /paper-research/api/tools/approval。两者都要求登录 Cookie 和允许的 Origin;待审批响应 只返回工具名、用途、参数 SHA-256 与过期时间,不返回完整参数、正文、一次性令牌或内部审批 ID。 登录后的 GET /paper-research/api/memories 只投影当前有效记录的内容、类型、来源 ID、版本和 生命周期字段;页面可查看记忆,修改和删除仍需通过动态工具审批。 路由冒烟基线位于 evaluation/datasets/tool-routing-v1.jsonl,覆盖本地读取、网络读取、受限计算 和三类写入审批场景。

result = await runtime.execute_tool("calculate", {"expression": "(2 + 3) * 4"})

pending = await runtime.execute_tool(
    "save_research_note",
    {"title": "结论", "content": "已确认的研究结论"},
)
token = runtime.approve_tool_request(pending.summary["approval_request_id"])
saved = await runtime.execute_tool(
    "save_research_note",
    {"title": "结论", "content": "已确认的研究结论", "approval_token": token},
)

图片语义入库分为三个阶段。裁剪阶段不调用视觉模型,也不会上传图片:

python scripts/crop_figures.py `
  --elements "$env:BUILD_DIR\elements.jsonl" `
  --corpus-dir "$env:PRA_CORPUS_DIR" `
  --output data/processed/figure-semantics-v1

视觉摘要支持百炼实时 API 和 z-ai 命令行。百炼接入使用创建 API Key 时一并显示的 业务空间专属 API Host;密钥只通过环境变量读取,不能写入命令、日志或仓库:

$env:DASHSCOPE_API_KEY = '<本机新建或重置后的 Key>'
$env:DASHSCOPE_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1'
python scripts/summarize_figures.py `
  --provider dashscope `
  --candidates data/processed/figure-semantics-v1/figure_candidates.jsonl `
  --model-id qwen3.7-plus `
  --model-id qwen3.7-plus-2026-05-26 `
  --workers 4

多个 --model-id 按顺序使用。仅当平台明确返回 AllocationQuota.FreeTierOnly 时才切换下一个模型;普通网络错误、限流和无效 JSON 会在当前模型重试。若允许免费额度用尽后按量付费,应在百炼控制台关闭“免费额度用完 即停”,平台会自动按“免费额度 → 资源包 → 节省计划 → 按量付费”扣减,此时通常无需 配置第二个模型。命令结束会输出各模型的实际输入、输出和总 Token;每成功一张即原子 更新 figures.jsonl,重跑可断点续传。--workers 4 会并发处理 4 张图片;若限流频繁, 可改为 --workers 2,程序会遵循 Retry-After 并指数退避。

未配置 DASHSCOPE_BASE_URL 时默认使用上面的北京共享端点;若能从控制台取得业务空间 专属 API Host,仍优先使用专属端点。JSON 模式默认不设置输出 Token 硬上限,避免在 JSON 对象中途截断;摘要长度由提示词约束。

也可以使用原有 z-ai 命令行;model-id 必须填写实际视觉模型及版本,不能用占位名称:

python scripts/summarize_figures.py `
  --provider zai-cli `
  --candidates data/processed/figure-semantics-v1/figure_candidates.jsonl `
  --model-id "<实际视觉模型及版本>"

生成 figures.jsonl 后,将图片摘要作为“一图一块”合并进文本块,再重建本地索引:

python scripts/build_chunks.py `
  --elements "$env:BUILD_DIR\elements.jsonl" `
  --sections "$env:BUILD_DIR\sections.jsonl" `
  --figures data/processed/figure-semantics-v1/figures.jsonl
python scripts/build_retrieval_index.py `
  --chunks data/processed/chunks/chunks.jsonl

图片向量文本只包含图名、图片类型、原始图注、视觉摘要和关键发现。坐标、相对路径、 置信度、模型与提示词版本作为检索元数据保存,不参与语义相似度计算。当前实际状态和 全量审计结果见图片语义入库状态。

检索运行结果可以在调用大模型前组装为安全的上下文预览:

python scripts/assemble_context.py `
  --run data/evaluations/example-retrieval-run.json `
  --chunks data/processed/chunks/chunks.jsonl `
  --token-budget 8192 --output-reserve 1200 `
  --output data/runtime/example-context.json

组装顺序固定为可信系统规则、必要对话历史、低信任短期记忆、低信任长期记忆、当前用户问题与 任务状态、检索证据。历史、记忆、任务状态和论文正文均属于低信任数据;记忆与证据分别使用 canonical JSON 封装,不能覆盖系统规则或触发工具。预算计算覆盖最终消息模板并预留输出 空间;如果空间冲突,先丢弃最旧记忆,至少保护可容纳的最高排名新证据。

scripts/answer.py 是调试生成边界的低层入口;它可以把已经组装好的上下文送入私人研究 回答模块:

python scripts/answer.py `
  --context data/runtime/example-context.json `
  --output data/runtime/example-answer.json

回答模型固定为 qwen3.7-plus-2026-05-26,使用 temperature=0.1、top_p=0.7、 max_tokens=1200 并关闭思考。模型只返回结构化 claims + citation_ids;本地验证器依据 AssembledContext.citations 白名单校验引用并追加 [E1] 标记,未知引用、截断输出或非法 JSON 均关闭失败。没有可用证据时在本地直接返回“证据不足”,不调用 API。

private_research 是当前唯一回答输出模式。它允许将已经加载版权分类的少量命中片段发送 给百炼,但不会上传整篇 PDF,也不会把上下文、证据正文、模型原始响应或答案正文写入审计 库。data/runtime/answer-audit-v1.sqlite3 只保存模型、Token、延迟、引用/chunk ID、版权分类 和答案哈希。最终回答 JSON 只包含中文答案、结构化 claims、最小引用元数据和调用统计;不 提供公开导出模式。v1 审计只记录已验证回答和本地证据不足结果;Provider 超时、非法 JSON 或引用校验失败不会写库,也不会伪装成“证据不足”。

本机私有可视化研究台

paper_research_agent.web 将现有 RAG 包装为常驻 FastAPI 服务:启动时只加载一次 6,252 个 chunks、BM25、FAISS、BGE 和 Reranker,后续问题复用同一运行时。本机只运行 一个 Uvicorn worker(工作进程),让所有请求共享索引和模型;同一会话的问答保持串行, 不同会话默认最多并发两个完整问答,容量由 PRA_WEB_MAX_INFLIGHT_RUNS(范围 1–16)控制。 容量耗尽时新请求快速返回繁忙响应,不建立无界队列;设为 1 可回退为全局串行。 论文比较的单次检索阶段最多并发六路。服务只监听 127.0.0.1:8092,不依赖 Nginx 或公网域名。

前端会话历史采用按需加载:登录后先返回最多 50 个会话的标题和更新时间,不携带历史消息; 随后只为当前会话加载最近 24 条消息。存在更早内容时由“加载更早消息”每次追加 24 条,避免 首屏一次解析全部会话、回答和 Agent 结果。这里优化的是界面历史记录的传输与渲染,不是主 Agent 的上下文水合(Context Hydration)。scripts/smoke_web_runtime.py --summary-only 可执行 不输出回答正文的真实运行时冒烟,并分别记录冷启动、请求和总耗时。

因为完整索引包含 30 篇 internal_research_only 论文,首页项目卡可以公开,但真实问答、 引用摘录、英文改写、短期记忆和上下文检查器全部要求站长登录。登录后由服务端生成不可猜测 的 conversation ID,并通过 HttpOnly + SameSite=Strict 签名 Cookie 绑定;本机 HTTP 运行时关闭 Secure,如果将来改为 HTTPS 再重新启用。浏览器不能自选 session ID,也不会 保存站长密码。POST 请求还会校验精确同源 Origin。

安装 Web 依赖后,以环境变量提供私有路径与凭据并启动:

python -m pip install -e ".[retrieval,web]"
$env:PRA_MAIN_AGENT_MODE = 'primary'
python scripts/serve_web.py --host 127.0.0.1 --port 8092

启动日志必须显示 主 Agent Web 启动模式:primary。若统一入口在本机调试时出现数据撕裂、 重复副作用、引用丢失或持续提交拒绝,可切到兼容模式并重启同一服务:

$env:PRA_MAIN_AGENT_MODE = 'legacy'
python scripts/serve_web.py --host 127.0.0.1 --port 8092

切换兼容模式不会删除主 Agent checkpoint、Conversation Store(会话存储)或事件库,也不要 手工修改本机 SQLite 状态。问题修复后复用原数据验证,再显式切回 primary。

混合并行研究还有独立的严格回滚开关。它默认开启且只接受大小写不敏感的 true / false; 1、yes、空白值或其他字符串都会令启动失败。需要回滚时设为 false,混合请求会在两个子执行器启动前以 parallel_hybrid_disabled 关闭失败,不会退回顺序执行或静默二选一;纯单任务不受影响。

$env:PRA_PARALLEL_HYBRID_RESEARCH_ENABLED = 'false'
python scripts/serve_web.py --host 127.0.0.1 --port 8092

本机登录使用 .env 中的 PRA_WEB_USER、PRA_WEB_PASSWORD,并单独设置至少 32 字节的 PRA_WEB_SESSION_SECRET。这些变量、DashScope Key、论文派生数据、模型缓存与运行数据库 均不得进入 Git。

研究台返回安全字段白名单:中文回答与 claims、引用编号、论文标题、官方链接、页码、版权 分类、短摘录,以及改写状态、入选证据/记忆数量和 Token 预算。它不会返回 PDF 路径、图片 路径、完整 figure JSON、系统提示词、Provider 原始响应或未选中证据全文。部署模板见 deploy/,推荐问题见 configs/web/recommended-questions-v1.json。

外部学术检索 Provider

search_scholarly_sources、resolve_paper_identifier、get_citation_graph 和 check_paper_status 保持稳定的公开工具契约,内部通过有序 Provider(提供方)注册表执行。 默认模式为 offline:不创建 HTTP 客户端、不读取论文 API Key,四个工具统一返回 provider_not_configured,不会用测试假数据冒充真实论文。

$env:PRA_SCHOLARLY_MODE = 'offline'
python scripts/serve_web.py

单元测试通过依赖注入使用确定性 Fixture Provider(测试假提供方),可覆盖成功、无结果、 限流、超时和多提供方降级;该实现只存在于测试代码,不能进入生产 Registry(注册表)。 真实接入必须显式设置 PRA_SCHOLARLY_MODE=live。无 Key 时使用免申请的 Crossref 和 arXiv; 配置 SEMANTIC_SCHOLAR_API_KEY 时优先使用既有 Semantic Scholar,失败后再尝试免 Key 来源。 工具参数可选 source=auto|crossref|arxiv|semantic_scholar,默认 auto 返回第一个成功来源; 明确选择来源时不跨库降级。OpenAlex 未接入。

$env:PRA_SCHOLARLY_MODE = 'live'
$env:PRA_PARALLEL_HYBRID_RESEARCH_ENABLED = 'true'
python scripts/serve_web.py --host 127.0.0.1 --port 8092

在页面问答中可以输入“在 arXiv 检索 attention transformer 相关论文,列出标题与链接”或 “通过 Crossref 解析 DOI 10.1038/nature14539”。入口沿用当前 Agent 问答,无需新按钮。 标题解析只给出候选;Crossref 摘要可能缺失,参考文献仅反映已登记数据,不支持完整反向引用图。 出版更新核查只返回登记的更新元数据,不能保证论文未撤稿。arXiv 只支持搜索和 ID 解析, 年份筛选采用投稿日期。PDF 链接只作为书目信息返回,不自动下载或入库。

每个提供方使用有界内存缓存(5 分钟、最多 128 项、总响应不超过 8 MB),重启即清空; Crossref 请求至少间隔 1 秒,arXiv 至少 3 秒。并发相同请求合并为一次 HTTP 请求, 限流后短期暂停该提供方,不自动重试。每次 HTTP 请求超时为 10 秒,响应上限 2 MB; 固定官方 HTTPS 地址,不跟随重定向,也不继承系统代理环境变量。 可以运行 python scripts/smoke_public_scholarly.py 做公开书目联网验收,输出仅含状态、数量与耗时。

回答下方的“外部学术 API 来源”卡片由后台工具实际返回结果生成,显示 Crossref/arXiv/ Semantic Scholar、实时 API 查询或缓存命中、查询时间、返回数量、公开标识符和官方链接。 卡片随会话历史恢复,刷新不重新查询;旧回答没有来源记录时不会伪造卡片。 只保存有界书目投影,不保存检索参数、摘要或原始响应。卡片说明工具返回了哪些书目, 不等同于本地全文事实验证,也不保证回答中的每句话都已被外部文献支持。

意图判定沿用现有解释模型,输出普通解释、本地、外部或混合信息需求;例如“给我几篇 RAG 的代表文献和链接”无需使用“联网”口令,也能进入学术检索。明确的问候与概念解释保留快捷 路径,其余请求进入现有语义规划。高置信纯外部需求只查外部书目,混合需求才同时启动本地与 外部分支;数据库偏好传递给工具路由。模型不能越过禁止联网、required 模式、只读白名单、 审批或引用校验。模型失败/低置信度采用既有降级,不新增独立分类模型或自动下载权限。

这里的“外部”是受控学术元数据与引用关系检索,不是通用网页搜索。并行学术分支同时受 network_read 风险白名单和四个固定工具名白名单约束,不能调用写工具、本地文件工具、计算 工具或任意 MCP 网络工具;越权请求在 Provider 调用前拒绝,也不会创建审批。

所有学术网络结果仍是低信任 research_context,不能直接成为论文引用;外部论文必须经过 许可核验、受控导入、冻结、解析和本地索引后,才能进入 citation_evidence 证据链。 Provider 离线、超时或请求失败时,本地分支和大模型综合仍可继续,结果会标记为降级并明确说明 “外部学术核验未完成”;两类证据都失败时仅返回无引用的模型背景说明,并标记 model_background_only,不会把时效性事实表述为已核验。

可选 MCP 只读工具

MCP(Model Context Protocol,模型上下文协议)只作为现有 Dynamic Tools 子图的工具 provider(提供方),不新增子图,也不进入固定 Local RAG 证据闭环。默认安装和默认运行均 关闭 MCP;安装可选依赖后,由管理员静态配置文件决定准入的 Server 与工具:

python -m pip install -e ".[agent,mcp]"
$env:PRA_MCP_ENABLED = 'true'
$env:PRA_MCP_CONFIG_PATH = 'D:\secure-config\mcp-servers.json'
python scripts/serve_web.py

示例见 deploy/mcp-servers.example.json。示例不含真实路径或密钥;生产配置必须把 Zotero 命令指向本项目固定 Python 环境,把 GitHub 命令指向已审查且固定版本的官方二进制。 GitHub PAT 只通过 GITHUB_PERSONAL_ACCESS_TOKEN 继承,禁止写入 JSON、日志或 Git。

所有 MCP 结果都是低信任 research_context,不能直接成为论文引用。Server 离线时应用 继续启动,相关工具不进入当次不可变 Registry snapshot(注册快照);安全事件只记录 Server ID、ready/degraded、工具数和 reason code。紧急关闭无需迁移或删除状态:

$env:PRA_MCP_ENABLED = 'false'
python scripts/serve_web.py

完整安装、升级审查、隐私、监控与回滚步骤见 MCP 工具接入与运维。

Ragas 评测

论文研究回答可使用固定版本 ragas==0.4.3 评估入选上下文精确率/召回率、回答忠实度、 回答相关性和逐 claim 引用忠实度。评分会按 chunk_id 水化实际入选的完整证据块,并仅在内存中处理真实问题、回答和证据正文;结果文件只保存 案例 ID、数字分数、耗时和安全异常类型。安装、准备检查、小规模冒烟和裁判校准步骤见 Ragas 论文研究 Agent 评测运行手册。

可中断、可编辑的计划执行

主 Agent 支持暂停、继续、取消、跳过步骤、调整目标和任务顺序、只重试失败步骤,以及单任务时间、调用次数和费用预算。所有编辑都保留已完成步骤及其产物;完整状态机、API 和恢复不变量见 可中断可编辑计划执行。

工程原则

  • 每个结论最终绑定 paper_id / element_id / page / evidence_span。
  • 所有实验记录语料、解析器、chunk、embedding 和检索配置版本。
  • 先评测检索,再引入生成与 Agent。
  • 索引可重建,数据导入幂等。
  • 受限论文只用于本地研究,不能由仓库重新分发。
  • 冻结清单中的选题理由、挑战提示和问题创意不得进入索引。

全量文本解析已覆盖 2286/2286 页,并通过跨记录完整性审计和 14 篇、42 页 视觉抽检。806 个图注对应区域已裁剪并由 qwen3.7-plus 生成结构化视觉摘要;当前统一 索引包含 5,446 个正文块和 806 个图片语义块,共 6,252 个 384 维向量。图片采用“视觉 模型转语义文本,再由文本 Embedding 入库”的方案,并非直接对图片像素生成向量。

基础检索评测仍包含开发期单审阅者银标集;论文级候选发现已经补充人工金标基线,多论文比较则 使用 20 题开发集和 10 题封存集执行完整生产链路评测。当前端到端样本仍只有 30 题,生成模型与 模型 Judge(裁判)同源,也尚未进行多次随机重复和第二审阅者盲审,因此这些结果用于内部归因和 版本比较,不应外推为跨语料、跨领域的泛化能力。 模型、正文、片段和索引只保存在本地忽略目录,发布要求见 检索基线发布门禁。

About

面向私有论文库的可复现、证据可追溯研究 Agent:双语图文检索、事实级证据编译、主 Agent 自适应编排、可恢复事件流与受控工具审批。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages