Files
oci-portal/docs/AI网关.md
T
wangdefa 7002e42c06
CI / test (push) Successful in 21s
美化项目与AI网关文档
2026-07-16 12:47:57 +08:00

25 KiB
Raw Permalink Blame History

OCI Portal logo

AI 网关

将多路 OCI Generative AI 统一为 OpenAI、Anthropic 与 xAI 兼容接口

OpenAI Anthropic xAI Streaming

快速接入 · 端点一览 · 路由机制 · Codex 接入 · 已知限制 · 兼容矩阵

Note

网关集中处理密钥鉴权、模型访问控制、渠道调度与协议适配。路径、参数和 响应结构以 Swagger YAML 或运行时 Swagger UI 为准;协议差异、 兼容改写和实测边界以本文为准。

文档属性 当前值
兼容快照 2026-07-16
API 基址 /ai/v1
首选对话协议 OpenAI Responses
会话模式 无状态,客户端携带完整上下文

快速接入

基础地址与鉴权

网关密钥在管理面板中创建。连接信息如下:

项目 配置
Base URL https://<网关地址>/ai/v1
Bearer 鉴权 Authorization: Bearer sk-...
API Key 鉴权 x-api-key: sk-...

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

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

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

再发起一条最小 Responses 请求;请将示例模型替换为模型列表中的可见模型:

curl "https://<网关地址>/ai/v1/responses" \
  -H "Authorization: Bearer $OCI_PORTAL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"xai.grok-4.3","input":"你好,请用一句话介绍自己。"}'

端点一览

协议域 端点 角色 流式
对话 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
向量、语音、重排与安全审核 对应专用端点

路由与全局行为

请求链路

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

可配置运行策略

策略 默认行为 配置入口
Responses 流式保险丝 开启;阈值 60 KB,按 instructionstools 两个字段的原始 JSON 值计算 设置 → AI → 流式保险丝
Grok 服务端搜索 xai. 模型默认注入 web_searchx_search;同名工具不重复覆盖 设置 → AI → Grok 服务端搜索工具
弃用模型过滤 开启后从模型列表、请求路由与探测候选中统一排除 设置 → AI → 模型治理

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

已知限制

instructions / tools 大体量流式断流

Warning

instructionstools 两个字段的原始 JSON 值合计超过约 64.5 KB 时, 上游流式请求可能在推理阶段静默断连:连接直接 EOF,不发送 error 或终态事件。 同一请求改为非流式实测可正常完成;单独扩大 input 未触发该限制。

该问题于 2026-07-13 通过字节级二分定位,2026-07-16 在 Chicago 复测仍存在: 70.4 KB 断流、59.7 KB 正常,API Key 与签名鉴权表现一致。本文及设置页中的 KB 均按 1024 B 计算。

协议 网关保护 客户端表现
Responses 保险丝默认开启;超过 60 KB 时改走非流式上游,并合成最小 SSE 序列 结果语义保留,但不再增量输出
Chat Completions / Messages 客户端尚未收到内容就断流时,自动改用非流式重做 合成对应 chunk / event 序列
已开始输出的流 无法透明重试;调用日志记录提前终止 客户端可能只收到部分事件

Responses 合成的最小事件序列为:response.createdresponse.output_item.doneresponse.completed。保险丝可在 设置 → AI → 流式保险丝 调整或关闭。

历史问题:完整请求体体积断流(已由上游修复)

2026-07-15 曾在完整请求体约 82 KB(含 input)时观测到纯体积流式断流。 2026-07-16 复核 83 KB、真实 Codex 形态 104.5 KB200 KB400 KB 请求均正常完成;Chicago 与 Phoenix、签名与 API Key 两条路径结果一致。

ZDR 与文件输入

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

File content is currently unsupported for ZDR customers

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

字段兼容矩阵

Important

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

矩阵索引

Responses · Chat Completions · Messages · Embeddings · 语音生成 · Rerank · Moderations · Models

展开参考规格
标记 含义
网关直接支持
➡️ 原样保留或透传;是否生效由 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 支持 SSEinstructionstools 的原始 JSON 值合计超过保险丝阈值时,预防性改走非流式上游(默认开启、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 和实测结果为准。

返回顶部