先定工具调用边界再谈效果——书生-A1.5 在科学工作流里的位置

文章导读
纠结把智能体放在流程开头还是结尾,本质不是编排偏好,而是工具边界问题。书生-A1.5 这类模型能稳定承担的是:读入已经整理好的材料、给出判断、组织下一步动作;它不能替你取数,不能替你确认仪器是否在线,也不知道某个数据文件放在哪台机器的哪个目录。所以顺序应该是先回答“哪一步必须调用外部工具、调用结果怎么回到模型”,再讨论效果。跳过这一步直接反复调提示词,常见的结局是结果不对却说不清是取数错了、还是判
📋 目录
  1. Ⅰ 画出当前科研流程里最耗时的一步
  2. Ⅱ 把必须读外部数据的步骤单独隔离
  3. Ⅲ 约定智能体的输入格式和输出格式
  4. Ⅳ 用同一批任务对比接工具前后
  5. Ⅴ 保留能复盘的工具调用记录
A A

纠结把智能体放在流程开头还是结尾,本质不是编排偏好,而是工具边界问题。书生-A1.5 这类模型能稳定承担的是:读入已经整理好的材料、给出判断、组织下一步动作;它不能替你取数,不能替你确认仪器是否在线,也不知道某个数据文件放在哪台机器的哪个目录。所以顺序应该是先回答“哪一步必须调用外部工具、调用结果怎么回到模型”,再讨论效果。跳过这一步直接反复调提示词,常见的结局是结果不对却说不清是取数错了、还是判断错了。

判断:书生-A1.5 更适合放在“外部数据已就位、需要判断与组织”的那一环,而不是流程最前端的取数环节。操作上先把科研流程拆成步骤,把必须读外部数据的环节单独隔离,用字段化输入和“结构化字段加自由文本”的输出约定接口,再用同一批任务记录耗时、返工次数、结论可核验比例,对比接工具前后的差别。验证方式看调用日志能否倒查到具体某一次调用。边界:模型结论仍需人工抽样核对,工具失败路径必须提前写好,否则排查成本会转移到排查模型“为什么胡说”上。

画出当前科研流程里最耗时的一步

先不要碰模型,用一张表把现在的工作流摊开。表里的耗时建议按你自己上一周的实际记录填,量级写“高/中/低”加频次(每次实验一次、每天一次之类),不要凭印象估数字,估出来的数据后面没法用来对比。

步骤人工耗时(量级/频次)依赖数据是否可自动化
文献检索与初筛中 / 每个课题一轮外部检索接口、本地 PDF 库部分可自动,判断仍需人
实验原始数据整理成表高 / 每次实验仪器导出文件、内部数据库脚本可自动,需固定格式
跑分析脚本并汇总结果中 / 每次实验整理后的数据表、脚本仓库可自动,失败要人看日志
结果解释与下一步假设高 / 每轮分析汇总结果、历史记录不适合全自动
图表与投稿材料核对低 / 每篇图源文件、期刊要求可自动校验格式

表格填完后判断插入位置:如果最耗时的一步落在“取数与整理”,把智能体放在这一步之后,让它读整理好的表格;如果最耗时的是“看懂结果并决定下一步”,可以让它更靠中间,但中间位置的代价是——它每一次判断都必须能看到上游脚本的输出,而不是只看到一段转述。适合放中间的场景通常是数据格式已经稳定、脚本每次跑完输出的字段一致;如果每次实验导出的文件都不一样,先把格式固定下来再谈放中间。

先定工具调用边界再谈效果——书生-A1.5 在科学工作流里的位置

把必须读外部数据的步骤单独隔离

隔离的意思是:把这些动作从“模型自己生成”的范畴里拿出来,写成显式的工具调用,模型只负责决定调哪个、传什么参数、拿到结果后怎么解释。不能只靠模型生成的典型动作包括:读取实验原始文件、查询内部数据库记录、拉取公开文献元数据、读取仪器状态、执行分析脚本。这些步骤共同点是结果必须来自模型之外的系统。

  • 数据来源与获取方式要成对写清:本地文件走脚本读取,内部库走只读账号的查询语句,公开接口走带超时和重试的 HTTP 调用;不要在提示词里写“请读取最新数据”,模型没有这个能力。
  • 失败时的替代路径必须提前定:接口超时是返回上一轮缓存结果并标注,还是直接中断并提示人工介入?两种都行,但要写死,不能让模型自由发挥。
  • 只读优先:涉及写文件、覆盖数据表、提交任务的接口,在调试阶段建议先做成只读或写副本,避免一次错误调用污染原始数据。

下面是一份工具清单配置骨架,字段名可按自己环境替换,放在工具注册处加载,用来给每次调用限定来源和兜底动作:

tools:
  - name: read_experiment_table
    source: local_filesystem
    entry: /data/exp/{run_id}/summary.csv
    timeout_s: 10
    on_failure: return_cached_and_flag
  - name: query_internal_db
    source: readonly_db
    statement_template: "select * from run_meta where run_id = :run_id"
    timeout_s: 15
    on_failure: abort_and_ask_human
  - name: fetch_paper_meta
    source: public_api
    timeout_s: 8
    on_failure: return_empty_with_reason

验证方式很直接:故意把 run_id 传成不存在的值,看返回是不是按 on_failure 里写的方式处理;如果模型绕过工具直接编了一段内容,说明提示词里的约束还不够硬。

约定智能体的输入格式和输出格式

接口约定不做好,后面每次换数据源都要重调一遍。输入侧要求字段化:不要给一整段描述,给结构。输出侧要求两部分——结构化字段供程序解析,自由文本供人阅读,两者必须同时存在,否则要么下游没法自动化,要么人看不懂。

先定工具调用边界再谈效果——书生-A1.5 在科学工作流里的位置
{
  "task": "interpret_run",
  "run_id": "exp-xxx",
  "inputs": {
    "summary_table": "<path or inline csv>",
    "previous_conclusion": "<short text or null>",
    "constraints": ["只基于 inputs 内数据作答", "无法判断时返回 needs_human"]
  },
  "required_output": {
    "structured": ["verdict", "confidence_level", "evidence_refs", "next_action", "needs_human"],
    "free_text": "一段不超过 200 字的解释"
  }
}

对应提示词片段可以这样写:先要求“先输出 JSON,再输出解释”,并要求 evidence_refs 里每一项都指向具体的表名、行号或 tool_call_id。这样约定后,下游解析失败会立刻暴露成格式问题,而不是伪装成“模型判断错了”。需要结合环境确认的一点是:如果下游解析器对多余字段敏感,记得要求模型只输出约定字段,禁止自行扩展。

用同一批任务对比接工具前后

判断值不值,不要看单次观感,固定一批任务做前后对比。任务挑选原则是同类型、可重复、有明确完成标准,比如“同一份实验数据出一段结论”这种,准备若干条后重复跑两轮:一轮只给模型文件内容(或人工转述),一轮让它通过工具自己取。

指标定义采集方式
耗时从任务下发到产出可用结果的总时长记录开始与结束时间戳,工具侧和客户端各打一条
返工次数同一任务被退回修改的次数在任务记录或工单里手工打点,注明退回原因类别
结论可核验比例抽查若干条结论,能对应到具体数据行或 tool_call_id 的比例抽样人工核对,逐条标“可核验/不可核验”,记录不可核验的原因

记录格式建议固定成一行一条,便于后面按原因归类:

先定工具调用边界再谈效果——书生-A1.5 在科学工作流里的位置
task_id,mode,duration_s,rework_count,verifiable_yes,verifiable_no,note
T01,no_tool,,
T01,with_tool,,,

如果接工具后耗时没有明显变化甚至变长,但返工次数下降、可核验比例上升,这通常是可以接受的结果:省下的时间在排查和返工上,只是没有体现在单次时长里。反之,如果返工次数上升,多半要先查输出格式是否被破坏,而不是先换模型。

保留能复盘的工具调用记录

接工具之后最常见的抱怨是“接了反而更难排查”。原因基本都是日志只记了模型说了什么,没记它调了什么。建议每次调用写一行 JSON,四个字段至少要有:时间、调用工具名、入参摘要、返回是否被正文引用。

{"ts":"2026-01-01T10:00:00Z","tool":"read_experiment_table","args_digest":"run_id=exp-xxx, cols=12","ok":true,"result_digest":"rows=48","cited_in_answer":true,"call_id":"c-0007"}
{"ts":"2026-01-01T10:00:02Z","tool":"query_internal_db","args_digest":"run_id=exp-xxx","ok":false,"error":"timeout","cited_in_answer":false,"call_id":"c-0008"}
  • 入参摘要不要存全量大对象,存能定位的键值和规模,敏感字段做脱敏。
  • cited_in_answer 的判定方式:要求模型在自由文本里带上 call_id,日志侧检查该 id 是否出现在最终输出里;没有出现就标 false,便于发现“调了工具但没用结果”的情况。
  • ok 为 false 的行单独看一遍,如果某类失败反复出现,问题在工具配置而不在模型,改配置比改提示词有效。

倒查路径因此变得确定:从一条可疑结论出发,找到它对应的 call_id,看时间和入参是否对得上这次任务、返回是否成功、结果有没有被正文引用。三步之内能定位到断点,才说明这套工具调用边界是站得住的。