开发者文档 工具调用
工具调用
由模型提出函数调用,由你的应用校验并执行。
使用前确认
需要:上游支持 tools 的 Chat Completions 模型;本例不使用流式。网关不检查 tools,原样交给上游;挑选模型时可参考控制台的「工具调用」标记。先完成快速开始中的环境变量配置,并把 YOUR_MODEL_ID 换成这把密钥可用的模型 ID。
完整示例
可从页头“下载代码”保存为 .py 文件,在配置好环境的服务端运行。
import os, json, urllib.request, urllib.error
BASE = os.environ["MOSSHUB_API_BASE"].rstrip("/")
KEY = os.environ["MOSSHUB_API_KEY"]
MODEL = "YOUR_MODEL_ID"
def chat(messages, **options):
body = {"model": MODEL, "messages": messages, "stream": False, **options}
request = urllib.request.Request(
BASE + "/v1/chat/completions",
data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
headers={"Authorization": "Bearer " + KEY,
"Content-Type": "application/json"}, method="POST")
try:
with urllib.request.urlopen(request, timeout=60) as response:
result = json.load(response)
except urllib.error.HTTPError as error:
raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error
choices = result.get("choices", [])
if not choices or not isinstance(choices[0].get("message"), dict):
raise RuntimeError("未返回有效消息,请检查错误信息与模型能力")
if choices[0].get("finish_reason") == "length":
raise RuntimeError("回答因输出上限而截断,请调整预算后重试")
return choices[0]["message"]
tools = [{"type": "function", "function": {
"name": "get_order_status", "description": "查询演示订单状态",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"], "additionalProperties": False},
}}]
messages = [{"role": "user", "content": "帮我查询订单 DEMO-1001 的状态。"}]
for _ in range(3):
message = chat(messages, tools=tools)
calls = message.get("tool_calls") or []
if not calls:
print(message.get("content") or "模型未提供文本回答")
break
messages.append({"role": "assistant", "content": message.get("content"), "tool_calls": calls})
for call in calls:
function = call.get("function", {})
try:
args = json.loads(function.get("arguments", "{}"))
except (json.JSONDecodeError, TypeError):
args = None
if function.get("name") != "get_order_status":
result = {"error": "未知工具"}
elif (not isinstance(args, dict) or set(args) != {"order_id"}
or not isinstance(args["order_id"], str)):
result = {"error": "参数无效"}
elif args["order_id"] != "DEMO-1001":
result = {"error": "演示订单不存在"}
else:
result = {"order_id": "DEMO-1001", "status": "已发货", "demo": True}
if not call.get("id"):
raise RuntimeError("工具调用缺少 id,不能回传结果")
messages.append({"role": "tool", "tool_call_id": call["id"],
"content": json.dumps(result, ensure_ascii=False)})
else:
raise RuntimeError("达到工具调用次数上限,交由应用处理")完整往返
- 在请求中声明函数名称和参数结构。
- 把带
tool_calls的assistant消息完整加入历史。 - 校验工具白名单、参数和当前用户权限,再执行应用自己的代码。
- 将结果通过
tool_call_id对应回传,让模型继续回答。
示例最多往返 3 次,使用固定演示订单,不调用真实订单服务。函数参数是模型产生的输入,不应直接拼接进 SQL、Shell 或文件路径。
流式边界
开启流式后,工具参数可能分成多段出现在 delta.tool_calls 中,需按 index 累计 function.arguments,结束后再解析 JSON。只拼接 delta.content 的文本解析器读不到工具调用。
继续阅读
实际可调用的模型、授权与价格以控制台为准。
页面字体:MiSans(小米,依《MiSans 字体知识产权许可协议》使用);Google Sans Flex(SIL Open Font License 1.1)。
页面字体:MiSans(小米,依《MiSans 字体知识产权许可协议》使用);Google Sans Flex(SIL Open Font License 1.1)。