# ADR-0005:使用独立 Model Gateway 隔离百炼出口 - **状态:** accepted - **日期:** 2026-07-13 ## 背景 在线 RAG 必须同步完成 Query Embedding、Rerank 和 Chat SSE,但 ADR-0004 又要求数据库感知 API 不持有百炼 Key、没有公网默认出口。让 API 或 Worker 直接调用百炼,会把业务数据、数据库凭据、模型凭据和公网出口集中到同一信任边界;只保留一次性 smoke/seed 工具则无法支持在线问答。 ## 决策 新增与 API 共用 backend 镜像的长期 `model-gateway` 服务: ```text browser -> web (edge + ingress) -> gateway (ingress + data) -> api (data + model) -> PostgreSQL/pgvector (data) -> model-gateway (model + egress) -> Alibaba Cloud Model Studio worker (data + model) -> PostgreSQL/pgvector -> model-gateway ``` - 只有 `model-gateway` 挂载 `bailian_api_key` 并连接 `egress`;它不连接 `data`、不挂数据库 Secret、上传卷或宿主端口。 - API 与 Worker 不挂百炼 Key、不连接 `egress`,只通过 internal `model` 网络访问固定的 `http://model-gateway:8000`。 - API 与 Worker 使用不同的内部令牌。调用必须同时携带 `Authorization: Bearer ...` 与 `X-RAG-Caller`;Gateway 用常量时间比较把令牌映射到调用者,不能只信任 header 或 Docker 来源地址。 - API 允许 Query Embedding、Rerank、Chat 和受控 provider health;Worker 额外允许 Document Embedding。任意越权调用失败关闭。 - Model Gateway 只接受固定 profile、固定模型和固定端点的 vendor-neutral DTO,不接受客户端提供 URL、模型名、维度或任意转发目标。 - Embedding、Rerank 和 Chat 继续复用现有 provider ports 与百炼 adapter,不引入 SDK、Redis、消息队列、服务网格或第二套实现。 - 日志只允许 trace、调用者、操作、profile、输入数量、usage、耗时、request ID 和脱敏错误码;禁止记录 Key、Authorization、URL、query、messages、候选正文或响应正文。 - 容器 readiness 只验证本地配置、Secret 和客户端初始化,不产生模型费用;真实探测使用受控内部端点和显式命令。 ## 内部接口 - `POST /internal/v1/embeddings`:接收 `texts` 和 `input_type=query|document`;Query 恰好一条,Document 为 1–10 条;返回 1024 维向量、resolved model、usage、request ID 和耗时。 - `POST /internal/v1/rerank`:接收 query、候选正文和 Top N;返回原始下标、score、受校验正文与 provider 元数据。 - `POST /internal/v1/chat/completions`:非流式内部调用,用于需要先完成引用校验的场景。 - `POST /internal/v1/chat/stream`:vendor-neutral SSE;流开始后的 provider 错误转换为终态 `error` 事件,取消必须关闭上游流。 - `GET /health/live` 与 `GET /health/ready`:不调用百炼。 公共 API 不把 Model Gateway 的内部 401/403 原样返回浏览器;这类错误统一映射为可观测的 503 配置故障。429、timeout、5xx 和非法响应分别映射为稳定、脱敏的错误码。首个输出之后不得自动重试 Chat,避免重复文本。 ## 被否决方案 1. **API 直接挂 Key 与 egress:** 数据库感知进程同时拥有数据、模型凭据和公网出口。 2. **Worker 直接调用百炼:** 会形成两个供应商调用实现和两个 Key 边界。 3. **Model Gateway 连接数据库验证审批:** 重新形成“数据 + Key + egress”的高风险组合。 4. **只依赖 Docker DNS 或来源 IP:** 网络成员不是应用层身份,不能替代内部令牌。 5. **引入通用 API Gateway、Redis、Celery 或服务网格:** 当前单机毕设规模没有足够收益,并增加部署与恢复面。 ## 后续约束 - `provider-smoke` 与真实 seed 必须使用 Model Gateway 客户端,不允许恢复直连百炼旁路。 - 普通在线查询只能使用知识库已激活的 embedding profile;Fake 与 Bailian profile 永不混查。 - Docker bridge 不是域名白名单。生产环境仍需主机防火墙或出口代理只放行获批的百炼域名。 - 改变模型调用者、内部鉴权、网络成员、Key 边界或 SSE 协议时,必须更新本 ADR 并重跑容器网络、Secret、取消和错误脱敏验收。 ## 验证要求 - Compose 合同证明百炼 Key 与 `egress` 只存在于 `model-gateway`。 - Model Gateway 无数据库 Secret、`data` 网络、上传卷和宿主端口;API/Worker 无百炼 Key和 `egress`。 - 缺失/错误令牌、调用者冒充、scope 越权、URL/模型/维度注入均有失败测试。 - Embedding、Rerank、Chat 的成功、401、429、timeout、5xx、非法响应、SSE 取消均由 hermetic contract test 覆盖。 - `make verify`、镜像 Secret 扫描、Docker 健康检查、网络隔离与真实三模型 smoke 全部通过后,才能宣称在线百炼模型边界可用。