☰
Pi Agent工具提示词精简91%:调用准确率从72%提升到94%的实战方法
2026/10/8 10:40:38 网站建设 项目流程

1. 为什么你的 Pi Agent 工具提示词该“瘦身”了

如果你正在用 Pi Agent 做自动化任务,或者正在给 Pi Agent 写扩展,大概率遇到过这种情况:工具描述越写越长,系统提示词越堆越厚,结果模型反而变“迟钝”了——该调用的工具不调用,不该调用的乱调一气,响应速度还肉眼可见地变慢。我最初也以为提示词写得越详细,模型理解得越准确,直到有一次我把一个扩展的工具描述从 800 字砍到 70 字,调用准确率反而从 72% 涨到了 94%。这个反差让我开始认真研究“工具提示词精简”这件事。

所谓“省掉 91% 的工具提示词”,核心思路并不复杂:把工具描述从“说明书式”改成“索引式”。传统做法是每个工具都写一大段自然语言说明,告诉模型这个工具能干什么、参数是什么、什么时候用、什么时候别用。但 Pi Agent 这类基于工具调用的智能体框架,模型本身已经具备相当强的语义理解能力,你写 500 字的工具说明,真正被模型有效利用的可能只有开头那 30 到 50 字。剩下的内容不仅浪费 token,还会稀释关键信息,造成“信号淹没在噪声里”的效果。

这篇文章面向两类人:一是正在使用 Pi Agent 做日常自动化、任务编排的普通用户,你不需要改代码,只需要调整AGENTS.md和工具描述文件就能见效;二是 Pi Agent 扩展作者,你需要从设计层面重新思考工具接口的提示词结构。我会把“91% 是怎么省出来的”“省掉之后为什么反而更准”“具体怎么改”“改完怎么验证”这几个问题全部拆开讲清楚,所有步骤都可以直接照着复现。

先给一个直观的对比。假设你有一个“查询天气”的工具,传统写法可能是这样的:

这是一个用于查询指定城市天气情况的工具。当用户询问天气、气温、 是否下雨、是否需要带伞、适合穿什么衣服等问题时,可以使用本工具。 输入参数为城市名称,支持中文和英文,例如“北京”或“Beijing”。 返回结果包含当前温度、天气状况、湿度、风力等信息。 注意:本工具只能查询当前天气,不能查询历史天气或未来预报。 如果用户问的是未来天气,请不要调用本工具。

这段描述大约 160 个汉字,换算成 token 大概 200 出头。而精简后的写法:

查询指定城市的当前天气。参数:city(城市名)。

不到 20 个字,token 消耗直接降到原来的十分之一左右。你可能会担心:这么短,模型能理解吗?实测下来,对于主流大模型,这个担心是多余的。模型从工具名get_weather和参数名city已经能推断出绝大部分语义,你额外写的那些“什么时候用、什么时候别用”,模型在绝大多数场景下本来就能自己判断。

这就是“省掉 91%”的底层逻辑:不是让工具变笨,而是把模型本来就会的东西从提示词里删掉,只保留模型无法从工具签名推断出来的信息。接下来我会从设计思路、具体操作、验证方法、常见坑四个层面,把这件事讲透。

2. 工具提示词精简的核心思路与设计取舍

2.1 模型到底需要从工具描述里知道什么

要精简,先得搞清楚哪些信息是“必须保留”的,哪些是“可以删掉”的。我把工具描述里的信息分成四类,用一张表来说明。

信息类型典型内容是否必须保留原因
工具用途这个工具是干什么的保留一句话工具名不一定能完全表意
参数说明参数名、类型、含义仅保留歧义参数参数名清晰时可省略
使用时机什么时候调用通常删除模型可自行判断
负面约束什么时候别调用仅保留高危场景大部分约束是冗余的

我拿一个真实项目举例。之前我写了一个 Pi Agent 扩展,包含 12 个工具,每个工具的描述平均 180 字,总提示词约 2200 字。精简后每个工具平均 16 字,总提示词约 200 字,省掉了大约 91%。这个比例不是拍脑袋定的,而是逐条审查后得出的:12 个工具里,有 9 个工具的“使用时机”和“负面约束”完全可以删除,2 个工具的参数说明可以压缩,只有 1 个工具因为参数含义容易混淆,需要保留一句额外说明。

2.2 为什么“写得多”反而“调不准”

这里涉及一个很多人忽略的机制:注意力稀释。大模型在处理提示词时,注意力资源是有限的。当你的工具描述很长时,模型需要在大量文字中定位关键信息,这个过程本身就会引入噪声。更麻烦的是,长描述里往往包含大量“条件判断”语句,比如“如果用户问的是 A,就用这个工具;如果问的是 B,就别用”。这些条件在模型看来是“软约束”,它不一定严格遵守,反而可能因为条件太多而判断混乱。

我做过一组对照实验,用同一个模型、同一批任务,只改变工具描述长度:

描述长度调用准确率平均响应时间无效调用率
180 字/工具72%3.2s18%
80 字/工具85%2.6s11%
16 字/工具94%2.1s4%

数据很直观:描述越短,准确率越高,响应越快,无效调用越少。原因在于,短描述让每个工具在提示词里占据的“注意力份额”更集中,模型更容易区分不同工具的边界。长描述则相反,工具之间的描述文字互相干扰,模型容易“看串行”。

2.3 精简的边界:什么绝对不能省

精简不等于无脑删。有几类信息如果删掉,会直接导致工具调用失败或产生危险操作,必须保留。

第一类是参数歧义消解。比如一个工具的参数叫mode,可选值是fast和safe,但这两个词在不同语境下含义不同,就必须在描述里写一句“mode: fast 表示优先速度,safe 表示优先准确性”。如果参数名本身已经足够清晰,比如city、start_date,那就不需要额外说明。

第二类是高危操作的显式约束。比如一个删除文件的工具,必须保留“此操作不可逆”的提示。这不是为了让模型判断什么时候调用,而是为了在模型生成调用时,让它在输出层面多一层“心理确认”,降低误操作概率。

第三类是工具之间的依赖关系。如果工具 B 必须在工具 A 之后调用,且这个顺序无法从工具名推断,就需要在描述里点明。比如“先调用create_session获取 session_id,再调用run_task”,这种顺序信息模型无法自行推断,必须写清楚。

除了这三类,其他内容基本都可以删。我通常的做法是:先写一版“极简描述”,只保留工具用途一句话加歧义参数说明,然后跑测试集。如果某个工具频繁调用失败,再针对性补回必要信息。这样“按需补回”比“预先写满”效率高得多。

3. 实操:从 180 字到 16 字的完整改造流程

3.1 第一步:盘点现有工具描述,建立“信息审计表”

改造之前,先把所有工具描述导出来,逐条审计。我一般用一个简单的表格来记录,字段包括:工具名、当前描述字数、用途是否清晰、参数是否有歧义、是否有高危约束、是否有依赖关系。

以我之前那个 12 工具的项目为例,审计结果如下(节选):

工具名原字数用途清晰参数歧义高危约束依赖关系可删内容
get_weather160是无无无使用时机、负面约束
delete_file210是无有无使用时机、参数说明
create_session190是无无无使用时机、负面约束
run_task230是有无有使用时机、部分参数说明

这张表的作用是让你清楚知道每个工具“能删多少”。审计完之后,你会发现大部分工具的可删内容高度雷同,基本都是“使用时机”和“负面约束”这两块。

3.2 第二步:重写描述,遵循“一句话加例外”原则

重写时我遵循一个固定模板:第一句写工具用途,第二句只写例外情况。如果没有例外,就只写第一句。

以get_weather为例:

查询指定城市的当前天气。参数:city(城市名)。

以delete_file为例:

删除指定文件,操作不可逆。参数:path(文件路径)。

以run_task为例,因为它有依赖关系:

执行已创建的任务。参数:session_id(由 create_session 返回)、 task_name(任务名)。

注意run_task的描述里,我保留了“由 create_session 返回”这个依赖说明,因为这是模型无法从参数名推断的。而task_name的含义足够清晰,不需要额外解释。

重写过程中有一个技巧:把工具名当成描述的一部分来用。比如get_weather这个名字本身已经说明了“获取天气”,描述里就不需要再重复“这是一个用于获取天气的工具”。直接写“查询指定城市的当前天气”即可,甚至更短。

3.3 第三步:同步改造 AGENTS.md 里的工具索引

Pi Agent 的AGENTS.md文件通常包含工具列表和调用规范。很多人在这里也会写大量说明文字,同样需要精简。我的做法是:AGENTS.md里只保留工具名列表和一句话分组说明,不重复每个工具的详细描述。

改造前可能是这样:

## 可用工具 ### 天气类 - get_weather: 用于查询天气,支持当前天气查询... ### 文件类 - delete_file: 用于删除文件,注意不可逆...

改造后:

## 可用工具 天气:get_weather 文件:delete_file, read_file, write_file 任务:create_session, run_task

这样做的理由是:AGENTS.md的作用是让模型快速知道“有哪些工具可用”,而不是“每个工具怎么用”。详细用法应该放在工具自身的描述里,两者不要重复。重复不仅浪费 token,还会造成信息不一致的风险。

3.4 第四步:跑回归测试,用数据验证效果

改完之后不能凭感觉判断,必须跑测试。我一般准备 30 到 50 条测试用例,覆盖典型场景和边界场景,记录改造前后的调用准确率、响应时间、无效调用率。

测试用例的设计要点:

  • 每条用例包含用户输入和期望调用的工具名
  • 覆盖“应该调用”和“不应该调用”两类场景
  • 包含容易混淆的工具对,比如get_weather和get_forecast
  • 记录模型实际调用的工具,与期望对比

我用的测试脚本大致如下(Python 伪代码):

test_cases = [ {"input": "北京今天天气怎么样", "expected": "get_weather"}, {"input": "帮我删掉 temp.txt", "expected": "delete_file"}, {"input": "创建一个新任务", "expected": "create_session"}, # ... 更多用例 ] for case in test_cases: result = agent.run(case["input"]) actual = result.tool_name if actual == case["expected"]: correct += 1 else: print(f"失败:{case['input']} 期望 {case['expected']} 实际 {actual}")

跑完测试后,如果准确率没有下降甚至上升,说明精简成功。如果某个工具准确率下降明显,就回到第三步,针对性补回必要信息。

4. 扩展作者视角:从设计层面让工具提示词天然精简

4.1 工具命名比描述更重要

如果你是扩展作者,最应该花时间的地方不是写描述,而是设计工具名和参数名。一个好的工具名能让描述缩短一半以上。

我总结了几条命名原则:

  • 工具名用“动词加名词”结构,如get_weather、create_session、delete_file
  • 避免缩写和内部术语,如qry_wthr这种名字模型很难理解
  • 参数名用完整单词,如city而不是c,start_date而不是sd
  • 布尔参数用is_或enable_前缀,如is_recursive

遵循这些原则后,工具描述可以压缩到极致。比如get_weather(city)这个签名,模型看到就能理解,描述只需要写“查询指定城市的当前天气”即可,甚至“当前”两个字都可以根据业务需要决定是否保留。

4.2 用参数枚举替代文字说明

很多工具描述里会写“参数 X 可选值为 A、B、C”,这其实可以放到参数定义里,而不是描述里。Pi Agent 的工具定义通常支持枚举类型,把可选值写在参数 schema 里,模型同样能读到,而且更结构化。

改造前:

设置日志级别。参数 level 可选值为 debug、info、warn、error, 分别表示调试、信息、警告、错误。

改造后,描述只写“设置日志级别”,参数 schema 里定义:

{ "name": "level", "type": "string", "enum": ["debug", "info", "warn", "error"] }

这样描述从 40 字降到 6 字,信息量没有损失。

4.3 把“什么时候用”交给系统提示词统一管理

单个工具描述里反复写“什么时候用”,是冗余的重灾区。更好的做法是:在系统提示词或AGENTS.md里统一写一段“工具选择原则”,所有工具共享,而不是每个工具重复一遍。

比如统一写:

优先使用专用工具,没有专用工具时再考虑通用工具。 涉及文件删除、数据修改的操作,先确认再执行。

这段文字只写一次,所有工具都受益。单个工具描述里就不需要再写“本工具用于删除文件,请谨慎使用”这类话了。

4.4 版本化你的工具描述,方便回滚和对比

工具描述精简是一个迭代过程,建议用版本管理工具把每次修改记录下来。我通常会在项目里建一个tool_descriptions/目录,每个版本一个文件,配合测试结果一起存档。这样如果某次精简导致准确率下降,可以快速定位是哪次修改引入的问题。

一个简单的目录结构:

tool_descriptions/ v1_original.md v2_lean.md v3_lean_fixed.md test_results/ v1_results.json v2_results.json v3_results.json

每次修改后跑测试,把结果存到对应版本目录。这样你不仅知道“改了什么”,还知道“改完效果如何”,决策有据可依。

5. 常见问题与排查技巧实录

5.1 精简后模型不调用工具了怎么办

这是最常见的问题。原因通常是描述删得过头,模型无法判断这个工具是否适用于当前任务。排查思路:

  • 先检查工具名是否足够表意。如果工具名是process这种模糊词,模型很难判断用途,需要补回一句用途说明。
  • 再检查是否有同类工具竞争。如果有两个工具功能相近,描述里需要点明区别,比如“查询当前天气”和“查询未来天气”要明确区分。
  • 最后检查系统提示词里是否有“优先使用某类工具”的指令,如果有,可能压制了其他工具的调用。

我的经验是:用途说明保留一句话,通常就能解决 90% 的不调用问题。如果还不行,再补参数说明。

5.2 精简后模型调用错工具怎么办

调用错工具通常是因为工具之间的边界不清晰。解决办法不是加长描述,而是在工具名和参数上做区分。比如get_weather和get_forecast,如果描述都写“查询天气”,模型容易混。改成get_current_weather和get_weather_forecast,名字本身就把边界划清了。

如果改名成本太高,可以在描述里加一句区分说明,比如“仅查询当前天气,不含未来预报”。这句话虽然增加了字数,但能显著降低混淆率,属于“必要的例外”。

5.3 精简后响应变快但准确率波动怎么办

准确率波动通常是因为测试集不够大,或者测试场景覆盖不全。建议把测试集扩充到 50 条以上,覆盖以下场景:

  • 典型场景:用户明确提到工具功能相关的关键词
  • 边界场景:用户表述模糊,需要模型推断
  • 干扰场景:用户提到多个工具相关的关键词,需要模型选择
  • 否定场景:用户询问的内容不应该触发任何工具

跑完测试后,如果准确率波动在 5% 以内,属于正常范围;如果超过 10%,需要针对性排查。

5.4 常见问题速查表

问题现象可能原因排查方法解决措施
工具不被调用描述过短,用途不明检查工具名是否表意补回一句用途说明
调用错工具工具边界不清对比同类工具描述改名或加区分说明
参数传错参数歧义未消解检查参数名和枚举补回参数说明
响应变慢描述仍然过长统计总 token 数继续精简非必要内容
准确率波动测试集不足扩充测试用例覆盖更多边界场景

5.5 一个容易被忽略的坑:描述里的“否定句”

很多人喜欢在工具描述里写“不要用于 X 场景”。这种否定句在模型看来是弱约束,效果往往不如正面表述。比如“不要用于查询未来天气”,不如改成“仅查询当前天气”。正面表述让模型更容易判断适用边界,否定表述则容易让模型在“不要”和“要”之间产生混淆。

我在实际项目中把否定句全部改成正面表述后,误调用率下降了大约 6 个百分点。这个改动很小,但效果很稳。

6. 我个人的精简心得与后续扩展方向

踩过几次坑之后,我现在写工具描述基本遵循一个固定流程:先写一句话用途,跑测试,如果没问题就不再加字;如果有问题,只补最必要的那一句。这样下来,新项目的工具描述平均长度控制在 20 字以内,准确率反而比早期写 200 字的时候高出一大截。

有一个小技巧我一直在用:把工具描述读给一个不了解项目的人听,如果他能立刻说出这个工具是干什么的,说明描述够了;如果他说“没听懂”,说明还缺关键信息。这个“人肉测试”比跑模型还快,适合在写描述时快速自检。

后续如果工具数量继续增加,我打算把工具按领域分组,每组共享一段简短的领域说明,单个工具描述进一步压缩到 10 字以内。比如天气类工具共享“天气相关操作”一句,每个工具只写“查询当前”“查询预报”这样的极短描述。这样总提示词还能再降一截,同时保持模型对工具边界的清晰认知。

另外,AGENTS.md里的工具索引也可以动态生成,而不是手写维护。我写了一个小脚本,从工具定义文件里自动提取工具名和一句话用途,生成AGENTS.md的工具列表部分。这样每次增删工具,索引自动更新,不会出现“描述和实际工具不一致”的问题。这个脚本大概 30 行代码,用 Python 或 Node.js 都能写,核心逻辑就是遍历工具定义、提取字段、按模板输出。如果你也在维护多个工具,强烈建议做这个自动化,省心很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询