学习
算法

暂无条目

工程

暂无条目

最佳实践
活动
第一期 · 从 agent 开发学会 llm 所有
第二期 · 如何成为 AI 时代的超级上下文
第二期题库
creative-studio-agent
evidence-rag-agent
finance-reconcile-agent
mini-llm-gateway
公开题面
order-ops-executor-agent
reliable-customer-service-agent
公开题面
safe-data-analyst-agent
说明文档
作业模板
第三期 · 一群人如何做好 vibe coding

暂无条目

Mini LLM Gateway原文 ↗

周期建议: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 正文或响应正文,从而核对可靠性。

功能要求

必须完成

  1. 固定 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 的用量记录,支持最小分页或条数限制。
  2. Gateway Key 鉴权与隔离
    • 使用 Authorization: Bearer <gateway-key>;缺失/无效 Key 返回 401,无权限模型返回 403。
    • 持久化和配置中只保存 Key 的单向哈希;日志、错误和用量记录最多保存不可逆摘要/短指纹,不得保存或回显明文。
    • 至少准备两个本地测试 Key,分别绑定不同 Key 标识;只能通过安全的本地初始化方式获得测试明文。
  3. 两个 Mock Provider 与模型别名
    • 实现两个行为可配置、结果可区分的 Mock Provider Adapter。
    • 外部请求只使用稳定别名;路由配置把别名映射到主 Provider、备用 Provider 和 Provider 模型名。
    • 响应和用量可显示别名及实际 Provider 标识,但不得把内部凭证或敏感配置暴露给调用方。
  4. 非流式路由与受控回退
    • 主 Provider 在超时、429 或 5xx 时可以尝试一次备用 Provider。
    • 主 Provider 返回 400、401、403 时禁止回退,应返回映射后的明确错误。
    • 总超时、单 Provider 超时、最大回退次数集中配置;不能无界重试。
  5. 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 前也不得触发回退。
  6. 每 Key 独立限流
    • 实现固定窗口、滑动窗口或令牌桶之一;限流计数以 Gateway Key 标识隔离。
    • 网关自身限流返回 429 和可理解的重试信息,不调用任何 Provider。
    • Key A 达到限制不能消耗或阻塞 Key B 的额度。
  7. 每请求唯一最终用量记录
    • 每次进入 POST /v1/chat/completions 的请求都分配唯一 request_id,包括鉴权、校验、网关限流、Provider 和流式失败。
    • 最终恰好写入一条用量记录,不得因回退写成两条“客户端请求”;可在同一记录中保存尝试次数和实际 Provider。
    • 记录至少包含请求 ID、Key 标识/不可逆指纹、模型别名、实际 Provider、状态、回退次数、输入/输出 token、耗时和时间。
    • 鉴权/校验失败的 token 为 0;不得保存 Prompt、响应正文或明文 Key。Mock token 计数算法需确定、可测试并写入文档。
  8. 可观测错误
    • 所有响应带请求 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 和可解释的提交历史。

公开可测试验收标准

IDGiven / 前置条件When / 操作Then / 可观察结果验证方式
AC-01服务与两个 Mock Provider 已启动调用 /health 与授权后的 /v1/models健康摘要不泄密;模型列表只含该 Key 可用别名且结构稳定HTTP 集成测试
AC-02无 Key、无效 Key、无模型权限 Key分别调用 Chat Completions依次得到稳定 401/401/403;响应有请求 ID,日志无明文 Key参数化安全测试
AC-03主 Provider 正常分别发送 stream:false 与 stream:true 请求非流式结构包含 choices/usage;流式 JSON chunk 合法且只有一个 [DONE]协议测试
AC-04主 Provider 在首响应前超时、返回 429 或 5xx分别请求同一模型别名每种场景最多回退一次并由备用成功;记录实际 Provider 与回退次数参数化集成测试
AC-05主 Provider 返回 400、401 或 403分别请求网关不调用备用 Provider,返回映射错误,用量记录显示回退 0 次自动化测试
AC-06流式主 Provider 已发送一个内容 chunk 后故障读取完整 SSE不切换 Provider;已有内容不重复;出现结构化终止错误且仅一个 [DONE]SSE 字节流测试
AC-07Key A 和 Key B 均有独立额度A 连续调用至限流,再由 B 调用A 得到网关 429 且 Provider 未被调用;B 仍能成功并发/限流测试
AC-08一次请求经历主失败、备用成功查询该 Key 的 /v1/usage该 request_id 只有一条最终记录,包含两次尝试摘要、实际 Provider 和合计 token数据一致性测试
AC-09分别触发鉴权失败、校验失败、限流、Provider 失败、成功和流中断按请求 ID 查询存储/测试接口每个入站请求恰好一条最终记录;失败 token 为 0 或已实际输出量;无正文/明文 Key参数化自动化测试
AC-10全新环境且没有任何真实 Provider 凭证按 README 初始化本地 Key、启动并跑全套测试四个接口、非流式/SSE、回退、限流和用量均可复现,未访问真实模型或公网人工复现 + 命令证据

技术讲解与追问准备

请准备说明: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 的代理、转售或多用户运营授权;活动也不承诺就业结果。