工具调用#
vLLM 当前支持命名函数调用,以及聊天完成 API 中 tool_choice
字段的 auto
和 none
选项。tool_choice
选项 required
尚不支持,但已 在路线图上。
快速开始#
启动已启用工具调用的服务器。此示例使用 Meta 的 Llama 3.1 8B 模型,因此我们需要使用 vLLM 示例目录中的 llama3 工具调用聊天模板
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://127.0.0.1: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: {get_weather(**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
。
自动函数调用#
要启用此功能,您应该设置以下标志
--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
)#
所有 Nous Research Hermes 系列模型(比 Hermes 2 Pro 新)都应受支持。
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
- 这是一个“更好”的版本,它在提供工具时添加了工具使用系统提示,从而在处理并行工具调用时提高了可靠性。
推荐标志:--tool-call-parser mistral --chat-template examples/tool_chat_template_mistral_parallel.jinja
Llama 模型 (llama3_json
)#
支持的模型
meta-llama/Meta-Llama-3.1-8B-Instruct
meta-llama/Meta-Llama-3.1-70B-Instruct
meta-llama/Meta-Llama-3.1-405B-Instruct
meta-llama/Meta-Llama-3.1-405B-Instruct-FP8
支持的工具调用是 基于 JSON 的工具调用。对于 Llama-3.2 模型中的 Pythonic 工具调用,请参阅下面的 pythonic
工具解析器。不支持其他工具调用格式,如内置的 python 工具调用或自定义工具调用。
已知问题
不支持并行工具调用。
该模型可以生成格式错误的参数,例如生成序列化为字符串而不是数组的数组。
tool_chat_template_llama3_json.jinja
文件包含“官方” Llama 聊天模板,但经过调整,使其与 vLLM 更好地配合使用。
推荐标志:--tool-call-parser llama3_json --chat-template examples/tool_chat_template_llama3_json.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
:这是一个从 Huggingface 上的原始聊天模板修改而来的模板。支持并行函数调用。
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
:这是一个从 Huggingface 上的原始聊天模板修改而来的模板,它与 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
具有 Pythonic 工具调用的模型 (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
一起使用)
标志:--tool-call-parser pythonic --chat-template {see_above}
警告 Llama 的较小模型经常无法以正确的格式发出工具调用。您的结果可能会有所不同。
如何编写工具解析器插件#
工具解析器插件是一个 Python 文件,其中包含一个或多个 ToolParser 实现。您可以编写类似于 vllm/entrypoints/openai/tool_parsers/hermes_tool_parser.py 中的 Hermes2ProToolParser
的 ToolParser。
以下是插件文件的摘要
# 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)
然后,您可以在命令行中使用此插件,如下所示。
--enable-auto-tool-choice \
--tool-parser-plugin <absolute path of the plugin file>
--tool-call-parser example \
--chat-template <your chat template> \