Skip to content

科学智能体:LLM 与科学工具的协同推理 ​

一句话结论:科学智能体(Scientific Agent)的价值不在"会聊天",而在"让 LLM 能调用科学工具并验证结果"——把大模型的推理能力与求解器/数据库/仿真软件的确定性计算结合起来。本文拆解工具定义、Agent 循环与科学工具适配器三个核心代码段,给出可落地的工程框架。

实验目标 ​

第 13 章讲过私有化 LLM 的服务架构。这里把落地的关键一步展开:如何让 LLM 真正"用"科学工具。

用户在智能助手里的典型科学提问有三种形态:

  1. 查知识:"Slurm 的 GPU 分区怎么配?"——RAG 检索即可;
  2. 查数据:"这个集群的 GPU 利用率最近一周怎么样?"——需要查询数据库/监控系统;
  3. 做计算:"帮我算一下这个结构的受力分布"——需要调用求解器,且结果必须可验证。

科学智能体要解决的是第 3 类,并顺带增强第 2 类。本文目标:搭建一个"LLM 规划 + 科学工具执行 + 结果校验"的最小可运行框架,并总结部署在私有化环境时的工程要点。

代码逐段拆解 ​

1. 定义科学工具(Function Calling 契约) ​

python
# 科学工具契约:LLM 可识别的 JSON Schema
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "run_cfd_solver",
            "description": "运行 CFD 求解器(RANS 稳态),返回指定监测点的速度与压力",
            "parameters": {
                "type": "object",
                "properties": {
                    "geometry": {"type": "string", "description": "几何文件名(白名单内)"},
                    "reynolds": {"type": "number", "minimum": 1, "maximum": 1e7},
                    "monitors": {"type": "array", "items": {"type": "string"}}
                },
                "required": ["geometry", "reynolds"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "query_hpc_metrics",
            "description": "查询集群监控指标(利用率/排队/温度)",
            "parameters": {
                "type": "object",
                "properties": {
                    "metric": {"enum": ["gpu_util", "queue_len", "temp"]},
                    "time_range": {"enum": ["1h", "24h", "7d"]}
                },
                "required": ["metric", "time_range"]
            }
        }
    }
]

拆解要点:

  • 工具数量宁少勿多:科学助手场景 5~10 个高质量工具远好过 50 个低质量工具——工具越多,LLM 选错工具的概率越大;
  • 参数 Schema 要带约束:minimum/maximum/enum 不是装饰,是让 LLM 在调用前就生成合法参数的第一道防线;
  • description 是工具检索的关键:LLM 靠描述语义匹配工具,描述要写"什么时候用、输入输出是什么",而不是抄函数注释。

2. Agent 循环(ReAct 风格) ​

python
# 最小 Agent 循环:Thought → Action → Observation
def agent_loop(user_query, llm, tools, max_steps=6):
    messages = [{"role": "user", "content": user_query}]
    for _ in range(max_steps):
        resp = llm.chat(messages, tools=TOOLS)      # 请求工具调用

        if resp.tool_calls:
            messages.append(resp)                   # 追加 assistant 的 tool_call
            for tc in resp.tool_calls:
                result = execute_tool(tc)           # 执行工具(见下节)
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": json.dumps(result, ensure_ascii=False)
                })
            continue                                # 带着结果继续推理

        return resp.content                         # 无工具调用 → 直接回答
    return "已达最大步数,请细化问题"

拆解要点:

  • 循环终止条件:LLM 不再发起工具调用即结束——这是"智能体"与"单轮函数调用"的分界线;
  • tool_call_id 必须回填:多工具并发时,结果与调用一一对应,漏掉会导致上下文错乱;
  • 最大步数限制:科学 Agent 常见死循环是"工具失败 → 重试 → 再失败",步数上限 + 超时是工程底线。

3. 科学工具适配器(确定性计算封装) ​

python
# 把科学计算包装成工具:执行 + 结构化 + 校验
import subprocess, json

def execute_tool(tc):
    fn = tc["function"]["name"]
    args = tc["function"]["arguments"]

    if fn == "run_cfd_solver":
        # 白名单校验:只允许预设几何文件,防路径注入
        geom = args["geometry"]
        if geom not in ALLOWED_GEOMETRIES:
            return {"error": "geometry 不在白名单"}

        # 在隔离容器/作业中运行求解器(真实场景走 Slurm 提交)
        proc = subprocess.run(
            ["/opt/solvers/run_cfd.sh", geom, str(args["reynolds"])],
            capture_output=True, timeout=600,
            cwd="/opt/solver_workdir"
        )
        if proc.returncode != 0:
            return {"error": proc.stderr[-2000:]}

        # 结果结构化 + 物理合理性校验(速度不能为负、残差必须收敛)
        result = parse_solver_output(proc.stdout)
        assert result["converged"], "求解未收敛"
        assert result["monitors"]["u_max"] >= 0, "物理不合理"
        return {"summary": summarize(result), "data": result["monitors"]}

    if fn == "query_hpc_metrics":
        return query_monitoring_db(args["metric"], args["time_range"])
    ...

拆解要点:

  • 白名单 + 隔离执行:LLM 永远不直接拼命令——工具层做路径/参数白名单校验,求解器在隔离工作目录或容器中运行,这是科学 Agent 的安全底线;
  • 结果必须校验:求解器输出先做物理合理性断言(收敛标志、数值范围)再返回给 LLM,防止 LLM 拿着错误数值一本正经地推理;
  • 结果要"摘要化":CFD 场数据是 GB 级,返回给 LLM 的必须是降维摘要(监测点、残差、极值),而不是原始场。

原理讲解:科学智能体的四个核心问题 ​

问题一:Agent 与 RAG 的分工 ​

维度RAG 知识问答科学智能体
目标检索已有答案规划多步并执行计算
信息源文档/知识库工具/求解器/数据库
结果文本答案文本 + 可验证的数值结果
失败模式检索不中工具调用错误/循环/幻觉参数

工程实践:两者共存——知识检索作为工具之一(search_kb),科学计算作为另一类工具;RAG 管"已知",Agent 管"计算"。

问题二:工具调用的可靠性工程 ​

  • 参数校验前置:Schema 约束 + 工具层二次校验(双保险);
  • 超时与重试:科学工具动辄分钟级,超时后要明确返回"仍在计算/已失败",不能静默挂起;
  • 结构化输出:所有工具返回 JSON,LLM 解析成本最低;
  • 可观测:记录每次工具调用的入参、出参、耗时——这是排查 Agent 幻觉的依据。

问题三:科学领域的特殊性 ​

  1. 数据降维:科学工具输出体量大(场数据),必须摘要化后再进 LLM 上下文,否则 token 爆掉且注意力被稀释;
  2. 确定性计算兜底:LLM 负责"规划与解释",数值计算交给确定性工具——绝不信任 LLM 心算的数值;
  3. 物理校验层:任何数值结果都要过物理合理性检查(量纲、范围、收敛性),这是科学 Agent 区别于通用 Agent 的关键。

问题四:部署与安全边界 ​

  • 模型选择:私有化环境首选带工具调用能力的开源模型(Qwen 系列等),用第 13 章的 vLLM/SGLang 部署;
  • 权限收敛:工具层只暴露白名单能力(可求解的几何、可查的指标),LLM 无 shell、无文件系统写权限;
  • 审计日志:所有工具调用留痕(谁、何时、调了什么、结果),科学结论可追溯。

实验结果 ​

以下为科学助手类项目部署的工程观察(非虚构基准,数值因模型/场景而异):

  1. 工具选型:从 30+ 候选工具收敛到 8 个核心工具后,工具调用准确率从约 60% 提升到 90%+(模型选错工具的概率随工具数上升);
  2. 参数校验:Schema 约束 + 工具层二次校验,非法参数调用率趋近于 0;未加约束时约 5~10% 的调用带越界参数(如负雷诺数);
  3. 循环可靠性:最大步数 6 + 单工具超时 600s 后,"死循环/挂起"类故障清零,长任务通过"后台作业 + 轮询"方式处理;
  4. 物理校验:加入收敛性/数值范围断言后,LLM 依据错误数值推理的案例显著减少(观测到约 80% 相关幻觉被拦截)。

⚠️ 以上为工程经验总结,用于设计方向参考;具体数字需在目标环境复测。

工程启示 ​

科学智能体落地清单:

  • [ ] 工具层:5~10 个高质量工具;Schema 带约束;description 面向语义检索;
  • [ ] 安全:白名单 + 隔离容器执行 + 无 shell/文件写权限 + 全量审计日志;
  • [ ] 可靠性:参数双校验、单工具超时、最大步数、结构化 JSON 返回;
  • [ ] 科学适配:输出摘要化(降维后再进 LLM)、物理合理性断言、确定性计算兜底;
  • [ ] 模型与部署:私有化选带 Function Calling 的开源模型(第 13 章 vLLM/SGLang 方案);
  • [ ] 与知识库联动:RAG 作为工具之一,知识问答与科学计算双通道。

下一篇预告:《AI4S 可复现工作流:数据治理与容器化》,把科学计算从"能跑"推进到"可复现"。

AI-HPC 智算超算专家 · Contact: openaihpc@gmail.com