智能体调外部函数/工具,最容易被忽略的一环是:返回值你信了它就脏了。接口偶尔少个字段、类型变了、返回个 null,模型拿着脏数据接着往下推,错误一路传导到最终回答。给函数返回值套一层 schema 校验,是我后来必加的护栏。用 Q&A 形式把这事讲清楚。

Q:模型不是挺聪明吗,脏一点的数据它自己能兜住吧?

A:不能指望。我搭的订单查询助手,工具返回里有个 amount 字段,正常是数字。某次上游接口异常,返回的是字符串 "null"(注意,是字符串而不是真 null)。模型拿到后,在回答里算总价时把它当成了某个值,给用户报了个离谱的金额。模型不会替你校验数据合法性,它默认你喂的都是对的。脏数据进去,错误答案出来。

Q:那 schema 校验具体校什么?

A:我至少校三样:

  1. 必填字段在不在。约定要返回 order_idamountstatus,少任何一个直接判不合格。

  2. 类型对不对amount 必须是 number,来个字符串就拦下。

  3. 取值范围/枚举合不合法status 只能是 paid/unpaid/refunded 里的一个,返回个 "成功" 这种野值就拦。

我用一个 JSON Schema 描述期望结构,工具一返回就先过校验,过了才让模型用:

{
  "type": "object",
  "required": ["order_id", "amount", "status"],
  "properties": {
    "order_id": { "type": "string" },
    "amount":   { "type": "number" },
    "status":   { "enum": ["paid", "unpaid", "refunded"] }
  }
}

Q:校验没过怎么办,直接报错给用户?

A:分情况,别一刀切报错。我的处理是:

  • 字段缺失/类型错 → 先重试一次工具调用,很多时候是上游瞬时抽风,重试就好了。

  • 重试还不过 → 不把脏数据给模型,而是给模型一个明确的"这次没拿到有效数据"的信号,让它礼貌地告诉用户"订单信息暂时查不到",而不是硬编。

  • 枚举越界这种 → 我会做一层兜底映射,比如上游偶尔返回中文"已支付",我映射成 paid 再放行,而不是直接拒。

最忌讳的是校验不过就把原始脏数据透传给模型——那校验白做了。

Q:实操有什么坑?

A:几个真的。

一是别把 schema 写太死。我一开始把每个字段都设成必填,结果上游一个可选字段偶尔不返回,校验天天报红,其实那字段压根不影响回答。后来分清楚"核心字段必填、辅助字段可选",误拦才降下来。

二是校验位置要在"工具返回后、喂给模型前",这个夹缝里。放早了工具还没返回,放晚了脏数据已经进模型了。

三是个我交过学费的细节:嵌套对象要递归校验。我最初只校了顶层字段,结果 items 数组里某个元素的价格是脏的,顶层看着挺好,模型用到明细时还是出错了。该往里钻就得往里钻。

Q:值得为这个花精力吗?

A:值。说个取舍——加了校验,确实会偶尔出现"上游其实数据没问题,只是格式跟我 schema 约定有点出入,被误拦了"的情况,需要回头放宽规则,有维护成本。但比起脏数据悄无声息混进回答、最后用户拿着错误金额来找你,这点维护成本太划算了。脏数据的可怕在于它不报错、只是默默错,schema 校验就是把"默默错"变成"明确拦"。

这套工具返回值校验,我是在一个零代码、还能把成品发布成 API 的平台上配的——工具节点后面挂一个 schema 校验节点,不过就走重试或兜底分支,逻辑拖出来连一下就成,不用自己写一堆 if-else 防御代码。

模型推理走的讯飞星辰 MaaS,现成 API 调,没自己搭算力。

Logo

一站式 AI 云服务平台

更多推荐