基于 Stanford STORM 扩展构建的个人研究平台。项目结构与定制说明见 docs/MY_CUSTOMIZATIONS.md。
make install # 安装依赖
cp .env.example .env # 配置 LLM 密钥(推荐 DeepSeek)
make test-fast # 离线跑确定性单测
make dashboard # 打开前端仪表盘STORM 写作阶段的语义筛选用 sentence-transformers/paraphrase-MiniLM-L6-v2(约 90MB)
做余弦 Top-K。运行时默认离线加载,本地没有缓存会直接失败。首次使用前下载一次:
PAPERPILOT_ALLOW_MODEL_DOWNLOAD=1 python -c "
from huggingface_hub import snapshot_download
snapshot_download('sentence-transformers/paraphrase-MiniLM-L6-v2')
"模型落到 ~/.cache/huggingface/hub/ 后,之后的运行全部离线读缓存,无需再设环境变量。
PaperPilot 是基于 Stanford STORM 扩展的论文调研与知识问答平台。系统面向科学论文、 本地 PDF、Zotero 文献库和企业内部文档,提供多 Agent 深度调研、证据约束问答、混合检索、 跨会话记忆、上下文治理、运行时恢复、公开 Benchmark 与 Langfuse 可观测性。
- 将 Parent-Child Retrieval 接入调研文章问答和企业文档知识库:先检索段落 Child,再按来源预算展开章节 Parent,引用仍定位原始 Child。
- 对生成文章的长段落进行二级切分,解决“Parent 与唯一 Child 内容完全相同、无法补充上下文”的产品边界。
- 新增冻结排名的 QASPER Parent-Context 诊断;官方 test 1,309 题中,gold evidence token coverage 从
0.808481提升至0.859614(+0.051133),完整 evidence Recall 基本不变。 - 使用真实 arXiv 与 DeepSeek API 验证 Muon 优化器完整调研和后续问答链路。
| 能力域 | 当前实现 | 工程边界 |
|---|---|---|
| 深度调研 | Persona Generator、Conv Simulator、Query Planner、Retriever、Outline、Section Writer、Polisher、Evaluator | 保留 Stanford STORM 的多视角调研与两阶段写作流程 |
| 知识问答 | 普通对话、会话召回、证据检索、证据充分性判断、按需升级深度调研 | 外部论文证据不写入用户长期记忆 |
| RAG | 领域 BM25、冻结 Embedding Profile、Exact/HNSW Dense、RRF、选择性 Cross-Encoder、来源过滤与引用映射 | 产品入口和公开 Benchmark 统一使用 RetrievalPipeline;ACL scoped 请求使用授权子集 Exact |
| Memory | SQLite WAL、事实与 episode、provenance、时间有效性、BM25/真实向量、RRF、MMR | 只保存稳定用户事实、偏好、决策和可复用流程 |
| Context | Pinned、Active、Summary、Memory、Evidence、Artifact 分层预算 | 支持结构化递归摘要、压缩 lineage 和恢复 |
| Runtime | LangGraph、SQLite checkpoint、节点重试、幂等、ACL、缓存、熔断与 trace | 对话状态、调研任务和控制面持久化 |
| Evaluation | SciFact、QASPER、LongMemEval-S、PIM 领域 Pilot、Context Pareto、Answer/Evidence F1 | smoke 仅用于确定性验证,quality profile 才可形成质量结论 |
| Observability | 本地 JSONL、SSE、Langfuse Trace/Span/Score | 敏感字段脱敏,远程观测失败不阻断业务链路 |
图中箭头表示执行或数据传递方向;蓝色表示检索数据,绿色表示控制流,深灰表示 STORM 调研主链,橙色表示外部依赖,紫色表示记忆与持久化。
PaperPilot 保留 Stanford STORM 的知识策展、视角生成、专家访谈、两阶段大纲生成、并行章节写作 与文章润色流程,并在其外围增加统一 RAG、Memory、Context、Agent Runtime、服务控制面和评测系统。 官方模块中文说明见 STORM_OFFICIAL_CN.md。
Stanford STORM Workflow
|
v
PaperPilot Retrieval / Memory / Context
|
v
Conversation Runtime / Production Control Plane
|
v
FastAPI + SSE + Web Dashboard + Langfuse
Source ingestion
-> structure-aware chunking
-> BM25 recall + Dense recall
-> Reciprocal Rank Fusion
-> optional Cross-Encoder rerank
-> relevance and forbidden-term gate
-> evidence package with provenance
-> Reader / article writer
-> citation validation
核心模块:
knowledge_storm/document_ingestion.py:PDF 解析、页码/标题保留与结构化切分。knowledge_storm/retrieval.py:BM25、Dense、RRF、Cross-Encoder 和持久化 Hybrid Index。knowledge_storm/retrieval_pipeline.py:产品与 Benchmark 共用的检索契约,固定retrieve/fuse/rerank/gatestage schema。knowledge_storm/retrieval_runtime.py:调研产物索引缓存和运行时适配。knowledge_storm/paperpilot_qa.py:带引用的调研结果问答。knowledge_storm/paperpilot_enterprise_kb.py:本地文档知识库、ACL、增量重建和缓存失效。
真实服务默认使用 SentenceTransformer。HashEmbeddingProvider 仅用于单元测试和 smoke profile,
不能作为公开质量结果。旧 JSON hash 索引不会被静默读取;系统会明确要求重建,避免检索行为悄然降级。
| Profile | 模型 | 维度 | 定位 |
|---|---|---|---|
legacy-multilingual |
paraphrase-multilingual-MiniLM-L12-v2 |
384 | 历史兼容与回归基线 |
cpu-zh |
BAAI/bge-small-zh-v1.5 |
512 | 中文 CPU 检索 |
cpu-multilingual |
Alibaba-NLP/gte-multilingual-base |
768 | 默认多语种 CPU 档 |
quality-multilingual |
Qwen/Qwen3-Embedding-0.6B |
1024 | GPU 或离线质量优先档 |
Profile 冻结模型 revision、最大序列长度、query/document 编码角色、归一化和必要批次。 语料达到 20,000 个向量时可自动构建 USearch HNSW;小库保留 Exact oracle。带 ACL 的请求 不会先从全库 ANN 取候选再过滤,而是 fail-closed 到授权子集 Exact,避免敏感候选进入后续链路。
RAG 的已知 bad case、工业方案对照和后续路线见 RAG_BAD_CASES_AND_ROADMAP.md。
- Session Recall:从当前用户的历史会话中检索消息和旧话题,用于“之前聊过什么”。
- Long-term Memory:保存用户稳定偏好、明确事实、长期决策和可复用流程,支持跨会话召回。
- Evidence:保存论文或内部文档中的外部事实、chunk、作者、标题、URL、页码和引用关系。
- Context:为当前 LLM 调用组装系统约束、近期消息、结构化摘要、召回记忆、证据与工具产物。
用户询问“之前聊过的 PIM 论文”时,Session Recall 负责找回旧会话中的论文指针,Evidence 负责重新取得论文原文,Long-term Memory 只补充用户偏好,不把论文结论伪装成用户事实。
稳定模块:
knowledge_storm/memory_policy.pyknowledge_storm/memory_store.pyknowledge_storm/context_engine.pyknowledge_storm/paperpilot_session_recall.pyknowledge_storm/conversation_runtime.pyknowledge_storm/control_plane.py
| 检索 | 记忆 | 上下文 | 回答 |
|---|---|---|---|
| Benchmark | 评估对象 | 主要指标 |
|---|---|---|
| SciFact | 跨论文科学事实检索 | Recall@10、MRR@10、nDCG@10、P95 |
| QASPER Retrieval | 论文内人工证据定位 | Evidence Recall@5、MRR@5、nDCG@5、P95 |
| QASPER Answer | 端到端 Reader | Answer F1、Exact Match、Evidence F1 |
| LongMemEval-S | 跨会话长期记忆 | Evidence-session Recall@5、类别 Recall、P50/P95 |
| QASPER Context | 上下文预算治理 | token ratio、gold evidence retention、validation rate |
| Context Pareto | 长上下文配置 | 质量、输入 Token、TTFT、成本和 Pareto frontier |
| PIM Domain Pilot | 50 条本地论文证据绑定问题 | Recall@5、MRR@5、Answer F1、Citation Precision、ANN Recall |
以下结果来自仓库中的公开数据集报告,延迟为本机 CPU 参考值,不代表线上 SLA。
| 累积里程碑 | 受影响评测 | 主要结果 | 结论 |
|---|---|---|---|
| P1:规划与结构化召回 | SciFact / QASPER Retrieval / PIM 固定集 | SciFact Recall@10 0.8114;QASPER Recall@5 0.5057 |
建立可复现基线;PIM/RAM 领域歧义固定案例通过 |
| P1+P2:选择性重排与证据治理 | SciFact / QASPER Retrieval / Evidence Governance | SciFact Recall@10 0.8264;QASPER Recall@5 0.5526;相对 P1 配对 CI 均不跨 0 |
Cross-Encoder 只在风险/不确定查询触发;Top K 内 recall-safe MMR 不替换已召回成员 |
| P1+P2+P3:Claim-Citation | QASPER Answer | 1451 条 test:Answer F1 0.5083、Evidence F1 0.5500、Claim support 0.9592、unsupported claim 0.0214、失败 0 |
相对 v5.5 的跨指纹方向性对比为 Answer F1 -0.0358;可信度可观测性增强,但传统答案覆盖仍需优化 |
| P1+P2+P3+P4:生产治理 | Production Governance 8-case | ACL/Trace 泄漏 0;失败率 0;缓存隔离、超时、熔断恢复、Release Gate 全部通过 |
完全离线、不调用 LLM;不重复运行未受影响的质量数据集 |
| LongMemEval-S Memory | LongMemEval-S | Recall@5 0.8003,P95 359.3 ms |
仅代表 evidence-session retrieval,不等同端到端回答准确率 |
| PIM Domain Pilot | 5 篇论文、797 chunks、50 questions | GTE Recall@5 0.7200;Answer F1 0.3983;Citation Precision 0.9237;真实向量 HNSW Recall@5 1.0000 |
私有领域 pilot;题目由模型生成,不作为公开榜单或生产 SLA |
| QASPER Parent Context | 官方 test 1,309 题、冻结 P2 Top-5 排名 | gold token coverage 0.808481 → 0.859614(+0.051133);完整 evidence Recall 0.552556 → 0.552641 |
衡量 Reader 可见证据覆盖,不是检索排名提升或 Answer F1 |
以下模型对比固定为 BM25 + Dense + RRF、关闭 Reranker 并使用 Exact oracle。只采样 10% query;SciFact 搜索完整 5,183 篇摘要,QASPER 保留抽中问题所属论文的全部 5,265 个段落和 hard negatives。该小样本用于工程选型,不替代完整 test 与置信区间。
| 数据集 | Profile | Recall@5 | nDCG@5 | Build | Query P95 |
|---|---|---|---|---|---|
| SciFact, 30 query | Legacy | 0.6583 | 0.5398 | 119.3 s | 84.3 ms |
| SciFact, 30 query | BGE small zh | 0.6167 | 0.5099 | 279.1 s | 179.6 ms |
| SciFact, 30 query | GTE multilingual | 0.6750 | 0.5738 | 2326.8 s | 328.1 ms |
| SciFact, 30 query | Qwen3 Embedding 0.6B | 0.7250 | 0.5973 | 8457.8 s | 1769.7 ms |
| QASPER, 131 query | Legacy | 0.4673 | 0.3626 | 133.3 s | 68.0 ms |
| QASPER, 131 query | BGE small zh | 0.3746 | 0.3012 | 154.6 s | 34.5 ms |
| QASPER, 131 query | GTE multilingual | 0.5457 | 0.4351 | 927.2 s | 201.9 ms |
| QASPER, 131 query | Qwen3 Embedding 0.6B | 0.5468 | 0.4348 | 2869.7 s | 345.0 ms |
100,000 个 384 维随机向量的本机微基准中,USearch HNSW 的 P95 为 21.591 ms,Exact
为 198.504 ms,HNSW Recall@10 为 0.9055。这是规模行为诊断,不是论文检索质量结论;
2,000,000 向量只报告原始 float32 容量估算,不外推延迟。完整协议、具体改善/退化案例与边界见
PAPERPILOT_RETRIEVAL_STACK_UPGRADE.md。
PIM 领域协议、三模型比较、50 条 Reader 评测和真实 Bad Case 见 PAPERPILOT_DOMAIN_PILOT.md。
详细协议、样本量、split、模型和证据等级见 PAPERPILOT_V55_PUBLIC_BENCHMARKS.md 与 PAPERPILOT_V56_MEMORY_CONTEXT.md。P1-P4 的 配对区间、失败候选与具体 Bad Case 见 RAG_BADCASE_PROGRESSIVE_RESULTS.md。
- Python 3.10 或 3.11。
- 调研真实模式需要 DeepSeek 或 MiniMax API Key。
- quality Benchmark 需要公开数据集和本地模型缓存。
git clone https://github.com/liyuyang/paperpilot.git
cd paperpilot
D:\SOFTWARE\spyder\envs\storm\python.exe -m pip install -e .D:\SOFTWARE\spyder\envs\storm\python.exe examples\storm_examples\start_paperpilot_service.py `
--service-root .\results\paperpilot_demo_service `
--host 127.0.0.1 `
--port 8002浏览器访问 http://127.0.0.1:8002。
也可以直接通过 Uvicorn 启动 ASGI 应用:
D:\SOFTWARE\spyder\envs\storm\python.exe -m uvicorn examples.storm_examples.paperpilot_service_api:app `
--host 127.0.0.1 `
--port 8002Web Dashboard 包含三个工作区:
- 论文调研模式:提交 arXiv 或本地 PDF 调研任务,查看 Agent Graph、实时节点状态、文章与 PDF。
- 智能问答模式:进行多轮聊天;证据不足时可升级检索或深度调研;展示时间与 Token 遥测。
- 开发者控制台:发现本地数据集、运行公开 Benchmark、查看命令、日志、状态与结果指标。
以下命令分别用于确定性 smoke 和真实论文质量评测。真实论文质量结论必须使用冻结数据 split、 真实 embedding 和完整样本,不能由 smoke 结果替代。
# 离线 smoke,仅验证数据适配器、指标和产物链路
D:\SOFTWARE\spyder\envs\storm\python.exe examples\storm_examples\run_paperpilot_public_benchmark.py `
--benchmark scifact `
--dataset-dir <scifact-dir> `
--output-dir <output-dir> `
--embedding hash `
--modes bm25 hybrid `
--smoke-limit 20
# quality profile,使用真实 embedding 与 Cross-Encoder
D:\SOFTWARE\spyder\envs\storm\python.exe examples\storm_examples\run_paperpilot_public_benchmark.py `
--benchmark qasper `
--dataset-dir <qasper-test-json> `
--output-dir <output-dir> `
--embedding real `
--modes bm25 dense hybrid hybrid_rerank `
--reranker `
--top-k 5
# PIM 领域 pilot,使用 50 条证据绑定问题比较三个真实 Embedding Profile
D:\SOFTWARE\spyder\envs\storm\python.exe examples\storm_examples\run_pim_domain_pilot.py `
--corpus "$env:PAPERPILOT_BENCHMARK_ROOT\domain-pim-v7\corpus.jsonl" `
--cases "$env:PAPERPILOT_BENCHMARK_ROOT\domain-pim-v7\cases.jsonl" `
--output-dir "$env:PAPERPILOT_BENCHMARK_ROOT\domain-pim-v7\runs" `
--model-cache "$env:PAPERPILOT_BENCHMARK_ROOT\models" `
--top-k 5Langfuse 是可选分析后端,不替代本地事件审计或固定 Benchmark evaluator。系统将一次调研或一轮 对话映射为 Trace;调研阶段、路由、检索、记忆与交付映射为嵌套 Span;每次 LLM 调用记录为 Generation,并上报模型、输入/输出摘要、Token、耗时、成本、结束原因和错误。密钥只从运行环境读取, 不得写入 README、脚本、提交记录或结果文件。
pip install -e ".[observability]"
export PAPERPILOT_OBSERVABILITY="langfuse"
export LANGFUSE_PUBLIC_KEY="<Langfuse public key>"
export LANGFUSE_SECRET_KEY="<Langfuse secret key>"
export LANGFUSE_BASE_URL="https://cloud.langfuse.com"
# 之后正常跑调研或问答(如 python examples/storm_examples/run_paper_storm_minimax.py ...),
# trace 会自动上报;未启用时事件写入 <output-dir>/observability/events.jsonl| 业务操作 | Trace / Span | Generation 与关键 Score | 可定位的问题 |
|---|---|---|---|
| 深度调研 | paperpilot.research;persona_generation、query_planning、retrieve_arxiv、knowledge_curation、outline_generation、article_generation、polish、pdf_export |
多角色 LLM 的 Token、延迟、成本与 provider error;run_success、run_score |
哪个阶段慢、空检索、生成失败、PDF 交付失败 |
| 多轮问答 | paperpilot.chat;classify、memory_recall、knowledge_retrieval、evidence_grade、deep_research、answer_with_citations |
intent_router、answer_generation;planner_fallback、trajectory_success、retrieval_triggered |
意图误判、路由 JSON 解析失败、不该检索却发起调研、引用回答异常 |
| 长期记忆 | memory_candidate_write、memory_recall |
memory_write_success、写入原因与候选摘要 |
显式记忆请求被跳过、跨会话召回不足、记忆污染 |
| Benchmark | paperpilot.benchmark |
metrics.json 对应的 Recall、nDCG、F1、P95 与 run success |
版本回归、质量/延迟权衡、bad case 是否修复 |
推荐的闭环是:
- 在 Tracing 按 Trace 名、版本、环境或
badcase标签筛选;先看失败率、P95、成本和 Score。 - 打开单条 Trace,沿 Span 树找耗时最长或 error 非空的阶段;再打开其 Generation 核验模型、Prompt 摘要、Token、finish reason 与 provider error。
- 将输入、路由决策、检索候选、证据分数和最终回答导出为固定
case_id;写入 Dataset 后在离线 Eval Harness 回归。 - 以相同数据指纹与检索配置重跑 Benchmark;只有指标和 bad case 均通过才进入发布候选。
典型信号:planner_fallback=1 表示 Planner 输出未通过结构化解析,需检查 intent_router Generation;
memory_write_success=0 且存在显式“请记住”输入,需查看 memory_candidate_write 的跳过原因;
run_success=1 但 run_score 偏低,代表任务交付成功但引用或证据质量仍需优化,而不是“系统完全正常”。
报告中的 remote_trace_id 仅在 SDK 返回时出现,不能假定其与 PaperPilot 本地 trace ID 等价。
未配置、不可达或 exporter 降级时,仍可在 <output-dir>/observability/events.jsonl 审计同一事件链路。
完整的输入合同、筛选步骤与本地 events 降级说明见 LANGFUSE_BADCASE_GUIDE.md。
Trace 与 Span 均携带 tags(版本、环境、badcase 等筛选维度)与 scores(run_success、run_score
等数值指标);当前发布线为 v1.0,所有示例命令中的脚本与路径在 examples/storm_examples/ 内可复现。
映射关系:
| PaperPilot 操作 | Langfuse 对象 | Score |
|---|---|---|
| 调研任务 | paperpilot.research trace + pipeline spans |
run success、scorecard metrics |
| 对话轮次 | paperpilot.chat trace + graph node spans |
trajectory success、retrieval triggered |
| Benchmark | paperpilot.benchmark trace |
metrics.json 数值指标、run success |
未启用 Langfuse 时,事件仍写入 <service-root>/observability/events.jsonl。测试环境设置
PAPERPILOT_OFFLINE_TESTS=1 后会禁用远程 exporter 和模型下载。
简历素材与指标表述边界见 PAPERPILOT_RESUME_GUIDE.md, 题库、追问与评分要点见 RAG_AGENT_INTERVIEW_PLAYBOOK.md。
| 变量 | 说明 |
|---|---|
PAPERPILOT_RETRIEVAL_EMBEDDING |
auto / real / hash;生产默认 real,hash 仅供测试 |
PAPERPILOT_RETRIEVAL_MODE |
hybrid / bm25 / dense / hybrid_rerank |
PAPERPILOT_EMBEDDING_PROFILE |
legacy-multilingual / cpu-zh / cpu-multilingual / quality-multilingual |
PAPERPILOT_RERANKER_PROFILE |
cpu-balanced / quality-gpu |
PAPERPILOT_RETRIEVAL_INDEX_CACHE_SIZE |
运行时索引 LRU 容量 |
PAPERPILOT_MODEL_CACHE |
SentenceTransformer/Cross-Encoder 模型缓存目录 |
PAPERPILOT_BENCHMARK_ROOT |
SciFact、QASPER、LongMemEval 等数据集根目录 |
PAPERPILOT_ZOTERO_ROOT |
Zotero 数据目录 |
PAPERPILOT_OBSERVABILITY |
设置为 langfuse 启用远程观测 |
PAPERPILOT_OFFLINE_TESTS |
设置为 1 禁止测试访问远程观测与模型下载 |
knowledge_storm/
document_ingestion.py # PDF 与结构化 chunk
retrieval.py # 领域 BM25 / Dense / RRF / Cross-Encoder
retrieval_profiles.py # Embedding 与 Reranker 冻结合同
dense_index.py # Exact / USearch HNSW 后端
text_analyzers.py # Jieba 领域词典与 CJK fallback
retrieval_pipeline.py # 产品与 Benchmark 的统一检索契约
retrieval_runtime.py # 调研产物索引与缓存
context_engine.py # 分层上下文预算、压缩与恢复
memory_policy.py # 长期记忆候选与写入策略
memory_store.py # SQLite temporal memory
conversation_runtime.py # LangGraph 会话运行时
control_plane.py # ACL、幂等、缓存、任务与 trace
paperpilot_service.py # 应用服务层
evaluation/public_benchmarks/ # SciFact/QASPER/LongMemEval adapters
evaluation/domain_pilot.py # 私有领域题集合同与证据校验
examples/storm_examples/ # FastAPI、MCP 与 Benchmark CLI
frontend/paperpilot_dashboard/ # 调研、问答和开发者控制台
tests/ # 离线单元、API、前端与评测契约测试
docs/ # 架构、评测协议、路线图与开发记录
当前系统已经完成查询规划、结构化召回、Embedding Profile、Exact/HNSW、领域分词、 选择性 Rerank、Parent Context 公平预算、证据冲突治理、Claim-Citation 校验、检索前 ACL、 运行韧性与离线发布门禁。剩余重点是优化 QASPER 抽象回答覆盖、GPU 质量档、真实论文向量的 HNSW Pareto,并把离线 Release Gate 接入 CI 与预发布 canary。相关案例和验收指标见 RAG_BAD_CASES_AND_ROADMAP.md。
MIT License。Stanford STORM 原始代码与本项目扩展均遵循仓库中的 LICENSE。

