PaperMind · 端到端运行流程详解

从用户提交 PDF 文件夹,到生成结构化研究提案(含创新点 + 实验方案)的完整代码执行路径、每次 LLM 调用与工具调用的输入输出全记录。

Plan-and-Execute + Reflexion 7 步漏斗式信息收敛 DeepSeek Function Calling BGE-m3 + Chroma 混合检索

0总览:七步漏斗流水线

整个系统由 WorkflowOrchestrator 编排,分三大阶段:预处理(步骤 1-3,带缓存)→ Plan(LLM 动态规划步骤 4-7)→ Execute(步骤 4-7,每步后插入 Reflexion 自校验)。

STEP 1
PDF 解析
PyMuPDF 提取章节结构
本地
→
STEP 2
结构化抽取
Function Calling 抽 9 字段
LLM 并行
→
STEP 3
向量索引
BGE-m3 → Chroma + BM25
本地
↓
STEP 4
Gap 识别
四类 Gap 信号综合推理
LLM RAG
→
STEP 5
创新点生成
四类来源 + 三维评分筛选
LLM 联网
→
STEP 6
实验设计
8 要素可执行方案
LLM
→
STEP 7
整合输出
Markdown 研究提案
LLM
核心设计哲学:漏斗式信息收敛 — 每步压缩信息,最后一步才做创造性推理(避免早期噪声干扰)。所有中间产物都是结构化 JSON / 向量,不依赖长上下文记忆。

1启动阶段(进程级)

用户运行 python run_backend.py 启动 FastAPI 服务,前端 npm run dev 启动 Vite。

启动命令

python run_backend.py
# 等价于:uvicorn backend.api.main:app --host 0.0.0.0 --port 8000

启动钩子(on_startup)

应用启动时预加载重型依赖,避免首次请求时才触发 import(torch 单独 import 100+ 秒):

# 顺序预加载
import torch              # ~5s
from transformers import AutoModel, AutoTokenizer   # ~3s
import chromadb           # ~2s

# 预热 Embedder 单例:加载 BGE-m3 模型 + 首次 forward(初始化 CUDA 上下文)
_embedder = get_default_embedder()
_embedder.embed_texts(["预加载测试文本"])
输入
无(进程启动)
输出
FastAPI 服务监听 0.0.0.0:8000,BGE 模型已 warmup,前端可访问 localhost:5173

2用户提交分析任务

前端发 HTTP 请求,后端创建任务并后台异步启动,立即返回 task_id。

HTTP 请求

# POST /api/analyze
{
  "folder_path": "D:/papers",
  "research_direction": "多模态学习"
}

路由处理 routes.py:157

  1. task_manager.create_task() → 生成 task_id(uuid),状态 pending
  2. asyncio.create_task(run_analysis(...)) → 后台异步启动,不阻塞响应
  3. 立即返回 {"task_id": "..."}

后台主流程 routes.py:51

# 初始化组件
client = DeepSeekClient()                                    # LLM 客户端
registry = build_default_registry()                          # 工具注册表
memory = MemoryManager()                                     # 双层记忆
orchestrator = WorkflowOrchestrator(client, registry, memory)

# 执行流水线
pipeline_output = await orchestrator.run_pipeline(...)

# 生成报告 + 评估
report = await ReportAgent(client).generate_report(final_results)
evaluation = await Evaluator(client).evaluate(...)

# 存结果
task_manager.update_task(task_id, status="completed", result={...})
SSE 进度推送:整个后台流程通过 progress_callback 实时推送 {stage, status, message, progress, payload} 到 GET /api/progress/{task_id},前端可流式渲染进度条。

3Phase 1:预处理(步骤 1-3,带缓存)

由 Controller._preprocess_papers() 编排,对每篇论文检查 PaperLibrary 缓存状态:已完成的步骤直接从磁盘加载(标记 cached),未完成的执行后写盘。

① PDF 解析 PyMuPDF 提取章节结构
parse_pdf.py
本地处理 并发 asyncio.gather 缓存 data/cache/parsed/{paper_id}.json

处理流程

  • PyMuPDF 提取每页文本 + 字号/字体信息
  • 启发式识别章节标题(字号 > 正文×1.15 或加粗 + 关键词匹配 abstract|introduction|method...)
  • 去页眉页脚(短行 < 80 字符且重复出现)
  • 提取图表标题(Figure X / 表 X 正则)
  • 合并跨页段落,修复断句
输入
{
  "file_path": "D:/papers/xxx.pdf"
}
输出:ParsedPaper
{
  "path": "D:/papers/xxx.pdf",
  "title": "Attention Is All You Need",
  "sections": [
    {
      "heading": "Abstract",
      "content": "...",
      "figure_captions": ["Figure 1: ..."]
    }
  ]
}
缓存复用:解析结果写入 data/cache/parsed/{paper_id}.json,PaperLibrary 标记 parse_status=done。下次同一论文直接 load_parsed() 加载,跳过解析。
② 结构化抽取 核心主干 · Function Calling 强制 JSON
extract_paper_structure.py:214
LLM 调用 并行 asyncio.gather + Semaphore(5) 缓存 data/cache/papers/{paper_id}.json + papers.jsonl

处理流程

  1. 长度判断:总字符 > 20000 → 按章节分块抽取后合并;否则一次性抽取
  2. 调用 LLM(_call_extract):强制 tool_choice={"type":"function","function":{"name":"extract_paper_fields"}}
  3. 字段完整性校验:缺失字段 → 针对性补抽(focus_fields 只补缺失的,不重跑整篇)
  4. 长论文合并:多块记录按置信度取最高 value,source_sections 去重合并
LLM Prompt · 抽取(核心)
[System]
你是论文结构化抽取助手。严格通过函数调用输出 JSON,
每个字段含 value/source_sections/confidence。
limitations 必须真实可溯源,严禁臆造。

[User]
请从以下论文中抽取结构化字段。

论文标题:{title}

论文正文:
## Abstract
{...}
## Introduction
{...}

抽取要求:
1. 必须抽取以下字段:title、task_problem、method、key_contributions、
   datasets、metrics、results、limitations、future_work
2. 每个字段必须是 FieldSource 结构:
   {
     "value": "字段值(字符串,尽量简洁完整)",
     "source_sections": ["原文出处章节标题列表"],
     "confidence": 0.0-1.0
   }
3. source_sections 必须标注字段信息来源于上面哪个章节(用章节标题原文),便于回溯核查
4. limitations 字段特别要求:必须是论文明确承认的局限,或可从实验结果直接推断的局限,
   严禁臆造或泛泛而谈。若论文未明确提及局限,value 填写"论文未明确陈述局限",confidence 设为较低值(如 0.3)
5. confidence 反映可信度:
   - 信息明确且原文直述 → 0.9-1.0
   - 需要从原文推断 → 0.6-0.8
   - 信息不足或模糊 → 低于 0.6
6. 严格输出 JSON,不要添加任何额外说明文字或 markdown 代码块标记
LLM Prompt · 针对性补抽(缺失字段)
[User]
前一次抽取缺失了以下字段:{", ".join(focus_fields)}。
请重点从原文中补抽这些字段,其他字段可留空。

{...同上 prompt...}
Function Calling Schema · extract_paper_fields
{
  "type": "function",
  "function": {
    "name": "extract_paper_fields",
    "description": "从论文中抽取结构化字段,每个字段含 value/source_sections/confidence",
    "parameters": {
      "type": "object",
      "properties": {
        "title": { "type": "object", "properties": {
          "value": {"type":"string"},
          "source_sections": {"type":"array","items":{"type":"string"}},
          "confidence": {"type":"number"}
        }},
        "task_problem": { ... 同上 ... },
        "method": { ... },
        "key_contributions": { ... },
        "datasets": { ... },
        "metrics": { ... },
        "results": { ... },
        "limitations": { ... },
        "future_work": { ... }
      },
      "required": ["title","task_problem","method","key_contributions",
                   "datasets","metrics","results","limitations","future_work"]
    }
  }
}
输入
{
  "paper_path": "D:/papers/xxx.pdf",
  "parsed_paper": {ParsedPaper dict}
}
输出:PaperRecord
{
  "path": "...",
  "title": {
    "value": "Attention Is All You Need",
    "source_sections": ["Title"],
    "confidence": 1.0
  },
  "task_problem": {
    "value": "序列建模任务...",
    "source_sections": ["Introduction"],
    "confidence": 0.9
  },
  "method": {
    "value": "Transformer 架构...",
    "source_sections": ["3 Method","3.1"],
    "confidence": 0.95
  },
  "limitations": {
    "value": "位置编码外推性差...",
    "source_sections": ["6 Conclusion"],
    "confidence": 0.7
  },
  ...
}
防编造机制:每个字段强制 source_sections 回溯到具体章节,limitations 严禁臆造。这是后续创新点论证可追溯性的基石。
③ 向量索引构建 BGE-m3 → Chroma + BM25
build_vector_index.py
本地处理 Chroma PersistentClient 持久化 失败降级 skip_rag

处理流程

  1. 分块:按段落累积到 ~500 字符落块,每块携带 section 标题
  2. 向量化:BGE-m3 本地 Embedding(无 API 成本),块内容 = section_heading + text
  3. 写入 Chroma:paper_chunks collection,metadata 含 paper_path/title/section
  4. 同步构建 BM25:倒排索引供关键词检索
输入
{
  "papers_json": [{ParsedPaper}, ...]
}
输出
{
  "indexed_count": 12,
  "status": "done"
}
定位:RAG 是"点查询工具"而非"分析引擎",仅在结构化摘要不够用时调用(步骤④⑤ 中需原文细节佐证时)。混合搜索 = Chroma 向量(α=0.6)+ BM25(α=0.4)分数归一化加权融合。

4Phase 2:Plan(LLM 动态规划)

让 LLM 根据任务自主规划步骤顺序/增减,体现动态编排。失败时回退默认七步计划。实际执行时过滤掉步骤 1-3(已由预处理完成),只执行步骤 4-7。

调用位置 controller.py:126

LLM Prompt · 动态规划
[System]
你是 Agent 编排器,负责生成可执行的动态计划。只输出 JSON。

[User]
你是论文创新 Agent 的 Controller。请为以下任务生成动态执行计划。

任务:分析文件夹 {folder_path} 中的 PDF 论文,
识别研究空白,生成 2-3 个创新点并设计实验方案。

可用 Agent:
- PaperParser:扫描文件夹并解析 PDF
- Extractor:单篇论文结构化抽取
- Indexer:向量索引构建
- GapAnalyzer:跨论文 Gap 识别
- InnovationGenerator:创新点生成与筛选
- ExperimentDesigner:实验方案设计
- Integration:整合输出研究提案

请生成执行计划,输出 JSON 数组,每个元素含:
- step: 步骤序号(整数)
- agent: Agent 名称(上述之一)
- action: 该步骤具体任务描述
- depends_on: 依赖的步骤序号列表

你可以根据任务自主调整顺序或增减步骤。
默认链路:解析→抽取→索引→Gap分析→创新生成→实验设计→整合。
严格只输出 JSON 数组,不要其他文本。
输入
"D:/papers" 或
"已上传的 12 篇论文"
输出:计划列表
[
  {"step":4,"agent":"GapAnalyzer",
   "action":"跨论文综合分析识别研究空白",
   "depends_on":[2]},
  {"step":5,"agent":"InnovationGenerator",
   "action":"针对 Gap 生成创新点并筛选",
   "depends_on":[4]},
  ...
]

5Phase 3:Execute(步骤 4-7 + Reflexion)

逐步执行计划,每步完成后插入 Reflexion 自校验钩子(仅对 Extractor / GapAnalyzer / InnovationGenerator 启用)。每步还根据结果动态调整剩余计划。

绕过 Function Calling 的设计:步骤 ④⑤⑥ 中,Controller 直接调用工具(参数已确定),不让模型再选一次工具。因为 DeepSeek 实测会把整段 JSON 当字符串传或漏传参数,浪费迭代次数。只让 LLM 做推理,不让它做参数路由。
④ Gap 识别 跨论文综合推理 · 四类 Gap 信号
analyze_gaps.py:88
LLM 调用 hybrid_search 工具 RAG 增强 evidence

处理流程

  1. 聚合对比矩阵:把 N 篇论文的 8 个字段聚合成文本(关键:让模型在全局视野下识别 Gap)
  2. 调用 LLM 做跨论文综合推理,识别四类 Gap
  3. RAG 增强:对每个 Gap 调用 hybrid_search 检索原文细节,补充 evidence
LLM Prompt · Gap 识别
[System]
你是一位严谨的学术研究分析专家,擅长跨论文综合推理与 Gap 识别。
只输出严格 JSON,不要输出任何其他内容。

[User]
你是一位资深学术研究者,需要从以下多篇论文的结构化对比中识别研究空白(Gap)。

## 论文对比矩阵
===== 论文 1: Attention Is All You Need =====
[研究任务/问题] 序列建模任务...
[核心方法] Transformer 架构...
[局限性] 位置编码外推性差...
[未来工作] 扩展到多模态...
===== 论文 2: BERT =====
[研究任务/问题] ...
[核心方法] ...
[局限性] ...

## 任务
请综合分析上述论文,识别以下四类 Gap 信号:
1. repeated_limitation(重复局限):多篇论文提到同一局限性,但无人解决
2. method_gap(方法空白):某类问题只有少数方法尝试且效果不佳
3. contradictory(矛盾结论):不同论文对同一问题给出冲突结论
4. unfulfilled_future(未兑现的未来工作):多篇论文指向同一未来方向但无人完成

对于单篇论文场景,重点关注该论文自身的 limitations 与 future_work 字段。

## 输出要求
严格输出 JSON:
{
  "gaps": [
    {
      "description": "Gap 的清晰描述",
      "gap_type": "repeated_limitation|method_gap|contradictory|unfulfilled_future",
      "source_papers": ["来源论文标题1"],
      "evidence": "论证依据,引用具体论文的具体字段",
      "confidence": 0.0到1.0之间的置信度
    }
  ]
}

只输出真正有证据支撑的 Gap,不要编造。每个 Gap 的 source_papers 至少包含 2 篇论文。
输入
{
  "papers_records": [
    {PaperRecord 1},
    {PaperRecord 2},
    ...
  ]
}
输出
{
  "gaps": [
    {
      "description": "位置编码外推性普遍较差",
      "gap_type": "repeated_limitation",
      "source_papers": ["Attention...","BERT..."],
      "evidence": "两篇均提及... [原文佐证]\n  - 《Attention》6 Conclusion: ...",
      "confidence": 0.85
    }
  ]
}
↻ Reflexion 自校验 针对性补抽(非整篇重跑)
reflexion.py:67
LLM 调用 置信度 < 0.7 触发重试

触发条件

仅对 Extractor / GapAnalyzer / InnovationGenerator 启用。步骤完成后,让 LLM 对照上下文检查结果质量。

LLM Prompt · 自校验
[System]
你是质量审核员,负责对照上下文检查 Agent 输出质量。只输出 JSON。

[User]
请对照上下文检查以下步骤的结果质量。

步骤:{step_name}
上下文:
步骤 2 结果:{抽取记录摘要...}

结果:
{result_str}

检查要求:
1. 评估结果是否准确、完整、无臆造;
2. 输出 0-1 的置信度(confidence);
3. 列出发现的问题(issues);
4. 置信度低于 {CONFIDENCE_THRESHOLD=0.7} 时 needs_retry=true;
5. 指出需重试的字段或方面(retry_fields)。

严格以 JSON 输出:
{"confidence": 0.85, "issues": ["问题1"], "needs_retry": false, "retry_fields": []}

重试逻辑

  1. confidence < 0.7 → needs_retry = true
  2. 调用 retry_func() 重新执行该步骤(针对性补抽,非整篇重跑)
  3. 最多重试 MAX_RETRIES=2 次
  4. 仍不达标 → 标记 needs_human_review,流程继续不阻塞
输入
{
  "step_name": "GapAnalyzer",
  "result": {步骤结果},
  "context": {依赖步骤结果}
}
输出
{
  "confidence": 0.85,
  "issues": ["..."],
  "needs_retry": false,
  "retry_fields": []
}
⑤ 创新点生成 四类来源 + 三维评分筛选 + 联网去重
generate_innovations.py:58
LLM 调用 web_search 工具(DuckDuckGo) 联网失败降级 skip_novelty_check

处理流程

  1. 调用 LLM:针对每个 Gap 从四类来源生成候选创新方向
  2. 规范化 + 排序:按三维评分之和降序
  3. 取 Top 2-3
  4. 联网新颖性去重:对每个创新点用 DuckDuckGo 搜索近 1-2 年 arXiv/Google Scholar,验证是否已有相同工作
LLM Prompt · 创新生成
[System]
你是一位学术创新生成专家,擅长从研究空白中挖掘可执行的创新方向。
只输出严格 JSON,不要输出任何其他内容。

[User]
你是一位富有创造力的学术研究者,需要基于以下研究空白(Gap)生成候选创新方向。

## 用户研究方向约束
用户的研究方向为:{research_direction}
生成的创新点应尽量与该方向相关,并在 supporting_evidence 中说明创新点与该方向的关联。

## 研究空白列表
- [repeated_limitation] 位置编码外推性普遍较差(来源: Attention..., BERT...)
- [method_gap] ...

## 任务
针对每个 Gap,从以下四类来源生成候选创新方向:
1. method_combination(方法组合):把 A 论文方法迁移到 B 论文问题
2. limitation_fix(局限改进):直接解决被反复提及的局限
3. cross_domain(跨域迁移):引入其他领域方法
4. new_scenario(新场景应用):把现有方法用到未被覆盖的数据/场景

对每个候选创新方向,用三维评分(0-10 分):
- novelty(新颖性)
- feasibility(可行性)
- significance(显著性)

## 输出要求
严格输出 JSON:
{
  "innovations": [
    {
      "title": "创新点标题",
      "idea": "创新思路详细描述",
      "source": "method_combination|limitation_fix|cross_domain|new_scenario",
      "gap_origin": "对应的 Gap 描述",
      "score": {"novelty": 8.0, "feasibility": 7.5, "significance": 8.0},
      "supporting_evidence": "论据支撑"
    }
  ]
}

生成多个候选(每个 Gap 至少 1-2 个),按综合得分(三项之和)从高到低排序。
输入
{
  "gaps": [{Gap}, ...],
  "research_direction": "多模态学习"
}
输出
{
  "innovations": [
    {
      "title": "基于 RoPE 的多模态位置编码",
      "idea": "...",
      "source": "limitation_fix",
      "gap_origin": "位置编码外推性差",
      "score": {"novelty":8.0,"feasibility":7.5,"significance":8.5},
      "novelty_check": "近 1-2 年无相同工作",
      "supporting_evidence": "..."
    }
  ]
}
⑥ 实验方案设计 8 要素可执行研究方案
design_experiments.py:34
LLM 调用
LLM Prompt · 实验设计
[System]
你是一位学术实验设计专家,擅长设计严谨可执行的研究方案。
只输出严格 JSON,不要输出任何其他内容。

[User]
你是一位资深学术研究者,需要为以下创新点设计可执行的研究方案。

## 创新点列表
- 基于 RoPE 的多模态位置编码: ...(来源: limitation_fix,Gap: 位置编码外推性差)

## 任务
为每个创新点设计完整、可执行的研究方案,包含:
- hypothesis(研究假设):清晰可验证的假设
- datasets(数据集列表):适合该研究的公开数据集
- baselines(基线方法列表):需要对比的现有方法
- metrics(评估指标列表):量化评估指标
- ablation(消融实验设计列表):验证各组件贡献
- steps(实验步骤列表):可复现的实验流程
- expected_results(预期结果):预期达到的性能或发现
- risks(风险):可能的失败点与应对

## 输出要求
严格输出 JSON:
{
  "experiment_plans": [
    {
      "innovation_title": "对应的创新点标题",
      "hypothesis": "研究假设",
      "datasets": ["数据集1","数据集2"],
      "baselines": ["基线方法1","基线方法2"],
      "metrics": ["指标1","指标2"],
      "ablation": ["消融实验1"],
      "steps": ["步骤1","步骤2","步骤3"],
      "expected_results": "预期结果描述",
      "risks": "风险与应对描述"
    }
  ]
}

每个创新点对应一条方案,方案须具体可执行。
输入
{
  "innovations": [{Innovation}, ...]
}
输出
{
  "experiment_plans": [
    {
      "innovation_title": "基于 RoPE 的多模态位置编码",
      "hypothesis": "RoPE 能提升多模态任务外推性",
      "datasets": ["COCO","VQA"],
      "baselines": ["ALiBi"," vanilla PE"],
      "metrics": ["BLEU","Accuracy"],
      "ablation": ["移除旋转矩阵"],
      "steps": ["..."],
      "expected_results": "...",
      "risks": "..."
    }
  ]
}
⑦ 整合输出 Markdown 研究提案 · 可追溯
report_agent.py:47
LLM 调用(max_tokens=8192) LLM 失败降级本地格式化

输入聚合 workflow.py:127

_build_final_results() 从各步骤的 tool_calls 里聚合 4 字段:

{
  "papers_records": [...],    # 步骤②所有抽取记录
  "gaps": [...],              # 步骤④所有 Gap
  "innovations": [...],       # 步骤⑤所有创新点
  "experiment_plans": [...]   # 步骤⑥所有实验方案
}
LLM Prompt · 整合报告
[System]
你是学术研究提案撰写专家,擅长把多篇论文的 Gap 分析、创新点与实验方案
整合为结构清晰、可追溯的研究提案。严格输出 JSON,不要输出任何额外说明文本。

[User]
请基于以下前序步骤产物,整合为一份结构化研究提案。

## 研究主题
{topic}

## 一、论文结构化记录(含 source_sections,可追溯)
----- 论文 1: Attention Is All You Need (path=...) -----
  [研究任务/问题] 序列建模...  (出处章节: Introduction)
  [核心方法] Transformer...  (出处章节: 3 Method; 3.1)
  [局限性] 位置编码外推性差  (出处章节: 6 Conclusion)
  ...

## 二、识别到的 Gap 列表
Gap 1 [repeated_limitation] (置信度=0.85): 位置编码外推性普遍较差
  来源论文: Attention...; BERT...
  论证: 两篇均提及...

## 三、创新点列表(含三维评分)
创新点 1: 基于 RoPE 的多模态位置编码 (来源=limitation_fix)
  创新思路: ...
  三维评分: 新颖性 8 / 可行性 7 / 显著性 9
  新颖性验证: 近 1-2 年无相同工作
  论据支撑: ...

## 四、实验方案列表
方案 1 (对应: 基于 RoPE 的多模态位置编码)
  研究假设: ...
  数据集: COCO, VQA
  ...

## 整合任务
1. 背景综述:基于 Gap 分析梳理领域现状与脉络
2. 创新点论证:对每个创新点补充 Gap 来源 + 创新思路 + 三维评分 + 论据支撑
3. 实验方案:保留每个创新点的完整实验方案要素
4. 参考文献溯源:所有引用论文的来源标注,可追溯至具体章节(source_sections)
5. Markdown 报告:按指定结构生成完整 Markdown 文本

## Markdown 报告结构要求
# 研究提案:[主题]
## 一、背景综述
## 二、创新点论证
### 创新点 1:[标题]
- Gap 来源:...
- 创新思路:...
- 三维评分:新颖性 X / 可行性 X / 显著性 X
- 论据支撑:...
## 三、实验方案
## 四、参考文献溯源

## 输出要求
严格输出 JSON:
{
  "background_review": "背景综述文本",
  "innovations": [...],
  "experiment_plans": [...],
  "references": [{"title":"...","path":"...","sections":[...]}],
  "markdown": "完整 Markdown 报告字符串"
}

注意:
- references 必须可追溯至具体章节(source_sections)
- 不得编造论文或证据,所有引用须来自上述论文记录
- 若某字段在输入中缺失,对应位置写"暂无"而非编造
输入
{
  "papers_records": [...],
  "gaps": [...],
  "innovations": [...],
  "experiment_plans": [...]
}
输出
{
  "background_review": "...",
  "innovations": [...],
  "experiment_plans": [...],
  "references": [
    {"title":"...","path":"...",
     "sections":["3 Method","6 Conclusion"]}
  ],
  "markdown": "# 研究提案:...\n## 一、背景综述\n..."
}

6评估阶段

流水线完成后,Evaluator 汇总工具调用追踪 + 输出质量评估,产出统一评估结果。

调用位置 evaluator.py:28

  1. ToolCallTracker 汇总工具调用成功率 / 总数 / 失败数 / 耗时
  2. QualityEvaluator 对每个创新点调 LLM 做三维评分校验
LLM Prompt · 质量评估
[System]
你是一位学术评审专家,擅长对创新点进行多维评分。只输出严格 JSON。

[User]
你是一位严谨的学术评审专家,请对以下创新点进行三维评分(0-10 分,保留一位小数)。

## 创新点信息
- 标题:{title}
- 思路:{idea}
- 论据支撑:{supporting_evidence}
- 新颖性检查:{novelty_check}

## 评分维度
- novelty(新颖性):与现有工作的差异程度
- feasibility(可行性):技术实现与资源获取的难度
- significance(显著性):学术或应用价值

## 输出要求
严格输出 JSON:
{
  "innovation_title": "...",
  "score": {"novelty": 8.0, "feasibility": 7.5, "significance": 8.0},
  "reasoning": "评分理由,简明扼要"
}

输出

{
  "innovations_scores": [...],
  "tool_call_success_rate": 0.89,
  "total_tool_calls": 47,
  "failed_tool_calls": 5,
  "avg_confidence": 0.78,
  "tool_calls": [...],
  "quality_assessment": {...}
}

7完整 LLM 调用清单

单次完整运行共触发 11 次 LLM 调用(不含工具内部重试)。

# 阶段 调用位置 Prompt 设计要点 输出格式
1Plancontroller.py:151Agent 编排器,生成动态计划JSON 数组
2步骤②extract_schema.py:102强制 Function Calling,source_sections 防编造,limitations 严禁臆造FieldSource JSON
3步骤②补抽extract_paper_structure.py:161只补缺失字段,不重跑整篇FieldSource JSON
4步骤②自校验extract_paper_structure.py:306对照原文逐字段检查置信度JSON
5步骤④analyze_gaps.py:113四类 Gap 信号识别,对比矩阵输入JSON gaps 列表
6步骤④ Reflexionreflexion.py:67质量审核员,对照上下文检查JSON confidence
7步骤⑤generate_innovations.py:81四类创新方向 + 三维评分 + 方向约束JSON innovations
8步骤⑤ Reflexionreflexion.py:67同上JSON confidence
9步骤⑥design_experiments.py:518 要素实验方案JSON plans
10步骤⑦report_agent.py:197整合 4 字段为 Markdown 研究提案JSON + markdown
11评估quality.py:73学术评审专家三维评分校验JSON score

工具调用清单

工具步骤输入输出特性
scan_folder①folder_pathpdf_files 列表本地
parse_pdf①file_pathParsedPaper本地 · 并发 · 缓存
extract_paper_structure②paper_path, parsed_paperPaperRecordLLM · 并发 · 缓存
build_vector_index③papers_jsonindexed_count本地 · 持久化
analyze_gaps④papers_recordsgaps 列表LLM · 内部调 RAG
hybrid_search④⑤query检索片段 + 分数Chroma + BM25
generate_innovations⑤gaps, research_directioninnovations 列表LLM · 内部调 web_search
web_search⑤query搜索结果摘要DuckDuckGo
design_experiments⑥innovationsexperiment_plansLLM
load_memory / save_memory⑤type, query历史 Gap/创新点Chroma 长期记忆

8Prompt 设计的 5 个核心原则

贯穿所有 prompt 的设计哲学。

① System 角色锚定

每个 prompt 都用 system 消息锁定角色("你是 XX 专家"),并在末尾强调"只输出严格 JSON",避免自由文本。

② 结构化输出强制

全部用 Function Calling 或显式 JSON Schema,避免 LLM 自由发挥导致解析失败。步骤② 用 tool_choice={"type":"function",...} 强制调用。

③ 防编造机制

source_sections 强制溯源 + "严禁臆造" + "缺失填暂无"。步骤② limitations 字段特别约束:论文未明确承认时填"论文未明确陈述局限"而非编造。

④ 上下文注入

把前序步骤的结构化产物作为"证据"喂给模型,而非让模型凭空推理。步骤④ 喂对比矩阵、步骤⑦ 喂 4 字段聚合。

⑤ 降级兜底

每个 LLM 调用都有 try/except,失败时回退到本地格式化或默认值。步骤⑦ LLM 失败 → _format_markdown() 本地组装。

9降级与容错策略

每个步骤都有失败兜底,局部失败不阻塞全局。

失败点降级路径影响
单篇论文解析失败隔离跳过,独立缓存可单独重跑不影响其他论文
LLM 输出非 JSONFunction Calling 强制 schema + parse_json_safe 程序层兜底该字段降级为空
工具调用超时/失败3 次重试 + 降级路径记录 degraded_steps
论文超长截断按章节分块抽取后合并去重无影响
Controller 规划失败异常捕获 + 回退默认七步无影响
向量索引构建失败跳过 RAG,仅用结构化字段做 Gap 分析Gap evidence 无原文佐证
联网搜索失败跳过新颖性去重,标记"未验证"novelty_check 为空
Reflexion 重试 2 次仍不达标标记 needs_human_review,流程继续评估报告标注
步骤⑦ LLM 整合失败本地 _format_markdown() 格式化组装报告样式简化
LLM 编造内容所有字段强制 source_sections 字段级回溯可人工核查
设计哲学:"工具即思维" — Function Calling 把"决策"显式化为工具调用,可观测、可回放;"降级即韧性" — 每个步骤都有失败兜底,局部失败不阻塞全局。