2.3 工具智能体:列席的执行专家


2.3 工具智能体:列席的执行专家

本节摘要:工具智能体是 OWL 连接外部世界的执行席:每个专家封装一类具体能力(搜索、浏览、执行代码、读文档),按结构化指令干活,按结构化格式回报。本节讲清它的接口契约、一次调用的完整生命周期、"专家答非所问"的排查法,以及专家席的纪律条款。

本节是与会名册的第三站:甲方代表管意图,主持人管过程,专家管动手。第 3 章会逐个介绍五类内置专家的能力细节,本节先回答一个更底层的问题——专家凭什么接活、凭什么可信

一、接口契约:专家靠什么读工单

工具智能体收到的不只是一句"帮我搜一下",而是一份结构化工单:函数名、参数说明、返回约定。框架从哪里拿到这些信息?答案是每个工具自带的函数签名与描述文字。执行侧把这些内容交给模型阅读,模型据此决定何时调用、怎么传参。看一个带完整契约的工具定义:

from camel.toolkits import FunctionTool def fetch_exchange_rate(currency: str, date: str = "today") -> str: """查询指定货币对人民币的汇率。 参数 currency: 货币代码,如 USD、EUR、JPY。 参数 date: 查询日期,格式 YYYY-MM-DD;不传则查最新。 返回: 一句话汇率描述,含中间价与涨跌幅。 """ # 演示实现:真实场景会请求行情服务 rates = {"USD": 7.12, "EUR": 7.78, "JPY": 0.048} if currency not in rates: return f"暂不支持货币 {currency}" return f"{currency} 对人民币中间价 {rates[currency]},较前日基本持平" rate_tool = FunctionTool(fetch_exchange_rate) # 框架把函数名、签名与 docstring 打包成工单交给模型, # 模型看到的是类似这样的描述: # 函数: fetch_exchange_rate(currency: str, date: str = 'today') # 用途: 查询指定货币对人民币的汇率

注意 docstring 里的三个要件:参数语义(currency 是"货币代码"而不是"货币名称")、格式约定(日期必须 YYYY-MM-DD)、返回形态(一句话描述含涨跌幅)。缺任何一件,专家就会按自己的想象补全——补全即事故源头。

二、一次调用的生命周期

从主持人下指令到结果入账,一次工具调用走五步:

二、一次调用的生命周期

生命周期里最值钱的设计是第 4 步的失败上报。专家与主持人之间有一条不成文纪律:失败也是合法回报。对比两种回报——"我尽力了但没找到数据"(如实)与"已获取相关信息"(含糊)——后者看似礼貌,实际把失败伪装成了成功,污染主持人的监控判断。写自定义工具时,务必让函数把失败原因说清楚:

def read_price_page(url_slug: str) -> str: """读取竞品定价页并返回价格文本。 参数 url_slug: 竞品公司标识,如 'compA'。 返回: 成功时为价格表文本;失败时以'失败:'开头并说明原因。 """ pages = {"compA": "基础版99元/月 专业版299元/月", "compB": None} if url_slug not in pages: return f"失败: 无 {url_slug} 的页面配置" content = pages[url_slug] if content is None: # 反爬拦截、页面改版等都要如实上报,不许返回空串糊弄 return "失败: 定价页内容未加载出来,疑似地区限制,建议改用搜索专家" return content # 输出: # read_price_page('compB') # -> '失败: 定价页内容未加载出来,疑似地区限制,建议改用搜索专家'

失败回报里带一句"建议改用搜索专家",看起来多嘴,实际是在给主持人递调度线索——第 4 章的实战日志里,主持人正是顺着这句建议完成了换人兜底。

三、专家答非所问:排查四步法

自定义工具最常见的故障不是报错,而是"专家接了单,干得驴唇不对马嘴"。按下面四步排查,命中率从高到低:

  1. 查契约:docstring 是否说了参数语义与返回形态?九成问题出在这里。修法是把一句含糊的"处理数据"改成"输入订单号列表,返回金额合计,保留两位小数"。
  2. 查拟单:在日志里找第 1 步生成的调用参数,看模型传了什么。参数传错说明契约歧义,参数传对说明是执行问题。
  3. 查校验:参数类型是否过严?字符串日期传成了对象、嵌套列表传成了逗号串,都会在第 2 步被退回重拟单,表现为"反复重试但不前进"。
  4. 查返回:返回值是否是模型读得懂的自然语言?返回裸字典、裸异常对象,模型只能瞎猜。
def audit_tool(docstring: str, returns_str: bool) -> list: """按排查四步法给自定义工具打分,返回整改建议。""" issues = [] if len(docstring) < 40: issues.append("契约过短:补参数语义与返回形态") if "参数" not in docstring: issues.append("缺参数说明:模型只能猜传参") if not returns_str: issues.append("返回非字符串:改为自然语言描述或结构化文本") return issues or ["体检通过"] # 输出: # audit_tool("处理数据", True) # -> ['契约过短:补参数语义与返回形态', '缺参数说明:模型只能猜传参']

案例展开:给会议临时外聘一位专家

背景:贯穿案例跑到中期,团队发现竞品 C 的定价不在官网,而在一份招商手册的附件里,内置五类专家都接不了这单。操作:写一个"手册解析专家"——封装现有文档解析能力,加上公司内部的文件柜检索逻辑,用 FunctionTool 包好后挂进工具列表。结果:下一轮对话,主持人就把"读取竞品C招商手册附件价格表"派给了这位外聘专家,两轮后交付价格文本。解读:外聘专家没有改变会议结构,只是扩充了专家席——这正是 1.3 节"可插拔"原则的日常用法。

变式:如果外聘工具调用很慢(比如每次要等十几秒的批处理),给它加一条"超时即报失败并建议拆分"的纪律,避免主持人干等。宁可让会开得慢,不可让会开得假。

本节要点回顾

  • 接口契约三要件:参数语义、格式约定、返回形态,全写在 docstring 里,缺一即事故;
  • 五步生命周期:拟单、校验、执行、回报、入账,校验失败不消耗真实调用;
  • 失败也是合法回报:如实上报失败原因并给调度线索,是工具智能体的核心纪律;
  • 排查四步法:查契约、查拟单、查校验、查返回,按命中率排序;
  • 下一节从"人"转向"事":议题与目标是怎么被拆出来的。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U