前言
今天使用的时候刚好遇到了服务端 400 的报错,如下图。
经过排查和 ToolSearch 有关系,Kimi 官方建议使用 Claude Code 的时候不能开启 ToolSearch。
什么是 ToolSearch?为什么不能开启?随着我慢慢排查,捋清楚了 ToolSearch 的流程。
我的排查过程
前提条件
为了 LLM 的可观测性,可 debug,我部署了 newAPI,我本地的 agent 的 provider 都走自己的 newAPI 网关,保存 LLM 调用的 request 和 response,把 log 都保存到了我的磁盘上。
对比前一条请求
我之前写了一个 skill 去 debug,主要是为了 diff 两个 request,看前缀 prompt 是否稳定。用这个 skill 去查询我的本地 log,找到报错的请求和前一条成功的请求后,给出的 diff 结果是这样的
这里 messages 追加了 3 条,另外 tools 中增加了一个 TaskCreate,难道是因为这个增加的 tool?具体新增的这个 tool 是这样定义的:
1 | { |
这个TaskCreate标记为延迟加载,能从字面上理解是后续加载的工具,不是一开始就加载的。
再看具体的messages
新增的三条 message 是这样的:
assistant的tool_use决定使用ToolSearch工具去查询TaskCreate这个工具(这条消息是LLM生成的)user的tool_result返回了type是tool_reference的工具TaskCreate- 运行时新增一条
system prompt,简单提示 Task 的一套工具如何使用猜测是 Anthropic 的实践下来的经验,也算是一种
prompt engineering了,在 LLM 首次使用一套工具时,插入一条prompt让 LLM 理解这一套工具的用法。
1 | { |
也就是说之前的 TaskCreate 工具是 LLM 用 ToolSearch 工具搜索出来的,搜索出来后,加入 tools 列表。
缓存是否有问题?
这里其实就明白大概是 ToolSearch 的问题了,但是又引出了疑问:
按照我之前的理解,提示词缓存的顺序是
tools + system prompt + messages,如果延迟工具添加以后,难道不会破坏缓存吗?
官方文档的prompt caching章节还真有解释:
- 延迟工具:不会影响缓存
- 在一些情况下,是会影响缓存的!其中就有
custom gateway,也就是接入第三方模型的时候。
为什么不能开启 ToolSearch
这个问题的答案也就清楚了:
- Claude Code 的
ToolSearch允许延迟加载工具到上下文中,但是会加入一种特殊的标记tool_reference,要求服务端识别,并且不把延迟加载的工具放在前缀中,不然影响缓存。 - 第三方服务端如果不适配,那么
tools前缀就会影响缓存。Kimi的选择是不适配这个功能,建议不开启ToolSearch,服务内部不认识tool_referrence,因此 Kimi 的服务端则直接返回了 400 的错误。
完整的 ToolSearch 流程
ToolSearch在系统提示词中的描述
为了节省上下文空间,有一些工具的使用方式不会被Claude Code加载到上下文中,在系统提示词中告诉 LLM 可以用 ToolSearch 这个工具去搜索,这些工具就是 deferred tools,以下就是这段系统提示词:
1 | The following deferred tools are now available via ToolSearch. Their schemas are NOT loaded — calling them directly will fail with InputValidationError. Use ToolSearch with query "select:<name>[,<name>...]" to load tool schemas before calling them: |
ToolSearch调用过程
CC 客户端和 Claude 服务端交互的 JSON 大致如下:
1 | { |
- Claude 服务端的行为:
- LLM推理的时候,认为自己要用TaskCreate这个工具了,但是不会用,具体的description和input_schema并没有在tools列表中。想起系统提示词中需要用
ToolSearch。 - 因此,推理中,就在后续messages中添加一条消息,给CC客户端返回一个
tool_use,决定使用ToolSearch工具去查询TaskCreate的具体信息。
- LLM推理的时候,认为自己要用TaskCreate这个工具了,但是不会用,具体的description和input_schema并没有在tools列表中。想起系统提示词中需要用
- CC 客户端做了三件事情:
- 在messages中构造第一条消息,返回
tool_result,表示找到了TaskCreate这个工具,类型是tool_reference。 - 构造第二条消息,是一条system prompt,简单提示TaskXXX这一套工具如何使用
- 在
tools添加TaskCreate的具体说明,并标注是延迟工具。
- 在messages中构造第一条消息,返回
- Claude 服务端:
会处理tools列表,将新增的deferred tool从tools中拿出来,防止影响prompt cache,在messages追加deferred tool的用法。