项目名称:ScholarCraft
定位:一个本地与远端混合模型驱动的科研调研Agent,能自主规划、调用工具、阅读论文并生成结构化报告。
技术栈:LangGraph + Ollama (Qwen3-4B) + 小米 MiMo API
进度:搜索系统全面升级、智能评估机制完善、工具能力增强、本地论文库扩充至26篇、报告质量显著提升


前言

在第一篇文章中,我记录了 ScholarCraft 从零到一实现核心闭环的全过程——环境搭建、模型选型、工具系统和状态机设计。当时 Agent 能跑通"搜索→读取→生成报告"的完整流程,但论文库只有 3 篇种子论文,搜索词靠本地 Qwen3-4B 生成,质量不稳定,也没有重试和评估机制。

"能跑通"只是第一步。真正让 Agent 变得好用,需要解决三个核心问题:搜索结果的质量如何保证?搜不到相关论文时怎么办?报告能不能每次都保持同样的深度和诚实度?

这篇文章记录的就是这个打磨过程。所有代码改动都经过了实际测试验证,每一步的决策逻辑我也会写清楚。


一、搜索系统全面升级

1.1 多角度搜索策略

初始版本的搜索只用 LLM 生成一个关键词,命中率完全取决于这个词有多精准。面对不熟悉的领域,本地 Qwen3-4B 往往只能给出泛泛的短语组合,搜索结果波动很大。

改进后的做法是要求 LLM 从四个维度生成查询变体:

搜索角度 目标 示例
综述角度 获取全景视角 diffusion model molecular generation survey review
经典方法角度 命中这个领域公认的方法名 DiffSBDD EDM GeoDiff molecular generation
最新进展角度 获取前沿预印本 diffusion model molecule generation 2024 recent advances
Benchmark 角度 获取标准化评测数据 QM9 ZINC GEOM diffusion model benchmark evaluation

四个角度的查询并行执行,结果合并去重。这个设计参考了学术文献调研的规范做法——综述提供全貌,经典方法提供锚点,最新进展提供前沿,Benchmark 提供对比基准。

在 tool_select_node 的 Prompt 中加入多角度指令后,搜索词质量变化明显。以前面对"扩散模型在分子生成中的应用",本地模型只能生成 diffusion model molecular generation survey 这种宽泛词;现在切换到 MiMo 驱动后,能给出 DiffSBDD EDM GeoDiff molecular generation 这种具体的方法名组合。

1.2 搜索词生成改用 MiMo

这是搜索质量提升最关键的一步。

本地 Qwen3-4B 在大多数工具选择任务上够用,但生成搜索词需要更强的领域知识——知道这个领域有哪些经典方法、哪些公认数据集、哪些常见评测基准。这些知识本地小模型不具备。

远端 MiMo-V2.5-Pro 的推理能力和知识储备远超本地模型。同一句"搜一下扩散模型在分子生成中的应用",MiMo 能生成:

text

"DiffSBDD EDM GeoDiff molecular generation"
"diffusion model QM9 ZINC MOSES benchmark molecular generation"

这就是为什么在 tool_select_node 中,搜索步骤和补充搜索步骤全部走 MiMo,而非搜索步骤(read_paper、compare)继续用本地 Qwen3-4B。这个分层的架构设计是项目面试叙事中很重要的一环。

1.3 强制先搜本地库

在多次运行中观察到 MiMo 在规划步骤时有时会直接跳到 search_arxiv,跳过本地搜索,导致本地已有的 26 篇论文被闲置。

修复方式是在 plan_task 的 system_prompt 中加了一条硬约束:

text

规划规则:第一步必须使用 search_local 优先检索本地论文库,
第二步使用 search_arxiv 补充最新预印本。

改动只有一行,但效果立竿见影——本地库再也不会被跳过。

1.4 新增 Semantic Scholar 工具

arXiv 是预印本平台,有两个固有缺陷:论文未经同行评审,质量参差不齐;没有引用统计,无法区分"奠基性论文"和"刚发上去的草稿"。

Semantic Scholar API 完美弥补了这两个缺陷。它免费、不需要 Key、支持按引用次数排序、返回发表在正式会议/期刊上的论文信息。

工具已经写好并注册到了 MCP Server。虽然当前 WSL 网络环境下 Semantic Scholar 的连接不稳定,暂时注释掉了自动调用,但架构上已经就绪。将来网络恢复只需取消注释即可启用三数据源(本地 + arXiv + Semantic Scholar)协同检索。


二、智能评估与流程控制

2.1 迭代式检索:搜不到就换个姿势再搜

最初的 Agent 搜一次就认了。如果搜索结果太少(比如只返回 1 篇),或者全都不相关,它照样继续往下走,最后生成的报告自然没什么内容。

现在在 evaluate_node 中增加了搜索质量检查。核心逻辑很简单:

  • 搜索完成后,统计有效论文数量

  • 如果少于 3 篇,且重试次数未满上限,就回到 tool_select_node,让 LLM 根据上轮搜索结果生成新的搜索词,再搜一轮

  • 如果数量够了,进行相关性评估

日志中可以清晰看到这个过程:

text

[EVAL] 只找到 1 篇有效论文,触发补充搜索(第1次重试)
[SELECT] 补充搜索模式,生成新查询词...
[CALL] 使用 arXiv 联网检索: 'equivariant diffusion model 3D molecular generation drug design'
[EVAL] 找到 4 篇有效论文,搜索完成,继续下一步
2.2 LLM 相关性评估

只检查数量是不够的。arXiv 有时会返回一堆完全不相关的论文——比如搜"分子生成扩散模型",能给你返回"星际分子云形成"的论文。如果只看数量,5 篇不相关的论文会被当作"够了"。

现在搜索完成后,让本地 Qwen3-4B 对搜索结果与用户需求的相关性打分(0-10 分),并给出简短理由。

在实际测试中,这条机制直接捕捉到了一次低相关性搜索结果:

text

[EVAL] 相关性评估: 2/10 (大多数论文与分子生成中的扩散模型应用无关,
仅有一篇标题提及扩散模型在分子生成中的调研,但其余内容涉及星际带、
硫分子、水冰和分子云形成,与用户需求匹配度低。)
[EVAL] 相关性不足(2/10),触发补充搜索
2.3 极低相关性提前终止

如果反复搜了几次还是搜不到,继续硬搜只是在浪费 API 额度。增加了提前终止逻辑:

  • 相关性已经低于 3 分

  • 且已经重试过一次

满足这两个条件时,直接停止搜索,把现有信息诚实输出。

2.4 模型分层调用的修正

在开发迭代中我犯过一个错误:把相关性评估、read_paper 等任务也交给 MiMo 处理。结果偶尔出现 JSON 解析失败,还浪费了不少额度。

修正后重新明确了分工:

任务 模型 原因
搜索词生成 + 补充搜索 MiMo API 需要广博领域知识,调用频次低
任务规划(初始拆解) MiMo API 强推理能力
相关性评估 本地 Qwen3-4B 评分任务,小模型足够用
read_paper 本地 Qwen3-4B 从已有列表里选 ID
报告生成 本地 Qwen3-4B 离线可用,格式稳定

这个分层设计是面试中讨论"混合模型策略"时的核心论据。


三、工具能力增强

3.1 read_paper 双路径修复

这是一个困扰了很久的问题:LLM 在 read_paper 步骤传入 arxiv_2604.27636v1 这类 ID,但 read_paper_detail 工具只能读本地库中的 paper_001 格式,导致频繁报错"未找到论文"。

修复方式是在 tool_call_node 中新增一个分支:如果 paper_id 以 arxiv_ 开头,就从前面搜索步骤的结果中直接提取对应论文的摘要,而不是去本地数据库查找。同时,如果 ID 是 paper_ 开头的本地 ID,正常走 MCP 调用路径。

text

[CALL] arXiv 论文,从搜索结果中提取: arxiv_2604.27636v1
[CALL] 提取成功: Generative structure search for efficient and diverse discov...
3.2 read_paper 上下文注入

之前的 LLM 在 read_paper 步骤不知道有哪些论文可选,经常生成空参数导致报错。现在在 tool_select_node 中,当步骤是 read_paper 时,会把前面搜索步骤返回的论文 ID 和标题列表注入 Prompt。

LLM 能看到类似这样的信息:

text

前面搜索步骤找到的论文列表(请从中选择 paper_id):
- ID: paper_001
  标题: Diffusion Models for Molecular Generation: A Survey
- ID: paper_013
  标题: Equivariant diffusion for molecule generation in 3D

有了这个上下文,LLM 终于能正确生成 {"paper_id": "paper_001"} 而不是瞎猜搜索词了。

3.3 compare 步骤激活

之前的 compare 步骤在 MiMo 规划时会被规划出来,但执行时被标记为 deferred(跳过)。原因很简单——不知道在对比步骤里能干什么。

现在新增了 _execute_compare 函数:收集前面所有搜索结果和已读论文的详细信息,调用本地 LLM 生成结构化的横向对比表格。

这意味着 MiMo 规划出来的每一个步骤都有实际执行,不会再有"规划了但跳过"的空白环节。


四、报告质量与论文库建设

4.1 结构化深度报告 Prompt

之前的 report_node Prompt 过于开放,只要求"包含摘要、方法对比、关键指标、总结",没有具体深度要求。结果是有时摘要只有两行,有时洋洋洒洒,质量波动很大。

现在通过 Prompt 明确要求:

  • 摘要 ≥150 字,必须包含研究背景、核心方法数量、关键发现和主要局限

  • 方法概览表格固定六列:方法名称/年份/来源/核心贡献/数据集/局限性,缺失信息填写"未提供"

  • 关键指标必须标注数据集名称和测试条件

  • 跨数据集指标不得直接对比

  • 检索策略声明必须包含数据源、关键词、筛选条件和最终纳入论文数量

这些规则让报告格式不再依赖 LLM 的临时发挥,每次输出的质量和深度保持一致。

4.2 空结果检测

在一次测试中,MiMo API 调用超时导致所有搜索结果为空,但 report_node 仍然被触发,LLM 编造了不存在的论文来填充报告。这是严重的数据可信度问题。

修复方式是在报告生成前增加空结果检测:如果 tool_results 中没有任何实质性论文数据,直接生成诚实声明,说明本次检索未找到相关论文及可能的原因。这彻底杜绝了"因空结果而编造"的情况。

4.3 本地论文库扩充:从 3 篇到 26 篇

这是整个阶段最耗时但也最有价值的一项工作。具体步骤如下:

用 Zotero(BetterBibTeX JSON 格式)导出文献元数据 → 写转换脚本 convert_zotero.py 将 Zotero 格式转为 ScholarCraft 的 JSON 格式 → 写 enrich_papers.py 脚本用 MiMo 自动填充 methoddatasetkey_metric 等字段 → 手工审核并补全核心方法论文的指标数据。

最终论文库覆盖了以下方向:

方向 论文数 代表工作
扩散模型方法 8篇 EDM、DiGress、FreeGress、UniGuide
VAE 方法 4篇 JT-VAE、Grammar VAE、Chemical VAE
GAN 方法 2篇 MolGAN、ORGAN
评测基准 2篇 GuacaMol、MOSES
综述 7篇 覆盖扩散模型、3D分子生成、药物设计
经典基础方法 3篇 Transformer、LoRA、JiT

本地搜索的返回量从以前的 2-3 篇提升到 9-12 篇,相关性评分首次出现 10/10。


五、端到端测试

运行 python app.py "帮我调研扩散模型在分子生成中的应用方法",Agent 完整执行了五个步骤:

text

[PLAN] 生成 5 个步骤
[SELECT] 步骤 1: search_local → 多角度搜索完成,合并去重后共 9 篇论文
[EVAL] 相关性评估: 10/10 → 搜索完成
[SELECT] 步骤 2: search_arxiv → 补充搜索后找到 5 篇论文
[EVAL] 相关性评估: 9/10 → 搜索完成
[SELECT] 步骤 3: read_paper → 从搜索结果中提取 arxiv 论文详情
[SELECT] 步骤 4: compare → 执行对比分析
[SELECT] 步骤 5: summarize → 生成结构化报告
[SAVE] 报告保存成功

零错误,五个步骤全部完成。最终报告中的方法对比表格列出了 EDM、FreeGress、UniGuide 等核心方法及其数据集和局限性,关键指标部分出现了 FreeGress 的 79% MAE 提升等具体数值。


六、总结与下一步

本文记录了 ScholarCraft 从第一篇博客时的"初始版本"到现在的完整升级过程:

改进维度 改进前 改进后
搜索策略 单关键词 多角度并行 + MiMo 驱动
评估机制 迭代重试 + 相关性打分 + 提前终止
报告质量 自由发挥 结构化深度 Prompt + 空结果检测
论文库 3篇 26篇多方向覆盖
compare 步骤 跳过 真实对比分析
read_paper 频繁报错 双路径 + 上下文注入

这些改进让 ScholarCraft 从一个"能跑通"的 Demo 升级成了一个"跑得好"的可靠系统。但还有一个关键能力缺失——记忆系统。当前 Agent 的每一次调研都是独立的,关闭终端再打开,它完全不记得之前做过什么调研、用户偏好什么方向。

在下一篇文章中,我将开始为 ScholarCraft 构建三层记忆系统:短期记忆(LangGraph Checkpointer 实现会话级上下文共享)、上下文管理(Token 预检与主动压缩机制)、长期记忆(SQLite + ChromaDB 实现跨会话偏好记录)。

完整的项目代码会同步更新到 GitHub,欢迎关注和交流。

本文是 ScholarCraft 系列的第二篇,后续文章将陆续更新。如果有任何工程落地上的问题或建议,欢迎在评论区讨论。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐