工具怎么设计
同样三个工具,名字和说明写得含糊,模型 30 次只选对 14 次;写清楚之后 30 次全对。讲清楚工具的名字、说明、参数、返回值和报错信息分别该怎么写。
- 约 35 分钟
- 难度:进阶
- 实测:2026-09-14 deepseek-flash
智能体好不好用,一大半取决于工具。模型能看到的只有工具的名字、说明和参数定义,看不到你的代码。说明书写得含糊,模型就只能猜:这个工具能干什么?什么时候该用它?参数填什么?
这一课先做一个实验,量一量说明书写得好坏的差别,然后讲具体怎么写。
实验:含糊的说明和清楚的说明
同样三个功能:在文档里搜索、读一个文档文件、查 PyPI 上的版本号。写两套说明书。
含糊的一套:名字是通用的动词,说明只有两三个字:
VAGUE = [
fn("search", "搜索", q="内容"),
fn("read", "读取", x="要读的东西"),
fn("lookup", "查找信息", name="名字"),
]
清楚的一套:名字说明操作的对象,说明写清楚能做什么、什么时候用、参数怎么填:
CLEAR = [
fn("search_docs", "在 httpx 官方文档里按英文关键词全文搜索,返回匹配的文件名和行号。"
"用户问 httpx 某个功能怎么用、某个参数是什么意思时,先用它。",
keyword="英文关键词,例如 timeout、proxy、follow_redirects"),
fn("read_doc", "读取 httpx 文档里某个文件的内容。通常在 search_docs 找到文件名之后使用。",
path="文档文件路径,例如 advanced/timeouts.md"),
fn("get_pypi_info", "查询某个 Python 包在 PyPI 上的最新版本号和发布信息。只在用户问版本号、是否已发布新版本时使用。",
package="PyPI 上的包名,例如 httpx"),
]
(fn 是一个生成工具说明书的小函数,完整代码见 code/05-agents/tool_design.py。)
然后准备 10 个问题,每个问题标注第一步应该调用哪个工具。其中"你好"这一题的正确答案是不调用任何工具。每个问题、每套说明书各问 3 次,只看模型第一步选了哪个工具,不真的执行:
QUESTIONS = [
("httpx 怎么设置代理?", "search_docs"),
("httpx 最新版本是多少?", "get_pypi_info"),
("帮我看看 advanced/ssl.md 里写了什么", "read_doc"),
("follow_redirects 参数是干什么的?", "search_docs"),
("requests 现在出到哪个版本了?", "get_pypi_info"),
("httpx 怎么上传文件?", "search_docs"),
("你好", None),
("把 quickstart.md 的内容给我看一下", "read_doc"),
("httpx 有没有发布 1.0 正式版?", "get_pypi_info"),
("httpx 的 event hooks 怎么用?", "search_docs"),
]
结果:
含糊的工具:14/30 次选对
httpx 怎么设置代理? 应该用 search_docs,实际 {'None': 2, 'search_docs': 1}
httpx 最新版本是多少? 应该用 get_pypi_info,实际 {'search_docs': 3}
帮我看看 advanced/ssl.md 里写了什么 应该用 read_doc,实际 {'read_doc': 2, 'get_pypi_info': 1}
follow_redirects 参数是干什么的? 应该用 search_docs,实际 {'search_docs': 1, 'None': 1, 'get_pypi_info': 1}
requests 现在出到哪个版本了? 应该用 get_pypi_info,实际 {'get_pypi_info': 1, 'search_docs': 2}
httpx 怎么上传文件? 应该用 search_docs,实际 {'None': 3}
httpx 有没有发布 1.0 正式版? 应该用 get_pypi_info,实际 {'search_docs': 3}
清楚的工具:30/30 次选对
同一个模型,只是说明书不同,正确率从 47% 变成了 100%。
含糊的说明书错在哪
不知道工具管什么范围。"搜索"是在哪里搜?网页、文档还是代码?模型不知道。于是"httpx 最新版本是多少"它 3 次都选了 search,因为"搜索"听起来最通用。
不知道什么时候该用。"httpx 怎么上传文件",3 次都没调用任何工具,模型直接凭记忆回答了。它不知道 search 能帮它找到更可靠的答案,也就没有理由去用。
名字和功能对不上。lookup 其实是查 PyPI 版本的,可"查找信息"这个说明和"读取"、"搜索"区分不开,模型只能随机选。"follow_redirects 参数是干什么的",3 次选了 3 个不同的结果。
清楚的说明书把这些都写明了:搜的是"httpx 官方文档","用户问 httpx 某个功能怎么用时,先用它";查版本的工具"只在用户问版本号时使用"。模型不需要猜。
名字
- 说清楚操作的对象。
search_docs比search好,get_pypi_info比lookup好。工具多了以后,通用的名字很容易撞在一起。 - 用动词开头,前后一致。
get_、search_、read_、create_,一套规则用到底。 - 别用缩写。
gpi你自己知道是什么,模型不知道。
说明
一个好的说明,回答三个问题:
- 它能做什么? "在 httpx 官方文档里按英文关键词全文搜索,返回匹配的文件名和行号。"
- 什么时候该用它? "用户问 httpx 某个功能怎么用时,先用它。"
- 什么时候不该用它? "只在用户问版本号、是否已发布新版本时使用。"
工具之间容易混淆时,第三点尤其重要。另外,说明里可以写工具之间的配合关系,比如 read_doc 的"通常在 search_docs 找到文件名之后使用",模型就知道先搜后读。
参数
- 每个参数都写说明,最好带例子。"英文关键词,例如 timeout、proxy、follow_redirects"。例子能告诉模型格式,也暗示了"文档是英文的,要用英文搜"。
- 参数越少越好。一个工具有七八个参数,模型很容易漏填或填错。能有默认值的给默认值。
- 用枚举限定取值。参数只能取几个固定值时,在 schema 里用
enum列出来(第 02 模块第 4 课用过)。 - 名字和类型要明确。
x、q、name这样的参数名,不如path、keyword、package。
返回值
工具的返回值会原样进入上下文,后面每一步都要为它付费。所以:
- 只返回有用的信息。上一课的
get_pypi_info只挑了版本号、简介、Python 版本要求四个字段,没有把 PyPI 返回的几十 KB 原始 JSON 全部塞进去。 - 限制长度。上一课的
grep_docs最多返回 20 条,read_doc一次最多 80 行,循环里还有一道 3000 字符的截断。 - 方便模型下一步使用。
grep_docs返回"文件名:行号:内容",模型可以直接拿文件名和行号去调用read_doc。 - 结果为空时说清楚。返回"没有找到 pool timeout",而不是一个空字符串。空字符串让模型困惑:是工具坏了,还是真的没有?
报错信息
报错信息是写给模型看的,要能帮它改正:
错误:没有这个文件 advanced/timeout.md,请先用 list_docs 查看有哪些文件
这一句说清楚了三件事:出了什么错、错在哪个参数、下一步该怎么做。对比 Python 默认的 FileNotFoundError: [Errno 2] No such file or directory,模型也能看懂,但不知道该调用哪个工具去找正确的文件名。
工具多了怎么办
工具越多,模型越难选对,每次请求的说明书也越长。一些经验:
- 合并功能相近的工具。如果
search_docs和search_api_reference的区别连你都说不清,就合并成一个,加一个参数区分。 - 按场景分组。不同的任务只给相关的那几个工具,第 6 课的多智能体会用到这个思路。
- 看轨迹。经常被用错的工具,就是说明书需要改的工具。
练习
- 在
tool_design.py的清楚组里,把search_docs说明里的"用户问 httpx 某个功能怎么用时,先用它"删掉,重新运行。"httpx 怎么上传文件"这一题的结果有变化吗? - 给两套工具都加一个功能:
list_docs,列出所有文档文件。含糊的一组叫list、说明是"列表",清楚的一组照本课的方法写。再加两个问题测试它。 - 找一个你以前写过的函数,按本课的方法给它写一份工具说明书,让模型来调用它。
自测
1. 一个好的工具说明应该回答哪几个问题?
它能做什么;什么时候该用它;什么时候不该用它(尤其是和别的工具容易混淆时)。可以再写上它和其他工具怎么配合,比如"通常在 search_docs 之后使用"。
2. 为什么工具的返回值要尽量短?
返回值会原样放进消息列表,智能体后面的每一步都要带着它调用模型,都要为它付费。返回值太长还会让模型抓不住重点,甚至撑满上下文窗口。只返回有用的字段,并设置长度上限。
3. 工具的报错信息写成什么样最好?
写给模型看,说清楚出了什么错、错在哪里、下一步该怎么做。比如"没有这个文件 X,请先用 list_docs 查看有哪些文件"。这样模型能自己改正,而不是反复犯同样的错误。
提问与讨论
这一课没看懂的地方,在这里问。看到别人的问题,也欢迎你来回答。
提问 +3 积分,回答别人 +6 积分。内容经审核后公开。
正在加载讨论…