LLM 功能 demo 到生产的坑:超时重试回退机制、JSON 校验、前端兜底方案,并提供了可直接复制的 Python 校验代码示例。
演示效果很好,全场鼓掌。然后你部署了它,一周之内奇怪的事情发生了:用户粘贴了一份 40 页的文档,模型返回了一种你的解析器从未见过的格式,本来应该显示有用答案的地方出现了一个错误页面。
听起来很熟悉?语言模型功能的行为与普通代码不同,"在我的笔记本上能用"和"对真实用户能用"之间的差距比往常更大。这是我希望更多团队使用的检查清单。
因为它确实就是。响应可能很慢、有速率限制,或者偶尔是胡说八道。所以给每次调用包装上基础知识:
硬超时(不要让用户盯着加载指示器看一分钟)
少量带退避的重试
一条仍然能给用户提供有用信息的备用路径
备用路径最为重要。如果摘要功能失败了,就显示原文。如果分类器失败了,就把项目路由到人工队列。一个枯燥的备用方案永远比一个坏掉的页面强。
即使你请求的是 JSON,你也未必总能收到有效的 JSON。在使用任何东西之前先验证。
import json
REQUIRED = {"category", "confidence"}
def parse_reply(raw: str) -> dict | None:
try:
data = json.loads(raw)
except json.JSONDecodeError:
return None
if not isinstance(data, dict) or not REQUIRED <= data.keys():
return None
return data
def classify(ticket_text: str) -> dict:
raw = call_model(ticket_text) # your model call, with timeout
result = parse_reply(raw)
if result is None:
return {"category": "needs_review", "confidence": 0.0}
return result
注意最后一个分支。当解析失败时,代码不会崩溃。它会优雅降级,并把该项目标记为待审查。
你不需要研究实验室。收集 30 到 50 个你认为是正确答案的真实案例,存储在一个文件中。每次你更改提示词、模型或设置时都运行它们。
为什么要费这个劲?因为提示词的调整很隐蔽。你修好了一个案例,却悄悄破坏了另外三个。没有测试集,你永远不会注意到,直到用户发现。
让这个集合保持真实。同样要包含那些丑陋的输入:拼写错误、混合语言、空字段、超长文本。
当出了问题时,你会想知道输入了什么、输出了什么。记录提示词版本、模型名称、延迟、令牌计数和一个请求 ID。对于实际文本要小心。用户内容可能包含姓名、电话号码和其他隐私信息。能脱敏或哈希的就脱敏或哈希,并设置一个保留期限。
可调试性和隐私性往相反的方向拉扯。要有意识地决定这个权衡,而不是意外地。
暗度陈仓。先对内部员工打开,然后对 5% 的用户,然后对所有人。并且保持一个能立即禁用模型路径的终止开关,不需要重新部署。
第一次提供商发生故障或者提示词更改在凌晨两点出问题的时候,你就会庆幸有它。
模型调用按请求计费,成本随流量和输入长度增长。加几个廉价的防护措施:
对输入长度设置上限并合理截断
缓存重复请求
设置每日支出警报
收到警报比收到意外账单要愉快得多。
告诉用户文本是机器生成的,并给她们一个轻松的修正或拒绝方式。一个"这不对"按钮同时也是免费的评估数据。几周后,这些修正就会成为你最好的测试案例。
无论你是单独工作还是在软件开发公司内部,拉合尔(译注:原文提到的地名)的客户依赖于你,要在发布后确定谁拥有这个功能。提示词和模型会漂移。需要有人每月运行评估集并审查日志。如果没有人负责,质量会缓慢而沉默地衰退。
如果该功能涉及更重的工作,比如微调、检索管道或自定义数据处理,可能值得引入一家你之前合作过的 AI 开发公司来避免付出高昂的学费。
这些都不华丽。但所有这些是把演示变成产品的分水岭。
你还有什么要补充的?在评论区留言吧。