最近在搭一个MCP服务器,打算把几个内部API封装成工具给Claude用。问题是我在系统Prompt里写了很长的工具使用说明,结果模型经常选错工具或者参数传得乱七八糟。试过把工具描述写详细点,但Prompt太长又影响响应速度。也试过让模型先“思考”再调用,但效果不稳定。想知道大家有没有比较实用的做法?比如工具描述的结构、Prompt里该强调什么,或者有没有办法让模型在调用前先确认一下意图?求实战经验,别甩官方文档。
MCP服务器里写Prompt模板,怎么优雅地让LLM自己选择工具?
全部回复
共 46 条工具描述里塞太多规则反而容易让模型晕,我一般只保留“什么时候用”和“必填参数”两块,其他细节靠工具名和参数名自己说话。让模型先确认意图这招我用过,在系统prompt里加一句“不确定就先问用户”,比让它自己闷头选稳多了。另外可以试试把相似工具合并成一个带action参数的工具,减少它纠结的空间。
我之前也踩过这个坑,系统prompt里堆一堆说明,模型反而更容易懵。后来我把每个工具的描述拆成“什么时候用”和“什么时候别用”两块,效果好了不少,尤其是负向边界比正向描述管用。参数那块我建议直接在工具schema里把enum和必填项卡死,别指望prompt里写“请传对格式”,模型该错还是错。至于让它先确认意图,我试过在MCP里加一个confirm工具,模型调用前先走一步,但多一轮交互延迟挺明显的,适合对准确性要求高的场景。还有个野路子是把工具按场景分组,prompt里只暴露当前任务相关的那几个,减少选择空间比写长说明有效得多。你们内部API如果参数复杂,可以考虑包一层适配工具,把脏活留在服务端,别让模型直接面对原始接口。
我踩过类似的坑,后来发现关键是把工具描述和系统Prompt的职责分开。工具描述只写清楚“这个工具干什么、参数是什么、什么场景用”,别塞太多业务逻辑进去,那些放到系统Prompt里用一两句话概括就行。然后我在系统Prompt里会加一个“决策规则”段落,用类似if-else的短句写,比如“用户问天气→调get_weather;问历史订单→调query_orders”,比长篇说明管用得多。还有个技巧是给每个工具加一个“反例”,比如“不要用get_weather查历史温度,那个走get_history”,模型对否定约束反而更敏感。关于调用前确认意图,我试过让模型先输出一个“tool_plan”字段,但经常变成走形式,后来改成在工具调用失败时自动重试并附带错误原因,成功率提升明显。另外工具数量别超过七八个,多了模型就晕,可以按场景拆成多个MCP服务器。最后响应速度问题,精简工具描述比精简系统Prompt更有效,因为工具描述每次都会进上下文。
我踩过类似的坑,后来发现关键不在工具描述写多细,而在描述之间的“区分度”。如果两个工具的功能边界模糊,模型再怎么思考也会摇摆,所以我会刻意让每个工具的description里包含“什么时候不该用它”,这比堆参数说明有用得多。系统Prompt里我也砍掉了大段教程,改成只写两三句路由原则,比如“涉及用户数据优先用X,涉及配置变更一律走Y”,剩下的交给工具自身描述去补。参数传错的问题,我一般会在工具schema里用enum和required卡死,再在描述里给一两个典型调用示例,模型抄样例比理解自然语言稳。至于调用前确认意图,我试过让模型先输出一个简短的plan再触发tool,确实能降错误率,但会多一轮token,看你能不能接受延迟。还有个偏方是把工具按场景分组,别一次性全塞给模型,用的时候动态暴露子集,效果挺明显。
我之前也踩过这个坑,后来把工具描述改成“什么场景下用”而不是“这个工具能干啥”,选错率明显降了。参数乱传的话可以在schema里加enum和必填约束,比在prompt里唠叨管用。另外别指望模型一次想清楚,我是在工具返回里带错误提示让它自己纠正,多轮下来反而稳。
工具描述别堆成说明书,我之前也踩过这坑。把每个工具拆成“干啥用+啥时候用+参数示例”三块,参数最好带个典型值,模型照着套比纯文字描述稳不少。系统prompt里我只留一句“先判断用户意图再选工具”,剩下的交给工具本身的description。另外可以加个“确认工具”做兜底,让模型拿不准时先调它反问一句,比硬猜强。