工具调用¶
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
接下来,发起一个请求以触发模型使用可用工具:
Code
from openai import OpenAI
import json
client = OpenAI(base_url="http://localhost: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模式定义的工具参数对象相匹配。为了获得最佳效果,我们建议在提示中明确指定预期的输出格式/模式,以确保模型的预期生成与引导式解码后端强制生成的模式保持一致。
要使用命名函数,您需要在聊天补全请求的tools参数中定义函数,并在聊天补全请求的tool_choice参数中指定其中一个工具的name。
必需的功能调用¶
vLLM支持聊天完成API中的tool_choice='required'选项。与命名函数调用类似,它也使用引导式解码,因此默认启用该功能,并适用于所有支持的模型。目前tool_choice='required'的引导式解码功能(如带有anyOf的JSON模式)仅在V0引擎中通过outlines引导解码后端获得支持。不过,对替代解码后端的支持已列入V1引擎的roadmap计划。
当设置tool_choice='required'时,模型将确保根据tools参数中指定的工具列表生成一个或多个工具调用。工具调用的数量取决于用户的查询。输出格式严格遵循tools参数中定义的架构。
无函数调用¶
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生成的ID要短得多。由于不满足此条件时会抛出异常,因此提供了以下额外的聊天模板:- 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 {see_above}
VLLM 还为 Llama 4 提供了基于 Python 和 JSON 的聊天模板,但推荐使用 Python 工具调用:
- 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.jinjaexamples/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.jinjaexamples/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-Miniai21labs/AI21-Jamba-1.5-Large
标志参数: --tool-call-parser jamba
xLAM 模型 (xlam)¶
xLAM工具解析器旨在支持生成各种JSON格式工具调用的模型。它能检测多种不同输出风格中的函数调用:
- 直接输出JSON数组:输出以
[开头并以]结尾的JSON数组字符串 - 思考标签:使用包含JSON数组的
标签... - 代码块:JSON代码块中的内容(
json ...) - 工具调用标签:使用
[TOOL_CALLS]或标签...
支持并行函数调用,解析器能有效分离文本内容与工具调用。
支持的模型:
- 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 {see_above}
Kimi-K2 模型 (kimi_k2)¶
支持的模型:
moonshotai/Kimi-K2-Instruct
参数选项: --tool-call-parser kimi_k2
混元模型 (hunyuan_a13b)¶
支持的模型:
tencent/Hunyuan-A13B-Instruct(聊天模板已包含在Hugging Face模型文件中。)
标志:
- 对于非推理场景:
--tool-call-parser hunyuan_a13b - 用于推理:
--tool-call-parser hunyuan_a13b --reasoning-parser hunyuan_a13b --enable_reasoning
支持Python工具调用的模型 (pythonic)¶
越来越多的模型输出Python列表来表示工具调用,而不是使用JSON。这样做的好处是天然支持并行工具调用,并消除了工具调用所需的JSON模式歧义。pythonic工具解析器可以支持此类模型。
举个具体例子,这些模型可以通过生成以下内容来查询旧金山和西雅图的天气:
[get_weather(city='San Francisco', metric='celsius'), get_weather(city='Seattle', metric='celsius')]
限制:
- 模型在同一代生成中不得同时生成文本和工具调用。对于特定模型来说,这可能不难修改,但社区目前对开始和结束工具调用时应发出哪些标记尚未达成共识。(特别是Llama 3.2模型没有发出此类标记。)
- 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 {see_above}
警告
Llama的小型模型经常无法以正确格式发出工具调用。结果可能因模型而异。
如何编写工具解析器插件¶
工具解析器插件是一个包含一个或多个ToolParser实现的Python文件。您可以编写一个类似于 vllm/entrypoints/openai/tool_parsers/hermes_tool_parser.py中Hermes2ProToolParser的ToolParser。
以下是一个插件文件的摘要:
Code
# 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)
然后你就可以像这样在命令行中使用这个插件。