工具调用¶
vLLM 目前支持指定函数调用,以及聊天补全 API 中 tool_choice
字段的 auto
、required
(自 vllm>=0.8.3
起) 和 none
选项。
快速入门¶
启动工具调用已启用的服务器。此示例使用 Meta 的 Llama 3.1 8B 模型,因此我们需要使用 vLLM 示例目录中的 llama3_json
工具调用聊天模板。
vllm serve meta-llama/Llama-3.1-8B-Instruct \
--enable-auto-tool-choice \
--tool-call-parser llama3_json \
--chat-template examples/tool_chat_template_llama3.1_json.jinja
接下来,发送一个请求,触发模型使用可用工具。
代码
from openai import OpenAI
import json
client = OpenAI(base_url="https://:8000/v1", api_key="dummy")
def get_weather(location: str, unit: str):
return f"Getting the weather for {location} in {unit}..."
tool_functions = {"get_weather": get_weather}
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City and state, e.g., 'San Francisco, CA'"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location", "unit"]
}
}
}]
response = client.chat.completions.create(
model=client.models.list().data[0].id,
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
tools=tools,
tool_choice="auto"
)
tool_call = response.choices[0].message.tool_calls[0].function
print(f"Function called: {tool_call.name}")
print(f"Arguments: {tool_call.arguments}")
print(f"Result: {tool_functions[tool_call.name](**json.loads(tool_call.arguments))}")
示例输出
Function called: get_weather
Arguments: {"location": "San Francisco, CA", "unit": "fahrenheit"}
Result: Getting the weather for San Francisco, CA in fahrenheit...
此示例演示了:
- 启用工具调用来设置服务器
- 定义一个实际函数来处理工具调用
- 发送带有
tool_choice="auto"
的请求 - 处理结构化响应并执行相应的函数
你还可以通过设置 tool_choice={"type": "function", "function": {"name": "get_weather"}}
来指定一个特定的函数,这称为指定函数调用。请注意,这将使用引导式解码后端——因此首次使用时,在 FSM 首次编译并缓存以供后续请求使用之前,会有几秒(或更长)的延迟。
请记住,调用者有责任:
- 在请求中定义适当的工具
- 在聊天消息中包含相关上下文
- 在应用程序逻辑中处理工具调用
有关更高级的用法,包括并行工具调用和不同模型特定的解析器,请参阅以下部分。
指定函数调用¶
vLLM 默认支持聊天补全 API 中的指定函数调用。它通过引导式解码使用 Outlines 实现此功能,因此默认启用,并且适用于任何受支持的模型。你可以保证得到一个可有效解析的函数调用——而非一个高质量的函数调用。
vLLM 将使用引导式解码来确保响应与 tools
参数中 JSON schema 定义的工具参数对象匹配。为了获得最佳结果,我们建议确保在提示中指定预期的输出格式/schema,以确保模型的预期生成与引导式解码后端强制生成的 schema 对齐。
要使用指定函数,你需要在聊天补全请求的 tools
参数中定义函数,并在聊天补全请求的 tool_choice
参数中指定其中一个工具的 name
。
强制函数调用¶
vLLM 支持聊天补全 API 中的 tool_choice='required'
选项。与指定函数调用类似,它也使用引导式解码,因此默认启用并适用于任何受支持的模型。tool_choice='required'
的引导式解码功能(例如带有 anyOf
的 JSON schema)目前仅在 V0 引擎中与引导式解码后端 outlines
一起支持。但是,对替代解码后端的支持已列入 V1 引擎的路线图。
当设置 tool_choice='required'
时,模型保证根据 tools
参数中指定的工具列表生成一个或多个工具调用。工具调用的数量取决于用户的查询。输出格式严格遵循 tools
参数中定义的 schema。
无函数调用¶
vLLM 支持聊天补全 API 中的 tool_choice='none'
选项。当设置此选项时,即使请求中定义了工具,模型也不会生成任何工具调用,而只会响应常规文本内容。
注意
当请求中指定了工具时,vLLM 默认会在提示中包含工具定义,无论 tool_choice
设置如何。要在 tool_choice='none'
时排除工具定义,请使用 --exclude-tools-when-tool-choice-none
选项。
自动函数调用¶
要启用此功能,你应该设置以下标志:
--enable-auto-tool-choice
-- 强制 自动工具选择。它告诉 vLLM 你希望模型在认为适当的时候生成自己的工具调用。--tool-call-parser
-- 选择要使用的工具解析器(如下所列)。未来将继续添加更多的工具解析器。你也可以在--tool-parser-plugin
中注册你自己的工具解析器。--tool-parser-plugin
-- 可选 工具解析器插件,用于将用户定义的工具解析器注册到 vLLM 中,注册的工具解析器名称可以在--tool-call-parser
中指定。--chat-template
-- 可选 自动工具选择。这是聊天模板的路径,该模板处理tool
角色消息和包含先前生成的工具调用的assistant
角色消息。Hermes、Mistral 和 Llama 模型在其tokenizer_config.json
文件中包含兼容工具调用的聊天模板,但你可以指定自定义模板。如果你的模型在tokenizer_config.json
中配置了特定于工具使用的聊天模板,此参数可以设置为tool_use
。在这种情况下,它将根据transformers
规范使用。有关此内容的更多信息,请参阅 HuggingFace 的此处;你可以在tokenizer_config.json
中找到一个示例,请参阅此处。
如果你喜欢的工具调用模型不受支持,请随时贡献一个解析器和工具使用聊天模板!
Hermes 模型 (hermes
)¶
所有比 Hermes 2 Pro 更新的 Nous Research Hermes 系列模型都应该受支持。
NousResearch/Hermes-2-Pro-*
NousResearch/Hermes-2-Theta-*
NousResearch/Hermes-3-*
请注意,Hermes 2 Theta 模型由于其创建过程中的合并步骤,已知其工具调用质量和功能有所下降。.
标志: --tool-call-parser hermes
Mistral 模型 (mistral
)¶
支持的模型:
mistralai/Mistral-7B-Instruct-v0.3
(已确认)- 其他 Mistral 函数调用模型也兼容。
已知问题:
- Mistral 7B 难以正确生成并行工具调用。
-
Mistral 的
tokenizer_config.json
聊天模板要求工具调用 ID 恰好为 9 位数字,这比 vLLM 生成的短得多。由于不满足此条件时会抛出异常,因此提供了以下附加聊天模板:- examples/tool_chat_template_mistral.jinja - 这是“官方”Mistral 聊天模板,但经过调整,使其与 vLLM 的工具调用 ID 兼容(前提是
tool_call_id
字段被截断为最后 9 位数字) - examples/tool_chat_template_mistral_parallel.jinja - 这是一个“更好”的版本,在提供工具时添加了工具使用系统提示,从而在并行工具调用方面提高了可靠性。
- examples/tool_chat_template_mistral.jinja - 这是“官方”Mistral 聊天模板,但经过调整,使其与 vLLM 的工具调用 ID 兼容(前提是
推荐标志: --tool-call-parser mistral --chat-template examples/tool_chat_template_mistral_parallel.jinja
Llama 模型 (llama3_json
)¶
支持的模型:
所有 Llama 3.1、3.2 和 4 模型都应该受支持。
meta-llama/Llama-3.1-*
meta-llama/Llama-3.2-*
meta-llama/Llama-4-*
支持的工具调用是基于 JSON 的工具调用。对于 Llama-3.2 模型引入的Pythonic 工具调用,请参阅下面的 pythonic
工具解析器。至于 Llama 4 模型,建议使用 llama4_pythonic
工具解析器。
其他工具调用格式,如内置的 Python 工具调用或自定义工具调用,不受支持。
已知问题:
- Llama 3 不支持并行工具调用,但 Llama 4 模型支持。
- 模型可能生成格式不正确的参数,例如将数组序列化为字符串而不是数组。
VLLM 为 Llama 3.1 和 3.2 提供了两个基于 JSON 的聊天模板:
- examples/tool_chat_template_llama3.1_json.jinja - 这是 Llama 3.1 模型的“官方”聊天模板,但经过调整,使其与 vLLM 更好地配合。
- examples/tool_chat_template_llama3.2_json.jinja - 这在 Llama 3.1 聊天模板的基础上增加了对图像的支持。
推荐标志: --tool-call-parser llama3_json --chat-template {见上方}
VLLM 还为 Llama 4 提供了 Pythonic 和基于 JSON 的聊天模板,但推荐使用 Pythonic 工具调用。
- examples/tool_chat_template_llama4_pythonic.jinja - 这是基于 Llama 4 模型的官方聊天模板。
对于 Llama 4 模型,使用 --tool-call-parser llama4_pythonic --chat-template examples/tool_chat_template_llama4_pythonic.jinja
。
IBM Granite¶
支持的模型:
-
ibm-granite/granite-3.0-8b-instruct
推荐标志:
--tool-call-parser granite --chat-template examples/tool_chat_template_granite.jinja
examples/tool_chat_template_granite.jinja:这是一个修改过的聊天模板,与 Hugging Face 上的原始模板不同。支持并行函数调用。
-
ibm-granite/granite-3.1-8b-instruct
推荐标志:
--tool-call-parser granite
可以直接使用 Huggingface 上的聊天模板。支持并行函数调用。
-
ibm-granite/granite-20b-functioncalling
推荐标志:
--tool-call-parser granite-20b-fc --chat-template examples/tool_chat_template_granite_20b_fc.jinja
examples/tool_chat_template_granite_20b_fc.jinja:这是修改自 Hugging Face 上的原始聊天模板,与 vLLM 不兼容。它融合了 Hermes 模板中的函数描述元素,并遵循论文中“响应生成”模式的相同系统提示。支持并行函数调用。
InternLM 模型 (internlm
)¶
支持的模型:
internlm/internlm2_5-7b-chat
(已确认)- 其他 InternLM2.5 函数调用模型也兼容。
已知问题:
- 尽管此实现也支持 InternLM2,但在使用
internlm/internlm2-chat-7b
模型进行测试时,工具调用结果不稳定。
推荐标志: --tool-call-parser internlm --chat-template examples/tool_chat_template_internlm2_tool.jinja
Jamba 模型 (jamba
)¶
AI21 的 Jamba-1.5 模型受支持。
ai21labs/AI21-Jamba-1.5-Mini
ai21labs/AI21-Jamba-1.5-Large
标志: --tool-call-parser jamba
xLAM 模型 (xlam
)¶
xLAM 工具解析器旨在支持以各种 JSON 格式生成工具调用的模型。它检测多种不同输出风格的函数调用:
- 直接 JSON 数组:以
[
开头和以]
结尾的 JSON 数组输出字符串 - 思考标签:使用包含 JSON 数组的
<think>...</think>
标签 - 代码块:代码块中的 JSON (
json ...
) - 工具调用标签:使用
[TOOL_CALLS]
或<tool_call>...</tool_call>
标签
支持并行函数调用,解析器可以有效地将文本内容与工具调用分离。
支持的模型:
- Salesforce Llama-xLAM 模型:
Salesforce/Llama-xLAM-2-8B-fc-r
,Salesforce/Llama-xLAM-2-70B-fc-r
- Qwen-xLAM 模型:
Salesforce/xLAM-1B-fc-r
,Salesforce/xLAM-3B-fc-r
,Salesforce/Qwen-xLAM-32B-fc-r
标志:
- 对于基于 Llama 的 xLAM 模型:
--tool-call-parser xlam --chat-template examples/tool_chat_template_xlam_llama.jinja
- 对于基于 Qwen 的 xLAM 模型:
--tool-call-parser xlam --chat-template examples/tool_chat_template_xlam_qwen.jinja
Qwen 模型¶
对于 Qwen2.5,tokenizer_config.json
中的聊天模板已包含对 Hermes 风格工具使用的支持。因此,你可以使用 hermes
解析器为 Qwen 模型启用工具调用。有关详细信息,请参阅Qwen 官方文档。
Qwen/Qwen2.5-*
Qwen/QwQ-32B
标志: --tool-call-parser hermes
MiniMax 模型 (minimax_m1
)¶
支持的模型:
MiniMaxAi/MiniMax-M1-40k
(配合 examples/tool_chat_template_minimax_m1.jinja使用)MiniMaxAi/MiniMax-M1-80k
(配合 examples/tool_chat_template_minimax_m1.jinja使用)
标志: --tool-call-parser minimax --chat-template examples/tool_chat_template_minimax_m1.jinja
DeepSeek-V3 模型 (deepseek_v3
)¶
支持的模型:
deepseek-ai/DeepSeek-V3-0324
(配合 examples/tool_chat_template_deepseekv3.jinja使用)deepseek-ai/DeepSeek-R1-0528
(配合 examples/tool_chat_template_deepseekr1.jinja使用)
标志: --tool-call-parser deepseek_v3 --chat-template {见上方}
Kimi-K2 模型 (kimi_k2
)¶
支持的模型:
moonshotai/Kimi-K2-Instruct
标志: --tool-call-parser kimi_k2
Hunyuan 模型 (hunyuan_a13b
)¶
支持的模型:
tencent/Hunyuan-A13B-Instruct
(聊天模板已包含在 Hugging Face 模型文件中。)
标志:
- 对于非推理:
--tool-call-parser hunyuan_a13b
- 对于推理:
--tool-call-parser hunyuan_a13b --reasoning-parser hunyuan_a13b --enable_reasoning
支持 Pythonic 工具调用的模型 (pythonic
)¶
越来越多的模型输出 Python 列表来表示工具调用,而不是使用 JSON。这具有固有地支持并行工具调用和消除工具调用所需 JSON schema 模糊性的优点。pythonic
工具解析器可以支持此类模型。
举一个具体的例子,这些模型可以通过生成以下内容来查询旧金山和西雅图的天气:
[get_weather(city='San Francisco', metric='celsius'), get_weather(city='Seattle', metric='celsius')]
限制
- 模型不得在同一生成中同时生成文本和工具调用。对于特定模型而言,这可能不难改变,但社区目前尚未就何时开始和结束工具调用时应发出哪些 token 达成共识。(特别是 Llama 3.2 模型不发出此类 token。)
- Llama 的小型模型难以有效使用工具。
示例受支持的模型:
meta-llama/Llama-3.2-1B-Instruct
⚠️ (配合 examples/tool_chat_template_llama3.2_pythonic.jinja使用)meta-llama/Llama-3.2-3B-Instruct
⚠️ (配合 examples/tool_chat_template_llama3.2_pythonic.jinja使用)Team-ACE/ToolACE-8B
(配合 examples/tool_chat_template_toolace.jinja使用)fixie-ai/ultravox-v0_4-ToolACE-8B
(配合 examples/tool_chat_template_toolace.jinja使用)meta-llama/Llama-4-Scout-17B-16E-Instruct
⚠️ (配合 examples/tool_chat_template_llama4_pythonic.jinja使用)meta-llama/Llama-4-Maverick-17B-128E-Instruct
⚠️ (配合 examples/tool_chat_template_llama4_pythonic.jinja使用)
标志: --tool-call-parser pythonic --chat-template {见上方}
警告
Llama 的小型模型经常无法以正确格式发出工具调用。结果可能因模型而异。
如何编写工具解析器插件¶
工具解析器插件是一个 Python 文件,包含一个或多个 ToolParser 实现。你可以编写一个类似于 vllm/entrypoints/openai/tool_parsers/hermes_tool_parser.py 中的 Hermes2ProToolParser
。
以下是插件文件的摘要:
代码
# import the required packages
# define a tool parser and register it to vllm
# the name list in register_module can be used
# in --tool-call-parser. you can define as many
# tool parsers as you want here.
@ToolParserManager.register_module(["example"])
class ExampleToolParser(ToolParser):
def __init__(self, tokenizer: AnyTokenizer):
super().__init__(tokenizer)
# adjust request. e.g.: set skip special tokens
# to False for tool call output.
def adjust_request(
self, request: ChatCompletionRequest) -> ChatCompletionRequest:
return request
# implement the tool call parse for stream call
def extract_tool_calls_streaming(
self,
previous_text: str,
current_text: str,
delta_text: str,
previous_token_ids: Sequence[int],
current_token_ids: Sequence[int],
delta_token_ids: Sequence[int],
request: ChatCompletionRequest,
) -> Union[DeltaMessage, None]:
return delta
# implement the tool parse for non-stream call
def extract_tool_calls(
self,
model_output: str,
request: ChatCompletionRequest,
) -> ExtractedToolCallInformation:
return ExtractedToolCallInformation(tools_called=False,
tool_calls=[],
content=text)
然后你可以在命令行中使用此插件,如下所示: