函数调用

让模型决定是否调用你定义的函数,附完整的两轮示例。可通过 Chat Completions 使用,也可走 Claude 原生 Messages 格式。

函数调用(Tool Calls)让模型决定“是否需要调用你定义的函数、传什么参数”。模型本身不会执行函数,由你的代码执行后,再把结果交还给模型。

流程:

  1. 请求里用 tools 描述可用函数。
  2. 模型返回 tool_calls(函数名 + JSON 参数)。
  3. 你的代码执行函数,把结果以 role: "tool" 消息追加到对话。
  4. 再请求一次,模型给出最终回答。

可以通过 Chat Completions 使用函数调用,下面的示例换 model 即可;支持 Claude 原生格式的模型也可以通过 Anthropic Messages 格式使用,见本页最后一节。是否支持函数调用取决于模型,请在 模型广场 选择合适的模型。

示例中的 your-model-id 请替换为模型广场中的模型 ID(也可以调用 GET /v1/models 查看)。

完整示例

tools.py
import json
import os

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["MYAIEXP_API_KEY"],
    base_url="https://ai.myaiexp.com/v1",
)
model = "your-model-id"  # 替换为模型广场中的模型 ID


def get_weather(city: str) -> str:
    # 这里用假数据代替真实的天气接口
    return json.dumps({"city": city, "weather": "sunny", "temperature_c": 22})


tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string", "description": "City name, e.g. Beijing"}},
                "required": ["city"],
            },
        },
    }
]

messages = [{"role": "user", "content": "What's the weather in Beijing right now?"}]

# 第 1 轮:模型决定要不要调用函数
first = client.chat.completions.create(model=model, messages=messages, tools=tools)
msg = first.choices[0].message

if not msg.tool_calls:
    print(msg.content)
else:
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_weather(**args)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": result})

    # 第 2 轮:把函数结果交还给模型,得到最终回答
    final = client.chat.completions.create(model=model, messages=messages, tools=tools)
    print(final.choices[0].message.content)

第 1 轮的原始返回

只看第 1 轮,可以用 curl:

tools.sh
# 函数调用:模型返回 tool_calls,由你的代码执行函数
curl -sS https://ai.myaiexp.com/v1/chat/completions \
  -H "Authorization: Bearer $MYAIEXP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-model-id",
    "messages": [
      {"role": "user", "content": "What'\''s the weather in Beijing right now?"}
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_weather",
          "description": "Get the current weather for a city",
          "parameters": {
            "type": "object",
            "properties": {
              "city": {"type": "string", "description": "City name, e.g. Beijing"}
            },
            "required": ["city"]
          }
        }
      }
    ]
  }'

模型决定调用函数时,返回的 finish_reason 是 tool_calls(以下为结构示意,content 可能为空或带一句说明):

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "",
        "tool_calls": [
          {
            "id": "call_...",
            "type": "function",
            "function": { "name": "get_weather", "arguments": "{\"city\": \"Beijing\"}" }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

Anthropic Messages 格式的工具调用

通过 /v1/messages 调用时,工具定义和返回结构是 Anthropic 原生格式:

  • 工具用 name、description、input_schema 描述(没有外层的 function)。
  • 模型要调用工具时,stop_reason 是 tool_use,content 里有 type: "tool_use" 的块,参数在 input 里(已是 JSON 对象,不是字符串)。
  • 把结果放进下一条 user 消息的 tool_result 块,tool_use_id 对应上一轮的 id。
anthropic_tools.py
import json
import os

import anthropic

client = anthropic.Anthropic(
    api_key=os.environ["MYAIEXP_API_KEY"],
    base_url="https://ai.myaiexp.com",  # 注意:不带 /v1
)

tools = [
    {
        "name": "get_weather",
        "description": "Get the current weather for a city",
        "input_schema": {
            "type": "object",
            "properties": {"city": {"type": "string", "description": "City name, e.g. Beijing"}},
            "required": ["city"],
        },
    }
]
messages = [{"role": "user", "content": "What's the weather in Beijing right now?"}]

# 第 1 轮
first = client.messages.create(model="your-model-id", max_tokens=1024, tools=tools, messages=messages)

if first.stop_reason == "tool_use":
    messages.append({"role": "assistant", "content": first.content})
    results = []
    for block in first.content:
        if block.type == "tool_use":
            # 这里用假数据代替真实的天气接口
            data = {"city": block.input["city"], "weather": "sunny", "temperature_c": 22}
            results.append({"type": "tool_result", "tool_use_id": block.id, "content": json.dumps(data)})
    messages.append({"role": "user", "content": results})

    # 第 2 轮
    final = client.messages.create(model="your-model-id", max_tokens=1024, tools=tools, messages=messages)
    print(final.content[0].text)

注意事项

  • Chat Completions 里的 arguments 是 JSON 字符串,需要 json.loads / JSON.parse 后再用,并建议做异常处理,模型偶尔会给出不合法参数。
  • 第 2 轮请求要把第 1 轮模型返回的 assistant 消息(含 tool_calls)原样放回 messages,再追加 tool 消息,tool_call_id 要一一对应。
  • 模型可能一次返回多个 tool_calls,要逐个执行并分别返回结果。
  • 是否支持函数调用以模型自身能力为准;不确定时可以先在 游乐场 或用上面的 curl 试一次。

本服务仅供学习与研究用途。请遵守各模型提供方的使用政策。

本页目录