从 Demo 到生产环境
一个能跑通的 demo 大概只走完了五分之一。五个鸿沟,隔开了「你试的时候能用」和「所有人都用的时候还能用」。
Demo 能跑。你拿给别人看,对方印象深刻。
从这里到生产环境,这道鸿沟比大多数软件都宽,因为失效模式很陌生:不确定、无声,而且往往要等到有人照着错误答案去行动时才会显形。
五个鸿沟,按它们咬人的先后排列。
1 · 度量
Demo 的验证方式就是试一下。生产环境需要一个可重复的答案来回答「这次改动有用吗」。
没有评测,每次改 prompt 都是猜,而且服务商在版本号不变的情况下更新模型,你也不会察觉。
**最低要求:**二十个存下来的例子,附上期望输出,每次改动都跑一遍。每一次生产环境的失败都往里加。这不是可选的基础设施——正是它让后面清单上的每一项变得可做。
2 · 失效处理
Demo 只走顺利的路径,生产环境什么都要接。
**服务商故障与速率限制。**遇到 429 和 5xx 时用带抖动的指数退避,加一个熔断器,免得一家服务商挂掉就引发连锁反应;还要事先决定降级行为:退回更小的模型、返回缓存结果,还是老老实实报错。要有意识地做决定,而不是等出事故时才发现自己没决定过。
格式错误的输出。让 schema 约束生成,解析后再校验,再加一次重试。永远不要假设输出长什么样。
**超时。**生成会卡住。设好超时,并处理中途断掉的流式输出片段。
**糟糕的输入。**空字符串、超长粘贴、其他语言、提示注入尝试。在为它花掉一次调用之前,先校验并限制输入长度。
3 · 可观测性
下周有用户报告一个坏答案时,你需要重建当时发生了什么。
**每次请求都记日志:**发出的完整 prompt(包括检索到的上下文)、原始响应、模型与版本、token 数、延迟,以及任何重试。量太大就采样,而不是全都记,但所有失败都要留下。
检索到的上下文是人们最常漏掉的一项,而它恰恰是你最需要的——面对检索增强生成(RAG)失败,问题几乎总是「正确的文本块有没有被检索到」,没有日志,事后根本无法回答。
**要设告警的:**错误率、延迟分位数、每小时成本,以及拒答或降级的比例。悄无声息的成本飙升是「没人监控」最典型的失效。
**给用户一条反馈通道。**一个点踩按钮,是你能搭起来的最便宜的、真实评测用例来源。
4 · 成本与滥用
Demo 只服务一个体贴的用户。生产环境要服务所有人,包括那个把一整本小说粘进你摘要功能的人。
调用之前限制输入长度。这既是成本控制,也是可用性控制。
按用户做速率限制,而不是只做全局的。
给 max_tokens 设上限,这样失控的生成不会带来没有上限的成本。
盯住平方级增长。对话历史每一轮都要重发,所以长会话的成本远高于感觉上该有的水平。要有意识地给历史上限。
对支出设告警,按小时而不是按月。月度账单不是一个发现死循环的好地方。
5 · 安全与信任
**永远不要把 API key 放进客户端代码。**所有调用都从你的后端走。见你的第一次 LLM API 调用。
**在检索处执行权限。**如果 RAG 索引的文档有不同的访问级别,就在查询时按发起请求的那个用户的权限过滤。否则你的助手会变成一条让人读到他们本来读不到的东西的路径——这是一个非常常见且严重的错误。
**把工具返回的结果当成不可信内容。**任何工具抓回来的东西,都可能夹带长得像指令的文本。让破坏性工具无法从不可信内容那里触达。
**给不可逆的操作加一道门。**发送、删除、付款、部署——都要人工确认。优先选可逆的操作:存草稿而不是发送,软删除而不是删除。
**在界面上管理预期。**用户信任流畅的输出。有出处就标出来,并且让「输出可能出错」这件事看得见。这是一个能减少真实伤害的产品决定。
管用的形态
成功的生产系统比 demo 让人以为的要窄。
**把范围收窄。**一个定义清晰的任务,胜过一个大而全的助手。更好评测,也更容易做可靠。
**步骤已知时,优先用工作流而不是 agent。**可预测、更便宜、可调试。只有当路径确实无法事先确定时,才去用 agent。
**在关键节点上保留人。**不可逆的操作之前先有人复核,尤其是在早期。
**先小范围上线。**真实用户会找到你想象不到的失效模式。
要点回顾
- 评测优先——没有它,任何其他改进都无法度量。
- 速率限制用退避处理,格式错误的输出用受约束的生成加校验处理,降级行为要在出事故之前就定好。
- 记下完整 prompt,包括检索到的上下文;对错误率、延迟和每小时成本设告警。
- 限制输入、按用户限速、给输出设上限,并盯住历史记录的平方级增长。
- key 放在服务端,权限在检索处执行,工具结果视为不可信,不可逆操作加一道门。
- 收窄范围,能用工作流就别用 agent,关键节点上要有人。
你已经走到了这条路径的终点。如果想回头重看某一层,路线图里有完整的地图。