Files
oci-portal/docs/AI网关.md
T

23 KiB
Raw Blame History

AI 网关

Note

OCI Portal AI 网关将多个 OCI GenAI 渠道统一为 OpenAI、Anthropic 与 xAI 兼容接口,并集中处理鉴权、模型访问控制、渠道调度和协议适配。

路径、参数与响应结构以 Swagger YAML 或运行时 Swagger UI 为准;协议差异、兼容改写和实测边界以本文为准。

兼容快照:2026-07-15

快速导航

快速接入

基础地址与鉴权

Base URL: https://<网关地址>/ai/v1

网关密钥在管理面板中创建,支持以下任一请求头:

Authorization: Bearer sk-...
x-api-key: sk-...

密钥可绑定渠道分组和模型白名单。全局模型黑名单会同时作用于模型列表、 请求路由和探测候选;开启「过滤弃用模型」后,OCI 已宣布弃用的模型也会从 列表与路由中移除。

可先用模型列表验证地址与密钥:

curl "https://<网关地址>/ai/v1/models" \
  -H "Authorization: Bearer $OCI_PORTAL_KEY"

端点一览

协议域 端点 角色 流式
对话 POST /ai/v1/responses OpenAI Responses,无状态主接口 SSE
对话 POST /ai/v1/chat/completions OpenAI Chat Completions 兼容层 SSE
对话 POST /ai/v1/messages Anthropic Messages 转换层 SSE
向量 POST /ai/v1/embeddings OpenAI Embeddings
语音 POST /ai/v1/audio/speech OpenAI Audio Speech 外壳
语音 POST /ai/v1/tts xAI TTS 格式转换层
检索 POST /ai/v1/rerank Cohere / Jina 风格文档重排
安全 POST /ai/v1/moderations OpenAI 外壳映射 OCI Guardrails
发现 GET /ai/v1/models 当前密钥可见模型列表

选择建议:

  • 新客户端优先使用 Responses
  • Anthropic SDK 或 Claude 生态客户端使用 Messages
  • 仅支持旧 OpenAI 对话协议的客户端使用 Chat Completions
  • Embeddings、TTS、Rerank 与 Moderations 使用各自专用端点

路由与全局行为

请求链路

flowchart LR
    A[客户端] --> B[网关密钥鉴权]
    B --> C[分组、白名单与全局过滤]
    C --> D[模型与能力匹配]
    D --> E[选择最小 Priority]
    E --> F[同优先级按 Weight 加权]
    F --> G[OCI GenAI]
    G -. 可重试且流未建立 .-> D

单次请求最多尝试三个渠道。模型不可用、限流、上游服务错误或网络错误可触发 换渠道;流式连接建立后不会切换渠道重试。

全局兼容边界

主题 当前行为
会话状态 网关不保存会话历史,客户端必须在每次请求中携带完整上下文
上游存储 Responses 请求始终强制 store:false
有状态字段 Responses 拒绝非空 previous_response_id、非 nullconversationbackground:true
对话上游 对话请求统一进入 OCI OpenAI 兼容面,当前供给以 xai.meta.openai. 前缀模型为主
推理强度 Responses reasoning.effort、Messages output_config.effort、Chat reasoning_effort 会传给上游;可用档位由模型决定
服务端工具 Responses 支持 web_searchx_searchcode_interpreter 和远程 mcp;命名容器管理与 File Search 不提供
文件输入 input_file 会被 OCI ZDR 形态拒绝,详见已知限制
Chat 定位 Chat Completions 只承担协议转换与兼容修复;新能力优先落在 Responses 与 Messages

Codex 接入

主配置

自定义模型提供方必须写在用户级 ~/.codex/config.toml。Codex 的项目级 .codex/config.toml 不允许改写 model_providermodel_providers

model = "xai.grok-4.3"
model_provider = "oci"

[model_providers.oci]
name = "oci-portal"
base_url = "https://<网关地址>/ai/v1"
env_key = "OCI_PORTAL_KEY"
wire_api = "responses"

自定义子代理

新版 Codex 可在 ~/.codex/agents/ 或项目级 .codex/agents/ 放置独立 TOML 文件,并为子代理覆盖模型。每个文件都需要 namedescriptiondeveloper_instructions

# .codex/agents/oci-worker.toml
name = "oci-worker"
description = "通过 OCI Portal 网关执行通用开发任务。"
developer_instructions = """
完成被分配的开发任务,保持改动聚焦,并返回验证结果。
"""
model = "xai.grok-4.3"

Important

codex-cli 0.144.1 已实测主会话和 multi-agent 子代理全链路可用。 内置 worker 可能先尝试 gpt-5.6-lunagpt-5.4;网关没有对应渠道时 会出现少量 404,随后由 Codex 回落到可用模型。自定义 agent 的模型覆盖是否 直接生效取决于 Codex 版本;0.144.1 的实测主要依赖自动回落。

Codex 工具兼容现状:

工具形态 网关处理 验证状态
function 原样透传 可用
namespace 子工具拍平为限定名 function,响应时还原 multi-agent 已端到端实测;MCP 同路径有单测
custom 顶层普通工具转换为 function,调用与历史记录双向回转 可用,但存在降级边界
custom:apply_patch 直接剥离,让模型回落到其他编辑方式 有意限制
tool_search namespace 已完整展开,目录搜索语义冗余,直接剥离 有意降级

配置语法参考 Codex SubagentsCodex Advanced Configuration

已知限制

超大流式请求

上游流式断流有两个独立触发维度,状态不同:

Warning

instructions + tools 合计超过约 64.5 KB 的流式请求,上游会在推理阶段 静默断连(纯 EOF,无 error / 终态事件);同请求非流式总是成功,input 正文完全不计入。2026-07-13 定位(字节级二分),2026-07-16 复测仍存在 70.4 KB 断 / 59.7 KB 过,ChicagoAPI Key 与签名行为一致)。

Note

完整请求体超过约 82 KB(含 input)的纯体积断流(2026-07-15 定位) 已被上游修复2026-07-16 复核 83 KB、真实 codex 形态 104.5 KB、200 KB、 400 KB 流式均正常完成(Chicago 与 Phoenix 两区、签名与 API Key 两路径对照)。

网关当前行为:

  • Chat Completions / Messages:若上游在客户端收到任何内容前断流,自动用 非流式重做,并合成对应 chunk / event 序列(可兜住 64.5 KB 断流)
  • Responses:直通协议中途无法透明重试(客户端已收到事件)。流式保险丝按 instructions + tools 字节和判定:超过阈值时预防性改非流式上游 + 合成最小 SSE 事件序列(response.createdresponse.output_item.doneresponse.completed),语义保留但无增量输出。默认开、60 KB,可在 设置 → AI → 流式保险丝 调整或关闭
  • 已开始输出的流:不能透明重试;调用日志会记录提前终止,客户端可能只拿到 部分事件

grok 服务端搜索工具默认注入

xai. 前缀模型的 Responses 请求,网关按开关默认注入 web_search / x_search 工具;请求 tools 已包含同名工具时保持原样,不覆盖参数。默认双开, 可在 设置 → AI → grok 服务端搜索工具 关闭。

ZDR 与文件输入

Responses 的 input_file 内容块(file_url / file_data)实测会被上游拒绝:

File content is currently unsupported for ZDR customers

网关强制 store:false,属于 ZDR 请求形态,因此当前不能通过该端点上传或引用文件。

规格与实测边界

本项目提供的是兼容接口,而不是 OpenAI、Anthropic 或 xAI 协议的完整实现。 部分 OCI OpenAI 兼容行为来自实测,未见 Oracle 文档合同,可能随上游调整。

字段兼容矩阵

矩阵基线:

标记 含义
网关直接支持
➡️ 原样保留或透传;是否生效由 OCI 上游决定
🔄 网关执行字段或协议转换后支持
部分支持、存在前置条件或语义降级

OpenAI Responses

POST /ai/v1/responses · 无状态主接口

网关以原始 JSON 为基底保留未知字段,但会强制关闭上游存储,并执行下表列出的 Codex 工具兼容改写。请求会重新编码,不承诺字节级原样转发。

核心字段
标准字段 状态 网关行为
model 必填;通过密钥白名单并匹配可用渠道后送往上游
input ➡️ 支持字符串或 item 数组;普通内容保留,Codex 工具历史项可能改写
instructionsmax_output_tokens ➡️ 类型可解析后保留,不做范围或模型能力校验
temperaturetop_p ➡️ 保留,不做取值范围校验
parallel_tool_calls 通常保留;若全部工具被剥离,则与 tool_choice 一并删除
text / text.format / text.verbosity ➡️ 整个对象保留;是否生效由 OCI 模型决定
reasoning ➡️ 整个对象保留;effort 不校验档位
tool_choice 普通形态保留;namespace 对象会重限定,全部工具被剥离时删除
store 🔄 无论客户端传什么,上游请求都强制改写为 false
stream 支持 SSE;网关按 instructions+tools 字节和触发预防性非流式回退(保险丝,默认开 60 KB,见已知限制
其余标准与未知顶层字段 ➡️ context_managementincludemetadatapromptprompt_cache_keyservice_tiertruncationuser 等均保留,由 OCI 决定是否接受
工具兼容
工具或参数 状态 网关行为
tools[].type=function ➡️ 非流式与流式均可,工具对象保留
web_search / x_search / code_interpreter Oracle 文档化的 xAI 服务端工具;参数与限制遵循 xAI 规格
tools[].type=mcp ➡️ 远程 MCP 由上游直连,server_urlrequire_approvalauthorization 等保留
tools[].type=namespace 🔄 function 上提并限定命名;响应、历史调用和 tool_choice 会反向还原;组内非 function 子工具被剥离
tools[].type=custom 顶层非 apply_patch 工具转为带 input schema 的 function;响应与多轮历史双向回转;format 会删除
custom:apply_patch 整体剥离;grok 系未针对 Codex 补丁格式训练,模型应回落其他编辑方式
tools[].type=tool_search 请求可被接受,但工具本身直接剥离
web_search.external_web_access=true 🔄 删除上游不识别的字段,保留 web_search
web_search.external_web_access=false 上游没有“仅缓存检索”对应能力,按不越权原则剥离整个工具

本地拒绝(返回 400):

  • 非空 previous_response_id
  • nullconversation
  • background:true
  • 未列入白名单的工具类型,例如 web_search_previewfile_searchcomputerimage_generationshell

响应边界:

  • 无工具还原且未触发流式升级时,普通响应保持直通语义
  • namespace / custom 调用会在非流式响应与命中的 SSE data 事件中定向还原
  • 普通 SSE 不补 data: [DONE]reasoning 增量不会被过滤
  • 未知模型返回 404,无可用渠道返回 503
  • 上游错误使用 OpenAI 风格错误外壳,但不保证字段与标准 OpenAI 完全一致

OpenAI Chat Completions

POST /ai/v1/chat/completions · 存量客户端兼容层

请求先转换为 Responses,再将 OCI Responses 响应桥接回 Chat Completions。 只有下表字段会进入上游请求。

展开字段矩阵
标准字段 状态 网关行为
model 必填,受密钥白名单和可用渠道限制
messages 🔄 必填,转换为 Responses input / instructions
system / developer 消息 文本按顺序合并为 instructions;块数组中的非文本内容忽略
user / assistant 文本 🔄 字符串和 text 块分别转为 input_text / output_text
image_url URL 或 data URI 转为 input_imagedetail 忽略
assistant tool_calls / role=tool 🔄 转为 function_call / function_call_output
max_completion_tokens 🔄 转为 max_output_tokens,优先于 max_tokens
max_tokens 🔄 未提供 max_completion_tokens 时转为 max_output_tokens
temperaturetop_pparallel_tool_calls 写入 Responses,不校验范围或模型能力
stream 🔄 Responses SSE 转为 chat.completion.chunk,末尾补 data: [DONE]
stream_options.include_usage 🔄 控制终块后的独立 usage 块
tools[].type=function 支持 namedescriptionparametersstrict 忽略
tool_choice 支持 auto / none / required 和具名 function
response_format json_objectjson_schema 转为 Responses text.format
reasoning_effort 转小写后映射为 reasoning.effort
store 🔄 客户端取值忽略,上游始终使用 store:false

不支持(返回 400):input_audiofilerefusal 等消息内容块,以及 function 之外的工具类型。

静默忽略字段

消息级 name / refusal / audio / 旧式 function_callstopseednfrequency_penaltypresence_penaltylogprobstop_logprobslogit_biasuseraudiomodalitiespredictionmetadatamoderationprompt_cache_keysafety_identifierservice_tierverbosityweb_search_optionsstream_options.include_obfuscation 及其他未知字段。

响应边界:

  • 非流式固定生成一个 choices[0];文本合并,函数调用转为 tool_calls
  • finish_reason 只生成 stoptool_callslength
  • reasoning、logprobs、refusal、annotations、audio、service tier 和 system fingerprint 不返回
  • usage 保留 prompt_tokenscompletion_tokenstotal_tokensprompt_tokens_details.cached_tokens
  • 已开始输出的流中断不会转换成标准 SSE 错误事件

Anthropic Messages

POST /ai/v1/messages · Anthropic 协议转换层

支持 Authorization: Bearerx-api-key,但不校验或使用 anthropic-versionanthropic-beta 请求头。

展开顶层字段矩阵
标准字段 状态 网关行为
model 用于模型与渠道选择;空字符串通常最终返回模型不存在
max_tokens 🔄 缺省或 ≤0 时使用 8192,再转为 max_output_tokens
messages 必须非空;角色、交替顺序和空内容不做完整校验
system 支持字符串或 text 块数组;文本块拼接,附加字段忽略
temperaturetop_p 写入 Responses,不校验范围或模型能力
stream 🔄 Responses SSE 桥接为 Anthropic 标准事件序列
tools 每个工具转为 Responses function;服务端工具类型不保留原语义
tool_choice 支持 autoanynone、具名 tool
output_config.effort 🔄 转小写后映射为 reasoning.effort

内容块兼容:

messages[].content 状态 网关行为
字符串 / text 🔄 user 转 input_textassistant 历史转 output_text
image 仅支持 base64url source
tool_use 🔄 转为 function_call,保留 ID、名称与输入
tool_result 转为 function_call_output;块数组只拼接 textis_error 与非文本结果丢失
null / 空块数组 消息可能从上游 input 中消失,不返回参数错误

不支持(返回 400):document、服务端工具结果及未知内容块。历史 thinking / redacted_thinking 会删除。

静默忽略字段

top_kstop_sequencesmetadatathinkingoutput_config 其余子字段、 cache_controlcontainerinference_geoservice_tier 及其他未知顶层字段。

响应边界:

  • 仅将 Responses output_text 转为 textfunction_call 转为 tool_use
  • stop_reason 只生成 end_turntool_usemax_tokens
  • 不生成 Anthropic thinking / signature 内容块
  • usage 只保留 input_tokensoutput_tokenscache_read_input_tokens
  • 流式上游错误与无终态断流会转成 Anthropic error 事件

OpenAI Embeddings

POST /ai/v1/embeddings · 向量化专用端点

标准字段 状态 网关行为
model 必填,受白名单限制,且需要 EMBEDDING 能力渠道
字符串 input 包装为单个输入后调用 OCI
字符串数组 input 按原顺序调用 OCI
dimensions 映射为 OCI 输出维度,不校验范围或模型能力
encoding_format=float 返回 float 数组;省略时相同

不支持(返回 400):token ID 数组、空数组、nullencoding_format=base64user 与其他未知字段静默忽略。

响应使用标准 object:"list" 外壳,向量为 float32 数组,不支持流式。

语音生成

两个端点最终使用同一 OCI xAI TTS 上游与渠道调度:

OpenAI Audio Speech

POST /ai/v1/audio/speech

标准字段 状态 网关行为
model 必填,受白名单限制,需要 TTS 能力渠道;当前为 xai.grok-tts
input 必填非空,随后保留
voice ➡️ 使用 xAI 音色 ara / eve / leo / rex / sal
response_format ➡️ 实测 mp3 可用,其余格式由上游决定
language(扩展) 🔄 上游必填;缺省时注入 "auto"
speedinstructions 与未知字段 ➡️ 保留,是否生效由上游决定

xAI TTS

POST /ai/v1/tts

接受 xAI 官方 TTS 格式, 转换为 OpenAI 兼容形态后进入同一上游。

字段 状态 网关行为
text 🔄 必填非空,转换为 input
language 必填,接受 BCP-47 或 auto
voice_id 🔄 转为 voice;缺省交给上游默认值 eve
output_format ➡️ {codec, sample_rate, bit_rate} 对象保留,实测生效
speed ➡️ 保留,实测可用
model(网关扩展) 缺省注入 xai.grok-tts,可覆盖,受白名单限制
其余未知字段 ➡️ 保留,是否生效由上游决定

共同响应边界:

  • 成功响应为一次性完整音频,Content-Type 透传上游,缺省 audio/mpeg
  • 不提供 HTTP 流式音频或 WebSocket 代理
  • 无 token 用量口径,调用日志只记时延与渠道

Rerank

POST /ai/v1/rerank · Cohere / Jina 风格协议

上游走 OCI typed 面,模型为 cohere.rerank-v4.0-pro-fast

字段 状态 网关行为
model 必填,受白名单限制,需要 RERANK 能力渠道
query 必填非空
documents 仅接受字符串数组;旧版 {"text": ...} 对象数组返回 400
top_n 可选,限制返回条数
return_documents true 时回带原文

max_tokens_per_doc 与未知字段静默忽略。响应按相关度降序, results[].index 指向输入下标,relevance_score 为 0~1 浮点;无 token 用量口径。

Moderations

POST /ai/v1/moderations · OpenAI 外壳映射 OCI Guardrails

标准字段 状态 网关行为
字符串 input 单条审核
字符串数组 input 逐条审核,单次 18 条

不支持(返回 400):多模态 input、空字符串条目、空数组或超过 8 条。 model 接受但忽略,不参与白名单判断。

响应边界:

  • categories 使用 OCI 原生维度 overall / blocklist / prompt_injection
  • 任一维度得分 ≥ 0.5 时 flagged=true
  • PII 命中放在扩展字段 results[].pii,包含 textlabelscoreoffsetlength,不参与 flagged
  • 实测中文人名与手机号识别较弱,英文 PII 识别正常
  • 响应 model 恒为 oci-guardrails

Models

GET /ai/v1/models · 当前密钥可见模型列表

响应使用 OpenAI Models 列表外壳,只返回同时通过以下条件的模型:

  1. 存在于当前渠道目录
  2. 匹配密钥绑定的渠道分组
  3. 不在全局模型黑名单
  4. 命中密钥模型白名单(配置时)
  5. 未被「过滤弃用模型」开关排除

网关不提供标准的单模型检索端点。

实现索引

端点 / 能力 主要实现
Responses 直通与 Codex 工具兼容 airesponses.go · responses.go
Chat Completions 转换 chatresponses.go · openai.go
Anthropic Messages 转换 anthresponses.go · anthropic.go
渠道路由与 Embeddings aigateway_chat.go
TTS 上游 genai_speech.go · aigateway_extras.go
Rerank / Moderations 上游 genai_guard.go · rerank.go · moderations.go
HTTP Handler 与流式桥接 aigateway.go · aigateway_extras.go

本文是兼容性快照,不替代 Swagger。标准接口、Codex 客户端与 OCI 上游均可能 变化,最终行为以当前版本代码、运行时 Swagger 和实测结果为准。