> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laozhang.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 老张API 函数调用（Function Calling）：Chat Completions 与 Responses 写法

> 用 OpenAI 格式的 tools 让 GPT、Gemini、DeepSeek、Grok、Qwen、GLM、Kimi 等模型调用你的函数：完整两轮请求示例、各模型该用哪个端点，以及 GPT-6 和 Responses 多轮回传的注意事项。

函数调用让模型返回"要调用哪个函数、参数是什么"，由你的程序执行函数，再把结果交回模型生成最终回答。老张API的 OpenAI 兼容接口对多数文本模型使用同一种 `tools` 写法，换模型只需改 `model`。

| 项目 | 内容 |
| - | - |
| Base URL | `https://api.laozhang.ai/v1` |
| 端点 | Chat Completions `/v1/chat/completions`；Responses `/v1/responses` |
| 计费 | 按模型的 token 价格，两轮请求分别计费；没有额外的函数调用费 |
| 模型价格 | [模型与价格总表](/models) |

## 各模型该用哪个端点

下表是 2026 年 10 月 14 日用同一个天气函数完成"调用 → 回传结果 → 最终回答"两轮的结果：

| 模型 | Chat Completions | Responses |
| - | - | - |
| `gpt-6.1-sol` | 不支持带工具 | 可用 |
| `gpt-6-sol` | 需加 `reasoning_effort: "none"` | 可用 |
| `gpt-5.6-luna`、`gpt-5.4-mini` | 可用 | 可用，按[多轮回传](#responses-多轮回传)的写法 |
| `grok-4.5` | 可用 | 可用 |
| `gemini-4-argon`、`gemini-3.8-flash` | 可用 | 不支持 |
| `deepseek-v4-pro`、`deepseek-v4-flash` | 可用 | 不支持 |
| `qwen3.7-max`、`glm-5.2`、`kimi-k2.5`、`MiniMax-M2.5` | 可用 | — |

表中标「—」的模型用 Chat Completions。拿不准时也先用 Chat Completions；GPT-6 系列用 Responses。Gemini 也可以用原生 `generateContent` 的 `functionDeclarations`，见 [Gemini 原生协议](/api-reference/gemini)。

## Chat Completions 示例

运行前安装 SDK（`python -m pip install openai`），并设置 `LAOZHANG_API_KEY` 环境变量。

```python theme={null}
import json
import os

from openai import OpenAI

client = OpenAI(api_key=os.environ["LAOZHANG_API_KEY"], base_url="https://api.laozhang.ai/v1")
MODEL = "gpt-5.4-mini"

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "查询城市当前天气",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]


def get_weather(city):
    return {"city": city, "temp_c": 18, "sky": "多云"}  # 换成你的实现


messages = [{"role": "user", "content": "巴黎现在天气怎么样？"}]
first = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = first.choices[0].message

if message.tool_calls:
    messages.append(message)
    for call in message.tool_calls:
        args = json.loads(call.function.arguments)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(get_weather(**args), ensure_ascii=False),
        })
    second = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
    print(second.choices[0].message.content)
else:
    print(message.content)
```

第一轮返回的 `message.tool_calls` 里有函数名和 JSON 字符串形式的参数。第二轮把模型的这条消息和每个 `tool` 结果一起发回去，`tool_call_id` 要和对应调用的 `id` 一致。

把 `MODEL` 换成上表中 Chat Completions 可用的其他模型，代码不用改。`gpt-6-sol` 还要在两次请求里都加上 `reasoning_effort="none"`，否则返回 400。

## Responses 示例

Responses 的工具定义少一层 `function`，结果以 `function_call_output` 回传：

```python theme={null}
import json
import os

from openai import OpenAI

client = OpenAI(api_key=os.environ["LAOZHANG_API_KEY"], base_url="https://api.laozhang.ai/v1")
MODEL = "gpt-6.1-sol"

tools = [{
    "type": "function",
    "name": "get_weather",
    "description": "查询城市当前天气",
    "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
        "additionalProperties": False,
    },
    "strict": True,
}]

question = {"role": "user", "content": "巴黎现在天气怎么样？"}
first = client.responses.create(model=MODEL, input=[question], tools=tools)

history = [question]
for item in first.output:
    if item.type != "function_call":
        continue
    args = json.loads(item.arguments)
    result = {"city": args["city"], "temp_c": 18, "sky": "多云"}  # 换成你的实现
    history.append({"type": "function_call", "call_id": item.call_id,
                    "name": item.name, "arguments": item.arguments})
    history.append({"type": "function_call_output", "call_id": item.call_id,
                    "output": json.dumps(result, ensure_ascii=False)})

second = client.responses.create(model=MODEL, input=history, tools=tools)
print(second.output_text)
```

### Responses 多轮回传

回传历史时只带 `call_id`、`name` 和 `arguments`，像上面的示例一样自己重建 `function_call` 项。不要依赖服务端保存的会话：

* 不要用 `previous_response_id` 接着上一轮。
* 不要把第一轮的 `output` 原样拼回 `input`。

老张API的同一个模型可能由多条官方线路承接，两轮请求不一定落在同一条线路上。这两种写法引用的是上一条线路上保存的对象，换了线路就会报 400：

* `The requested item was created under a different Azure OpenAI resource`
* `Previous response with id '...' not found`

只回传内容、不回传 ID 的写法不受影响。

## 常见问题

### `gpt-6.1-sol` 带 tools 为什么报 400？

OpenAI 对 `gpt-6.1-sol` 的规定是：Chat Completions 中函数工具不能和推理同时使用，而这个模型的 `reasoning_effort` 又不能设为 `none`。改用 Responses 即可，示例见上文。

### 模型一次返回多个函数调用怎么办？

逐个执行，每个结果单独回传，并带上对应的 `tool_call_id`（Chat Completions）或 `call_id`（Responses）。上面两个示例都已经用循环处理了多个调用。

### 参数不是合法 JSON 怎么办？

先用 `json.loads` 校验，失败时把错误信息作为函数结果回传，让模型重新生成。Responses 中给工具加 `"strict": true` 并在 `parameters` 里写 `"additionalProperties": false`，可以让参数严格符合 schema。

### 函数调用会额外收费吗？

不会。工具定义和函数结果都算作输入 token，模型返回的调用参数算作输出 token，按模型单价计费。服务端工具（例如[联网搜索](/api-capabilities/web-search)）另有按次费用。

## 相关文档

* 让模型搜索网页并引用来源：[联网搜索](/api-capabilities/web-search)
* Chat Completions 与 Responses 的选择、GPT-6 的参数规则：[OpenAI 模型接入](/api-reference/openai#chat-completions-与-responses-怎么选)
* Gemini 原生格式的函数调用：[Gemini 原生协议](/api-reference/gemini)

## 参考资料

* OpenAI：[Function calling](https://developers.openai.com/api/docs/guides/function-calling)
* Google：[Function calling with the Gemini API](https://ai.google.dev/gemini-api/docs/function-calling)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.