ARTICLE · 1296908
第75讲|AI 说调用工具,就真调用了吗?它只递来一张单子,程序验过才办
你问 AI「5 斤布料合多少米」,它回你一句「我来调用换算工具」,接着报出「5 斤 = 2500 米」。看上去它真用了工具,答案也是工具算的,可这个数一点意义都没有。
这一讲拆开工具调用里最要紧的一步:AI 说「调用工具」的时候,程序收到的到底是什么,参数缺了、写错了、乱搭了,程序该怎么拦。最后在自己电脑上搭两道检查,用真模型各跑三次,再拿判分脚本看它拦没拦住。写代码和装环境交给 AI,先跟着看就行。
结论先放前面:AI 调用工具,只是递来一张写着工具名和参数的单子。单子格式对不对、事情说不说得通,都得程序先查;两道都过了才去办,查不过就把原因退回给它。
▍ 它说「调用」,程序收到的是一串字
工具调用(function calling)听起来像 AI 自己按下了按钮。其实模型回给程序的,只是一段写好的文字:要用哪个工具,参数是什么,比如 {"value": 5, "from_unit": "jin", "to_unit": "m"}。
阿里云百炼的官方文档说得很直白:「大模型仅输出字符串格式」,入参是一段 JSON 字符串,要程序自己解析;工具真正运行,「由您的计算环境而非大模型来完成」。
所以「它调用了」这句话,准确的说法是「它提了一个调用请求」。办不办、怎么办,全在程序。模型写下的参数,在程序眼里是一份外来的输入,跟用户在网页表单里随手填的一样,不能拿来就用。

▍ 工具说明书:告诉它参数该长什么样
程序要先给模型一份工具说明书,模型才知道手边有什么工具、参数怎么填。说明书里写三样:工具叫什么(name),干什么用(description),参数长什么样(parameters)。
参数那一栏用的是一种通用的格式描述(JSON Schema):每个参数是数字还是文字,哪几个必须填(required),单位只能从哪几个里挑(enum)。本讲的换算工具写了三个必填参数:数值、原单位、目标单位,单位只认 mm、cm、m、km、g、kg、jin(市斤)、liang(市两)八个。
要注意,这份说明书是写给模型「参考」的,官方文档用的就是这个词,还提醒「可能选择错误的工具」。说明书管不住它,它照着填也可能填错。 真正的关卡,得程序自己设。

▍ 第一道闸:结构校验,先看单子填没填对
第一道检查只看形状,不懂业务,行内叫结构校验。它查五件事:是不是合法的 JSON,必填参数齐不齐,数值是不是真的数字,单位在不在清单里,有没有说明书上没写的多余参数。
我们先不接模型,拿十组参数直接送进去试,一组正常、九组故意写坏,这一步只测程序、不算模型实测。缺了数值、单位写成「斤」这个汉字、单位写了清单里没有的「英寻」,全被第一道拦下,退回一句写明原因的「拒绝」。
更值得看的是拆掉这道闸会怎样。不是 JSON、缺数值、单位不认识的,执行器直接崩溃报错;数值写成了文字 "3.5"、多带一个没人认的 round 参数,执行器不声不响照算,那个 round 被悄悄扔掉,一句报错都没有,坏输入就这么混过去了。

▍ 第二道闸:业务校验,再看事情说不说得通
第一道闸过了,只能说明单子填得规整。斤和米都在清单里,{"value": 5, "from_unit": "jin", "to_unit": "m"} 每一格都合规,可斤是重量、米是长度,这件事本身就办不成。
所以还要第二道,查这件事在业务上说不说得通,叫业务校验。本讲的规则写在程序里:两个单位必须同一类,数值不能是负数,也不能大到离谱。
2026-10-30 我们用百炼上的 qwen3.7-plus(2026-05-26 版)问「我买了 5 斤布料,用你的换算工具算一下合多少米」,跑了三次。三次它都真发出了斤换米的调用,格式全对,三次都被第二道闸拦下,执行器一次也没算;它读到退回的原因,转头向用户解释斤和米不能直接换,要知道布料的克重和幅宽才行。

▍ 反面:拆了闸,它报出「5 斤 = 2500 米」
对照组只改一处:两道闸都拆掉,模型发来什么参数就直接算。同一句话,同一个模型,又跑三次。
三次它发出的还是那个斤换米的调用。执行器不管类别,照着倍数一乘,送回「5 jin = 2500 m」;模型三次都把这个数报给了用户,两次在后面补了一句「斤和米其实不能直接换算」,一次就只有「5 斤 = 2500 米」这一句。
开头那个答案就是这么来的。JSON 合法、程序也跑了、还返回了一个数,不等于结果是对的。 就算后面跟着一句提醒,读者先看到、先记住的还是那个假数。

▍ 两道闸都拦不住的:它自己猜的参数
还有一类问题,两道闸都查不出来。我们问「这段路大概三点五,帮我换成米」,故意不说单位,跑了三次。
两次它反问「三点五是公里还是米」;有一次它自己定成了公里,发出 {"value": 3.5, "from_unit": "km", "to_unit": "m"},回答「3.5 公里 = 3500 米」,没提单位是它猜的。这个调用形状对、单位同类,两道闸都放行了。另一句「帮我把这段距离换算成米」连数都没给,三次它都老实反问,没有编一个数去调用。
校验管得了格式和道理,管不了它猜的。 能做的是在判分时多查一句:参数里的单位,在用户原话里找不找得到,找不到就标出来。要紧的参数拿不准,就让程序停下来问人;能花钱、能改东西的操作,更要人点头再办,百炼文档的工具安全原则也是这么写的。

▍ 动手:自己搭两道闸,再用脚本验一遍
想自己跑一遍,不用会写代码。把下面这段发给你常用的 AI 编程工具,环境让它来装;装不上,就把报错整段贴回去。
▍ 可以直接复制这段发给 AI
帮我用 Python 3.11 以上、只用标准库写一个工具调用实验。做一个换算工具 convert_unit,参数是 value、from_unit、to_unit,单位只认 mm、cm、m、km、g、kg、jin、liang,按 OpenAI 兼容接口的 tools 格式写好说明。模型返回的调用先过两道检查再执行:第一道查参数是不是合法 JSON、必填齐不齐、value 是不是数字、单位在不在清单里、有没有多余参数;第二道查两个单位是不是同一类、数值是不是非负且不离谱。任何一道不过,就把写明原因的「拒绝」作为工具结果送回模型,不执行。执行器每算一次自己记一笔账。模型走阿里云百炼,密钥只从环境变量 DASHSCOPE_API_KEY 读,模型名也用环境变量配。再写一个开关,可以拆掉两道检查做对照。另写一个判分脚本,只看调用记录和执行器的账:执行器算过的每一笔都必须是两道都放行的;跨类别的请求执行器一次都没算;正常请求的答案等于判分脚本自己算的。写完先拿几组故意写坏的参数测两道检查,再给我看结果。
我们照这个思路实际跑了五组、每组三次,一共十五次,结果在下面这张表里。判分脚本不看模型说得多好听,只对三本账:模型发了什么调用,闸门放没放行,执行器真算了什么。十五次里,开着闸的十二次全部判对;拆闸那三次全部判错,执行器账上都记着那笔「2500」。
唯一要你自己盯的是 Python 版本号,和密钥别写进代码、别贴进聊天。调用模型接口一般按用量计费,有没有额度、单价多少,以百炼控制台当前页面为准;这十五次只是这一天、这个模型、这几句话的小样本。


▍ 一句话记住
AI 调用工具,只是递来一张单子:程序先查格式、再查道理,两道都过才去办,查不过就把原因退回去;它自己猜的参数闸门拦不住,要紧的就停下来问人。
▍ 追更《从0了解AI》
这是《AI智能体原理与实战》的第 75 讲。 下一讲换个角度:每一步都让 AI 自己决定,有必要吗?同一批任务分别用固定流程和让模型选路各跑一遍,比一比哪一步才值得交给它。
觉得有用就关注一下,往后一讲一讲接着更;顺手点个赞或在看,也转给正在给 AI 接工具的朋友。
想再往深里学一步?下面这篇是星球配套的实操篇,里面有这个小实验的完整实验包:分步提示词、两道检查和执行器的写法、十组测试参数、五组请求、预期结果、重置方法和判分脚本,还有跑不对时怎么查。
这个小实验的完整实验包:分步提示词、两道检查与执行器、十组测试参数、五组请求、预期结果、重置方法、判分脚本、跑不对时怎么查。下面这篇是星球配套的实操篇















































































