AI 应用后端工程化:从原型到可交付系统 · 第 19 篇 · 第五章 · 产品化接口
当能力从后台功能变成公开 API,需要重新处理密钥、调用者身份、应用配置、错误和响应协议。
内部调试功能变成公开 API 后,调用者不再是同一套后台页面。第三方脚本可能重试、并发、传入异常数据,也需要独立凭证和稳定错误。给现有函数加一个路由,只解决了“能够访问”,没有解决“可以长期依赖”。
新的信任边界
flowchart LR
Client[外部客户端] --> Key[API Key 验证]
Key --> Quota[应用/用户配额]
Quota --> Resolve[解析发布配置]
Resolve --> Service[AI 用例]
Service --> Stream[流式响应]
Service --> Usage[(用量记录)]
Stream --> Client
EndUser[终端用户标识] --> Resolve
API Key 识别调用应用,终端用户 ID 区分这个应用的最终使用者,发布配置决定运行行为。三种身份不能混成一个 user_id,否则撤销应用密钥、隔离会话和统计用量都会困难。
API Key 怎样保存
创建时生成足够随机的密钥,只向用户展示一次。数据库保存前缀和哈希,验证时对提交值计算哈希比较。这样数据库泄露不会直接暴露可用密钥,列表页也只能显示前几位帮助识别。
import hashlib
import secrets
def issue_api_key() -> tuple[str, str, str]:
secret = f"app_{secrets.token_urlsafe(32)}"
prefix = secret[:12]
digest = hashlib.sha256(secret.encode("utf-8")).hexdigest()
return secret, prefix, digest
生产中可加入服务端 pepper,并使用常量时间比较。密钥记录包含创建者、作用域、最后使用、过期和撤销时间。轮换时允许新旧密钥短暂共存,不要求所有客户端瞬间切换。
终端用户不是账号表的复制
调用方可能拥有自己的用户体系,只向 API 提供一个稳定外部 ID。服务将它映射为 EndUser,用于会话、记忆、配额和删除请求。这个 ID 必须在应用命名空间内唯一,应用 A 的 user-1 与应用 B 无关。
不要允许客户端伪造另一个应用 ID,API Key 已经确定应用范围。涉及隐私时应支持按终端用户导出与删除数据,并明确保留期。
辅助 AI 功能也要有产品边界
优化 Prompt、生成建议问题看似小功能,仍会消耗模型配额并处理用户内容。需要输入长度限制、模型超时、内容安全和用量记录。它们可以使用与主聊天不同的模型和温度,但配置应集中,不在 Handler 中散落硬编码。
输出最好结构化,例如建议问题数组,而不是让客户端解析编号文本。模型格式不合法时,服务可以有限重试或返回明确错误,不能悄悄用空数组伪装成功。
流式协议需要结束语义
聊天 API 使用 SSE 时,客户端要区分文本增量、工具状态、用量和最终结束。连接断开不一定代表任务失败,服务需要取消策略和幂等请求 ID。
每个事件包含类型与序号,最后发送 done 及完成原因。HTTP 已返回 200 后发生错误,无法再修改状态码,只能发送错误事件,因此流式协议必须在文档中明确。
限流不只是保护服务器
模型调用按量计费,API Key 泄露可能造成直接经济损失。限流应同时考虑每秒请求、并发、Token 和日预算。返回标准 429 与重试时间,避免客户端立即重试形成风暴。
配额维度可包含应用与终端用户。单个用户的异常流量不应耗尽整个应用,应用超预算时则统一停止。用量记录关联请求 ID,方便账单争议追踪。
向后兼容从第一天开始
公开字段名、错误码和流事件一旦被客户端使用,修改成本远高于内部函数。响应中新增字段通常安全,删除或改义需要版本。文档给出 curl 示例、错误列表和重试规则,契约测试从 OpenAPI 验证真实响应。
一个坏接口会把内部异常文本直接返回,客户端开始依赖这句中文判断错误。下一次重构后文本变化,集成全部失败。稳定机器码与面向人的 message 必须分开。
类比支付开放平台
支付 API 同样有商户密钥、终端订单、签名、幂等、配额和版本。AI 接口只多了流式与不确定输出。练习可以实现密钥创建和撤销,验证数据库只有哈希;随后用同一幂等键重复发起聊天,确认不会重复扣两次配额。
四个提交完成对外边界
a36ff98:增加 Prompt 优化和建议问题等辅助 AI 服务。4706cf8:建立 API Key 与 EndUser 模型。0034c86:补齐密钥处理器、服务和路由。a72a3df:实现 OpenAPI 聊天入口与服务,能力正式面向外部调用。
从辅助功能到身份模型,再到密钥管理和聊天接口,顺序体现了公开 API 的核心:先知道提供什么,再知道谁在调用,最后建立稳定协议。