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

# Gemini 原生协议

> 使用模型路径、原生 contents 和 candidates 调用 Gemini。

本指南直接调用 Gemini 的 `generateContent` 协议。先确认渠道和模型支持原生 Gemini 请求；本例使用部署方签发的网关令牌，放入 `x-goog-api-key` 请求头。

## 地址与请求结构

| 项目 | 本例约定 |
| - | - |
| 请求 | `POST /v1beta/models/{model}:generateContent` |
| 根地址 | `API_ROOT_URL` 不含 `/v1` 或 `/v1beta`，允许部署路径前缀 |
| 模型 | 放在路径中，不放进请求体；使用管理员确认的裸模型 ID |
| 指令与输入 | `systemInstruction`；`contents[].parts` |
| 对话角色 | `user` / `model`，不是 `assistant` |
| 输出 | `candidates[].content.parts`；检查 `finishReason` 与 `promptFeedback` |

项目从模型路径分配渠道；请求头中的令牌用于网关认证，上游认证由渠道适配器负责。项目也接受查询参数 `key`，但本例只使用请求头，避免密钥出现在 URL 中。

## 运行准备

需要 Node.js 22.18+ 或 24；使用内置 `fetch`，无需 Google SDK。预先设置 `API_KEY`，再设置根地址与实际模型：

```sh theme={null}
export API_ROOT_URL="https://gateway.example.com"
export API_MODEL="YOUR_MODEL_ID"
# API_KEY must already be set in the process environment.
```

保存为 `native-gemini.mts` 后运行 `node native-gemini.mts`；文档目录中运行 `node examples/native-gemini.mts`。本例限制模型 ID 为字母、数字、点、下划线或连字符，拒绝 `models/` 前缀、路径和动作后缀；这是示例的地址校验范围，不是网关全部模型命名规则。

## TypeScript

完整示例：

```typescript theme={null}
const { API_ROOT_URL, API_KEY, API_MODEL } = process.env;
if (!API_ROOT_URL || !API_KEY || !API_MODEL) {
  throw new Error('Set API_ROOT_URL, API_KEY, and API_MODEL first.');
}
// This example accepts a bare model ID, without models/ or an action suffix.
if (!/^[A-Za-z0-9._-]+$/.test(API_MODEL) || ['.', '..'].includes(API_MODEL)) {
  throw new Error('Use a bare model ID containing letters, digits, dots, underscores, or hyphens.');
}

try {
  const response = await fetch(`${API_ROOT_URL.replace(/\/+$/, '')}/v1beta/models/${encodeURIComponent(API_MODEL)}:generateContent`, {
    method: 'POST', redirect: 'error', signal: AbortSignal.timeout(60_000),
    headers: { 'Content-Type': 'application/json', 'x-goog-api-key': API_KEY },
    body: JSON.stringify({
      systemInstruction: { parts: [{ text: 'Answer briefly in plain text.' }] },
      contents: [{ role: 'user', parts: [{ text: 'Say hello in one short sentence.' }] }],
    }),
  });
  if (!response.ok) {
    console.error(`Request failed (HTTP ${response.status}). No automatic retry.`);
    process.exitCode = 1;
  } else {
    const result = await response.json();
    if (result.error || result.promptFeedback?.blockReason
      || !Array.isArray(result.candidates) || result.candidates.length !== 1) {
      throw new Error('Blocked or missing candidate.');
    }
    const candidate = result.candidates[0];
    if (candidate.finishReason !== 'STOP' || candidate.content?.role !== 'model'
      || !Array.isArray(candidate.content.parts) || candidate.content.parts.length === 0) {
      throw new Error('No complete text response.');
    }
    const text = candidate.content.parts.map((part: Record<string, unknown>) => {
      if (!part || typeof part.text !== 'string' || Object.keys(part).some(
        (key) => !['text', 'thought', 'thoughtSignature'].includes(key),
      ) || (part.thought !== undefined && typeof part.thought !== 'boolean')) {
        throw new Error('Unsupported content part.');
      }
      return part.thought === true ? '' : part.text;
    }).join('');
    if (!text.trim()) throw new Error('Empty visible text.');
    console.log(text);
  }
} catch {
  console.error('Gemini request failed or did not produce complete plain text. No automatic retry.');
  process.exitCode = 1;
}
export {};
```

## 读取结果

本例要求恰好一个候选、`finishReason: STOP`、`role: model` 和非空可见文本。`promptFeedback.blockReason`、`MAX_TOKENS`、`SAFETY`、错误对象及工具/媒体块均使示例失败。它跳过标记为 `thought: true` 的文本；只有思考内容而没有可见答案也会失败。成功打印拼接后的回答，失败不输出部分答案、不跟随重定向、不自动重试。

工具调用使用 `tools[].functionDeclarations`、`functionCall` 和 `functionResponse`，不能直接复用 Chat 的工具消息。多轮时保留整个 model 内容（包括渠道返回的 `thoughtSignature` 和工具标识）再加入新 user 内容；展示时隐藏 thought 不意味着重放时可以丢弃签名。本例只展示单轮文本，不实现原生工具闭环。

## 流式路径与支持边界

原生 SSE 使用 `POST /v1beta/models/{model}:streamGenerateContent?alt=sse`。`stream: true` 加在 `generateContent` 请求体里不能代替切换动作。每个 SSE `data` 是 Gemini 响应对象，不是 Chat delta 或 Responses 的具名事件。按候选索引处理 parts 和最终 `finishReason`；HTTP 成功或 EOF 都不能单独证明正常完成。网络数据块可能截断一个 UTF-8 字符或 SSE 事件。

本文可执行示例覆盖 `generateContent` 文本响应；[原生 SSE 与工具闭环](/zh/guides/native-gemini-streaming)提供完整 Python 流式实现。图片/音频扩展与真实渠道仍需另行实现和联调。不要把 [Chat / Responses 流式工具示例](/zh/guides/streaming-tools)的事件解析器用于 Gemini。

项目未实现 `/v1beta/...:countTokens`，当前返回 404，不能依赖供应商 SDK 的计数方法。模型路由、可选字段及不同渠道的转换能力应按部署验证。

[Gemini generateContent 参考](/zh/api-reference/gemini-generate) · [错误处理](/zh/guides/errors)

协议依据：[Google generateContent / streamGenerateContent](https://ai.google.dev/api/generate-content)。项目端点和认证行为以本仓库路由及适配器为准。

[Read in English](/en/guides/native-gemini)


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