Skip to content

Tool Calling

Aphrodite currently supports named function calling, as well as the auto, required (as of aphrodite-engine>=0.9.0), and none options for the tool_choice field in the chat completion API.

Quickstart

Start the server with tool calling enabled. This example uses Meta’s Llama 3.1 8B model, so we need to use the llama3_json tool calling chat template from the Aphrodite examples directory:

Terminal window
aphrodite run 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

Next, make a request that triggers the model to use the available tools:

from openai import OpenAI
import json
client = OpenAI(base_url="http://localhost:2242/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))}")

Example output:

Function called: get_weather
Arguments: {"location": "San Francisco, CA", "unit": "fahrenheit"}
Result: Getting the weather for San Francisco, CA in fahrenheit...

This example demonstrates:

  • Setting up the server with tool calling enabled
  • Defining an actual function to handle tool calls
  • Making a request with tool_choice="auto"
  • Handling the structured response and executing the corresponding function

You can also specify a particular function using named function calling by setting tool_choice={"type": "function", "function": {"name": "get_weather"}}. Note that this will use the guided decoding backend - so the first time this is used, there will be several seconds of latency (or more) as the FSM is compiled for the first time before it is cached for subsequent requests.

Remember that it’s the caller’s responsibility to:

  1. Define appropriate tools in the request
  2. Include relevant context in the chat messages
  3. Handle the tool calls in your application logic

For more advanced usage, including parallel tool calls and different model-specific parsers, see the sections below.

Named Function Calling

Aphrodite supports named function calling in the chat completion API by default. It does so using Outlines through guided decoding, so this is enabled by default and will work with any supported model. You are guaranteed a validly-parsable function call - not a high-quality one.

Aphrodite will use guided decoding to ensure the response matches the tool parameter object defined by the JSON schema in the tools parameter. For best results, we recommend ensuring that the expected output format / schema is specified in the prompt to ensure that the model’s intended generation is aligned with the schema that it’s being forced to generate by the guided decoding backend.

To use a named function, you need to define the functions in the tools parameter of the chat completion request, and specify the name of one of the tools in the tool_choice parameter of the chat completion request.

Required Function Calling

Aphrodite supports the tool_choice='required' option in the chat completion API. Similar to the named function calling, it also uses guided decoding, so this is enabled by default and will work with any supported model. The guided decoding features for tool_choice='required' (such as JSON schema with anyOf) are currently only supported in the V0 engine with the guided decoding backend outlines. However, support for alternative decoding backends are on the roadmap for the V1 engine.

When tool_choice='required' is set, the model is guaranteed to generate one or more tool calls based on the specified tool list in the tools parameter. The number of tool calls depends on the user’s query. The output format strictly follows the schema defined in the tools parameter.

None Function Calling

Aphrodite supports the tool_choice='none' option in the chat completion API. When this option is set, the model will not generate any tool calls and will respond with regular text content only, even if tools are defined in the request.

Automatic Function Calling

To enable this feature, you should set the following flags:

  • --enable-auto-tool-choicemandatory Auto tool choice. It tells Aphrodite that you want to enable the model to generate its own tool calls when it deems appropriate.
  • --tool-call-parser — select the tool parser to use (listed below). Additional tool parsers will continue to be added in the future. You can also register your own tool parsers in the --tool-parser-plugin.
  • --tool-parser-pluginoptional tool parser plugin used to register user defined tool parsers into aphrodite, the registered tool parser name can be specified in --tool-call-parser.
  • --chat-templateoptional for auto tool choice. It’s the path to the chat template which handles tool-role messages and assistant-role messages that contain previously generated tool calls. Hermes, Mistral and Llama models have tool-compatible chat templates in their tokenizer_config.json files, but you can specify a custom template. This argument can be set to tool_use if your model has a tool use-specific chat template configured in the tokenizer_config.json. In this case, it will be used per the transformers specification. More on this here from HuggingFace; and you can find an example of this in a tokenizer_config.json here.

If your favorite tool-calling model is not supported, please feel free to contribute a parser & tool use chat template!

Hermes Models (hermes)

All Nous Research Hermes-series models newer than Hermes 2 Pro should be supported.

  • NousResearch/Hermes-2-Pro-*
  • NousResearch/Hermes-2-Theta-*
  • NousResearch/Hermes-3-*

Note that the Hermes 2 Theta models are known to have degraded tool call quality and capabilities due to the merge step in their creation.

Flags: --tool-call-parser hermes

Mistral Models (mistral)

Supported models:

  • mistralai/Mistral-7B-Instruct-v0.3 (confirmed)
  • Additional mistral function-calling models are compatible as well.

Known issues:

  1. Mistral 7B struggles to generate parallel tool calls correctly.

  2. Mistral’s tokenizer_config.json chat template requires tool call IDs that are exactly 9 digits, which is much shorter than what Aphrodite generates. Since an exception is thrown when this condition is not met, the following additional chat templates are provided:

Recommended flags: --tool-call-parser mistral --chat-template examples/tool_chat_template_mistral_parallel.jinja

Llama Models (llama3_json)

Supported models:

All Llama 3.1, 3.2 and 4 models should be supported.

  • meta-llama/Llama-3.1-*
  • meta-llama/Llama-3.2-*
  • meta-llama/Llama-4-*

The tool calling that is supported is the JSON-based tool calling. For pythonic tool calling introduced by the Llama-3.2 models, see the pythonic tool parser below. As for Llama 4 models, it is recommended to use the llama4_pythonic tool parser.

Other tool calling formats like the built-in python tool calling or custom tool calling are not supported.

Known issues:

  1. Parallel tool calls are not supported for Llama 3, but it is supported in Llama 4 models.
  2. The model can generate parameters in an incorrect format, such as generating an array serialized as string instead of an array.

Aphrodite provides two JSON-based chat templates for Llama 3.1 and 3.2:

Recommended flags: --tool-call-parser llama3_json --chat-template {see_above}

Aphrodite also provides a pythonic and JSON-based chat template for Llama 4, but pythonic tool calling is recommended:

For Llama 4 model, use --tool-call-parser llama4_pythonic --chat-template examples/tool_chat_template_llama4_pythonic.jinja.

IBM Granite

Supported models:

InternLM Models (internlm)

Supported models:

  • internlm/internlm2_5-7b-chat (confirmed)
  • Additional internlm2.5 function-calling models are compatible as well

Known issues:

  • Although this implementation also supports InternLM2, the tool call results are not stable when testing with the internlm/internlm2-chat-7b model.

Recommended flags: --tool-call-parser internlm --chat-template examples/tool_chat_template_internlm2_tool.jinja

Jamba Models (jamba)

AI21’s Jamba-1.5 models are supported.

  • ai21labs/AI21-Jamba-1.5-Mini
  • ai21labs/AI21-Jamba-1.5-Large

Flags: --tool-call-parser jamba

xLAM Models (xlam)

The xLAM tool parser is designed to support models that generate tool calls in various JSON formats. It detects function calls in several different output styles:

  1. Direct JSON arrays: Output strings that are JSON arrays starting with [ and ending with ]
  2. Thinking tags: Using <think>...</think> tags containing JSON arrays
  3. Code blocks: JSON in code blocks (json ...)
  4. Tool calls tags: Using [TOOL_CALLS] or <tool_call>...</tool_call> tags

Parallel function calls are supported, and the parser can effectively separate text content from tool calls.

Supported models:

  • Salesforce Llama-xLAM models: Salesforce/Llama-xLAM-2-8B-fc-r, Salesforce/Llama-xLAM-2-70B-fc-r
  • Qwen-xLAM models: Salesforce/xLAM-1B-fc-r, Salesforce/xLAM-3B-fc-r, Salesforce/Qwen-xLAM-32B-fc-r

Flags:

  • For Llama-based xLAM models: --tool-call-parser xlam --chat-template examples/tool_chat_template_xlam_llama.jinja
  • For Qwen-based xLAM models: --tool-call-parser xlam --chat-template examples/tool_chat_template_xlam_qwen.jinja

Qwen Models

For Qwen2.5, the chat template in tokenizer_config.json has already included support for the Hermes-style tool use. Therefore, you can use the hermes parser to enable tool calls for Qwen models. For more detailed information, please refer to the official Qwen documentation

  • Qwen/Qwen2.5-*
  • Qwen/QwQ-32B

Flags: --tool-call-parser hermes

MiniMax Models (minimax_m1)

Supported models:

Flags: --tool-call-parser minimax --chat-template examples/tool_chat_template_minimax_m1.jinja

DeepSeek-V3 Models (deepseek_v3)

Supported models:

Flags: --tool-call-parser deepseek_v3 --chat-template {see_above}

DeepSeek-V3.1 Models (deepseek_v31)

Supported models:

Flags: --tool-call-parser deepseek_v31 --chat-template {see_above}

Kimi-K2 Models (kimi_k2)

Supported models:

  • moonshotai/Kimi-K2-Instruct

Flags: --tool-call-parser kimi_k2

Hunyuan Models (hunyuan_a13b)

Supported models:

  • tencent/Hunyuan-A13B-Instruct (The chat template is already included in the Hugging Face model files.)

Flags:

  • For non-reasoning: --tool-call-parser hunyuan_a13b
  • For reasoning: --tool-call-parser hunyuan_a13b --reasoning-parser hunyuan_a13b --enable_reasoning

GLM-4.5 Models (glm45)

Supported models:

  • ZhipuAI/GLM-4.5
  • ZhipuAI/GLM-4.5-Air

Flags: --tool-call-parser glm45

Models with Pythonic Tool Calls (pythonic)

A growing number of models output a python list to represent tool calls instead of using JSON. This has the advantage of inherently supporting parallel tool calls and removing ambiguity around the JSON schema required for tool calls. The pythonic tool parser can support such models.

As a concrete example, these models may look up the weather in San Francisco and Seattle by generating:

[get_weather(city='San Francisco', metric='celsius'), get_weather(city='Seattle', metric='celsius')]

Limitations:

  • The model must not generate both text and tool calls in the same generation. This may not be hard to change for a specific model, but the community currently lacks consensus on which tokens to emit when starting and ending tool calls. (In particular, the Llama 3.2 models emit no such tokens.)
  • Llama’s smaller models struggle to use tools effectively.

Example supported models:

Flags: --tool-call-parser pythonic --chat-template {see_above}

Llama's smaller models frequently fail to emit tool calls in the correct format. Results may vary depending on the model.

How to Write a Tool Parser Plugin

A tool parser plugin is a Python file containing one or more ToolParser implementations. You can write a ToolParser similar to the Hermes2ProToolParser in https://github.com/aphrodite-engine/aphrodite-engine/blob/main/aphrodite/endpoints/openai/tool_parsers/hermes_tool_parser.py.

Here is a summary of a plugin file:

# import the required packages
# define a tool parser and register it to aphrodite
# 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)

Then you can use this plugin in the command line like this.

Terminal window
--enable-auto-tool-choice \
--tool-parser-plugin <absolute path of the plugin file>
--tool-call-parser example \
--chat-template <your chat template> \