科研AI Agent实战复盘:用Harness Engineering给大模型系好缰绳 要说清楚科研AI Agent这个项目得先从一次翻车开始。去年我给某课题组搭了一套“智能调研助手”当时的概念很朴素让大模型帮我搜文献、提假设、写实验方案。结果第一次实跑模型给了我一份看起来非常专业的综述然后整篇综述里引了三篇根本搜不到的“参考文献”。那一刻我意识到科研场景里真正难的不是让大模型“变聪明”而是给它套上一整套可控的框架。现在圈子里管这个叫Harness Engineering翻译成大白话就是你得给模型系好缰绳而不是放任它在知识原野上狂奔。这篇文章就是我从0到1构建科研AI Agent的完整复盘。我会把文献检索、假设生成、实验设计三个核心模块的工程思路、Prompt设计、评估方法、踩过的坑全部摊开讲。适合谁看呢两类人。第一类是你手上有科研场景想用大模型提升效率的研究生和科研人员第二类是做AI应用开发的工程师想看看“业务和模型之间那层框架”究竟该怎么设计。我先说明白这不是一篇纯教程更接近一份项目实战复盘所以每段都会有实操细节和真实翻车记录。1. 我被“自由对话式AI”坑了之后才理解Harness Engineering真正在解决什么1.1 科研场景为什么容不下“自由发挥”你或许也试过把一段研究想法直接丢给大模型让它“帮我设计实验”或者“找几篇相关文献”。结果往往是这样它给出了结构漂亮的答案但仔细一查实验条件在真实环境里根本无法实现文献里的作者和标题对不上号更别提“可复现性”这种科研命根子了。科研场景有一个和日常问答截然不同的约束每一步输出都需要负责。你让AI帮你搜文献它就不能凭空编一篇出来你让AI提假设它就得分清楚哪些有文献支持、哪些是纯粹脑补你让AI写实验设计它就必须考虑对照组、样本量、测量指标这些硬约束。而通用对话式AI的设计目标是“给你一个好答案”不是“给你一个可审计的过程”。所以我在这个项目里给自己定的第一个原则就是不要把大模型当作答案来源而是把它当作一个能力很强的执行单元它必须在一个被设计好的框架里工作。这个框架就是标题里说的Harness。1.2 Harness Engineering 到底是干什么的“Harness”的本义更接近“缰绳”或“控制装置”。给狗系牵引绳不是为了不让它跑而是保证它跑的方向和速度是你可控的。对LLM来说Harness层做三件事约束行为边界、接驳外部工具、强制输出校验。我拆成三个工程层级来看工具层大模型要能调用外部世界。文献检索、数据库查询、代码执行、文档解析都通过统一接口暴露给模型。此时模型不是“闭卷考试”而是“开卷加可查资料”。编排层控制流程不乱跑。科研Agent的执行不是一个Prompt就能完成的它是一个有顺序、有分支、有回退的工作流先检索再摘要再生成假设再设计实验。编排层用状态机或任务图把流程固化下来。校验层每个输出都要过检查。假设没有依据打回。文献引用不存在打回。实验设计缺对照组打回。只有通过校验结果才会呈现给人类。这三层合起来就是我们项目里所说的Harness Engineering。它解决的核心问题是把LLM从“什么都敢说”变成“说了就要负责”。1.3 我们给Agent定下的四条硬性要求在动手写代码前我和组里一起列了一张行为清单。这张清单之后变成了所有模块的验收标准编号硬性要求对应模块1任何结论都必须能追溯具体文献文献检索、假设生成2假设必须明确变量、可证伪、有潜在检验路径假设生成3实验设计必须包含对照组和缺陷自检实验设计4每个关键决策点必须暂停并征求人类确认编排层这张表现在看很朴素但在实际开发中每一条都逼着改了不少设计。比如“任何结论都能追溯文献”这条直接导致我们不能让模型自由引用必须把文献卡片做成结构化对象并强制带上文献编号。很多你以为靠“文案提示”就能解决的风险最后都被证明要靠“工程结构”才能解决。2. 文献检索模块让Agent同时具备“搜得准”与“读得懂”两种能力2.1 三路并行的检索入口文献检索看起来简单不就是“搜关键词”吗但科研检索和普通网页搜索差别很大。网页搜索答案即时而科研检索要求全不能漏、准相关性高、新关注时间窗口。如果只靠关键词搜索你很容易漏掉那些用词不同的重要工作。我的方案是搭三条检索通道让它们并行跑再合并结果关键词检索把研究问题拆成多组布尔检索式走学术检索接口。拿回来的结果是“文本匹配型”的候选文献召回快但依赖检索词质量。语义检索把研究描述编码成向量到文献库的向量索引中找语义相近的文章。它弥补了关键词不一致导致的漏检。引文追踪选择几篇“种子文献”向前追踪其引用的工作向后追踪引用它的工作。这一步能快速把某个子领域的主干脉络串起来。三路结果合并后按“来源通道交叉程度”和“语义相似度”加权排序。比如一篇文献在关键词检索和引文追踪里同时出现它的排序自然更高因为不同通道同时命中说明相关性比较可靠。2.2 用Prompt压出真正好用的检索词如果你直接让LLM“给我算几个检索词”它大概率会把你研究问题里的名词原样重写一遍。问题在于科研文献用词非常多样同一个概念可能有缩写、别名、上位词、下位词。真正好用的检索式需要在几个不同粒度的词之间做组合。我设计的一版Prompt结构大致是这样system_prompt 你是一名科研文献检索专家。给定一个研究问题你需要生成多组检索式。 要求 1. 每组检索式包含4~8个词涵盖核心概念、同义别名、上位词、下位词、英文常用缩写。 2. 至少有一组是全称检索至少有一组是组合限定检索。 3. 不要直接照抄研究问题原文要拆分出独立概念。 4. 输出格式为JSON数组每个元素包含query检索式和rationale为什么这样组。 这里的关键是“拆分出独立概念”这句话能有效防止模型把整个问题当成一个关键词。比如“探究多孔材料在低温环境下的隔热性能”模型需要拆出“多孔材料”“隔热性能”“低温环境”三个概念再分别扩展。实测下来这样生成的检索式召回率比直接复述要高很多。2.3 “两级摘要”文献阅读策略这是整个文献检索模块里让我最得意也最想推荐给你参考的设计。一开始我也犯过傻把检索回来的前二十篇全文直接塞进上下文让模型总结。结果上下文爆了输出却一塌糊涂模型顾此失彼甚至把上一篇文献的结论串到下一篇里。后来我改成两级摘要策略。第一级只看标题和摘要让模型快速判断“这篇是否与研究问题相关”输出包含“相关性评分”和“一句话理由”的半结构化结果。这一步把候选文献从几百篇迅速压到几十篇。第二级对筛选后的文献做全文分块精读。把PDF文本切成长度适中的段落逐段提取信息最终汇总成一张结构化文献卡片。卡片字段如下字段说明文献编号全局唯一用于所有结论追溯研究问题作者要回答的问题方法具体用什么方法、样本、数据关键结果最主要的一到两个发现局限作者自述的局限或你能看出的局限与当前课题的关联点由Agent根据本项目问题生成两级摘要的好处非常明显第一级过滤掉80%的噪音第二级只精读真正相关的文章token消耗大幅降低而且每张卡片都是独立对象后续假设生成模块可以直接读取不用再去翻原文。更重要的是每一张卡片都带文献编号这为“任何结论都必须能追溯到文献”提供了数据基础。2.4 回源校验不给模型凭空编造的机会我在开头提到的翻车事故就是模型生成了三篇根本不存在的文献。这个问题的根源在于在自由对话模式下模型会依据训练数据里的记忆拼接出“看起来很像样”的参考文献。要根治它不能在Prompt里反复说“不要编造”因为这不改变模型的生成机制。我的做法是在工程上切断编造的可能所有文献卡片必须由检索接口返回的真实文献记录生成。如果模型在摘要阶段引用了一张不存在的卡片校验层会直接拦截。具体来说卡片里的“文献编号”必须在检索结果集合中存在关键论断要能从对应原文片段中找到相似度足够高的匹配。加了这个回源校验之后我们的Agent大概有半个月没再“发明”过文献。这件事让我形成了一条原则在科研这种低容错场景里与其指望模型克制不如用工程手段让它根本没有机会犯错。提示在科研Agent里所有要进入“结论”层的信息都必须能追溯原始来源。这条规则建议在框架层面直接实现而不是在Prompt里反复叮嘱。3. 假设生成把大模型的发散脑洞压进可验证的逻辑轨道3.1 先找“研究缺口”再谈“提出假设”文献检索做完手里已经有一堆文献卡片了。下一步是假设生成。这一步很多人会直接写Prompt“根据以上文献提出几个研究假设。”这种做法的结果几乎可以预料模型会把文献里已有的主流观点换个说法再吐出来全是正确的废话。我把流程调整为“先识别缺口再生成假设”。先让Agent对文献卡片做归类和对比输出以下四类信息稳定结论多篇文献反复出现、互相印证的发现矛盾结论不同文献之间在相似问题上结论不一致未覆盖领域文献在某个方向上存在明显空白方法局限已有研究的样本、技术或指标存在缺陷。研究缺口只可能从这四类信息里产生。比如“矛盾结论”意味着可能有调节变量没被识别“方法局限”意味着可能有更优的测量或实验方案。先做这一步模型生成的假设才不会变成无源之水。这也让我后来有了一个判断标准如果一个假设的“依据文献编号”填不满三条它就不该被列出来。3.2 用结构化模板逼出可检验的假设假设要进入实验设计阶段它就不能只是一句话。它需要承载足够多的信息才能让后面实验设计模块接得住。我给每个假设设计了这样一张输出结构{ hypothesis_id: H-001, 假设陈述: 增加间隔层孔隙率会显著提升多孔保温材料在低温下的隔热性能, 背景依据: [R-017, R-032], 关键变量: { 自变量: 间隔层孔隙率, 因变量: 隔热性能稳态热流密度, 控制变量: [环境温度, 材料厚度, 湿度], 潜在干扰变量: [孔隙分布均匀性] }, 潜在机制: 孔隙率提高降低了固体热传导路径同时低温下气体导热占比降低, 可检验性评估: 自变量可通过压制成型参数调节因变量可通过热流计实测具备实验室可操作性, 证伪思路: 如果在孔隙率梯度范围内热流密度无显著变化则假设不成立 }为什么非得用这种笨重的结构化模板两个原因。第一非结构化的一段文字很难做后续处理排序、打分、转实验设计这些环节都没法稳定工作第二结构化本质上是把“科研方法论的常识”固化成了字段约束——模型想把“因变量”写成一句含糊的话都不行因为字段定义要求它写清楚是什么、怎么测。经过这一层最后进入实验设计的假设都已经自带“可操作化”的基因。3.3 打分排序假设也得排队没有哪个团队有精力验证所有合理假设所以Agent还得会排序。我设计了一套简单的加权打分分数来源都是结构化字段不靠模型“感觉”。依据强度假设引用的文献卡片数量加上这些文献之间的共识程度权重最高。新颖度假设的关键词与已有文献卡片关键词的语义重叠度越低得分越高。可检验性如果结构化字段里“关键变量”每个都有明确测量方式此维度满分。资源成本预估需要的实验周期和样本量成本越低调权越高保证有些“好但太贵”的假设不会被顶到第一位。最后这四项加权求和Agent输出一个排序后的Top 5列表。但请注意排序仅供人类参考Agent不会自己拍板“就做这个”。它会在列表后面附上三个问题来问研究者比如“组里目前是否有满足自变量调节的成型设备”。这一步又回到了我们所说的“关键决策点必须暂停并征求人类确认”。3.4 反向论证为了避免“爱上自己的假设”科研里有种很隐蔽的认知偏差一旦你提出一个看起来很合理的假设你会不自觉地去寻找支持它的证据而忽略反对它的证据。LLM虽然没有情绪但它被优化成“尽量满足用户”所以你让它“评估这个假设”它倾向说“这个假设合理建议验证”。我给假设生成模块加了一道强制工序对每个假设Agent必须独立输出两个“潜在反对证据来源”。它不是让你证明假设错而是要求模型主动去想文献里有没有和这个假设冲突的结果实验里可能出现哪种结果让假设站不住实测下来这个简单的约束非常有效。很多初筛排在Top的假设在加入反向论证后都被降级了因为它暴露了“其实没有对立证据只是没人做过”的假新颖或者暴露了“变量之间存在强混淆”的真问题。科研Agent要是少了这道工序生成的所谓假设很可能就是一篇“漂亮但不设防”的空想。4. 实验设计不是让Agent写方案而是让它给自己挑毛病4.1 从假设到变量清单第一步是“翻译”拿到假设之后实验设计模块的工作不是从零开始写一篇文章而是把假设里的信息“翻译”成可执行的实验结构。这个区别很关键。我以3.2的假设为例Agent第一步会生成如下清单自变量设置孔隙率梯度比如低、中、高三档每档若干重复样本因变量测量热流密度测量记录稳态后的平均值控制变量环境温度恒定在设定低温值材料厚度、压制压力保持一致干扰变量处理孔隙分布均匀性在制样后进行扫描确认样本不均匀则标记剔除。这一步看起来简单但它是整条流水线里最容易被做坏的环节。因为很多LLM生成的实验方案会自动默认某些变量不需要控制。我们选择把“变量清单”作为实验设计的第一产物就是为了让这些隐含假设在开始设计细节之前就被暴露出来。变量清单不OK后面全白搭。4.2 内置基础规则对照组、随机化、重复数实验设计的常见错误过于“程式化”所以我直接在Harness层固化了一批规则Agent不用每次都从零判断而是逐条检查是否存在合适的对照条件尤其是要归因“因为A所以B”的假设必须有对照组。分组是否随机化如果有分配偏差结论可能被混淆。重复样本数量是否足够不能只看“越多越好”要结合效应量和方差来算。是否规定了主分析指标没有主指标跑完再看数据就变成了“围着结果讲故事”。这些规则用校验层的代码实现Agent生成的方案如果不满足这些Checklist会在输出阶段被自动打回。举一个真实翻车例子早期版本让Agent设计一个材料对比实验它写了三组不同配方却没有设置标准对照组。当时要不是同学多看了一眼整个实验做完都无法回答“材料性能变好到底是因为配方还是因为工艺变化”。后来我把“对照缺失检测”写成了硬规则这种低级问题就再也出不来了。4.3 样本量、统计功效与“算给你看”实验设计光有结构还不够还必须靠谱。最靠谱的方式是让Agent在方案里直接把统计计算写成代码由代码执行引擎跑出结果而不是模型用文字说“大概需要30个样本”这种主观话。我设计的流程是Agent根据假设中的效应量估计、显著性水平、预期统计功效生成一段样本量计算脚本。执行引擎收到脚本后运行返回值再回填到方案里。示意如下# 样本量估算示意伪代码使用你环境里的统计库 def estimate_sample_size(effect_size, alpha0.05, power0.8): # 从正态分布表读取对应的 z 值 z_alpha 1.96 z_beta 0.84 n 2 * ((z_alpha z_beta) ** 2) / (effect_size ** 2) return math.ceil(n) print(estimate_sample_size(0.5)) # 中等效应量下的参考样本量代码跑出来之后Agent会把结果写进方案同时给出一个“如果样本量受限最小可行实验可以怎么缩减”的建议。这样做有一个特别重要的收益可以直接发现“这个实验设计根本做不起”。如果要求每组样本量达到数百而组数又很多Agent会在方案里标记成本风险而不是硬着头皮给一个好看但执行不了的方案。4.4 执行前的最后一道闸门缺陷自检加人工确认整套流程走到这里实验方案已经比较完整了但我不打算让它直接成为最终方案。最后一步是让Agent先对自己开一枪输出一份缺陷自检报告。自检报告包含假设里的每个变量是否都有操作定义是否有基线和对照组是否规定了主要分析指标与统计方法方案可能存在哪两个最严重的风险最需要人类判断的三个问题是什么自检报告完成后Agent进入等待状态把方案和自检报告一起呈现给研究者。只有人类点了确认方案才会进入下一步。这一步看起来拖慢了自动化但它恰恰是科研Agent和普通自动化产品最大的分水岭科研工作者要的不是“AI替我做”而是“AI把80%的重复事务性工作做完把最关键的判断留给我”。5. 这条从0到1的工程路线我踩过的五个最值得说的坑5.1 坑一把整个文献库塞进上下文结果什么都没干成最早版本我以为大模型上下文窗口大就能把检索结果全塞进去。做了一次几千字的全文输入模型输出确实顺滑但幻觉率飙升还被长文里的次要信息带偏。后来改成两级摘要加动态召回一次只向模型提供最相关的小批量文献卡片质量立刻上来了。这话不太好听上下文窗口再大也扛不住“没检索就喂数据”的偷懒。好的检索策略永远胜过于大的上下文。5.2 坑二编造文献这个问题靠“承诺”解决不了前文提过模型“发明”了三篇文献。我当时的第一反应是改Prompt“严禁编造文献”。结果你猜怎么着它编得更像了。后来才明白生成式模型的“编造”不是态度问题而是机制问题。你没法通过态度约束来改变机制。只有建立回源校验让每一个文献编号必须能在检索结果里找到问题才真正解决。这件事成了我后来设计任何Agent模块的默认原则不能把反幻觉的希望寄托在模型自觉上要靠工程护栏。5.3 坑三假设生成总在复述主流观点跑了一个月后我发现Agent产出的假设越来越“安全”翻来覆去都是文献共识的换皮版本。原因不在模型而在流程设计我们没有把“找矛盾”和“找局限”作为前置步骤。后来改成“先识别四类信息再生成假设”并加入“反向论证”之后假设才开始出现真正有信息增量的东西。如果你也遇到“AI提的假设很合理但没什么新意”的困惑大概率不是模型迟钝而是流程没逼它去找差异。5.4 坑四方案看起来完美但团队根本做不起有一版实验设计模块产出的方案条件完整、统计规范唯一的问题是按它写的流程整个实验需要一年半预算超出现有三倍。方案在纸面上越完美越容易让人忽略现实约束。后来我做了两件事一是在方案模板里增加“预估周期”和“资源成本”字段二是加入“最小可行实验替代方案”的输出要求。现在Agent建议任何大型实验时都会自动附上一个能先验证核心机制的轻量版本。这个轻量版本反而往往就是团队真正会去跑的那个版本。5.5 坑五自动化越顺畅越要警惕“Agent自嗨”开发后期所有模块都稳定了Agent可以在不到半小时内走完“检索-假设-实验设计”全流程。听起来很爽但那时候出现了一个更隐蔽的问题有些方案虽然技术上完美却偏离了课题组真正关心的科学问题方向。自动化越顺畅研究者越容易机械地点“确认”放弃思考。为避免这种情况我最终在所有关键节点强制加入暂停和提问并让Agent在输出里固定列出三个“需要人类判断的问题”。效果立竿见影研究者重新回到了决策者的位置而不是流程中的一个审批按钮。技术栈方面简单交代的话核心就三样Python作为主语言一个大模型推理接口我用的是私有化部署的开源权重模型也可以接商用接口再加一个向量数据库存文献分块。编排逻辑完全用状态机写没有上重型框架原因是科研Agent的流程相对固定状态机更直观、更好排查。复刻这个项目时不必纠结具体工具重要的是把检索、摘要、假设、实验设计这几层之间的数据接口定义清楚。这个项目做完我最大的体会是Harness Engineering在科研场景下本质上是“用工程手段把科学方法论固化下来”。它不一定需要多复杂的技术更需要你反复问自己一个问题——如果这个Agent现在撒了个谎你能发现吗如果每一步都能回答“能”框架就立住了。最后分享一个小技巧让Agent产出的每一个结论都带上可追溯的编号或引用这个习惯能为你后期审计省下大量时间。接下来我打算把多Agent对抗式评审加进去让两个Agent互相审对方提出的假设看看能不能把“反向论证”这一步做得更狠。等有结果了再回来继续更新。