ineso22 commited on
Commit
5a8f07a
·
verified ·
1 Parent(s): 2b66a29

Upload docs/tool_calling_guide_cn.hf_temp_rename.md with huggingface_hub

Browse files
docs/tool_calling_guide_cn.hf_temp_rename.md ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MiniMax-M2.1 工具调用指南
2
+
3
+ [英文版](./tool_calling_guide.md) | [中文版](./tool_calling_guide_cn.md)
4
+
5
+ MiniMax-M2.1 支持与 MiniMax-M2 相同的工具调用语法。
6
+
7
+ ## 简介
8
+
9
+ MiniMax-M2.1 模型支持工具调用功能,使模型能够识别何时需要调用外部工具,并以结构化格式输出工具调用参数。本文档提供了有关如何使用 MiniMax-M2.1 工具调用功能的详细说明。
10
+
11
+ ## 基础示例
12
+
13
+ 以下 Python 脚本基于 OpenAI SDK 实现了一个天气查询工具调用示例:
14
+
15
+ ```python
16
+ from openai import OpenAI
17
+ import json
18
+
19
+ client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
20
+
21
+ def get_weather(location: str, unit: str):
22
+ return f"Getting the weather for {location} in {unit}..."
23
+
24
+ tool_functions = {"get_weather": get_weather}
25
+
26
+ tools = [{
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
+
42
+ response = 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
+
49
+ print(response)
50
+
51
+ tool_call = response.choices[0].message.tool_calls[0].function
52
+ print(f"Function called: {tool_call.name}")
53
+ print(f"Arguments: {tool_call.arguments}")
54
+ print(f"Result: {get_weather(**json.loads(tool_call.arguments))}")
55
+ ```
56
+
57
+ **输出示例:**
58
+ ```
59
+ Function called: get_weather
60
+ Arguments: {"location": "San Francisco, CA", "unit": "celsius"}
61
+ Result: Getting the weather for San Francisco, CA in celsius...
62
+ ```
63
+
64
+ ## 手动解析模型输出
65
+
66
+ **我们强烈建议使用 vLLM 或 SGLnag 来解析工具调用。** 如果您无法使用支持 MiniMax-M2.1 的推理引擎(如 vLLM 和 SGLang)的内置解析器,或需要使用其他推理框架(如 transformers、TGI 等),您可以使用以下方法手动解析模型的原始输出。这种方法需要您自己解析模型输出的 XML 标签格式。
67
+
68
+ ### 使用 Transformers 的示例
69
+
70
+ 这是一个使用 transformers 库的完整示例:
71
+
72
+ ```python
73
+ from transformers import AutoTokenizer
74
+
75
+ def 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 tokenizer
95
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
96
+ prompt = "What's the weather like in Shanghai today?"
97
+ messages = [
98
+ {"role": "system", "content": "You are a helpful assistant."},
99
+ {"role": "user", "content": prompt},
100
+ ]
101
+
102
+ # Enable function calling tools
103
+ tools = get_default_tools()
104
+
105
+ # Apply chat template and include tool definitions
106
+ text = tokenizer.apply_chat_template(
107
+ messages,
108
+ tokenize=False,
109
+ add_generation_prompt=True,
110
+ tools=tools
111
+ )
112
+
113
+ # Send request (using any inference service)
114
+ import requests
115
+ payload = {
116
+ "model": "MiniMaxAI/MiniMax-M2.1",
117
+ "prompt": text,
118
+ "max_tokens": 4096
119
+ }
120
+ response = 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 parsing
128
+ raw_output = response.json()["choices"][0]["text"]
129
+ print("Raw output:", raw_output)
130
+
131
+ # Use the parsing function below to process the output
132
+ tool_calls = parse_tool_calls(raw_output, tools)
133
+ ```
134
+
135
+ ## 🛠️ 工具调用定义
136
+
137
+ ### 工具结构
138
+
139
+ 工具调用需要在请求体中定义 `tools` 字段。每个工具由以下部分组成:
140
+
141
+ ```json
142
+ {
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
+ **字段说明:**
169
+ - `name`:函数名称
170
+ - `description`:函数描述
171
+ - `parameters`:函数参数定义
172
+ - `properties`:参数属性定义,其中键是参数名称,值包含详细的参数描述
173
+ - `required`:必需参数列表
174
+ - `type`:参数类型(通常为 "object")
175
+
176
+ ### 内部处理格式
177
+
178
+ 在 MiniMax-M2.1 模型内部处理时,工具定义会被转换为特殊格式并连接到输入文本中。以下是一个完整示例:
179
+
180
+ ```
181
+ ]~!b[]~b]system
182
+ You are a helpful assistant.
183
+
184
+ # Tools
185
+ You may call one or more tools to assist with the user query.
186
+ Here 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
+
192
+ When 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]user
202
+ When were the latest announcements from OpenAI and Gemini?[e~[
203
+ ]~b]ai
204
+ <think>
205
+ ```
206
+
207
+ **格式说明:**
208
+
209
+ - `]~!b[]~b]system`:系统消息开始标记
210
+ - `[e~[`:消息结束标记
211
+ - `]~b]user`:用户消息开始标记
212
+ - `]~b]ai`:助手消息开始标记
213
+ - `]~b]tool`:工具结果消息开始标记
214
+ - `<tools>...</tools>`:工具定义区域,每个工具都用 `<tool>` 标签包装,内容为 JSON Schema
215
+ - `<minimax:tool_call>...</minimax:tool_call>`:工具调用区域
216
+ - `<think>...</think>`:生成过程中的思考过程标记
217
+
218
+ ### 模型输出格式
219
+
220
+ MiniMax-M2.1 使用结构化的 XML 标签格式:
221
+
222
+ ```xml
223
+ <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
+
235
+ 每个工具调用使用 `<invoke name="function_name">` 标签,参数使用 `<parameter name="parameter_name">` 标签包装。
236
+
237
+ ## 手动解析工具调用结果
238
+
239
+ ### 解析工具调用
240
+
241
+ MiniMax-M2.1 使用结构化的 XML 标签,这需要一种不同的解析方法。核心函数如下:
242
+
243
+ ```python
244
+ import re
245
+ import json
246
+ from typing import Any, Optional, List, Dict
247
+
248
+
249
+ def 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_str
257
+
258
+
259
+ def convert_param_value(value: str, param_type: str) -> Any:
260
+ """Convert parameter value based on parameter type"""
261
+ if value.lower() == "null":
262
+ return None
263
+
264
+ param_type = param_type.lower()
265
+
266
+ if param_type in ["string", "str", "text"]:
267
+ return value
268
+ elif param_type in ["integer", "int"]:
269
+ try:
270
+ return int(value)
271
+ except (ValueError, TypeError):
272
+ return value
273
+ 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 value
279
+ 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 value
286
+ else:
287
+ # Try JSON parsing, return string if failed
288
+ try:
289
+ return json.loads(value)
290
+ except json.JSONDecodeError:
291
+ return value
292
+
293
+
294
+ def parse_tool_calls(model_output: str, tools: Optional[List[Dict]] = None) -> List[Dict]:
295
+ """
296
+ Extract all tool calls from model output
297
+
298
+ Args:
299
+ model_output: Complete output text from the model
300
+ 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 fields
306
+
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 present
329
+ if "<minimax:tool_call>" not in model_output:
330
+ return []
331
+
332
+ tool_calls = []
333
+
334
+ try:
335
+ # Match all <minimax:tool_call> blocks
336
+ 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 blocks
341
+ for tool_call_match in tool_call_regex.findall(model_output):
342
+ # Iterate through all invokes in this block
343
+ for invoke_match in invoke_regex.findall(tool_call_match):
344
+ # Extract function name
345
+ name_match = re.search(r'^([^>]+)', invoke_match)
346
+ if not name_match:
347
+ continue
348
+
349
+ function_name = extract_name(name_match.group(1))
350
+
351
+ # Get parameter configuration
352
+ 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
+ break
361
+
362
+ # Extract parameters
363
+ 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 newlines
371
+ 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 convert
377
+ 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_dict
387
+ })
388
+
389
+ except Exception as e:
390
+ print(f"Failed to parse tool calls: {e}")
391
+ return []
392
+
393
+ return tool_calls
394
+ ```
395
+
396
+ **使用示例:**
397
+
398
+ ```python
399
+ # Define tools
400
+ tools = [
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 output
415
+ model_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 calls
424
+ tool_calls = parse_tool_calls(model_output, tools)
425
+
426
+ # Output results
427
+ for call in tool_calls:
428
+ print(f"Function called: {call['name']}")
429
+ print(f"Arguments: {call['arguments']}")
430
+ # Output: Function called: get_weather
431
+ # Arguments: {'location': 'San Francisco', 'unit': 'celsius'}
432
+ ```
433
+
434
+ ### 执行工具调用
435
+
436
+ 完成解析后,您可以执行相应的工具并构造返回结果:
437
+
438
+ ```python
439
+ def 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 result
445
+ 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 results
464
+ 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 None
476
+ ```
477
+
478
+ ### 将工具执行结果返回给模型
479
+
480
+ 在成功解析工具调用后,您应该将工具执行结果添加到对话历史中,以便模型在后续交互中可以访问和利用这些信息。请参考 [chat_template.jinja](https://huggingface.co/MiniMaxAI/MiniMax-M2.1/blob/main/chat_template.jinja) 了解连接格式。
481
+
482
+ ## 参考文献
483
+
484
+ - [MiniMax-M2.1 模型仓库](https://github.com/MiniMax-AI/MiniMax-M2.1)
485
+ - [vLLM 项目主页](https://github.com/vllm-project/vllm)
486
+ - [SGLang 项目主页](https://github.com/sgl-project/sglang)
487
+ - [OpenAI Python SDK](https://github.com/openai/openai-python)
488
+
489
+ ## 获取支持
490
+
491
+ 如果遇到任何问题:
492
+
493
+ - 通过邮箱 [model@minimax.io](mailto:model@minimax.io) 等官方渠道联系我们的技术支持团队
494
+
495
+ - 在我们的仓库提交 Issue
496
+
497
+ - 通过我们的 [官方企业微信交流群](https://github.com/MiniMax-AI/MiniMax-AI.github.io/blob/main/images/wechat-qrcode.jpeg) 反馈
498
+
499
+ 我们会持续优化模型的使用体验,欢迎反馈!