周期建议:10–14 天。只连接两个本地 Mock Provider;不得使用真实模型账号、Provider Key 或 Key 池。
项目背景
一个小型 AI 应用同时面对“不同 Provider 协议不一致、模型名称经常变化、上游超时/限流、调用成本难核对”等问题。如果每个业务都直接连接模型,鉴权、重试、回退和用量统计会散落在各处;如果网关设计不严谨,又可能把不同调用方的数据混在一起,重复输出流,或在已经向客户端发送内容后切换 Provider 造成拼接答案。
团队需要一个最小、本地、OpenAI-compatible 的 LLM Gateway 教学样板。它只验证契约、路由、故障边界、流式语义、每 Key 限流和用量留痕,不建设真实商业平台。
项目目标
交付一个本地可运行的 HTTP 服务,实现以下固定公开接口:
GET /health
GET /v1/models
POST /v1/chat/completions
GET /v1/usage
系统通过 Gateway Key 鉴权,把模型别名路由到两个可控 Mock Provider,支持非流式和 SSE,在严格规则下回退,并确保每个入站 Chat Completion 请求最终只产生一条用量记录。
用户故事
- 作为应用开发者,我希望使用稳定的 OpenAI-compatible 接口和模型别名,从而不关心 Mock Provider 差异。
- 作为调用方负责人,我希望自己的 Key 有独立限流和独立用量视图,从而避免相互干扰。
- 作为平台开发者,我希望超时和上游错误按明确规则回退,从而避免重复或拼接输出。
- 作为审计者,我希望每个请求有唯一记录且不泄漏 Key、Prompt 正文或响应正文,从而核对可靠性。
功能要求
必须完成
- 固定 HTTP 契约
GET /health 返回服务状态和两个 Mock Provider 的可用摘要,不泄漏配置或密钥。
GET /v1/models 返回当前 Gateway Key 可用的模型别名列表,采用 OpenAI 风格的 object: "list" 与 data 结构。
POST /v1/chat/completions 至少支持 model、messages、stream;非法 JSON、空消息、未知别名和超限字段返回稳定错误结构。
- 非流式成功响应至少包含
id、object、created、model、choices 和 usage。
GET /v1/usage 只返回当前 Gateway Key 的用量记录,支持最小分页或条数限制。
- Gateway Key 鉴权与隔离
- 使用
Authorization: Bearer <gateway-key>;缺失/无效 Key 返回 401,无权限模型返回 403。
- 持久化和配置中只保存 Key 的单向哈希;日志、错误和用量记录最多保存不可逆摘要/短指纹,不得保存或回显明文。
- 至少准备两个本地测试 Key,分别绑定不同 Key 标识;只能通过安全的本地初始化方式获得测试明文。
- 两个 Mock Provider 与模型别名
- 实现两个行为可配置、结果可区分的 Mock Provider Adapter。
- 外部请求只使用稳定别名;路由配置把别名映射到主 Provider、备用 Provider 和 Provider 模型名。
- 响应和用量可显示别名及实际 Provider 标识,但不得把内部凭证或敏感配置暴露给调用方。
- 非流式路由与受控回退
- 主 Provider 在超时、
429 或 5xx 时可以尝试一次备用 Provider。
- 主 Provider 返回
400、401、403 时禁止回退,应返回映射后的明确错误。
- 总超时、单 Provider 超时、最大回退次数集中配置;不能无界重试。
- SSE 流式语义
stream: true 时使用 text/event-stream,每个正常内容事件格式为 data: <JSON>\n\n。
- 每个已建立并完成的流必须且只能出现一次
data: [DONE]\n\n。
- 只有在任何内容 chunk 发给客户端之前,且错误为超时、
429 或 5xx 时才允许切换备用 Provider。
- 一旦首个内容 chunk 已发送,后续上游失败不得切换 Provider;应发送一个结构化终止错误事件并以唯一
[DONE] 结束,审计状态标记为失败/部分输出。
400、401、403 在首 chunk 前也不得触发回退。
- 每 Key 独立限流
- 实现固定窗口、滑动窗口或令牌桶之一;限流计数以 Gateway Key 标识隔离。
- 网关自身限流返回
429 和可理解的重试信息,不调用任何 Provider。
- Key A 达到限制不能消耗或阻塞 Key B 的额度。
- 每请求唯一最终用量记录
- 每次进入
POST /v1/chat/completions 的请求都分配唯一 request_id,包括鉴权、校验、网关限流、Provider 和流式失败。
- 最终恰好写入一条用量记录,不得因回退写成两条“客户端请求”;可在同一记录中保存尝试次数和实际 Provider。
- 记录至少包含请求 ID、Key 标识/不可逆指纹、模型别名、实际 Provider、状态、回退次数、输入/输出 token、耗时和时间。
- 鉴权/校验失败的 token 为 0;不得保存 Prompt、响应正文或明文 Key。Mock token 计数算法需确定、可测试并写入文档。
- 可观测错误
- 所有响应带请求 ID;错误结构能区分网关校验、网关限流、Provider 错误、超时和流中断。
- 提供受控输入或测试配置,稳定触发两个 Provider 的各类错误,不依赖随机故障。
可选增强
- 配置热加载、健康熔断或按权重路由;必须保持默认确定性测试路径。
- 管理员本地汇总视图,但不得扩展为公网租户管理或计费系统。
max_tokens 等更多兼容字段;必须明确支持子集,不能声称完整兼容所有 OpenAI API。
- 用 SQLite 等持久化用量记录,并证明重启后一致性。
非功能要求
- 可运行性:一条本地命令启动网关和两个 Mock Provider;不设置真实 Key 也能验收。
- 可靠性:请求 ID 唯一;最终用量写入具备 exactly-once 的可观察效果;回退和 SSE 不能产生拼接答案或重复
[DONE]。
- 性能:Mock 正常路径下,网关自身增加的 p95 延迟应小于 100ms(不含配置的 Provider 延迟),并说明测量方法。
- 并发:至少用自动化测试证明两个 Key 的限流隔离和同一请求的最终记录唯一。
- 安全:Key 使用单向哈希校验与常量时间比较;日志默认脱敏;请求体、消息长度和并发有上限。
- 隐私:默认不记录 Prompt/响应正文;用量查询严格按 Key 隔离。
- 兼容性:README 明确实现的是 OpenAI-compatible 子集、已支持字段和不支持项。
范围与限制
范围内
- 本地单进程或小型多进程网关。
- 两个 Mock Provider、稳定模型别名、Gateway Key、路由/回退、SSE、限流和用量审计。
- 合成消息、合成 Key 和确定性错误场景。
范围外
- 真实 OpenAI/其他 Provider 账号、API Key 池、凭证托管或账号共享。
- OAuth、用户注册、支付、充值、余额、开票、价格结算、转售或代充。
- 公网多租户服务、生产 SLA、跨地域高可用和真实商业网关运营。
- 代理个人 Codex 账号、共享 Codex 会话或把订阅能力转给其他用户。
- 声称完整实现 OpenAI API,或复制现有网关的参考实现代码。
技术与时间限制
- 周期为 10–14 天;先完成非流式契约,再实现 SSE、回退、限流和唯一用量。
- 技术栈可自选,但 HTTP/SSE 行为必须能通过自动化客户端测试,不要求复杂前端。
- 两个 Provider 必须是仓库内可运行 Mock;不得读取
OPENAI_API_KEY 或任何真实 Provider 凭证。
- Gateway Key 是本地合成测试凭证:明文只在初始化/请求端短暂存在,仓库、持久层和日志只放哈希或不可逆摘要。
- 不要求也不允许为了本作业把网关公开到互联网;本地或受控测试环境即可。
澄清机制
在“澄清 Issue”写明背景、歧义、候选方案、推荐、影响和未回复时的可逆假设。
例如“上游在第三个 chunk 失败后能否切备用”已有明确安全答案:不能拼接 Provider;若要改变必须先提出并证明协议语义。仅影响错误文案的问题可先记录假设;任何真实 Provider、账号共享、Key 池、付款、转售、公网多租户、隐私留存或费用问题都必须停止并等待组织者确认。题面未覆盖的 D/or 协议状态应显式记录,不能偷偷归入成功。
交付物与证据
- 可运行源码、依赖锁文件、安全配置示例、Mock Provider 和测试 Key 初始化工具。
README.md:架构、兼容子集、Key 生命周期、启动、curl 示例、故障矩阵、SSE 语义、测试和限制。
docs/PRD.md:调用方、协议、错误/回退规则、范围、验收映射和澄清决策。
docs/PLAN.md:鉴权、路由、Provider、SSE、限流、用量写入的数据流与并发策略。
- 自动化测试:覆盖四个接口、Key 隔离、模型权限、回退矩阵、首 chunk 边界、唯一
[DONE]、限流隔离和唯一用量。
docs/TEST_EVIDENCE.md:命令、结果、HTTP/SSE 证据、验收映射和敏感信息扫描结果。
docs/AI_COLLABORATION.md:AI 建议、本人协议核验与未采纳建议;不得粘贴私人会话全文。
docs/RETROSPECTIVE.md、阶段 Issue、PR 和可解释的提交历史。
公开可测试验收标准
技术讲解与追问准备
请准备说明:OpenAI-compatible 子集边界;模型别名如何与 Provider 解耦;Key 哈希和指纹的区别;为什么 400/401/403 不回退;为何首 chunk 后不能切换;唯一 [DONE] 如何保证;每请求一条最终用量怎样处理并发和异常退出;限流为什么按 Key 隔离。
验收可能临时修改一种错误语义或增加一个模型别名。你需要先画出非流式/流式状态变化,评估鉴权、回退、用量和兼容性影响,再在独立分支实现并提供协议回归证据。
安全与合规
- 只允许两个本地 Mock Provider 和合成 Gateway Key;仓库、数据库、日志和证据不得出现真实或明文 Provider Key。
- 禁止账号共享、Codex 中转、Key 池、OAuth、支付、充值、转售、公网多租户或代替他人使用订阅。
- 不记录 Prompt/响应正文,不跨 Key 返回用量;错误、追踪和截图全部脱敏。
- 不得提交、共享或中转 Codex/模型账号、会话、Token、API Key、Cookie、私钥。
- 本项目是本地教学样板,不代表获得任何 Provider 的代理、转售或多用户运营授权;活动也不承诺就业结果。