透明协议桥:Responses-speaking client → Chat Completions upstream。
设计为对接单一 NewAPI 上游,由 NewAPI 负责 provider 聚合与模型路由,bridge 只做协议转换。
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/uvicorn codex_chat_bridge.app:app --host 127.0.0.1 --port 18090| 变量 | 说明 | 默认值 |
|---|---|---|
BRIDGE_UPSTREAM_BASE_URL |
NewAPI 入口(必填) | — |
BRIDGE_UPSTREAM_API_KEY |
API 密钥 | 空 |
BRIDGE_UPSTREAM_TIMEOUT_SECONDS |
上游超时 | 60 |
BRIDGE_UPSTREAM_STREAMING |
是否以流式方式请求上游 | true |
BRIDGE_UPSTREAM_MAX_RETRIES |
400 兼容回退最大重试次数 | 2 |
BRIDGE_MAX_CONCURRENT_REQUESTS |
最大并发请求数 | 20 |
BRIDGE_MAX_BODY_BYTES |
请求体最大字节数(超出返回 400) | 10485760(10 MiB) |
BRIDGE_UNSUPPORTED_TOOL_POLICY |
无法映射的 Responses 内置工具策略(ignore / reject / error / passthrough;无效值启动时报 ConfigError) |
ignore |
GET /healthGET /metrics(Prometheus)GET /v1/modelsPOST /v1/responsesPOST /v1/responses/compactPOST /v1/chat/completions(透传:原生 Chat Completions 客户端直连上游,不做协议转换)
Responses client → /v1/responses → routes.py → response_service.py → responses_to_chat/ → upstream →
↑ ↓
chat_to_responses/ ← Chat Completions response
↓
Responses SSE/JSON → client
Chat client → /v1/chat/completions → routes.py → chat_relay_service.py → upstream(verbatim)
↓
上游 status/body/SSE 原样透传 → client
/v1/chat/completions是透明中继:按 URL 区分格式(标准 OpenAI 分法)。原生 Chat 请求不经 Responses↔Chat 转换、不经 reasoning policy 改写、不经 400 compat body 改写、不落 session store —— 客户端发什么上游收什么,上游返回什么客户端收什么,仅保留网络层(429/5xx/超时)重试。
核心模块:
api/routes.py— 薄 HTTP 层:路由、并发门控、FastAPI 入口api/response_service.py— 响应服务层:请求编排、会话解析、上游错误归一化、流式/非流式分发api/chat_relay_service.py— Chat Completions 透明中继层:原始 body 透传上游,status/body/SSE 原样返回,仅保留网络重试responses_to_chat/— Responses→Chat 请求转换(单职拆分:items/content/media/tools/request/orphan/errors)chat_to_responses/— Chat→Responses 响应恢复(对称 convert() 入口:response/text/tools/annotations/inline_think)protocol/— SSE 解析、会话存储、TypedDict 类型定义stream_state/— 流式状态机(envelope/message/reasoning +ToolStateStorefacade;tool path 已拆为tool_types.py/tool_items.py/tool_progress.py/tool_namespace.py)inline_think_sm.py— InlineThink 三态状态机(detecting→reasoning→text),独立于 MessageStateerrors.py— BridgeError 异常层级,统一错误传播bridge_context/— 请求级工具上下文(schema 注册、namespace 映射、nested namespace normalizer)response_semantics.py— 共享响应语义:lifecycle/status/incomplete、usage 映射、REQUEST_ECHO_FIELDS 与 session 持久化策略protocol/session.py— 稳定 facade;内部已拆为session_store.py/reasoning_cache.py/session_bridge.pytool_arguments.py— canonicalize_tool_arguments(JSON 排序/归一化)reasoning_policy.py— canonical effort 归一化 + provider bucket 分发responses_to_chat/request.py— 统一 request field policy(token / stream / passthrough / response_format)upstream.py— 稳定 facade;内部已拆为upstream_endpoints.py/upstream_executor.pyupstream_compat.py— 400 compat retry(含 explicittool_choice/ thinking-mode 冲突回退)
bridge 将调用方的 reasoning 强度归一化为四档 canonical effort:
unspecified(未传)none(off/disabled/false/minimal/none)high(low/medium/high)xhigh(max/xhigh)
内部按 provider 能力分为两类:
| 内部类别 | 行为 | 适用模型 |
|---|---|---|
effort |
unspecified → provider_default;有显式 effort → 仅传 reasoning_effort |
deepseek、glm、openai-like 等 |
passthrough |
始终 provider_default,不传 reasoning 参数 |
kimi 等 |
旧的 4 bucket(openai_like / deepseek / glm / kimi)已合并为上述 2 类。
更完整的冻结设计见:docs/reasoning-policy-freeze.md
- 非流式 + 流式 Responses ↔ Chat 双向转换
- 文本 / 图片 /
input_audio/ refusal / reasoning / function-call / custom-tool / tool-search 已覆盖 previous_response_id会话延续(messages 深拷贝隔离 + tool_context 合并 + TTL 自动续期;streamed assistant replay 保留 chat-side tool shape)- Hosted Responses tools 行为可配置:
ignore/reject/passthrough - 原生 Chat Completions 请求(
/v1/chat/completions)透明中继:不转换、不改写、不落会话,客户端与上游端到端直连 - 不做多上游路由、provider 管理、本地 CLI
bridge 只验证 自己拥有的职责:
- 代码与回归:
pytest -q - 风格/静态门禁:
ruff check . - 服务健康:
GET /health - 桥暴露面:
GET /v1/models、POST /v1/responses - 流式语义:SSE 事件顺序、
response.failed、previous_response_id、tool roundtrip
bridge 不负责 下列事项,也不再提供对应脚本/文档工作流:
- 模型 alias 导出
- CPA / NewAPI 路由与 distributor / channel 分发
- key scope / tenant scope 排查
- 顶层 CLI 或其它入口的 provider 选择问题
因此,bridge 侧 smoke 的前提是:上游模型名与凭据已由外层系统单独验证可用。
相关文档:
uv run --extra dev pytest -q # 当前基线:363 passed
uv run --extra dev ruff check .