Gemini Enterprise Agent Platform
Gemini Enterprise Agent Platform 是 Google Cloud 面向 Gemini 和合作伙伴模型的托管平台现用名称,之前的文档将其称为 Vertex AI。AISIX 为应用提供统一的兼容 OpenAI API,以调用该平台托管的模型。
此配置适用于需要使用 AISIX 认证、模型允许列表、速率限制和用量核算的 Agent Platform 模型。为保持兼容性,AISIX 继续使用 google-vertex 作为服务提供方标识符,使用 vertex 作为适配器标识符。AISIX 使用 GCP OAuth2 Bearer Token 向 Agent Platform API 认证,并可从服务账号密钥签发该 Token。
准备工作
开始前,请准备以下内容:
- 一套 AISIX 环境:
- 对于 AISIX Enterprise 或 AISIX Cloud,需要一个已关联网关的环境和具有写入作用域的 Admin Token。使用 AISIX Enterprise 时,请按照 AISIX Enterprise 快速入门操作。如需申请 AISIX Cloud 访问权限,请联系 API7。
- 对于开源 AISIX 网关,请准备本地 AISIX 安装,或使用开源 AISIX 网关快速入门中的 Docker 环境。配置网关以加载声明式资源文件。
- 已在目标 GCP 项目中启用 Agent Platform API(
aiplatform.googleapis.com)。 - 目标模型支持的 Agent Platform 位置,以及拥有 Agent Platform User(
roles/aiplatform.user)角色的服务账号。当前 Gemini 示例使用global。 - GCP 项目 ID 和 Agent Platform 模型 ID。
curl和jq。
使用 AISIX Enterprise 或 AISIX Cloud 配置
导出控制面连接信息:
# AISIX_CP 是 Admin API 基础 URL;应包含 /api,且不含尾部斜杠
# 本地私有化部署快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CONTROL_PLANE_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
创建 Agent Platform 服务提供方密钥、模型别名和调用方 API Key。服务提供方密钥存储 GCP 项目、位置和凭证模式;模型则选择发布方模型 ID。
创建 Agent Platform 服务提供方密钥
使用 GCP 凭证设置创建服务提供方密钥:
PROVIDER_KEY_ID=$(curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "vertex-prod",
"provider": "google-vertex",
"api_base": "https://aiplatform.googleapis.com",
"config": {
"project": "my-gcp-project",
"region": "global",
"service_account_json": {
"type": "service_account",
"private_key": "-----BEGIN PRIVATE KEY-----\nYOUR_SERVICE_ACCOUNT_PRIVATE_KEY\n-----END PRIVATE KEY-----\n",
"client_email": "vertex-sa@my-gcp-project.iam.gserviceaccount.com",
"token_uri": "https://oauth2.googleapis.com/token"
}
},
"allowed_environments": ["'"$ENV_ID"'"]
}' | jq -r '.provider_key.id')
❶ provider 选择 Agent Platform 的兼容性目录条目,该条目通过 vertex 协议适配器路由流量。
❷ AISIX Cloud 要求为此平台服务提供方设置 api_base。对于 global 位置,请使用 https://aiplatform.googleapis.com;https://global-aiplatform.googleapis.com 并非全局端点。对于区域位置,请使用与 config.region 匹配的 https://<region>-aiplatform.googleapis.com。代理或私有端点可以替代任一 Origin。
❸ config 是结构化凭证,包含 project、region,且必须恰好包含一种凭证模式。示例使用嵌套对象形式的 service_account_json。也可以把它作为包含密钥文件 JSON 文本的字符串发送;控制面会解析该字符串并存储解析得到的对象。通过 config 提供凭证时,请省略 api_key;此服务提供方会拒绝非空的 api_key。
控制面会在创建服务提供方密钥和轮换其凭证时检查 service_account_json。该对象的 type 必须为 service_account,private_key 必须是以 -----BEGIN 开头的 PEM 编码密钥,client_email 和 token_uri 必须是非空字符串。未通过这些检查的值(包括无法解析为 JSON 对象的字符串)会被以 400 拒绝,错误消息会点名该字段。在此检查之前以字符串形式保存 service_account_json 的服务提供方密钥,存储的是字符串,网关无法加载,因此其上的每个请求都会失败;重新保存一次其凭证即可修复。
除非你已经自行管理短期 GCP 访问 Token,否则请使用 service_account_json。AISIX 会签名 JWT、签发并缓存 OAuth Token,并在到期前刷新。如果使用 access_token,你需要负责刷新它。当前适配器不会发现应用默认凭证、元数据服务器凭证或工作负载身份联合凭证。
服务提供方密钥中的机密信息遵循服务提供方密钥中介绍的凭证处理行为。
该命令保存返回的服务提供方密钥 ID,以供模型资源使用。allowed_environments 允许该环境引用此密钥。
创建模型
将面向调用方的别名映射到 Agent Platform 模型 ID:
MODEL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "gemini-prod",
"model_name": "gemini-3.6-flash",
"provider_key_id": "'"$PROVIDER_KEY_ID"'"
}' | jq -r '.model.id')
❶ model_name 是 Agent Platform 发布方模型 ID。当前示例 Gemini 3.6 Flash 已在 global 正式发布。Google 说明该模型会忽略自定义 temperature、top-P 和 top-K 值,因此通过 AISIX 调用时请省略 temperature 和 top_p。请求还必须以用户消息结尾。Google 会拒绝最后一轮角色为 model 的 GenerateContent 请求,而 AISIX 会将最后一条 OpenAI assistant 消息映射为该角色。
❷ provider_key_id 将模型关联到上一步保存的 Agent Platform 凭证。
其他受支持的示例包括 Agent Platform 上的 Claude、Llama 等兼容 OpenAI 的 MaaS 模型,以及 Mistral 和 AI21 的合作伙伴发布方模型。
AISIX 根据 model_name 选择 Agent Platform 路由:
| 模型 ID 系列 | AISIX 如何将其发送到 Agent Platform |
|---|---|
Gemini 模型,例如 gemini-* | 使用 Google Gemini 发布方路由。 |
Claude 模型,例如 claude-* | 使 用 Anthropic 发布方路由,并采用 Anthropic Messages 请求体。 |
| 兼容 OpenAI 的 MaaS 模型,例如 Llama、DeepSeek、Qwen、GPT-OSS、MiniMax、Moonshot 或 Z.ai | 使用 Agent Platform 兼容 OpenAI 的 chat-completions 路由。 |
| Mistral 和 AI21 模型 | 使用合作伙伴发布方路由,并采用兼容 OpenAI 的请求体。 |
创建调用方 API Key
创建可访问 Agent Platform 模型别名的 API Key 资源。服务器会生成密钥,并仅返回一次明文:
AISIX_API_KEY=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/api_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "vertex-caller",
"allowed_models": ["'"$MODEL_ID"'"]
}' | jq -r '.plaintext')
allowed_models 通过 ID 引用模型,因此调用方只能使用 Agent Platform 别名。请安全存储明文密钥;读取端点不会再次返回它。
使用开源 AISIX 网关配置
对于开源网关,请设置 adapter: vertex,并将项目、区域和凭证模式放入服务提供方密钥的 api_key 值中。以下示例从环境变量读取结构化凭证:
export VERTEX_CREDENTIAL='{"project":"my-gcp-project","region":"global","service_account_json":{"type":"service_account","private_key":"-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----\n","client_email":"vertex-sa@my-gcp-project.iam.gserviceaccount.com","token_uri":"https://oauth2.googleapis.com/token"}}'
对于新网关,请使用此完整资源文件。对于现有网关,请将这些条目合并到其当前文件中,并保留其他资源:
_format_version: "1"
provider_keys:
- display_name: vertex-prod
provider: google-vertex
adapter: vertex
api_key: ${VERTEX_CREDENTIAL}
api_base: https://aiplatform.googleapis.com
models:
- display_name: gemini-prod
provider: google-vertex
model_name: gemini-3.6-flash
provider_key: vertex-prod
api_keys:
- display_name: vertex-caller
key_env: VERTEX_CALLER_KEY
allowed_models:
- gemini-prod
凭证必须包含 project、region,以及 access_token 或 service_account_json 中的恰好一个。在资源文件中,service_account_json 必须是密钥文件的 JSON 对象,而不是包含其内容的字符串。对于其他 Agent Platform 发布方,请使用上文介绍的相同 model_name 值。
对于 AISIX OSS 的标准 Agent Platform 位置,可以省略 api_base。AISIX 会根据凭证中的 region 推导 Origin:global 使用 https://aiplatform.googleapis.com,us 和 eu 多区域分别使用 https://aiplatform.us.rep.googleapis.com 和 https://aiplatform.eu.rep.googleapis.com,us-central1 等区域位置使用 https://<region>-aiplatform.googleapis.com。代理、私有端点或其他端点覆盖需要显式设置 api_base。
导出调用方密钥:
export VERTEX_CALLER_KEY="YOUR_CALLER_API_KEY"
如果 AISIX 安装在本地,请在加载前验证文件:
aisix validate --resources resources.yaml
验证后,在网关进程环境中提供文件引用 的环境变量,再启动网关。仅当这些变量已经可供进程使用时,才重新加载现有网关;否则,请使用更新后的环境重启网关。
如果使用 Docker,请调整开源 AISIX 网关快速入门中的验证和启动命令。挂载此 resources.yaml 文件,并在两个命令中使用 -e 传入它引用的每个环境变量。资源加载后,为通用验证请求设置 AISIX_API_KEY:
export AISIX_API_KEY="$VERTEX_CALLER_KEY"
验证服务提供方连接
导出 AISIX 网关 Origin:
# AISIX_PROXY 不含尾部斜杠或端点路径
# 本地快速入门使用 http://127.0.0.1:3000
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
通过 AISIX 代理发送 chat-completions 请求。示例使用 Gemini。Gemini 本身会拒绝不含用户或助手消息的请求,因此当请求只包含 system 或 developer 消息时,AISIX 会代为补上一条空白的用户消息,模型据此按系统指令作答。
curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-prod",
"messages": [
{
"role": "user",
"content": "Say hello from Agent Platform."
}
]
}'
网关返回兼容 OpenAI 的响应,其中包含面向调用方的别名:
{
"object": "chat.completion",
"model": "gemini-prod",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello from Agent Platform!"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 4,
"completion_tokens": 4,
"total_tokens": 8
}
}
在 Agent Platform 日志、指标、配额用量或服务提供方侧请求记录中查找测试请求。如果 AISIX 返回 Token 签发或上游认证错误,请检查服务账号密钥、位置、Agent Platform API 启用状态、IAM 角色和模型访问权限。
端点和内容支持
Agent Platform 提供的能力多于当前 AISIX vertex 适配器能够转换的范围。网关行为同时取决于调用方路由和 model_name 所选择的发布方系列。
| 路由 | 使用 google-vertex 服务提供方密钥时的行为 |
|---|---|
/v1/chat/completions | 支持,包括流式传输。Gemini 发布方转换接受文本、图片、音频、视频和文件内容作为输入,返回推理内容和生成的图片,并支持函数调用;Claude 转换接受图片和 PDF 文档作为输入。其他合作伙伴发布方的行为取决于其协议。 |
/v1/embeddings | 支持 Google 发布方的文本嵌入模型,例如 gemini-embedding-001。AISIX 将文本输入发送到 publishers/google/models/<model>:predict;不支持合作伙伴和多模态嵌入格式。这些模型只接受文本,Token ID 形式的输入会以 400 拒绝。使用 gemini-embedding-001 时,每个请求只发送一个输入字符串。AISIX 会将输入数组作为一个上游请求转发,但该模型只接受一个输入,包含多项的数组可能被拒绝。 |
/v1/responses | 通过基于 Chat 的 Responses 桥接支持,并非原生 Agent Platform Responses 端点。text.format 会转换为聊天的 response_format,并按 Gemini 上的结构化输出传达给模型。其他没有 Chat 等价项的字段会被忽略。 |
/v1/messages | Claude 模型使用 Agent Platform 自己的 Anthropic Messages API,/v1/messages/count_tokens 使用其 Token 计数 API,参见 Agent Platform 上的 Claude。其他发布方通过转换为 Chat 支持,且无法使用 /v1/messages/count_tokens。 |
/v1/completions | vertex 适配器不支持。 |
/v1/images/generations、/v1/audio/*、/v1/videos 和 /v1/rerank | vertex 适配器或这些路由的服务提供方规则不支持,即使 Agent Platform 另有原生媒体服务。Gemini 图片模型改为通过 /v1/chat/completions 生成图片,参见 Gemini 上的图片。 |
/v1/files、/v1/batches 和 /v1/fine_tuning/jobs | 不支持,因为 AISIX 作业接口不接受 vertex 适配器。 |
/passthrough/google-vertex/* | 即使配置了透传路由,也不能作为调用原生 Agent Platform API 的变通方案。透传路由会绕过适配器,因此凭证注入既不会从服务账号 JSON 签发 OAuth Token,也不会从结构化凭证提取访问 Token。 |
对于 Gemini 发布方模型,AISIX 会序列化文本部分、媒体内容、系统指令、Gemini 上的生成设置所述的生成设置和函数调用,详见 Gemini 上的函数调用。内联媒体以 inlineData 发送。调用方的 format 或 URL 中的扩展名指明了媒体类型时,gs:// 或 https:// URL 以 fileData 交给 Gemini 自行读取;否则以及 http:// URL 都由网关下载后内联发送。参见媒体输入与 URL 获取。响应中的函数调用会以工具调用的形式返回,思考文本作为推理内容返回,生成的图片按 Gemini 上的图片所述返回。其他非文本响应部分(例如音频)不会返回。
Agent Platform 返回的错误会带着它自己的错误信息原文传给调用方;没有错误信息的错误以状态码命名。
Gemini 上的生成设置
AISIX 会把 Gemini 定义了的每个 OpenAI chat 字段按原值写入其 generationConfig 字段,Agent Platform 拒绝的取值由 Agent Platform 返回错误。通用规则参见请求参数处理。
| 请求字段 | Gemini 字段 |
|---|---|
temperature、top_p | temperature、topP |
max_completion_tokens,缺省时为 max_tokens | maxOutputTokens |
stop | stopSequences;单个字符串以单元素数组发送。/v1/messages 请求的 stop_sequences 以 stop 到达这里。 |
seed、presence_penalty、frequency_penalty | seed、presencePenalty、frequencyPenalty |
n | candidateCount |
logprobs、top_logprobs | responseLogprobs、logprobs |
来自 /v1/messages 请求的 top_k | topK |
reasoning_effort | thinkingConfig,见下文。 |
modalities | responseModalities,转为大写,且只在请求发送时写入。参见 Gemini 上的图片。 |
response_format | 参见 Gemini 上的结构化输出。 |
在 Gemini 3 及更新版本,以及 AISIX 无法识别为更早代次的模型名上,reasoning_effort 会变成 thinkingConfig.thinkingLevel:minimal、low、medium 和 high 分别以 MINIMAL、LOW、MEDIUM 和 HIGH 发送。在 Gemini 2.5 上,它会变成 thinkingConfig.thinkingBudget,使用 Google 为其 OpenAI 兼容端点公布的预算:minimal 和 low 为 1024,medium 为 8192,high 为 24576。在 Gemini 2.5 Flash 和 Flash-Lite 上,none 对应预算 0。用 budget_tokens 开启 thinking 的 /v1/messages 请求会改为把这个精确预算发给 Gemini 2.5,因此超过模型上限的预算会收到 Agent Platform 自己的 400,例如 gemini-2.5-flash 上的 thinking_budget is out of range; supported values are integers from 1 to 24576。模型没有对应设置的档位(例如 max、xhigh,以及 Gemini 2.5 Pro 或 Gemini 3 上的 none),以及更早模型上的所有档位,都不会设置预算或等级。但这不代表请求一定成功:要求推理内容的调用方仍会发送 includeThoughts,部分模型会拒绝它,详见 Gemini 上的推理内容。
service_tier 为 flex 或 priority 时,以 X-Vertex-AI-LLM-Shared-Request-Type 请求头发送,用于选择 Agent Platform 的 Flex PayGo 或 Priority PayGo。auto、default 和 scale 在 Agent Platform 上没有对应设置,会被丢弃。服务提供方密钥的 request.default_headers 或转发的调用方请求头为该请求头提供的值优先。
Gemini 返回的每个 candidate 都会成为一个 choice,按其 candidate 索引编号,流式和 非流式请求都是如此;candidate 的 logprobsResult 作为该 choice 的 logprobs 返回。被 Gemini 拦截的提示词(返回 promptFeedback.blockReason 且没有 candidate)以 content_filter 结束,content 为 null。
其他 chat 字段在 Gemini 请求中没有位置,会被丢弃。只携带回放推理内容的 assistant 轮次(无论推理内容是 reasoning_content,还是 Mistral thinking、Databricks reasoning 等推理内容部件)会被排除在 contents 之外。AISIX 会以点名字段的 400 invalid_request_error 拒绝以下取值:不是字符串的 stop、reasoning_effort 或 service_tier,以及不是对象、或 type 不是 text、json_object、json_schema 的 response_format。1.7.0 及更早版本的网关只向 Gemini 发送 temperature、top_p、输出上限和结构化输出字段。
Gemini 上的推理内容
AISIX 只在调用方要求推理内容时才向 Gemini 请求思考内容。在 Gemini 2.5 及更新版本,以及 AISIX 无法识别为更早代次的模型名上,这样的请求会带上 thinkingConfig.includeThoughts: true,与 Gemini 上的生成设置所述的预算或等级并列。
| 路由 | 视为调用方要求推理内容的条件 |
|---|---|
/v1/chat/completions | reasoning_effort 非空且不是 none。 |
/v1/messages | thinking.type 为 enabled 或 adaptive,且 thinking.display 不是 omitted。单独发送 output_config.effort 不算。 |
/v1/responses | reasoning.effort 非空且不是 none。 |
实际设置关闭了思考时,AISIX 不发送 includeThoughts:/v1/messages 的 thinking.budget_tokens 为 0,或者 effort 被 effort 映射改写成 none。只由映射写入的 effort 不算调用方要求:它仍会设置预算或等级,但 Gemini 不会为它返回思考内容。
无论请求如何设置,思考部分都不会进入答案文本。其文本会原样放入调用方所用路由的推理字段:
/v1/chat/completions上是message或delta中的reasoning_content。/v1/messages上是signature为空的thinking块。/v1/responses上是reasoning项。
在流式响应中,只含思考内容的帧会在到达时立即发送,因此第一个事件可能是推理内容而不是文本。Gemini 也可能在没有被要求时发送思考内容:gemini-nano-banana-2.1 就是如此,所以未要求推理内容的客户端仍可能看到该模型返回的 reasoning_content。对话历史中的推理内容不会发回 Gemini,生成的推理内容也不在输出安全护栏的范围内。
没有对应 Gemini 设置的 effort(例如 max 或 xhigh),在调用方要求推理内容时只会单独发送 includeThoughts。默认不思考的模型会以自己的 400 拒绝,AISIX 将其透传:Thinking_config.include_thoughts is only enabled when thinking is enabled。这一结果实测于 gemini-2.5-flash-lite、gemini-2.5-flash-image 和 gemini-3.5-transcribe。对这些模型请发送其支持的档位,或者不发送 effort。
1.8.0 或更早版本的网关从不向 Gemini 请求思考内容,因此调用方收不到推理内容,向上述模型发送 max 或 xhigh 的请求会返回 200。
Gemini 上的图片
Agent Platform 上的 Gemini 图片模型(例如 gemini-nano-banana-2.1 和 gemini-2.5-flash-image)在 /v1/chat/completions 上返回生成的图片,流式和非流式都支持。每张图片是 message.images 中的一个条目,流式响应中则是 delta.images 中的一个条目:
{"type":"image_url","image_url":{"url":"data:image/png;base64,...","detail":"auto"},"index":0}
图片不会进入 content,文本部分的行为不变。1.8.0 或更早版本的网关不返回生成的图片。
图片只在 Chat 上返回。/v1/messages 和 /v1/responses 会丢弃图片并保留文本,因此在这两个路由上,只有图片的答案可能是内容为空的 200。/v1/images/generations 不接受此适配器。
读取最后一个条目得到最终图片。思考图也会返回,并按响应顺序排列;index 是图片在响应中的位置,流式响应中跨帧累计。没有任何标记说明哪张是最终图。实测中,gemini-nano-banana-2.1 常返回两张几乎相同的图片,最终图在最后;gemini-2.5-flash-image 返回一张。
如果非流式图片请求在解码响应时失败,请关闭上游压缩。当 AISIX 返回 502 upstream_decode_error,消息为 upstream returned an unparseable body: error decoding response body 时,请在服务提供方密钥上设置 accept-encoding: identity 后重试:
{
"request": {
"default_headers": {
"accept-encoding": "identity"
}
}
}
在资源文件中,在服务提供方密钥下写入相同的值:
request:
default_headers:
accept-encoding: identity
request.default_headers 的生效方式参见上游请求头。另外,单张图片的 base64 超过 16 MiB(单个流式帧的上限)时,流式响应会在 200 之后报错。
用 modalities 选择输出。AISIX 只在客户端发送 modalities 时才将其大写后写入 generationConfig.responseModalities,不按模型列表检查。实测中,["text", "image"] 和 ["image"] 在上述两个模型上可用;["text"] 在这两个模型上都会收到上游的 400,AISIX 将其透传。
改图时把图片放进 user 消息。对话历史中的 assistant images 发回 Gemini 时不带 thoughtSignature,因此在 gemini-nano-banana-2.1 上不适合用来改图:实测中模型看不到原图,prompt_tokens 为 12,图像 Token 为 0,结果换了场景。请改为把图片放进 user 消息的 image_url 部分。同样的测试保留了原图场景,prompt_tokens 为 1125,其中图像 Token 为 1120。在 gemini-2.5-flash-image 上,两种写法效果没有差别。
{
"model": "gemini-image",
"modalities": ["text", "image"],
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "把天空改成阴天。"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}}
]
}
]
}
回放的 data: URL 以 inlineData 发送,媒体类型已知的 gs:// 或 https:// URL 以 fileData 发送。AISIX 无法写入的条目会在联系上游之前以 400 invalid_request_error 拒绝,并指明 messages[i].images[j]。这包括 http:// URL,因为 AISIX 只为 user 轮次下载媒体。images 不是数组时同样会被拒绝。
被拒绝和失败的图片以 content_filter 结束。Gemini 的 IMAGE_PROHIBITED_CONTENT、NO_IMAGE、IMAGE_OTHER 和 IMAGE_RECITATION 与 IMAGE_SAFETY 一样映射为 content_filter,响应同时带文字时也是如此。响应仍是 HTTP 200:
| 路由 | 结果 |
|---|---|
/v1/chat/completions | finish_reason: content_filter |
/v1/messages | stop_reason: refusal |
/v1/responses | status: incomplete,并带 incomplete_details.reason: content_filter |
安全护栏读取文本,不读取图片。输出安全护栏不扫描生成的图片,也不会因图片而阻断,规则与图片生成相同。同一响应中的文本照常扫描、脱敏和阻断,文本匹配类安全护栏会放行只有图片的响应。custom 安全护栏对没有文本的响应仍会判定 ,因此可能阻断只有图片的响应,参见钩子收到什么。
图片不进入记录和缓存。生成的图片数据不会进入用量事件、访问日志或导出器,即使设置了 content_mode: full。在 content_mode: full 下,客户端发送的输入图片会导出为一个 part,其中的 base64 换成占位符,http 或 https 图片 URL 保持原样,详见采集内容中的 Base64 媒体。含图片的响应不会写入响应缓存。
Gemini 上的响应 ID
客户端收到的 id 取决于路由:
| 路由 | id |
|---|---|
/v1/chat/completions,非流式 | Gemini 的 responseId。Gemini 未返回时,为网关生成的 chatcmpl-<uuid>。 |
/v1/chat/completions,流式 | 从第一个带 responseId 的帧起,后续每一帧都使用该值。此前的帧共用一个生成的 chatcmpl-<uuid>;整个流都没有 responseId 时,全程使用同一个生成的 ID。 |
/v1/messages,非流式 | Gemini 的 responseId。Gemini 未返回时,为网关生成的 msg_<uuid>。 |
/v1/messages,流式 | 网关生成的 msg_<uuid>,不会是 responseId。 |
/v1/responses | 网关生成的以 resp_ 开头的 ID,不会是 responseId。 |
客户端可以依赖这些路由上的 id 不为空,但不能依赖 id 就是 Google 给出的 ID,也不能依赖聊天流第一帧的 id 与最后一帧相同。
要在 Google 的记录中查找某次调用,请读取 provider_request_id。三个路由上它都记录 responseId,因此控制面的用量记录和导出中都有值,其中 OTLP 和 Datadog 把它命名为 gen_ai.response.id。生成的 ID 不会记录到这个字段。
其它由 AISIX 转换响应的上游未返回 ID 时,同样会得到生成的 ID。1.8.0 及更早版本的网关在 /v1/chat/completions 和非流式 /v1/messages 上对 Gemini 返回空 id,provider_request_id 也不记录 responseId。
Gemini 上的 Token 用量
AISIX 会将 Agent Platform 的各项 Token 计数映射到规范化响应,而不只是它们的总和。思考 Token(thoughtsTokenCount)按 Google 的计费口径计入 completion_tokens,并在 completion_tokens_details.reasoning_tokens 中单独标明。上下文缓存命中(cachedContentTokenCount)仍是 prompt_tokens 的子集,在 prompt_tokens_details.cached_tokens 中报告。
以上是 Chat Completions 的字段名。同样的数值到达 Responses 调用方时叫 output_tokens_details.reasoning_tokens 和 input_tokens_details.cached_tokens;Anthropic Messages 调用方看到的缓存命中是 cache_read_input_tokens,且没有单独的 reasoning 计数器——该协议本身没有这一概念。
用量记录保留的是 Gemini 自己的计数,而不是调用方看到的数值。当 Gemini 把思考 Token 报告在 candidatesTokenCount 之外时,记录中的 completion_tokens 为 candidatesTokenCount,reasoning_tokens 为 thoughtsTokenCount,total_tokens 为 totalTokenCount。这仅在提示词 + 补全 + 推理 Token 之和等于该总数时适用。如果 Gemini 没有上报总数,或上报的总数与这些计数对不上,记录会像 1.4.0 及更早版本的网关对所有 Gemini 响应所做的那样,把思考 Token 计入 completion_tokens。控制面对这两种形式的计价结果相同,详见推理 Token 如何计费。
Gemini 上的函数调用
Gemini 发布方模型在 /v1/chat/completions、/v1/messages 和 /v1/responses 上支持函数调用,流式和非流式均可。Messages 和 Responses 请求经由 Chat 转换到达 Gemini,因此以下规则对三个路由都适用:
tools中的函数工具会作为函数声明发送给 Gemini。在 Gemini 2.5 及更新版本(包括-latest别名)上,函数的parameters原样作为parametersJsonSchema发送。在更早的系列上,当 Gemini 的类型化parametersschema 子集能够表达时,AISIX 会将其转换为该 schema;无法表达时(例如使用了oneOf、allOf、const或非字符串的enum),原样作为parametersJsonSchema发送。1.7.0 及更早版本的网关对 Gemini 2.5 模型也会转换为类型化 schema,从而去掉additionalProperties。tool_choice映射为 Gemini 的函数调用模式:none、auto和required分别对应NONE、AUTO和ANY;指定函数名时对应仅允许该函数的ANY。required模式的allowed_tools对应仅允许所列函数的ANY;auto模式下不设置模式。- 旧版
functions和function_call字段会作为函数声明和函数调用模式发送,参见旧版函数调用。 - OpenAI 的
custom工具接收自由文本,Gemini 没有对应的声明,因此会被丢弃。 - Gemini 返回的每个函数调用都会成为一个独立的工具调用,并行调用也是如此。流式响应中,每个调用会以完整形式到达,并带有各自的
index。以函数调用结束的轮次,其结束原因为tool_calls,在 Messages 和 Responses 上则为对应的结束原因。 - 对话历史中的助手工具调用和工具结果会以函数调用和函数响应的形式发回 Gemini。值为 JSON 对象的工具结果会直接作为函数响应发送;其他结果则以
{"content": "<text>"}形式发送。
原样回传工具调用 ID。 Gemini 3 要求在下一次请求中随函数调用一并回传它返回的思维签名,而任何客户端协议都没有承载该签名的字段。 因此,AISIX 会把签名附加在返回的工具调用 ID 上,格式为 <id>__thought__<signature>。这类 ID 比通常的更长,但只包含字母、数字、_ 和 -。请在重放的助手轮次和对应的工具结果中都原样回传每个 ID,让 Gemini 拿回自己的签名。当 Gemini 3 的历史中没有签名时(例如该历史由其他模型生成),AISIX 会改为发送 Google 文档中给出的占位签名。
签名只供 Gemini 使用。当在 Agent Platform Gemini 模型上开始的对话转到其他任何上游继续时,AISIX 会移除 __thought__ 后缀,只发送基础 ID,使对话可以在服务提供方之间切换。安全护栏从不读取工具调用 ID,因此既不扫描基础 ID,也不扫描签名,但仍会扫描函数名称和参数。请参阅安全护栏行为。
以下情况 AISIX 会返回 400 invalid_request_error,而不是直接丢弃:
- 既不是函数工具也不是
custom工具的工具,例如托管的网页搜索工具。不支持 Gemini 内置工具。 - 不是数组的
tools,或没有名称的函数工具。 none、auto、required以外的tool_choice字符串,其他类型或未指定函数名的tool_choice对象,或数字、布尔值形式的tool_choice。即使请求没有发送工具,也会做此检查。- 在更早的助手轮次中找不到对应工具调用的工具结果。
- 参数不是合法 JSON 的重放助手工具调用。