# Chat Completions

OpenAI 兼容的对话补全端点,适合 OpenAI SDK、旧版函数调用和工具调用客户端。

```text
POST https://api.clomio.ai/v1/chat/completions
```

> **分组要求:** OpenAI 分组原生支持;Grok 分组支持 xAI 兼容 Chat/Responses bridge;Claude 分组也可经网关转换支持 Chat Completions,但启用 **Claude Code only** 的 Claude 分组只允许 `/v1/messages`,会拒绝本端点。模型和工具能力以当前 Key 分组为准，见 [端点 × 分组](#/api-usage)。

---

## 请求头

| 请求头 | 必填 | 值 |
|--------|:----:|-----|
| `Authorization` | 是 | `Bearer 你的密钥` |
| `Content-Type` | 是 | `application/json` |

---

## 请求参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|:----:|------|
| `model` | string | 是 | 模型名,以控制台分组为准 |
| `messages` | array | 通常是 | Chat 语义主输入；部分兼容客户端也可传 `input`，但这种写法应改用 Responses 端点 |
| `temperature` | number | 否 | 随机性;推理模型可能忽略采样参数 |
| `top_p` | number | 否 | 核采样 |
| `max_tokens` | integer | 否 | 最大输出 token 数;兼容旧客户端 |
| `max_completion_tokens` | integer | 否 | 最大输出 token 数;与 `max_tokens` 同时存在时优先使用 |
| `stream` | boolean | 否 | 为 `true` 时 SSE 流式返回 |
| `stream_options.include_usage` | boolean | 否 | 流式结束前附带 usage 块 |
| `stop` | string/array | 否 | 普通 Chat→Responses 转换路径当前不保证透传；需要强 stop 时优先用 Responses 原生路径验证 |
| `n` | integer | 否 | 普通 Chat→Responses 转换路径当前不保证透传，通常按 1 条处理 |
| `presence_penalty` | number | 否 | 普通 Chat→Responses 转换路径当前不保证透传 |
| `frequency_penalty` | number | 否 | 普通 Chat→Responses 转换路径当前不保证透传 |
| `response_format` | object | 否 | 普通 Chat→Responses 转换路径当前不保证透传；JSON 输出建议直接用 Responses `text.format` 验证 |
| `tools` | array | 否 | 工具定义;支持 `type:"function"`,部分路径也接受 `web_search`/`web_fetch` 等原生工具类型 |
| `tool_choice` | string/object | 否 | `auto`/`none`/`required` 或指定函数,如 `{"type":"function","function":{"name":"get_weather"}}` |
| `functions` | array | 否 | 旧版函数定义,会兼容转换为工具 |
| `function_call` | string/object | 否 | 旧版函数选择,会兼容转换为 `tool_choice` |
| `reasoning_effort` | string | 否 | 推理强度,如 `low`/`medium`/`high`/`xhigh` |
| `service_tier` | string | 否 | 服务层级,如 `auto`/`default`/`flex`,按上游能力生效 |
| `seed` | integer | 否 | 普通 Chat→Responses 转换路径当前不保证透传 |

**messages 元素:**

| 字段 | 类型 | 说明 |
|------|------|------|
| `role` | string | `system` / `user` / `assistant` / `tool`;旧版函数回传也可用 `function` |
| `content` | string/array/null | 文本;多模态时为数组,含 `text`、`image_url` 等 |
| `reasoning_content` | string | assistant 推理内容回传字段;转换到 Responses/Claude 时会尽量保留 |
| `tool_calls` | array | assistant 发起的工具调用,每项含 `id`、`type:"function"`、`function{name,arguments}` |
| `tool_call_id` | string | `role:"tool"` 时必填,对应上一轮 `tool_calls[].id` |
| `name` | string | `role:"function"` 或具名消息兼容字段 |
| `function_call` | object | 旧版 assistant 函数调用字段 |

**多模态 content 示例:**

```json
[
  {"type": "text", "text": "这张图里有什么?"},
  {"type": "image_url", "image_url": {"url": "https://example.com/cat.png", "detail": "auto"}}
]
```

**请求边界:** 请求体不能为空且必须是合法 JSON；`model` 必须存在且为非空 string；`stream` 如出现必须是 boolean，否则返回 400 `invalid stream field type`。`messages` 是 Chat Completions 语义下的主输入；部分兼容客户端在没有 `messages` 但有 `input` 时会按 Responses ingress 能力路由。OpenAI 和 Grok 分组可使用本端点，Claude Code only 分组只允许 `/v1/messages`。请求体过大时返回 413 `invalid_request_error`。

### 兼容性说明

- 客户端只需要按本页 Chat 格式处理；服务会根据所选分组和模型返回 SSE 或 JSON。
- 普通 Chat→Responses 转换只保留当前转换器显式支持的字段。`response_format`、`presence_penalty`、`frequency_penalty`、`seed`、`n` 以及部分 `stop` 语义不保证透传；如果业务强依赖这些字段，请直接用 [Responses](#/api-responses) 做最小验证。
- 若请求没有 `messages` 但有 Responses 风格 `input`，会按兼容模式处理；部分 Chat 专用参数在该模式下不会生效，请改用 [Responses](#/api-responses) 发送 Responses 格式。
- 当模型映射到 `gpt-image-*` 这类图片模型时，Chat 请求会按图片能力处理；需要稳定控制图片格式时，建议直接使用 [Images](#/api-images)。

---

## 响应

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 本次请求 ID |
| `object` | string | `chat.completion` 或流式 `chat.completion.chunk` |
| `created` | integer | 时间戳 |
| `model` | string | 实际使用的模型 |
| `choices` | array | 结果数组,含 `message`/`delta`、`finish_reason` |
| `usage` | object | `prompt_tokens` / `completion_tokens` / `total_tokens`,可能含缓存和推理 token 明细 |
| `service_tier` | string | 上游返回时透出 |

`finish_reason` 常见值: `stop`、`length`、`tool_calls`、`content_filter`。工具调用时读取 `choices[0].message.tool_calls`;流式时累积 `choices[].delta.content`、`delta.reasoning_content`、`delta.tool_calls`。

```json
{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1730000000,
  "model": "gpt-5.4",
  "choices": [{
    "index": 0,
    "message": { "role": "assistant", "content": "你好!有什么可以帮你?" },
    "finish_reason": "stop"
  }],
  "usage": { "prompt_tokens": 12, "completion_tokens": 9, "total_tokens": 21 }
}
```

---

## 最小可验证 curl

下面请求可验证路由、鉴权、`model`/`messages` 基本形态和非流式响应；把 `stream` 改成字符串（如 `"false"`）可验证 400 `invalid stream field type`。

## 示例:基础调用

```bash
curl https://api.clomio.ai/v1/chat/completions \
  -H "Authorization: Bearer 你的密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [
      {"role": "system", "content": "你是简洁的助手。"},
      {"role": "user", "content": "用一句话介绍你自己"}
    ]
  }'
```

```python
from openai import OpenAI
client = OpenAI(api_key="你的密钥", base_url="https://api.clomio.ai/v1")

resp = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "用一句话介绍你自己"}],
)
print(resp.choices[0].message.content)
```

---

## 示例:流式输出

```bash
curl https://api.clomio.ai/v1/chat/completions \
  -H "Authorization: Bearer 你的密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [{"role": "user", "content": "写一首关于秋天的短诗"}],
    "stream": true
  }'
```

流式返回每块形如 `data: {"choices":[{"delta":{"content":"秋"}}]}`,以 `data: [DONE]` 结束。若流已经开始后才出错,不会再返回普通 JSON 错误体,而是写 `event: error` / `data: ...` 并尽量补 `data: [DONE]` 收尾。

---

## 示例:多模态(发图片)

```bash
curl https://api.clomio.ai/v1/chat/completions \
  -H "Authorization: Bearer 你的密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "你的多模态模型名",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "这张图里有什么?"},
        {"type": "image_url", "image_url": {"url": "https://example.com/cat.png"}}
      ]
    }]
  }'
```

> 也可用 `data:image/png;base64,...` 内联图片。是否支持多模态取决于所选模型和分组上游能力。

---

## 示例:函数 / 工具调用

```json
{
  "model": "gpt-5.4",
  "messages": [{"role": "user", "content": "北京现在天气如何?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "查询城市天气",
      "parameters": {
        "type": "object",
        "properties": { "city": {"type": "string"} },
        "required": ["city"]
      }
    }
  }],
  "tool_choice": "auto"
}
```

模型决定调用工具时,`choices[0].message.tool_calls` 会给出函数名与参数;你执行后把结果以 `role:"tool"` 和对应 `tool_call_id` 追加进 `messages` 再请求一次。


## 常见请求错误

下面表格列出常见 OpenAI-style `{"error": ...}` 错误。鉴权、Key 状态或分组限制错误的字段可能略有不同。

| HTTP | `error.type` | `message` | 来源 / 处理 |
|------|--------------|-----------|-------------|
| 400 | `invalid_request_error` | `Request body is empty` | 请求体为空；发送 JSON body |
| 400 | `invalid_request_error` | `Failed to parse request body` | JSON 非法 |
| 400 | `invalid_request_error` | `model is required` | `model` 缺失、非 string 或空字符串 |
| 400 | `invalid_request_error` | `invalid stream field type` | `stream` 不是 boolean |
| 413 | `invalid_request_error` | `Request body too large, limit is ...` | 请求体超过服务限制;减少附件/上下文或分批 |
| 404 | `not_found_error` | `Chat Completions API is not supported for this platform` | 当前 Key 分组不开放 Chat；Grok 分组可用时不会命中此项 |
| 403 | `permission_error` | `This group is restricted to Claude Code clients (/v1/messages only)` | Claude Code only 分组只允许 Messages |
| 403 | `content_policy_violation` / `permission_error` | 内容审计命中,或当前分组不支持请求模型并返回 Available models | 调整内容、模型或分组 |
| 404 | `model_not_found` | 模型不在当前分组可用列表里 | 核对模型名和 `/v1/models` |
| 429 | `rate_limit_exceeded` / `rate_limit_error` | API Key 金额窗口、用户/分组 RPM、平台日/周/月额度、pending 队列或并发限制 | 看 `Retry-After`、控制台额度/并发和用量窗口 |
| 499 | `api_error` | `context canceled` | 客户端主动断开或超时取消 |
| 503 | `billing_service_error` / `api_error` | 服务暂时不可用或上游繁忙 | 稍后重试；持续出现带 request_id 工单 |

---

## 实战场景

### 场景一:流式输出并在最后读取 usage

```python
from openai import OpenAI
client = OpenAI(api_key="你的密钥", base_url="https://api.clomio.ai/v1")

usage = None
stream = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "用三点总结缓存命中率优化方法"}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")
    if chunk.usage:
        usage = chunk.usage
print("\nusage=", usage)
```

### 场景二:旧版 `functions/function_call` 兼容

```bash
curl https://api.clomio.ai/v1/chat/completions \
  -H "Authorization: Bearer 你的密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [{"role":"user","content":"查一下上海天气"}],
    "functions": [{
      "name": "get_weather",
      "description": "查询城市天气",
      "parameters": {
        "type":"object",
        "properties":{"city":{"type":"string"}},
        "required":["city"]
      }
    }],
    "function_call": {"name":"get_weather"}
  }'
```

### 场景三:工具结果回传并继续生成

```json
{
  "model": "gpt-5.4",
  "messages": [
    {"role":"user","content":"北京现在天气如何?"},
    {"role":"assistant","content":null,"tool_calls":[{
      "id":"call_weather_1",
      "type":"function",
      "function":{"name":"get_weather","arguments":"{\"city\":\"北京\"}"}
    }]},
    {"role":"tool","tool_call_id":"call_weather_1","content":"{\"temp\":\"28C\",\"condition\":\"晴\"}"}
  ]
}
```

### 场景四:结构化信息抽取(JSON 模式)

```python
import json
from openai import OpenAI
client = OpenAI(api_key="你的密钥", base_url="https://api.clomio.ai/v1")

resume = "张三,3 年后端经验,擅长 Go 和 PostgreSQL,邮箱 zhang@example.com"
r = client.chat.completions.create(
    model="gpt-5.4",
    messages=[
        {"role": "system", "content": "把简历抽取成 JSON:name, years, skills(数组), email。"},
        {"role": "user", "content": resume},
    ],
    response_format={"type": "json_object"},
)
data = json.loads(r.choices[0].message.content)
print(data["name"], data["skills"])
```

---

> 需要 Claude 原生 extended thinking、`cache_control` 或 `count_tokens` 时,见 [Messages](#/api-messages);需要 OpenAI Responses 形态时,见 [Responses](#/api-responses)。

## 字段约束速查

| 字段 | 可选值/范围 | 说明 |
|---|---|---|
| `model` | 当前 `/v1/models` 中的非空字符串 | 模型由 Key 分组决定；不要把其他分组模型名混用 |
| `messages` | 至少 1 项；`role`=`system`/`developer`/`user`/`assistant`/`tool` | `content` 可为字符串或 content block 数组 |
| `stream` | `true` / `false` | `true` 返回 SSE；默认 `false` |
| `temperature` | `0` 至 `2` | 越高越随机；推理模型可能忽略 |
| `top_p` | `0` 至 `1` | 与 temperature 通常只设置一个 |
| `max_tokens` / `max_completion_tokens` | 正整数 | 输出上限；优先使用 `max_completion_tokens` |
| `tool_choice` | `auto` / `none` / `required` / 指定函数对象 | 仅在请求含 `tools` 时有意义 |
| `response_format` | `text`、`json_object`、`json_schema` 对象 | JSON 模式要求提示词明确要求 JSON |
| `parallel_tool_calls` | `true` / `false` | 是否允许一轮返回多个工具调用 |

## 完整响应与错误

非流式成功响应至少包含 `id`、`object:"chat.completion"`、`model`、`choices[]` 和 `usage`；流式响应是 `data:` SSE，最后以结束事件收尾。错误统一形如：

```json
{
  "error": {
    "type": "invalid_request_error",
    "message": "model is required",
    "code": "invalid_request"
  }
}
```

| HTTP | 典型错误 | 处理 |
|---:|---|---|
| 400 | `Request body is empty`、`Failed to parse request body`、`model is required` | 修正 JSON 和必填字段 |
| 400 | `invalid stream field type` | `stream` 必须是真正的 JSON boolean |
| 401 | `Invalid API key` / `API key is disabled` | 检查 Key 头和状态 |
| 403 | `does not support the requested model` / Claude-only 限制 | 换模型或分组 |
| 404 | `Chat Completions API is not supported for this platform` | 当前分组未开放 Chat |
| 413 | `Request body too large` | 缩小上下文或附件 |
| 429 | `rate_limit_exceeded` / `rate_limit_error` | 按 `Retry-After` 退避并降低并发 |
| 502/503 | `Upstream request failed` / `No available accounts` | 带 `x-request-id` 重试或提交工单 |
