# Gemini 原生兼容

Gemini 原生兼容入口用于接入会按 Google Gemini REST 形状请求 `/v1beta/models...` 的 SDK、CLI 或工具。它不是 OpenAI-compatible `/v1` 入口,Base URL 必须填服务根地址。

| 项 | 值 |
|---|---|
| Base URL | `https://api.clomio.ai`(线路可换 `https://sub.qazwc.com` / `https://crs.qazwc.com`) |
| 路径前缀 | `/v1beta` |
| Key 分组 | Google/Gemini 平台分组 |
| 推荐鉴权 | `Authorization: Bearer 你的Gemini分组密钥` 或 `x-goog-api-key: 你的Gemini分组密钥` |
| 官方形状参考 | [Gemini generateContent](https://ai.google.dev/api/generate-content)、[Gemini API versions](https://ai.google.dev/gemini-api/docs/api-versions)、[Models API](https://ai.google.dev/api/models) |

> Google GenAI SDK 默认常用 `v1beta` 以访问预览能力。Clomio 的 Gemini 原生兼容也是围绕 `/v1beta/...` 路径工作;不要把 Base URL 写成 `https://api.clomio.ai/v1`。

---

## 端点

| 方法 | 路径 | 用途 |
|---|---|---|
| `GET` | `/v1beta/models` | 列出当前 Gemini 分组可见模型 |
| `GET` | `/v1beta/models/{model}` | 查询单个 Gemini 模型元数据 |
| `POST` | `/v1beta/models/{model}:generateContent` | 非流式生成 |
| `POST` | `/v1beta/models/{model}:streamGenerateContent?alt=sse` | SSE 流式生成 |
| `POST` | `/v1beta/models/{model}:countTokens` | 计数；部分模型不支持时可能返回估算或错误 |

服务端也兼容部分 `/v1beta/models/{model}/{action}` 形态,但新接入建议使用官方冒号 action 形态,例如 `models/gemini-2.5-flash:generateContent`。路由会先接收 `POST /v1beta/models/*modelAction`，再解析 `{model}:{action}` 或 `{model}/{action}`；未知 action 会由服务返回 Google 风格 unsupported 错误。

---

## 鉴权优先级

Gemini 原生入口使用 Google/Gemini 风格鉴权。服务端按以下顺序取 Key:

1. `x-goog-api-key`
2. `Authorization: Bearer ...`
3. `x-api-key`
4. Query `key=...`(仅 `/v1beta` / `/antigravity/v1beta` 兼容)

不要使用 query `api_key=...`;该参数已废弃,会返回 400:

```json
{
  "error": {
    "code": 400,
    "message": "Query parameter api_key is deprecated. Use Authorization header or key instead.",
    "status": "INVALID_ARGUMENT"
  }
}
```

---

## generateContent 最小示例

```bash
curl https://api.clomio.ai/v1beta/models/gemini-2.5-flash:generateContent \
  -H "Authorization: Bearer 你的Gemini分组密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [{ "text": "你好,用一句话介绍 Gemini 原生接口" }]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 512,
      "temperature": 0.7
    }
  }'
```

流式 SSE:

```bash
curl 'https://api.clomio.ai/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse' \
  -H "x-goog-api-key: 你的Gemini分组密钥" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [{ "text": "用一句话回答:SSE 是什么?" }]
      }
    ]
  }'
```

---

## 常用请求字段

| 字段 | 说明 |
|---|---|
| `contents[].role` | `user` / `model` 等会话角色 |
| `contents[].parts[].text` | 文本输入片段 |
| `systemInstruction` | 系统指令 |
| `generationConfig.maxOutputTokens` | 最大输出 token |
| `generationConfig.temperature` / `topP` / `topK` | 采样参数 |
| `generationConfig.stopSequences` | 停止序列 |
| `generationConfig.thinkingConfig` | 思考/推理相关配置,是否生效取决于模型 |
| `generationConfig.imageConfig.aspectRatio` / `imageSize` | 图像相关模型的图片配置 |
| `tools[].functionDeclarations` | 函数调用声明 |
| `tools[].googleSearch` | Google Search grounding 工具声明 |
| `toolConfig` | 工具调用配置 |
| `safetySettings` | 安全设置,是否可用取决于模型 |

### `thoughtSignature` 兼容性

函数调用响应可能包含 `thoughtSignature`。继续发送工具结果时请原样保留该字段；如果客户端丢失或修改签名，Gemini 可能返回 `INVALID_ARGUMENT`。排查时保存 request_id、请求体和完整错误响应。

`countTokens` 是辅助估算端点；部分模型可能返回估算值或不支持该操作。不要把它的失败等同于主 `generateContent` 失败。

---

## 模型列表与模型名

```bash
curl https://api.clomio.ai/v1beta/models \
  -H "Authorization: Bearer 你的Gemini分组密钥"
```

返回的是 Google/Gemini 风格模型对象,模型名通常带 `models/` 前缀。请求路径里的 `{model}` 可以写 `gemini-2.5-flash`,也可以按客户端习惯由 SDK 拼出 `models/gemini-2.5-flash`。实际可见模型以当前分组模型列表为准。

不要把 Gemini 模型查询误写成 OpenAI 的 `GET /v1/models/{id}`。OpenAI-compatible 模型端点只支持 [Models](#/api-models) 里的 `GET /v1/models` 列表;Gemini 单模型查询走本页的 `GET /v1beta/models/{model}`。

---

## Google 风格错误体

Gemini 原生入口的错误体更接近 Google API 风格:

```json
{
  "error": {
    "code": 401,
    "message": "Invalid API key",
    "status": "UNAUTHENTICATED"
  }
}
```

鉴权、分组、路径、限流和计费错误都会按这个结构返回,固定包含 `error.code`、`error.message`、`error.status`。`status` 是 Google RPC 风格字符串,例如 400 → `INVALID_ARGUMENT`、401 → `UNAUTHENTICATED`、403 → `PERMISSION_DENIED`、429 → `RESOURCE_EXHAUSTED`。

| 状态码 | message / 关键词 | 含义与处理 |
|---:|---|---|
| 400 | `API key group platform is not gemini` | Key 不是 Gemini 分组;换 Gemini 分组 Key |
| 400 | `Missing model in URL` / `Missing action in URL` | 路径缺模型或 action;检查 `/v1beta/models/{model}:generateContent` |
| 400 | `Request body is empty` / `Failed to read request body` | Body 为空或无法读取 |
| 401 | `API key is required` / `Invalid API key` / `API key is disabled` | Key 缺失、错误或禁用 |
| 401 | `User associated with API key not found` / `User account is not active` | Key 绑定用户异常 |
| 403 | `No active subscription found for this group` | 分组需要有效订阅 |
| 403 | `Insufficient account balance` | 余额不足 |
| 403 | `API Key is not assigned to any group...` | Key 未绑定分组 |
| 404 | `missing path` / `invalid model action path` / `Unsupported action: ...` | 路径或 action 不支持 |
| 413 | `Request body too large...` | 请求体过大 |
| 429 | `Upstream rate limit exceeded, please retry later` | 请求频率过高;降并发后重试 |
| 502 | `Upstream authentication failed` / `Upstream access forbidden...` / `Upstream request failed` | 上游鉴权或请求失败，带时间和错误体提交工单 |
| 503 | `No available Gemini accounts` / `Upstream service overloaded...` | 当前 Gemini 服务暂时不可用或上游过载 |

上游 failover 耗尽时有一个例外:如果最后一个 Gemini 上游返回了非空响应体,网关会优先保留该上游状态码、响应头和原始 body。此时 body 可能仍是 Google 风格 JSON,也可能是上游自己的 JSON/text;排障时请同时保存 HTTP status、`x-request-id`/`x-goog-request-id`、响应体和 Clomio request_id。只有没有可透传 body 时,才会映射成上表里的 `Upstream ...` 消息。

---

## 和其他入口的边界

- OpenAI SDK / Codex / Grok 仍用 `https://api.clomio.ai/v1`,不要改成本页 Base URL。
- Claude Code / Anthropic SDK 用 `https://api.clomio.ai`,但请求形状是 `/v1/messages`,不是 `/v1beta/models...`。
- Antigravity 专用入口也不带 `/v1`,但路径以 `/antigravity/...` 开头,见 [Antigravity 接入](#/antigravity)。
- Videos 仅 Grok 分组支持;Gemini 原生入口不提供 `/v1/videos/*`。

## 字段约束速查

| 字段 | 可选值/范围 | 说明 |
|---|---|---|
| URL action | `generateContent`、`streamGenerateContent`、`countTokens` | action 必须和模型路径绑定 |
| `contents[].role` | `user` / `model` | 多轮消息按时间顺序排列 |
| `parts[]` | `text`、`inlineData`、`fileData`、`functionCall`、`functionResponse` | 图片/文件使用对应结构 |
| `generationConfig.temperature` | `0` 至 `2` | 随机性 |
| `generationConfig.topP` | `0` 至 `1` | 核采样 |
| `generationConfig.topK` | 正整数 | 候选采样数量 |
| `generationConfig.maxOutputTokens` | 正整数 | 输出上限 |
| `generationConfig.candidateCount` | 正整数，通常为 `1` | 多候选能力以上游模型为准 |
| `safetySettings[].threshold` | `BLOCK_NONE`、`BLOCK_ONLY_HIGH`、`BLOCK_MEDIUM_AND_ABOVE`、`BLOCK_LOW_AND_ABOVE` | 类别由 Google API 定义 |

## 完整请求示例：多模态与流式

```bash
curl 'https://api.clomio.ai/v1beta/models/gemini-2.5-flash:generateContent' \
  -H 'Authorization: Bearer 你的 Gemini 分组密钥' \
  -H 'Content-Type: application/json' \
  -d '{
    "contents":[{"role":"user","parts":[
      {"text":"描述这张图片"},
      {"inlineData":{"mimeType":"image/png","data":"BASE64_DATA"}}
    ]}],
    "generationConfig":{"temperature":0.2,"topP":0.9,"maxOutputTokens":512}
  }'
```

流式请求追加 `?alt=sse` 并使用 `:streamGenerateContent`；每个 SSE 块都是 Gemini response 增量对象，客户端应合并 `candidates[].content.parts[]`。

## 错误速查

| HTTP | `error.status`/关键词 | 处理 |
|---:|---|---|
| 400 | `INVALID_ARGUMENT`、`Missing model/action` | 检查 URL、JSON 和字段范围 |
| 401 | `UNAUTHENTICATED` | 检查 `x-goog-api-key`/Authorization |
| 403 | `PERMISSION_DENIED`、余额/订阅不足 | 检查分组和账户额度 |
| 404 | `NOT_FOUND`、模型或 action 不存在 | 使用 `/v1beta/models` 返回的模型 |
| 429 | `RESOURCE_EXHAUSTED` | 降低 RPM/并发，按 Retry-After 重试 |
| 500/502/503 | Gemini 服务或上游暂时不可用 | 记录 `x-request-id`、`x-goog-request-id` 和原始 body |
