跳转到主要内容
工具调用 tool_calls 让 Kimi 大模型从“说”进化到“做”:模型根据对话上下文决定是否调用工具、以 JSON 格式生成调用参数,由你的应用执行工具并回传结果,模型再基于结果生成最终回复。借助 tool_calls,Kimi 大模型能帮你搜索互联网内容、查询数据库,甚至操作智能家居。本页用一个联网搜索案例走通从定义、注册到执行的完整流程,并覆盖流式输出等场景的注意事项。

一次工具调用的完整流程

一次工具调用 tool_calls 包含以下步骤:
  1. 使用 JSON Schema 格式定义工具;
  2. 通过 tools 参数将定义好的工具提交给 Kimi 大模型,你可以一次性提交多个工具;
  3. Kimi 大模型会根据当前聊天的上下文,决定使用哪个或哪几个工具,Kimi 大模型也可以选择不使用工具;
  4. Kimi 大模型会将调用工具所需要的参数和信息通过 JSON 格式输出;
  5. 使用 Kimi 大模型输出的参数,执行对应的工具,并将工具执行结果提交给 Kimi 大模型;
  6. Kimi 大模型根据工具执行结果,给予用户回复;
如果你的应用需要挂载大量工具(几十上百个),建议使用动态加载工具按需注入工具定义,而不是一次性全部提交——可以显著降低 token 消耗并提升工具选择的准确率。

用工具调用让模型学会联网搜索

Kimi 大模型的知识来源于训练数据,无法回答时效性强的问题。下面用“搜索引擎”和“网页浏览器”两个工具,演示如何让模型自己搜索最新知识并据此作答。

用 JSON Schema 定义工具

人在网上查资料时,通常先打开搜索引擎(例如百度或必应)搜索内容、浏览搜索结果,再打开一个或多个结果网页获取需要的知识。把这两个动作抽象成工具,就是“搜索引擎”和“网页浏览器”——用 JSON Schema 描述后提交给 Kimi 大模型,它就能和人一样搜索并浏览网页。 工具定义使用 JSON Schema 格式编写:
JSON Schema is a vocabulary that you can use to annotate and validate JSON documents. JSON Schema 是一种用于描述 JSON 数据格式的 JSON 文档。
我们定义以下 JSON Schema:
这个 JSON Schema 定义了一个 JSON Object,这个 JSON Object 中包含了一个名为 name 的字段,并且该字段的类型为 string,例如:
通过 JSON Schema 来描述我们的工具定义,能让 Kimi 大模型更清晰和直观地知道我们的工具需要哪些参数,以及每个参数的类型和介绍。接下来让我们来定义前文提到的“搜索引擎”和“网页浏览器”这两个工具:
在使用 JSON Schema 定义工具时,我们使用以下固定的格式来定义一个工具:
其中,namedescriptionparameters.properties 由工具提供方定义,其中 description 描述了工具的具体作用、以及在什么场合需要使用工具,parameters 描述了成功调用工具所需要的具体参数,包括参数类型、参数介绍等;最终,Kimi 大模型会根据 JSON Schema 的定义,生成一个满足定义要求的 JSON Object 作为工具调用的参数(arguments)。

把工具注册给模型

search 工具提交给 Kimi 大模型,看看它能否正确调用工具:
本页示例默认使用最新模型 kimi-k3。K3 使用顶层 reasoning_effort(当前仅支持 "max")。换用 kimi-k2.6kimi-k2.5 等其他模型时,只需替换 model 字段,但各模型的参数配置存在差异,详见模型参数参考
代码运行成功后,模型返回如下内容:
finish_reasontool_calls 表示本次返回的不是模型回复,而是模型选择执行工具——可以通过 finish_reason 的值判断当前回复是否是一次工具调用。 此时 message 中的 content 为空,因为模型还在执行 tool_calls,尚未生成面向用户的回复;新增的 tool_calls 字段是一个列表,包含本次需要调用的所有工具调用信息——这说明 模型可以一次性选择多个工具进行调用,可以是多个不同的工具,也可以是相同工具使用不同参数进行调用tool_calls 中每个元素都代表一次工具调用:模型为每次调用生成唯一的 id,用 function.name 表明工具函数名称,把执行参数放在 function.arguments 中(arguments 是合法的、被序列化的 JSON Object;type 目前是固定值 function)。 接下来,用模型生成的工具调用参数去执行具体的工具。

执行工具并回传结果

Kimi 大模型不会替你执行工具——收到模型生成的参数后,需要由你的应用自行执行。为什么模型不自己执行工具?设想一个典型场景: 你向用户提供一个基于 Kimi 大模型的智能机器人,在这个场景有三个角色:用户、机器人、Kimi 大模型。用户向机器人提问,机器人调用 Kimi 大模型 API,并将 API 的结果返回给用户。当使用 tool_calls 时,用户向机器人提问,机器人带着 tools 调用 Kimi API,Kimi 大模型返回 tool_calls 参数,机器人执行完 tool_calls,将结果再次提交给 Kimi API,Kimi 大模型生成返回给用户的消息(finish_reason=stop),此时机器人才会把消息返回给用户。 整个 tool_calls 过程对用户而言是透明、隐式的:用户并不直接“看到”工具调用,只看到机器人返回的最终回复。 下面的完整示例以“机器人”的视角执行模型返回的 tool_calls,演示工具执行循环:
我们使用 while 循环来执行包含工具调用在内的代码逻辑,这是因为 Kimi 大模型通常不会只执行一次工具调用,尤其是在联网搜索这个场景,通常,Kimi 大模型会先选择调用 search 工具,通过 search 工具获取搜索结果后,再调用 crawl 工具将搜索结果中的 url 转换为具体的网页内容,整体的 messages 结构如下所示:
至此,我们完成了“联网查询”工具调用的全过程,如果你实现了自己的 searchcrawl 方法,那么当你向 Kimi 大模型要求联网查询时,它会调用 searchcrawl 两个工具,并根据工具调用结果给予你正确的回复。

处理流式输出中的 tool_calls

流式输出模式(stream)下,tool_calls 同样适用,但有几点需要额外注意:
  • 在流式输出的过程中,由于 finish_reason 将会在最后的数据块中出现,因此建议使用 delta.tool_calls 字段是否存在来判断当前回复是否包含工具调用;
  • 在流式输出的过程中,会先输出 delta.content,再输出 delta.tool_calls,因此你必须等待 delta.content 输出完成后,才能判断和识别 tool_calls
  • 在流式输出的过程中,我们会在最初的数据块中,指明当前调用 tool_callstool_call.idtool_call.function.name,在后续的数据块中将只输出 tool_call.function.arguments
  • 在流式输出的过程中,如果 Kimi 大模型一次性返回多个 tool_calls,那么我们会额外使用一个名为 index 的字段来标识当前 tool_call 的索引,以便于你能正确拼接 tool_call.function.arguments 参数,我们使用流式输出章节中的代码例子(不使用 SDK 的场合)来说明如何操作:
以下是使用 openai SDK 处理流式输出中的 tool_calls 的代码示例:

用 tool_calls 代替 function_call

tool_calls 由函数调用(function_call)进化而来,function_calltool_calls 的子集——在某些特定语境下,或阅读兼容性代码时,可以将两者划等号。由于 OpenAI 已将 function_call 等参数(例如 functions)标记为“已废弃”,我们的 API 将不再支持 function_call,请用 tool_calls 代替。相比 function_calltool_calls 有以下优点:
  • 支持并行调用,Kimi 大模型可以一次返回多个 tool_calls,你可以在代码中使用并发的方式同时调用这些 tool_call 以减少时间消耗;
  • 对于没有依赖关系的 tool_calls,Kimi 大模型也会倾向于并行调用,这相比于原顺序调用的 function_call,在一定程度上降低了 Tokens 消耗;

注意事项

  • finish_reason=tool_calls 时,message.content 偶尔不为空:通常是模型在解释需要调用哪些工具、为什么调用。当工具调用耗时较长,或一轮对话需要串行多次调用工具时,这段描述性语句能减少用户等待的焦虑,也方便用户理解工具调用的流程并及时干预和矫正(例如终止错误的工具调用,或在下一轮对话中通过提示词矫正模型的工具选择);
  • tools 参数中的内容也会被计算在总 Tokens 中,请确保 toolsmessages 中的 Tokens 总数合计不超过模型的上下文窗口大小。

保证每个 tool_call 都有对应的 tool 消息

工具调用场景下,消息不再是 system / user / assistant 的简单交替:
而是会变成:
当 Kimi 大模型生成了 tool_calls 时,请确保每一个 tool_call 都有对应的 role=tool 的 message,并且这条 message 设置了正确的 tool_call_idrole=tool 的 messages 数量与 tool_calls 的数量不一致会导致错误;role=tool 的 messages 中的 tool_call_idtool_calls 中的 tool_call.id 无法对应也会导致错误。

排查 tool_call_id not found 错误

如果你遇到 tool_call_id not found 错误,可能是由于你未将 Kimi API 返回的 role=assistant 消息添加到 messages 列表中,正确的消息序列应该看起来像这样:
你可以在每次收到 Kimi API 的返回值后,都执行 messages.append(message) 来将 Kimi API 返回的消息添加到消息列表中,以避免出现 tool_call_id not found 错误。 注意:添加到 messages 列表中位于 role=tool 的 message 之前的 assistant messages,必须完整包含 Kimi API 返回的 tool_calls 字段及字段值。我们推荐直接将 Kimi API 返回的 choice.message “原封不动”地添加到 messages 列表中,以避免可能产生的错误。