跳转到主要内容
函数调用(Function Call)是一种通过提示工程实现的模型扩展能力,开发者可预先定义可用的函数,模型会根据用户输入自动决定是否调用函数,并以 JSON 格式输出调用参数。常见应用场景包括天气查询、网页搜索、数据库检索等。

使用 vLLM 进行函数调用(推荐)

请确保已成功部署 vLLM 并能够正常启动服务。MiniMax-M1 集成了自定义的 tool_call_parser,无需手动解析模型输出。在启动 vLLM 服务时,添加以下参数即可启用函数调用成功(新增参数为 --enable-auto-tool-choice--tool-call-parser minimax--chat-template examples/tool_chat_template_minimax_m1.jinja
SAFETENSORS_FAST_GPU=1 VLLM_USE_V1=0 vllm serve MiniMaxAI/MiniMax-M1-40k \
    --trust-remote-code \
    --quantization experts_int8 \
    --dtype bfloat16 \
    --enable-auto-tool-choice \
    --tool-call-parser minimax \
    --chat-template examples/tool_chat_template_minimax_m1.jinja
如果是通过 Docker 方式使用的 vLLM,在 Docker 启动命令中同样添加上述参数即可。
docker run --runtime nvidia --gpus all \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    --env "SAFETENSORS_FAST_GPU=1" \
    --env "VLLM_USE_V1=0" \
    -p 8000:8000 \
    --ipc=host \
    vllm/vllm-openai:latest \
    --model MiniMaxAI/MiniMax-M1-40k \
    --trust-remote-code \
    --quantization experts_int8 \
    --dtype bfloat16 \
    --enable-auto-tool-choice \
    --tool-call-parser minimax \
    --chat-template examples/tool_chat_template_minimax_m1.jinja
参数解释:
  • --tool-call-parser minimax 关键参数,启用 MiniMax-M1 自定义解析器
  • --enable-auto-tool-choice 启用自动工具选择
  • --chat-template 模板文件需要适配 tool calling 格式,可以在 GitHub 获取

通过 OpenAI SDK 使用函数调用

以下示例演示如何通过 OpenAI SDK 实现天气查询函数调用:
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? use celsius."}],
    tools=tools,
    tool_choice="auto"
)

print(response)
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": "celsius"}
Result: Getting the weather for San Francisco, CA in celsius...

函数调用定义格式说明

函数定义格式

函数调用需要在请求体中定义 tools 字段,每个函数由以下部分组成:
{
  "tools": [
    {
      "name": "search_web",
      "description": "搜索函数。",
      "parameters": {
        "properties": {
          "query_list": {
            "description": "进行搜索的关键词,列表元素个数为1。",
            "items": { "type": "string" },
            "type": "array"
          },
          "query_tag": {
            "description": "query的分类",
            "items": { "type": "string" },
            "type": "array"
          }
        },
        "required": ["query_list", "query_tag"],
        "type": "object"
      }
    }
  ]
}
字段说明:
  1. name : 函数名称
  2. description : 函数功能描述
  3. parameters : 函数参数定义
    • properties : 参数属性定义,key 是参数名,value 包含参数的详细描述
    • required : 必填参数列表
    • type : 参数类型(通常为 “object”)

模型内部处理格式

在模型内部处理时,函数定义会被转换为特殊格式并拼接到输入文本中。以下为模型内部处理时的输入格式示例,用户无需手动构造:
<begin_of_document><beginning_of_sentence>system ai_setting=MiniMax AI
MiniMax AI是由上海稀宇科技有限公司(MiniMax)自主研发的AI助理。<end_of_sentence>
<beginning_of_sentence>system tool_setting=tools
You are provided with these tools:
<tools>
{"name": "search_web", "description": "搜索函数。", "parameters": {"properties": {"query_list": {"description": "进行搜索的关键词,列表元素个数为1。", "items": {"type": "string"}, "type": "array"}, "query_tag": {"description": "query的分类", "items": {"type": "string"}, "type": "array"}}, "required": ["query_list", "query_tag"], "type": "object"}}
</tools>
If you need to call tools, please respond with <tool_calls></tool_calls> XML tags, and provide tool-name and json-object of arguments, following the format below:
<tool_calls>
{"name": <tool-name>, "arguments": <args-json-object>}
...
</tool_calls><end_of_sentence>
<beginning_of_sentence>user name=用户
OpenAI 和 Gemini 的最近一次发布会都是什么时候?<end_of_sentence>
<beginning_of_sentence>ai name=MiniMax AI

模型输出格式

模型输出的函数调用格式如下:
<think>
Okay, I will search for the OpenAI and Gemini latest release.
</think>
<tool_calls>
{"name": "search_web", "arguments": {"query_tag": ["technology", "events"], "query_list": ["\"OpenAI\" \"latest\" \"release\""]}}
{"name": "search_web", "arguments": {"query_tag": ["technology", "events"], "query_list": ["\"Gemini\" \"latest\" \"release\""]}}
</tool_calls>

手动解析模型输出

我们推荐使用 OpenAI Chat Completions API,其会自动在服务端应用 Chat Template,主流推理框架已有完善的支持。 如使用的框架不支持 Tool Calling,未使用 vLLM 内置解析器,或使用其他推理框架(如 Transformers、TGI 等),可参考以下方法手动解析模型输出,需根据实际模型输出格式调整解析逻辑。

手动应用 Chat Template

以下是使用 transformers 库的完整示例:
from transformers import AutoTokenizer

def get_default_tools():
    return [
        {
          "name": "get_current_weather",
          "description": "Get the latest weather for a location",
          "parameters": {
              "type": "object",
              "properties": {
                  "location": {
                      "type": "string",
                      "description": "A certain city, such as Beijing, Shanghai"
                  }
              },
          },
          "required": ["location"],
          "type": "object"
        }
    ]

# 加载模型和分词器
model_id = "MiniMaxAI/MiniMax-M1-40k"
tokenizer = AutoTokenizer.from_pretrained(model_id)
prompt = "What's the weather like in Shanghai today?"
messages = [
    {"role": "system", "content": [{"type": "text", "text": "You are a helpful assistant created by MiniMax based on MiniMax-M1 model."}]},
    {"role": "user", "content": [{"type": "text", "text": prompt}]},
]

with open("/vllm-workspace/examples/tool_chat_template_minimax_m1.jinja", "r") as f:
    tokenizer.chat_template = f.read()

# 启用函数调用工具
tools = get_default_tools()

# 应用聊天模板,并加入工具定义
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
    tools=tools
)

# 发送请求(这里使用任何推理服务)
import requests
payload = {
    "model": model_id,
    "prompt": text,
    "max_tokens": 4000
}
response = requests.post(
    "http://localhost:8000/v1/completions",
    headers={"Content-Type": "application/json"},
    json=payload,
    stream=False,
)

# 模型输出需要手动解析
raw_json = response.json()
raw_output = raw_json["choices"][0]["text"]
print("原始输出:", raw_output)

# 使用下面的解析函数处理输出
function_calls = parse_function_calls(raw_output)

解析函数调用

当需要手动解析时,需要解析模型输出的 XML 标签格式:
import re
import json
def parse_function_calls(content: str):
    """
    解析模型输出中的函数调用
    """
    function_calls = []

    # 匹配 <tool_calls> 标签内的内容
    tool_calls_pattern = r"<tool_calls>(.*?)</tool_calls>"
    tool_calls_match = re.search(tool_calls_pattern, content, re.DOTALL)

    if not tool_calls_match:
        return function_calls

    tool_calls_content = tool_calls_match.group(1).strip()

    # 解析每个函数调用(每行一个JSON对象)
    for line in tool_calls_content.split('\n'):
        line = line.strip()
        if not line:
            continue

        try:
            # 解析JSON格式的函数调用
            call_data = json.loads(line)
            function_name = call_data.get("name")
            arguments = call_data.get("arguments", {})

            function_calls.append({
                "name": function_name,
                "arguments": arguments
            })

            print(f"调用函数: {function_name}, 参数: {arguments}")

        except json.JSONDecodeError as e:
            print(f"参数解析失败: {line}, 错误: {e}")

    return function_calls

# 示例:处理天气查询函数
def execute_function_call(function_name: str, arguments: dict):
    """
    执行函数调用并返回结果
    """
    if function_name == "get_current_weather":
        location = arguments.get("location", "未知位置")
        # 构建函数执行结果
        return {
            "role": "tool",
            "content": [
              {
                "name": function_name,
                "type": "text",
                "text": json.dumps({
                    "location": location,
                    "temperature": "25",
                    "unit": "celsius",
                    "weather": "晴朗"
                }, ensure_ascii=False)
              }
            ]
          }
    elif function_name == "search_web":
        query_list = arguments.get("query_list", [])
        query_tag = arguments.get("query_tag", [])
        # 模拟搜索结果
        return {
            "role": "tool",
            "content": [
              {
                "name": function_name,
                "type": "text",
                "text": f"搜索关键词: {query_list}, 分类: {query_tag}\n搜索结果: 相关信息已找到"
              }
            ]
          }

    return None

将函数执行结果返回给模型

成功解析函数调用后,应将函数执行结果添加到对话历史中,以便模型在后续交互中能够访问和利用这些信息。

单个结果

假如模型调用了 search_web 函数,可以参考如下格式添加执行结果,name 字段为具体的函数名称。
{
  "role": "tool",
  "content": [
    {
      "name": "search_web",
      "type": "text",
      "text": "test_result"
    }
  ]
}
对应如下的模型输入格式:
<beginning_of_sentence>tool name=tools
tool name: search_web
tool result: test_result
<end_of_sentence>

多个结果

假如模型同时调用了 search_webget_current_weather 函数,可以参考如下格式添加执行结果,content 包含多个结果。
{
  "role": "tool",
  "content": [
    {
      "name": "search_web",
      "type": "text",
      "text": "test_result1"
    },
    {
      "name": "get_current_weather",
      "type": "text",
      "text": "test_result2"
    }
  ]
}
对应如下的模型输入格式:
<beginning_of_sentence>tool name=tools
tool name: search_web
tool result: test_result1
tool name: get_current_weather
tool result: test_result2<end_of_sentence>

常见问题

Tool Call 回应不是合法的 JSON 格式

请检查发送的请求,如果请求中的 Tool Call 调用引导也不是合法的 JSON 格式,说明应用了错误的 chat template,请使用 tool_chat_template_minimax_m1.jinja

参考资料

获取支持

如果在部署 MiniMax 模型过程中遇到任何问题:
  • 通过官方邮箱 api@minimaxi.com 联系我们的技术支持团队
  • 在我们的 GitHub 仓库提交 Issue
我们会持续优化 Function Call 的部署体验,欢迎您的反馈!
I