Team Ai
Modelpublic

MiniMaxAI/MiniMax-M2.5

sourceHugging Faceotherupdated 7mo agoView on Hugging Face
1.5klikes579kdownloads
tool_calling_guide.md487 linesDownload Raw Back to docs
1# MiniMax-M2.5 Tool Calling Guide2 3[English Version](./tool_calling_guide.md) | [Chinese Version](./tool_calling_guide_cn.md)4 5MiniMax-M2.5 supports the same toolcall syntax as MiniMax-M2.6 7## Introduction8 9The MiniMax-M2.5 model supports tool calling capabilities, enabling the model to identify when external tools need to be called and output tool call parameters in a structured format. This document provides detailed instructions on how to use the tool calling features of MiniMax-M2.5.10 11## Basic Example12 13The following Python script implements a weather query tool call example based on the OpenAI SDK:14 15```python16from openai import OpenAI17import json18 19client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")20 21def get_weather(location: str, unit: str):22    return f"Getting the weather for {location} in {unit}..."23 24tool_functions = {"get_weather": get_weather}25 26tools = [{27    "type": "function",28    "function": {29        "name": "get_weather",30        "description": "Get the current weather in a given location",31        "parameters": {32            "type": "object",33            "properties": {34                "location": {"type": "string", "description": "City and state, e.g., 'San Francisco, CA'"},35                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}36            },37            "required": ["location", "unit"]38        }39    }40}]41 42response = client.chat.completions.create(43    model=client.models.list().data[0].id,44    messages=[{"role": "user", "content": "What's the weather like in San Francisco? use celsius."}],45    tools=tools,46    tool_choice="auto"47)48 49print(response)50 51tool_call = response.choices[0].message.tool_calls[0].function52print(f"Function called: {tool_call.name}")53print(f"Arguments: {tool_call.arguments}")54print(f"Result: {get_weather(**json.loads(tool_call.arguments))}")55```56 57**Output Example:**58```59Function called: get_weather60Arguments: {"location": "San Francisco, CA", "unit": "celsius"}61Result: Getting the weather for San Francisco, CA in celsius...62```63 64## Manually Parsing Model Output65 66**We strongly recommend using vLLM or SGLang for parsing tool calls.** If you cannot use the built-in parser of inference engines (e.g., vLLM and SGLang) that support MiniMax-M2.5, or need to use other inference frameworks (such as transformers, TGI, etc.), you can manually parse the model's raw output using the following method. This approach requires you to parse the XML tag format of the model output yourself.67 68### Example Using Transformers69 70Here is a complete example using the transformers library:71 72```python73from transformers import AutoTokenizer74 75def get_default_tools():76    return [77        {78          "name": "get_current_weather",79          "description": "Get the latest weather for a location",80          "parameters": {81              "type": "object", 82              "properties": {83                  "location": {84                      "type": "string", 85                      "description": "A certain city, such as Beijing, Shanghai"86                  }87              }, 88          }89          "required": ["location"],90          "type": "object"91        }92    ]93 94# Load model and tokenizer95tokenizer = AutoTokenizer.from_pretrained(model_id)96prompt = "What's the weather like in Shanghai today?"97messages = [98    {"role": "system", "content": "You are a helpful assistant."},99    {"role": "user", "content": prompt},100]101 102# Enable function calling tools103tools = get_default_tools()104 105# Apply chat template and include tool definitions106text = tokenizer.apply_chat_template(107    messages,108    tokenize=False,109    add_generation_prompt=True,110    tools=tools111)112 113# Send request (using any inference service)114import requests115payload = {116    "model": "MiniMaxAI/MiniMax-M2.5",117    "prompt": text,118    "max_tokens": 4096119}120response = requests.post(121    "http://localhost:8000/v1/completions",122    headers={"Content-Type": "application/json"},123    json=payload,124    stream=False,125)126 127# Model output needs manual parsing128raw_output = response.json()["choices"][0]["text"]129print("Raw output:", raw_output)130 131# Use the parsing function below to process the output132tool_calls = parse_tool_calls(raw_output, tools)133```134 135## 🛠️ Tool Call Definition136 137### Tool Structure138 139Tool calls need to define the `tools` field in the request body. Each tool consists of the following parts:140 141```json142{143  "tools": [144    {145      "name": "search_web",146      "description": "Search function.",147      "parameters": {148        "properties": {149          "query_list": {150            "description": "Keywords for search, list should contain 1 element.",151            "items": { "type": "string" },152            "type": "array"153          },154          "query_tag": {155            "description": "Category of query",156            "items": { "type": "string" },157            "type": "array"158          }159        },160        "required": [ "query_list", "query_tag" ],161        "type": "object"162      }163    }164  ]165}166```167 168**Field Descriptions:**169- `name`: Function name170- `description`: Function description171- `parameters`: Function parameter definition172  - `properties`: Parameter property definition, where key is the parameter name and value contains detailed parameter description173  - `required`: List of required parameters174  - `type`: Parameter type (usually "object")175 176### Internal Processing Format177 178When processing within the MiniMax-M2.5 model, tool definitions are converted to a special format and concatenated to the input text. Here is a complete example:179 180```181]~!b[]~b]system182You are a helpful assistant.183 184# Tools185You may call one or more tools to assist with the user query.186Here are the tools available in JSONSchema format:187 188<tools>189<tool>{"name": "search_web", "description": "Search function.", "parameters": {"type": "object", "properties": {"query_list": {"type": "array", "items": {"type": "string"}, "description": "Keywords for search, list should contain 1 element."}, "query_tag": {"type": "array", "items": {"type": "string"}, "description": "Category of query"}}, "required": ["query_list", "query_tag"]}}</tool>190</tools>191 192When making tool calls, use XML format to invoke tools and pass parameters:193 194<minimax:tool_call>195<invoke name="tool-name-1">196<parameter name="param-key-1">param-value-1</parameter>197<parameter name="param-key-2">param-value-2</parameter>198...199</invoke>200[e~[201]~b]user202When were the latest announcements from OpenAI and Gemini?[e~[203]~b]ai204<think>205```206 207**Format Description:**208 209- `]~!b[]~b]system`: System message start marker210- `[e~[`: Message end marker211- `]~b]user`: User message start marker212- `]~b]ai`: Assistant message start marker213- `]~b]tool`: Tool result message start marker214- `<tools>...</tools>`: Tool definition area, each tool is wrapped with `<tool>` tag, content is JSON Schema215- `<minimax:tool_call>...</minimax:tool_call>`: Tool call area216- `<think>...</think>`: Thinking process marker during generation217 218### Model Output Format219 220MiniMax-M2.5 uses structured XML tag format:221 222```xml223<minimax:tool_call>224<invoke name="search_web">225<parameter name="query_tag">["technology", "events"]</parameter>226<parameter name="query_list">["\"OpenAI\" \"latest\" \"release\""]</parameter>227</invoke>228<invoke name="search_web">229<parameter name="query_tag">["technology", "events"]</parameter>230<parameter name="query_list">["\"Gemini\" \"latest\" \"release\""]</parameter>231</invoke>232</minimax:tool_call>233```234 235Each tool call uses the `<invoke name="function_name">` tag, and parameters use the `<parameter name="parameter_name">` tag wrapper.236 237## Manually Parsing Tool Call Results238 239### Parsing Tool Calls240 241MiniMax-M2.5 uses structured XML tags, which require a different parsing approach. The core function is as follows:242 243```python244import re245import json246from typing import Any, Optional, List, Dict247 248 249def extract_name(name_str: str) -> str:250    """Extract name from quoted string"""251    name_str = name_str.strip()252    if name_str.startswith('"') and name_str.endswith('"'):253        return name_str[1:-1]254    elif name_str.startswith("'") and name_str.endswith("'"):255        return name_str[1:-1]256    return name_str257 258 259def convert_param_value(value: str, param_type: str) -> Any:260    """Convert parameter value based on parameter type"""261    if value.lower() == "null":262        return None263        264    param_type = param_type.lower()265    266    if param_type in ["string", "str", "text"]:267        return value268    elif param_type in ["integer", "int"]:269        try:270            return int(value)271        except (ValueError, TypeError):272            return value273    elif param_type in ["number", "float"]:274        try:275            val = float(value)276            return val if val != int(val) else int(val)277        except (ValueError, TypeError):278            return value279    elif param_type in ["boolean", "bool"]:280        return value.lower() in ["true", "1"]281    elif param_type in ["object", "array"]:282        try:283            return json.loads(value)284        except json.JSONDecodeError:285            return value286    else:287        # Try JSON parsing, return string if failed288        try:289            return json.loads(value)290        except json.JSONDecodeError:291            return value292 293 294def parse_tool_calls(model_output: str, tools: Optional[List[Dict]] = None) -> List[Dict]:295    """296    Extract all tool calls from model output297    298    Args:299        model_output: Complete output text from the model300        tools: Tool definition list for getting parameter type information, format can be:301               - [{"name": "...", "parameters": {...}}]302               - [{"type": "function", "function": {"name": "...", "parameters": {...}}}]303    304    Returns:305        Parsed tool call list, each element contains name and arguments fields306    307    Example:308        >>> tools = [{309        ...     "name": "get_weather",310        ...     "parameters": {311        ...         "type": "object",312        ...         "properties": {313        ...             "location": {"type": "string"},314        ...             "unit": {"type": "string"}315        ...         }316        ...     }317        ... }]318        >>> output = '''<minimax:tool_call>319        ... <invoke name="get_weather">320        ... <parameter name="location">San Francisco</parameter>321        ... <parameter name="unit">celsius</parameter>322        ... </invoke>323        ... </minimax:tool_call>'''324        >>> result = parse_tool_calls(output, tools)325        >>> print(result)326        [{'name': 'get_weather', 'arguments': {'location': 'San Francisco', 'unit': 'celsius'}}]327    """328    # Quick check if tool call marker is present329    if "<minimax:tool_call>" not in model_output:330        return []331    332    tool_calls = []333    334    try:335        # Match all <minimax:tool_call> blocks336        tool_call_regex = re.compile(r"<minimax:tool_call>(.*?)</minimax:tool_call>", re.DOTALL)337        invoke_regex = re.compile(r"<invoke name=(.*?)</invoke>", re.DOTALL)338        parameter_regex = re.compile(r"<parameter name=(.*?)</parameter>", re.DOTALL)339        340        # Iterate through all tool_call blocks341        for tool_call_match in tool_call_regex.findall(model_output):342            # Iterate through all invokes in this block343            for invoke_match in invoke_regex.findall(tool_call_match):344                # Extract function name345                name_match = re.search(r'^([^>]+)', invoke_match)346                if not name_match:347                    continue348                349                function_name = extract_name(name_match.group(1))350                351                # Get parameter configuration352                param_config = {}353                if tools:354                    for tool in tools:355                        tool_name = tool.get("name") or tool.get("function", {}).get("name")356                        if tool_name == function_name:357                            params = tool.get("parameters") or tool.get("function", {}).get("parameters")358                            if isinstance(params, dict) and "properties" in params:359                                param_config = params["properties"]360                            break361                362                # Extract parameters363                param_dict = {}364                for match in parameter_regex.findall(invoke_match):365                    param_match = re.search(r'^([^>]+)>(.*)', match, re.DOTALL)366                    if param_match:367                        param_name = extract_name(param_match.group(1))368                        param_value = param_match.group(2).strip()369                        370                        # Remove leading and trailing newlines371                        if param_value.startswith('\n'):372                            param_value = param_value[1:]373                        if param_value.endswith('\n'):374                            param_value = param_value[:-1]375                        376                        # Get parameter type and convert377                        param_type = "string"378                        if param_name in param_config:379                            if isinstance(param_config[param_name], dict) and "type" in param_config[param_name]:380                                param_type = param_config[param_name]["type"]381                        382                        param_dict[param_name] = convert_param_value(param_value, param_type)383                384                tool_calls.append({385                    "name": function_name,386                    "arguments": param_dict387                })388    389    except Exception as e:390        print(f"Failed to parse tool calls: {e}")391        return []392    393    return tool_calls394```395 396**Usage Example:**397 398```python399# Define tools400tools = [401    {402        "name": "get_weather",403        "parameters": {404            "type": "object",405            "properties": {406                "location": {"type": "string"},407                "unit": {"type": "string"}408            },409            "required": ["location", "unit"]410        }411    }412]413 414# Model output415model_output = """Let me help you query the weather.416<minimax:tool_call>417<invoke name="get_weather">418<parameter name="location">San Francisco</parameter>419<parameter name="unit">celsius</parameter>420</invoke>421</minimax:tool_call>"""422 423# Parse tool calls424tool_calls = parse_tool_calls(model_output, tools)425 426# Output results427for call in tool_calls:428    print(f"Function called: {call['name']}")429    print(f"Arguments: {call['arguments']}")430    # Output: Function called: get_weather431    #         Arguments: {'location': 'San Francisco', 'unit': 'celsius'}432```433 434### Executing Tool Calls435 436After parsing is complete, you can execute the corresponding tool and construct the return result:437 438```python439def execute_function_call(function_name: str, arguments: dict):440    """Execute function call and return result"""441    if function_name == "get_weather":442        location = arguments.get("location", "Unknown location")443        unit = arguments.get("unit", "celsius")444        # Build function execution result445        return {446            "role": "tool", 447            "content": [448              {449                "name": function_name,450                "type": "text",451                "text": json.dumps({452                    "location": location, 453                    "temperature": "25", 454                    "unit": unit, 455                    "weather": "Sunny"456                }, ensure_ascii=False)457              }458            ] 459          }460    elif function_name == "search_web":461        query_list = arguments.get("query_list", [])462        query_tag = arguments.get("query_tag", [])463        # Simulate search results464        return {465            "role": "tool",466            "content": [467              {468                "name": function_name,469                "type": "text",470                "text": f"Search keywords: {query_list}, Category: {query_tag}\nSearch results: Relevant information found"471              }472            ]473          }474    475    return None476```477 478### Returning Tool Execution Results to the Model479 480After successfully parsing tool calls, you should add the tool execution results to the conversation history so that the model can access and utilize this information in subsequent interactions. Refer to [chat_template.jinja](https://huggingface.co/MiniMaxAI/MiniMax-M2.5/blob/main/chat_template.jinja) for concatenation format.481 482## References483 484- [MiniMax-M2.5 Model Repository](https://github.com/MiniMax-AI/MiniMax-M2.5)485- [vLLM Project Homepage](https://github.com/vllm-project/vllm)486- [SGLang Project Homepage](https://github.com/sgl-project/sglang)487- [OpenAI Python SDK](https://github.com/openai/openai-python)