ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ScienceBuddy:双层递归自进化科研Agent Harness设计

ScienceBuddy:双层递归自进化科研Agent Harness设计 1. 项目缘起科研场景为什么需要独立设计 Agent Harness做科研类 Agent 的人和做通用 Agent 的人对可靠两个字的理解是完全不同的。通用 Agent 聊个天、查个地图、订个外卖答错一个环节用户大概率只是觉得这产品有点笨。但科研 Agent 一旦在文献结论、数据引用、实验参数上出了错轻则浪费几天实验周期重则整篇论文的立论基础都得推翻。ScienceBuddy 这个项目从一开始就不想做什么都能干一点的助手而是想做一个在科研流程里真正能扛事、出错了能自己发现并修正的 Agent Harness——也就是承载 Agent 思维与执行的那套骨架系统。我最初调研过一圈现成的 Agent 框架比如 LangGraph、AutoGen 这类通用编排方案。它们的问题倒不是不能跑而是太顺滑了默认假设模型输出基本可靠、工具调用一次就成功、中间环节出了错可以低成本重试。但科研场景恰恰相反模型输出大概率不可靠工具调用往往要跨多个数据源重试的成本也不是几秒钟而是可能牵扯到污染实验环境的风险。ScienceBuddy 在架构上的核心选择就是放弃顺滑主动引入一套双层递归自进化机制用结构化的方式管理不确定性而不是靠运气。先说清楚这套 Harness 到底在管什么。它管的是 Agent 的完整生命周期目标拆解、规划行动、工具调用、结果校验、错误恢复、经验沉淀。普通框架把这几件事揉在一个循环里看起来简单实际上模型一烧就乱。ScienceBuddy 的思路是把每个环节都做成独立的受控组件然后用一套递归机制让 Agent 在任务内部和任务之间不断自我修正。英文里管这种设计叫 Harness Engineering说白了就是把让模型发挥能力这件玄学的事变成一套可以测试、可以监控、可以迭代的工程系统。这套系统适合谁去参考如果你正在做科研自动化、文献综述工具、实验辅助 Agent或者你的 Agent 需要对接大量高风险的业务工具科学领域只是其中一个场景那 ScienceBuddy 的很多设计思路是可以直接平移过去的。代码层面我不打算贴完整实现那个太长而且项目在持续迭代。我更想讲清楚的是里面那些不写下来就容易被忽略的设计决策和踩坑经验。2. 双层递归自进化两个层面的自己改自己2.1 第一层递归任务执行中的行动计划自修正ScienceBuddy 的第一层递归发生在单个科研任务的执行过程中。比如让 Agent调研一下 2023 年以来钙钛矿太阳能电池稳定性方面的主要进展这在通用框架里可能就是一个大 prompt 加几次工具调用。但 ScienceBuddy 会把任务层层拆成子任务每个子任务有自己的行动计划这个行动计划本身还有一个递归修正循环。具体机制是这样的Agent 每完成一个子任务不会直接进入下一个而是先过一遍成果校验器。这个校验器会对当前结果提三个问题这个结论有没有直接引用来源引用的来源是否经过权威性过滤结论与已知常识是否存在冲突如果三个问题里任何一个不过关Harness 就会把校验结果和失败原因打包重新喂回给规划器让规划器调整接下来行动计划。这里有一个容易被忽略的关键点就是返工的姿态。很多 Agent 框架一遇到校验失败就直接重新生成整个答案导致模型陷入反复横跳甚至把原本正确的中间结论也改坏了。ScienceBuddy 的做法是只允许修正后续的行动计划和当前子任务的局部输出冻结已经通过校验的前序结果。这个设计像极了科研论文的审稿流程审稿人提意见作者只修改被质疑的部分不会因为某个小问题就把整篇文章重写。实现上这个冻结机制需要一个结构化的状态对象来承载任务进度。我用的是一个逐层嵌套的字典结构每个子任务有 status、artifact、validation_report 三个字段只有 status 为 passed 的子任务结果才有资格被后续步骤引用。这样规划器在生产下一步计划时上下文里只会出现经过校验的事实不会把原始模型输出直接铺进去。如果读者在复刻这套机制时跳过这个状态管理细节只是用对话历史的自然累积那递归自修正执行到第三四轮的时候上下文里就会被各种失败信息污染模型会越来越糊涂。2.2 第二层递归跨任务的技能与策略进化第一层递归解决的是当前任务怎么完成得更好第二层递归解决的是下一次类似任务怎么从第一天就做得更好。这是 ScienceBuddy 区别于大多数 Agent 项目的地方也是自进化三个字真正落地的位置。第二层的实现机制是经验仓库。每当一个任务整体完成ScienceBuddy 会把整个执行轨迹压缩成一条结构化经验记录包含任务类型、规划策略、踩过的坑、最终有效的解法路径、以及无效方法的失败特征。这些经验会被周期性离线聚合成策略模型在下一次处理同类任务时规划器会优先参考这些策略而不是从零开始推理。举个例子假设某个 Agent 在处理比较两种催化剂性能类任务时多次出现同一个问题第一次工具调用时只检索了英文库漏了中文研究的重要数据导致结论偏差。第一层递归会在这次任务内部修正方向但修正过程很痛苦等于先犯错再纠错。第二层递归就聪明在这里经验仓库里记下了比较类科研任务必须先做语言覆盖检查这条策略下一次同类任务还没开始规划策略提示就已经注入了初始行动计划里错误在发生之前就被规避掉了。这里要注意策略注入和盲目套模板之间的分寸。我把策略分成两类硬性策略和软性参考。硬性策略是高置信度的避坑规则必须注入软性参考是历史方案的低置信度相似推荐只作为候选提示。这种区分避免了经验仓库变成教条库不同科研子领域的差异很大强行套用相似任务的经验有时反而适得其反。两层的名字里都有递归但含义略有不同。第一层是闭环修正执行到一半发现问题就回到规划环节重新规划第二层是累积进化一个任务结束后的经验沉淀会影响未来所有相似任务的起点。两层嵌套起来就形成了当前任务自修正 长期能力自进化的双轨结构。我认为这是科研 Agent 可靠性设计里比较值得复刻的一种模式。3. Harness 层的关键设计边界、沙箱与确定性3.1 工具调用的边界治理科研 Agent 的工具调用和普通 Agent 有一个本质区别科研工具往往有毒副作用。我说的不是安全意义上的毒而是状态污染的毒。你调用一个数据库查询接口它会改写本地缓存你启动一个计算容器它会在宿主机留下进程和临时文件。如果 Agent 的执行是不可回溯的那么一次失败的实验模拟可能污染后续所有数据。ScienceBuddy 的 Harness 层因此引入了一个非常朴素但有效的设计所有工具调用都在独立沙箱里执行沙箱与主流程之间只通过结构化数据通信。实际实现中简单工具走的是子进程隔离复杂工具走的是轻量容器。每次工具调用的输入输出都有完整记录失败时可以随时从最后一个可靠状态回滚。这里我想强调一点沙箱的重点不是防恶意代码而是防半成品的状态泄漏。即使你的工具完全可信执行过程中产生的中间态也可能带偏后续判断。我有一个印象很深的调试经历Agent 在查询某个蛋白质数据库时工具内部默默加载了一份过期配置导致后续所有序列比对结果都朝着一个细微但方向性偏差的角度偏移。这个偏差单看每一步都不明显但因为 Harness 每次都是从主流程的信任边界重新拉取环境沙箱重建后问题立刻消失排查才得以收敛。3.2 确定性优先的编排循环Agent Harness 里的一个反直觉设计是规划的入口必须确定性。很多人觉得 Agent 的强项就是随机性、创造性、发散性所以编排环节也要尽量让模型自由发挥。但 ScienceBuddy 在编排循环上反其道而行主循环是一个完全确定性的有限状态机只在状态机的特定出口挂载 LLM 决策点。我打个比喻这就像自动驾驶方向盘、油门、刹车的物理控制逻辑是完全确定性的AI 只在高层的路径规划决策里介入。如果 AI 直接接管方向盘任何一个感知错误都可能让车飞出路面。ScienceBuddy 的主循环定义了 INIT → PLAN → EXECUTE → VALIDATE → REVISE → COMPLETE 这几个固定状态模型只负责在每个状态里产出该产出的内容状态间的转换规则是硬编码的。这个设计让整个 Harness 是可测试的。线上任何一个环节出了问题日志里能精确定位到是转移到哪个状态时失败而不是一头雾水地重放整个 prompt 链。这种确定性和灵活性之间的平衡恰好也是 Harness Engineering 和单纯套一个大 prompt的核心区别。前者是可以工程化调优的后者只能靠玄学式地调整措辞。我在 ScienceBuddy 上做的几乎每一次可靠性优化都是围着这座确定性的骨架做加法比如增加校验器数量、细化失败分类、在状态转换处加条件守卫。骨架本身几乎没动过但系统的可靠性上限被持续抬高。3.3 失败恢复的幂等设计科研任务动辄跑几十分钟甚至几小时中间任何一次工具调用失败如果从头重跑成本完全不可接受。ScienceBuddy 在失败恢复上做了幂等化设计。每个工具调用都有一个任务内唯一的 call_id工具的输出会以 call_id 为键缓存。哪怕失败后重试只要输入参数相同且上一次的部分副作用已经被沙箱隔离清理系统可以直接复用缓存的输出不用重新执行。这个设计听起来简单落地时有一个容易被忽略的坑Token 生成式模型的输出天然带有随机性即使同一 prompt 重试两次结果也可能不同。所以缓存键不能只包含输入参数还得显式约定当前任务的确定性种子。ScienceBuddy 对规划器的采样温度做了分段设计探索阶段允许稍高的温度让方案多样执行阶段的校验和重试统一用接近 0 的温度保证缓存命中逻辑不会被模型随机性搅乱。4. 核心模块的实操实现与关键参数4.1 规划器与校验器的协作方式规划器是 ScienceBuddy 里最耗 Token 的模块因为每层递归都会唤起规划器。为了控制成本我没有用一整个大规划的模式而是让规划器只产出当前步的最优动作以及一个轻量的长期路线图。长期路线图由一层较弱的模型生成当前步的最优动作则由强模型重点保障。这样既保证了方向上有规划又避免每次规划都消耗满格能力。规划器的输出是一个 JSON 结构包含三个字段action_type、target、rationale。rationale 字段里要求模型写出选择这个动作的理由不是为了给用户看而是为了后续校验错误时对齐模型意图和实际结果。比如模型说选择 Python 代码执行工具来计算统计显著性结果代码跑出来一个异常值校验器把 rationale 提取出来做归因可以快速判断是代码写错、数据源错、还是统计方法本身选错。这个对齐设计让递归修正的路径短了很多归因准确率从大约 60% 提升到了 85% 以上。校验器这边我维护了一个预定义检查器列表每个检查器只做一件事。文档引用检查器验证引用格式和 DOI 有效性数值一致性检查器对比多个结论里引用的同一数据是否自洽逻辑连贯性检查器评估结论链是否有跳跃。这些检查器全部是确定性代码不依赖模型判断因为它们本身就是简单规则。真正的模型级校验只在所有确定性检查器通过后才会触发此时让模型充当怀疑的审稿人从全局视角寻找隐藏矛盾。4.2 经验仓库的聚合与注入策略经验仓库是第二层递归的物理载体它的数据结构和聚合频率值得展开讲。仓库里每一条经验记录我设计成五个部分task_signature、plan_signature、failure_trace、solution_trace、lessons。task_signature 是对任务描述做语义哈希得到的聚类标识同一类任务会聚在一起。plan_signature 记录的是初始计划的模板指纹用于判断是否照着经验做了但结果仍然失败的情况。failure_trace 和 solution_trace 分别记录失败路径和最终有效路径lessons 是从两者对比中萃取的自然语言规则。聚合过程是离线的我不会让每次任务结束都立即影响策略库因为单个任务的样本方差太大。实际操作是每完成 20 个相似任务触发一次策略聚合把这一批任务的 lessons 做一致性比对只有被重复验证过至少三次的经验才能晋级为硬性策略。这个门槛过滤掉了很多偶然因素。有一次 Agent 在一个数据源特别干净的查询里成功了经验聚合差点把跳过重复数据清洗写成策略幸好晋级门槛设了三次验证的规则这条偶然经验最终未能入库避免了后续在脏数据场景中误导规划器。注入策略方面硬性策略会在每次规划前注入到规划器 prompt 的开头作为约束软性参考则以可选附注的形式放在 prompt 末尾。我同时做了一个小技巧策略注入时会标注这条策略的验证次数和最近一次生效时间当 Agent 解决不了问题时它可以在 REVISE 阶段主动质疑策略的适用性——这个机制防止了经验仓库变成一种新型的prompt 固化。4.3 工具注册与动态加载机制Harness 最容易被做烂的地方是工具注册。有些人直接维护一个巨大的工具列表一次性把所有工具的描述、参数 schema 塞给模型结果模型在大列表里挑花了眼经常选错工具。ScienceBuddy 采用的是分层的工具路由Harness 层维护一个粗粒度的工具目录按科研场景分类每次规划时先在目录上做一次基于关键词的粗筛把候选工具从几十个收敛到三五个再把筛选后的工具描述注入给模型。这个粗筛器是规则加小模型的混合体规则占七成小模型占三成。规则部分处理典型的命名匹配和参数类型匹配小模型部分处理模糊的用户意图到工具映射。这样做的效果很直接工具选择准确率从 68% 提升到 91%模型的决策方差明显降低。我见过很多 Agent 项目的失败不是能力问题而是工具太多了导致选择困难这个分层路由思路算是性价比很高的解法。动态加载机制我还特意做了一个版本化设计。每个工具注册时带一个 schema_versionHarness 在注入工具描述时会检查模型输出中的工具调用是否遵循了当前版本。如果遇到版本不匹配不是简单重试而是刷新工具描述后让模型重新理解一次。这个机制源于我踩过的一个坑工具更新 schema 后旧版缓存没清Agent 按旧参数调用接口报错信息又不够直观整整排查了两个小时才发现是版本错位。5. 构建过程中的关键取舍与踩坑实录5.1 递归深度失控时的熔断机制递归自进化的一个天然风险是递归可能陷入循环。第一层递归在任务内部修正时如果校验器连续多次返回同样类型的失败规划器理论上会一直尝试修改计划消耗更多 Token产出却越来越贫瘠。ScienceBuddy 写了一个三级熔断机制。第一级是次数熔断连续三次同类失败就自动停止当前子任务的执行转入手动归因模式第二级是资源熔断统计每次修正消耗的平均 Token 数一旦超过预算的 150% 就触发电子围栏第三级是路径熔断跟踪规划器每次修正后行动计划的差异度如果差异度在两次修正之间小于一个阈值比如 2%说明模型已经在自己纠正自己了这时候也立刻熔断。熔断机制上线之前我跑过一次压测让 Agent 处理一个带有矛盾文献的任务结果系统在递归修正循环里转了十七轮Token 消耗了常规任务的三十倍最后产出的结论居然是从第三轮那次修正版本倒退回初始版本的。这个案例深刻地说明一个道理自进化的前提是有明确的停止条件。没有熔断的自进化不是智能是灾难。5.2 Prompt 设计与上下文预算管理科研 Agent 的上下文管理比通用 Agent 复杂得多因为一个任务过程中会产生大量引用片段、工具输出、校验报告。如果一股脑塞进对话历史Context Window 很快就会被撑爆。ScienceBuddy 的做法是上下文分池管理核心池保留当前计划、当前子任务输入输出、最近一轮校验报告知识池存放检索到的文献摘要和工具长输出但只有被显式引用的部分才会进核心池策略池存放经验仓库注入的策略只在关键节点参与。三个池子之间通过一个引用机制联动。模型输出的任何论断如果引用了知识池里的某个条目必须在输出里带上 pool:knowledge:{id} 的引用标识。校验器会校验这些引用的真实性确保模型没有张冠李戴。我在实验中发现这个显式引用机制对幻觉的抑制作用比任何提示词技巧都有效因为它在生成阶段就逼着模型做了一次来源核对的心理动作。CPU 和 GPU 成本方面分池管理还有一个额外收益可以针对不同池子做缓存知识池的检索结果在任务里去重同一个文献摘要不需要为每个子任务重新注入一遍。实际跑下来典型任务的平均 Token 消耗降低了约四成而结论质量没有下降。5.3 高可靠环境的日志与可观测性最后聊聊可观测性。Agent 系统最让人头疼的就是过程不可重现同一个 prompt 在同一个模型上两次输出可能完全不同。ScienceBuddy 在日志系统上做了一个全量追踪的设计每次规划、每次工具调用、每次校验判定都会记录一份 trace 文件包含当时的完整上下文快照、模型参数、随机种子、工具响应耗时。这个 trace 文件是调试的核心凭据。写到这里我想分享一个建议给 AI Agent 项目做日志不要只记错误要记成功。成功路径的 trace 同样重要因为它能让你后期训练校准器和优化策略时有正向的参照样本。我在完善第二层经验聚合时最大的瓶颈恰恰是缺少高质量的成功案例。所谓自进化不只是从失败中学习更是从成功中提炼可复制的模式。少了成功样本的聚合系统只学会躲坑没学会提效。6. 从 ScienceBuddy 看科研 Agent 的可靠性上限对我来说ScienceBuddy 这个项目的价值不在某一个具体的模块而在于它提供了一条清晰的路径通过结构化架构来驯服大模型的随机性。第一层递归让单次任务具备纠错能力第二层递归让系统具备跨任务的学习能力Harness 层的确定性骨架为每一层提供了可观测、可控制的轨道。三层协同下来科研 Agent 从偶尔好用的概率性工具变成了稳定可用的可靠工程系统。当然这套架构并不是银弹。它在需要高度创造性发散的任务里会显得笨重确定性的状态机也会拖慢一些本可以极速完成的小任务的响应速度。但这个权衡在科研场景里是完全值得的因为科研用户最看重的从来不是花哨而是每一步结论都经得起推敲。ScienceBuddy 的设计本质上是在用工程复杂度换取认知可靠性这个方向我认为是对的也值得更多做 Agent 基础设施的人沿着这个思路继续探索。如果你手头也在做科研自动化的 Agent或者正被通用 Agent 框架的不可控弄得头大我建议先不要急着加更多模型能力而是回头审视一下你的 Harness 骨架状态流是否明确、失败恢复是否幂等、上下文管理是否有结构化边界、经验沉淀是否被纳入系统设计。这四个问题想清楚了可靠性自然上一个台阶。科学本身追求的就是确定性那帮助科学家干活的 Agent也应该在确定性上多花心思。
返回列表