ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MiniCPM3 工具调用(Function Call)实战指南:从 vLLM 服务部署到本地推理

2026/9/23 22:26:57 拓冰建站 浏览量
MiniCPM3 工具调用(Function Call)实战指南:从 vLLM 服务部署到本地推理 大模型本地部署模型量化微调LoRA工具调用openBMBAscend【免费下载链接】MiniCPMMiniCPM4 MiniCPM4.1: Ultra-Efficient LLMs on End Devices, achieving 3 generation speedup on reasoning tasks项目地址https://gitcode.com/OpenBMB/MiniCPM点击查看免费下载本文聚焦 MiniCPM3-4B 的工具调用能力基于仓库demo/minicpm3/function_call/目录下的完整示例讲解如何通过 vLLM 启动 OpenAI 兼容的工具调用服务、使用标准 OpenAI SDK 触发模型发起函数调用以及如何在本地脚本中直接完成生成调用 → 执行工具 → 回填结果 → 继续对话的多轮闭环。读完本文你将掌握 MiniCPM3 工具调用从服务端到客户端的完整接入方案并理解其背后的聊天模板与 AST 解析原理。一、MiniCPM3 工具调用能力概览MiniCPM3-4B 在 Berkeley Function Calling Leaderboard (BFCL) 的评估章节其工具调用能力是 MiniCPM3 进阶功能的重要组成部分。在 MiniCPM3 的工具调用设计中核心思路是工具即代码将 JSON Schema 描述的工具定义通过自定义聊天模板转换为 Python 函数签名让模型以写代码的方式调用函数结构化输出模型在|thought_start|...|thought_end|中输出思考过程在|tool_call_start|...|tool_call_end|中输出形如func1(params_nameparams_value)的 Python 调用服务端解析由 vLLM 的工具解析器tool parser或本地脚本中的fc2dict将上述文本解析为标准化的tool_calls结构。仓库中与本主题直接相关的文件全部位于 demo/minicpm3/function_call/ 目录文件作用README.md工具调用的两种接入方式速览服务端 本地function_calling.py本地多轮工具调用推理脚本vLLM 离线推理minicpm_tool_parser.pyvLLM 工具解析插件将模型输出解析为 OpenAI 格式的 tool_callsminicpm_chat_template_with_tool.jinja带工具定义的 MiniCPM3 聊天模板requirements.txt依赖声明vllm与datamodel_code_generator二、方式一启动 vLLM 工具调用服务OpenAI 兼容2.1 服务端启动命令在仓库根目录下执行以下命令即可启动一个支持自动工具选择的 vLLM OpenAI 兼容服务python -m vllm.entrypoints.openai.api_server \ --model openbmb/MiniCPM3-4B \ --dtype auto \ --api-key token-abc123 \ --tensor-parallel-size 1 \ --trust-remote-code \ --enable-auto-tool-choice \ --tool-call-parser minicpm \ --tool-parser-plugin minicpm_tool_parser.py关键参数说明参数含义--model openbmb/MiniCPM3-4B指定加载的模型权重首次运行会从 Hugging Face 拉取--dtype auto自动选择精度类型--api-key token-abc123服务端要求的访问密钥客户端调用时需保持一致--tensor-parallel-size 1张量并行度为 1单卡即可运行--trust-remote-code信任并执行仓库中的远程代码MiniCPM3 需要自定义代码务必开启--enable-auto-tool-choice开启自动工具选择模型根据用户提问自主决定是否调用工具--tool-call-parser minicpm指定工具解析器注册名为minicpm--tool-parser-plugin minicpm_tool_parser.py指定解析插件文件路径即本文后面要分析的minicpm_tool_parser.py其中minicpm这个解析器名称对应 minicpm_tool_parser.py 中的注册语句ToolParserManager.register_module(minicpm) class MiniCPMToolParser(ToolParser): ...也就是说vLLM 通过ToolParserManager按名称查找到MiniCPMToolParser类再结合--tool-parser-plugin指定的文件完成模型原始输出到 OpenAItool_calls格式的转换。2.2 客户端调用示例服务启动后默认监听http://localhost:8000使用 OpenAI Python SDK 即可调用from openai import OpenAI client OpenAI(base_urlhttp://localhost:8000/v1, api_keytoken-abc123) tools [ { type: function, function: { name: get_current_weather, description: Get the current weather in a given location, parameters: { type: object, properties: { location: { type: string, description: The city and state, e.g. San Francisco, CA, }, unit: {type: string, enum: [celsius, fahrenheit]}, }, required: [location], }, } } ] messages [{role: user, content: Whats the weather like in Boston today?}] completion client.chat.completions.create( modelopenbmb/MiniCPM3-4B, messagesmessages, toolstools, tool_choiceauto ) print(completion)要点说明base_url指向 vLLM 的/v1端点api_key必须与服务端--api-key保持一致tools使用 OpenAI 标准的 Function Calling JSON Schema 描述tool_choiceauto表示由模型自主决定是否需要调用工具与--enable-auto-tool-choice配合。服务端收到请求后会先将上述tools交给聊天模板生成带 Python 函数定义的提示词再驱动模型生成调用最终由MiniCPMToolParser.extract_tool_calls把模型输出解析成completion.tool_calls返回给客户端。三、方式二在本地直接运行工具调用推理如果不需要启动常驻服务可以直接运行仓库提供的本地推理脚本python function_call.py对应 docs/README-minicpm3-cn.md 进阶功能章节中的工具调用示例3.1 脚本整体流程function_calling.py 采用 vLLM 离线推理 APIvllm.LLM完整流程如下定义工具get_delivery_date查询订单配送日期参数为必填的order_id构造 system/user 消息用户提问 Hi, can you tell me the delivery date for my order? The order id is 1234 and 4321.用tokenizer.apply_chat_template(messages, toolstools, tokenizeFalse, add_generation_promptTrue)将消息与工具定义渲染成模型输入用LLM.generate得到模型输出文本用fc2dict解析输出若包含tool_calls则执行工具脚本中为fake_tool_execute模拟并把roletool的结果回填到消息列表循环继续生成否则结束对话。核心代码如下while True: prompt tokenizer.apply_chat_template( messages, toolstools, tokenizeFalse, add_generation_promptTrue ) outputs llm.generate([prompt], sampling_params) response outputs[0].outputs[0].text msg fc2dict(response) if ( tool_calls in msg and msg[tool_calls] is not None and len(msg[tool_calls]) 0 ): messages.append(msg) print(msg) for toolcall in msg[tool_calls]: tool_response fake_tool_execute(toolcall) tool_msg { role: tool, content: tool_response, tool_call_id: toolcall[id], } messages.append(tool_msg) print(tool_msg) else: messages.append(msg) print(msg) breakfake_tool_execute是仓库内置的假工具执行器它从toolcall[function][arguments][order_id]中取出订单号并返回一个 JSON 字符串配送日期固定为2024-09-05def fake_tool_execute(toolcall): data { delivery_date: 2024-09-05, order_id: toolcall.get(function, {}) .get(arguments, {}) .get(order_id, order_id), } return json.dumps(data)在实际项目中你只需要把fake_tool_execute替换成真实的工具实现如天气查询、搜索、数据库操作等。3.2 多轮多工具调用的消息结构脚本中注释了一段完整的多工具 工具结果回填示例消息展示了模型一轮内同时调用两次get_delivery_date分别查1234和4321时messages应如何组织# assistant 轮携带两个 tool_calls注意 role 为 assistant { content: , tool_calls: [ {type: function, function: {name: get_delivery_date, arguments: {order_id: 1234}}, id: call_b4ab0b4ec4b5442e86f017fe0385e22e}, {type: function, function: {name: get_delivery_date, arguments: {order_id: 4321}}, id: call_628965479dd84794bbb72ab9bdda0c39}, ], role: assistant, } # tool 轮每个调用结果以 roletool 回填并用 tool_call_id 关联 {role: tool, content: {delivery_date: 2024-09-05, order_id: 1234}, tool_call_id: call_b4ab0b4ec4b5442e86f017fe0385e22e}, {role: tool, content: {delivery_date: 2024-09-05, order_id: 4321}, tool_call_id: call_628965479dd84794bbb72ab9bdda0c39}, # 最终 assistant 轮携带 thought 并直接回答 {content: Both your orders will be delivered on 2024-09-05., role: assistant, thought: \nI have the information you need, both orders will be delivered on the same date, 2024-09-05.\n},需要注意tool_calls中每条调用都带独立的id工具执行结果通过tool_call_id与之对应这是多工具场景下消息关联的关键约定。3.3 采样参数脚本使用SamplingParams(temperature0.8, top_p0.95, max_tokens1000)控制生成temperature0.8与top_p0.95在保证稳定性的同时留有一定多样性max_tokens1000为单次生成预留充足长度以容纳多工具调用。四、原理剖析聊天模板如何把工具定义变成代码function_calling.py 第 78-80 行调用tokenizer.apply_chat_template(..., toolstools, ...)MiniCPM3-4B 的 tokenizer 会加载模型自带的聊天模板仓库同时提供了独立的 minicpm_chat_template_with_tool.jinja 供参考其设计逻辑是JSON Schema → Pydantic/类型注解通过json_to_python_type宏把string/integer/boolean/number/null/array/object分别映射为str/int/bool/float/None/List[...]/Dict[...]enum字段则生成Enum类生成函数签名tool_parser宏为每个工具生成def get_delivery_date(order_id: str None): ...形式的 Python 函数定义参数默认值取自parameters中的default字段注入调用规则与输出格式在提示词中明确告诉模型——可直接回答时给出 thought 后直接回答信息不足时给出 thought 后追问信息充分时给出 thought 后按如下格式调用函数|thought_start| {explain ...} |thought_end| |tool_call_start| python func1(params_nameparams_value, params_name2params_value2...) func2(params)|tool_call_end| {answer the users question directly or ask the user for more information}这种把函数调用视为代码生成的设计使得 MiniCPM3 能以自然语言理解任务、以 Python 语法表达工具调用模型输出天然具备结构便于后续解析。 ## 五、原理剖析fc2dict 与 AST 解析器 无论是本地脚本还是 vLLM 服务端最终都依赖 [minicpm_tool_parser.py](https://link.gitcode.com/i/a1b0ed24bf3fd5f244ed19c191459012) 中的 fc2dict 函数把模型输出的文本块解析成结构化字典。 ### 5.1 fc2dict 的解析流程 fc2dict 依次完成以下步骤 1. **分离思考内容**若输出同时包含 |thought_start| 与 |thought_end|用 rsplit(thought_end, 1) 从右侧切分提取 |thought_start|...|thought_end| 之间的内容为 thought_string 2. **分离工具调用块**同理用 rsplit(tool_call_end, 1) 提取 |tool_call_start|...|tool_call_end| 之间的 Python 代码块其余部分作为 content 3. **清理代码块**去除 围栏、python 语言标记并将 Python 关键字参数名如 from、type临时改写成 from_、type_ 形式避免语法错误 4. **AST 解析**用 ast.parse 把代码块解析为语法树对每个 ast.Call 调用 resolve_ast_call 还原出 {函数名: 参数字典} 5. **还原关键字**把第 3 步改写过的参数名k kw _恢复为原始关键字名 6. **返回结构**最终返回 {content: ..., tool_calls: [{name: ..., arguments: ...}], role: assistant}若解析失败则回退为 {content: ..., role: assistant, thought: ...} 并记录错误日志。 ### 5.2 resolve_ast_call 与 resolve_ast_by_type 这两个函数来自 gorilla 项目的实现思路README 的 Thanks 部分对此致谢职责如下 - resolve_ast_call(elem)沿 ast.Attribute 链还原点号路径的函数名如 module.submodule.func并把关键字参数逐个通过 resolve_ast_by_type 转换为 Python 原生值 - resolve_ast_by_type(value)递归处理 ast.Constant含 Ellipsis、UnaryOp负号、List、Dict、NameConstant布尔值、BinOp、Name、Call、Tuple、Lambda、Subscript 等 AST 节点类型覆盖了模型可能生成的各类字面量与表达式。 ### 5.3 vLLM ToolParser 的接入 MiniCPMToolParser 继承 vLLM 的 ToolParser 基类实现两个核心方法 - extract_tool_calls(model_output, request)非流式场景调用 fc2dict 后把 tool_calls 组装成 vLLM 协议中的 ToolCall(functionFunctionCall(name..., argumentsjson.dumps(...))) 列表arguments 以 JSON 字符串形式返回 - extract_tool_calls_streaming(...)流式场景基于 |thought_end|、|tool_call_start|、|tool_call_end| 三个标记将生成过程分为三类分支处理工具调用开始case 1、工具调用结束case 2、生成结束case 3此时用 fc2dict 收尾。流式解析同样使用正则 r(\w)\(((?:[^()]*|\([^()]*\))*)\) 匹配带嵌套括号的函数调用再经 ast.parse 与 resolve_ast_call 提取函数名与参数。 类中还定义了关键标记与停止符 python self.thought_start_token |thought_start| self.thought_end_token |thought_end| self.tool_call_start_token |tool_call_start| self.tool_call_end_token |tool_call_end| self.stop_token_ids [2, 73440]其中stop_token_ids2为 EOS73440为工具调用结束专用 token id保证生成在工具调用块闭合后及时收尾。六、依赖与运行环境运行本目录示例前请按 requirements.txt 安装依赖datamodel_code_generator vllmvllm提供LLM/SamplingParams本地推理与vllm.entrypoints.openai.api_server服务端以及 ToolParser 基类与协议定义datamodel_code_generator服务于聊天模板中从 JSON Schema 生成 Pydantic 数据类BaseModel/Field的类型推导能力是模板正确渲染的前置依赖本地推理脚本还需要transformersAutoTokenizer与openaiSDK客户端示例。首次加载openbmb/MiniCPM3-4B会自动下载模型权重请确保网络可达同时务必开启trust_remote_code否则 MiniCPM3 的自定义 tokenizer 与模型代码无法加载。七、两种接入方式选型建议维度vLLM 服务端方式一本地脚本方式二适用场景多客户端并发调用、需要 OpenAI 兼容 API 的集成单机实验、快速验证、离线批处理工具执行客户端拿到tool_calls后自行执行并回传脚本内通过fake_tool_execute模拟可替换为真实工具流式输出支持extract_tool_calls_streaming不支持脚本为一次性生成多轮闭环需客户端维护messages脚本内while循环自动维护结语MiniCPM3 的工具调用能力将函数调用建模为代码生成配合 minicpm_chat_template_with_tool.jinja 的模板注入与 minicpm_tool_parser.py 的 AST 解析形成了从服务部署到本地推理的完整闭环。无论是通过 vLLM 启动 OpenAI 兼容服务对外提供工具调用 API还是在脚本中实现多轮工具交互都可以直接复用本目录的示例代码快速落地。对于需要进一步定制如接入真实搜索/数据库工具、调整思考格式、扩展参数类型的场景本文剖析的模板与解析器源码即是你的最佳起点。赞分享大模型本地部署模型量化微调LoRA工具调用openBMBAscend【免费下载链接】MiniCPMMiniCPM4 MiniCPM4.1: Ultra-Efficient LLMs on End Devices, achieving 3 generation speedup on reasoning tasks项目地址https://gitcode.com/OpenBMB/MiniCPM点击查看免费下载相关推荐Qwen3-8B vLLM 部署调用实战从离线推理到 OpenAI API 服务Qwen3 8B vLLM 部署调用实战从离线推理到 OpenAI API 服务 本指南基于《开源大模型食用指南》的 Qwen3 专题完整演示如何在本机U大模型人工智能教程本地部署微调PaddleOCR-VL 海光 DCU 部署实战从本地推理、vLLM 加速到 Docker Compose 服务化部署PaddleOCR VL 海光 DCU 部署实战从本地推理、vLLM 加速到 Docker Compose 服务化部署 PaddleOCR 在飞桨文档解析模型人工智能计算机视觉OCR深度学习大模型RAGQwen2-7B-Instruct vLLM 部署调用从离线推理到 OpenAI API 服务的完整实战指南Qwen2 7B Instruct vLLM 部署调用从离线推理到 OpenAI API 服务的完整实战指南 本文基于 Datawhale《开源大模型食用指南大模型人工智能教程本地部署微调上一篇Android-Review中的View系统从MeasureSpec到自定义View的实战教程下一篇OpenToonz 新手教程4 步做出你的第一个弹跳球动画创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考