工具怎麼設計
同樣三個工具,名字和說明寫得含糊,模型 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 點。內容經審核後公開。
正在載入討論…