online branch: main

2026-08-29

RSS llms.txt GitHub

改一句 Prompt 也可能翻车:如何发布、验证和回退?

$
AI 应用可观测性与评估:改一句 Prompt 也可能翻车:如何发布、验证和回退?

业务问答 Agent 准备增加一条规则:“回答必须引用知识库依据。”开发人员改完 Prompt,在几个示例上试了试,随后发布到生产。第二天点踩变多了,有人说答案太啰嗦,也有人说引用与问题无关。

“新 Prompt 好不好”太宽泛。团队需要回答几件可以查证的事:哪些请求用了新版本,负面反馈是否真的集中在这些请求上,问题来自 Prompt 还是检索数据,以及能否先恢复旧版本。版本记录、运行链路和用户反馈只有连在一起,发布才可观察,也才可回退。

Prompt 已经是运行配置

Prompt 影响模型看到的任务、上下文和输出要求。它虽然是文本,却和模型参数、工具路由一样,会改变应用行为。直接写在代码里可以运行,但每次修改都跟着代码部署;出问题时,还要从提交记录里反推线上请求究竟用了什么内容。

一个可控的 Prompt 发布机制至少需要三样东西:保留每次修改的历史快照,用一个可移动的指针决定生产流量使用哪份快照,并把真实运行记录关联回当时的版本。这是通用配置治理方法,可以由 Git、配置中心、自建服务或 Prompt 平台实现。

Langfuse 用 version 和 label 表达这层关系。同名 Prompt 每次创建都会得到新的 version ID,旧版本不会被覆盖。Label 指向某个版本,适合表达 stagingproduction 或实验分组。应用按 production 获取 Prompt,发布时只需把该标签移到新版本;出现异常,再把标签指回旧版本。

latest 是 Langfuse 自动维护的标签,只表示最近创建的版本。它没有说明这份 Prompt 是否通过验证,因此不适合作为默认的生产发布策略。SDK 在未指定 label 或 version 时,默认返回带 production 标签的版本。

这次修改可以按下面的节奏上线:先创建新版本,让旧版本继续承接生产流量;在开发或 staging 环境检查变量、消息结构和典型问题;确认基本行为后移动 production 标签;最后观察新版本关联的 Trace、成本、延迟和反馈。这里不需要复杂审批系统,但每次发布都应留下版本、时间和操作人。

prompt = langfuse.get_prompt(
    "business-qa",
    label="production",
)

messages = prompt.compile(question=user_question)

获取 Prompt 后,还要把该对象关联到对应 Generation。只记录编译后的字符串,会丢掉 Prompt 名称和版本关系;发生问题时仍然难以按版本筛选。关联完成后,可以从 Trace 看出这次生成使用哪一版,也能按 Prompt 版本聚合延迟、成本和 Score。

客户端缓存会让发布表现得没那么“瞬时”。Langfuse SDK 缓存已获取的 Prompt,以减少网络请求,也在平台短暂不可用时继续提供配置。Label 移动后,少量请求可能在缓存有效期内继续使用旧版本。需要更快生效时,应根据业务风险调整缓存 TTL 或禁用缓存;排查时也要核对 Trace 上记录的真实版本,不能只根据发布时间猜测。

反馈要回到产生答案的那次执行

发布后的回答有没有帮助,接口状态和模型自评都不能替用户决定。用户点踩、重新提问、复制答案、接受建议或转人工,都会提供一些线索。这里最容易犯的错,是收集了事件,却没有把事件关联回原始请求

显式反馈由用户主动给出,例如点赞、点踩、星级和文字意见。信号直接,但参与率通常不高。隐式反馈来自行为,例如复制、重试、修改、放弃流程或最终完成任务,覆盖更广,含义也更容易误读。复制可能说明答案有用,也可能只是用户准备拿去大改。

设计反馈时,先写清行为在产品里的含义,再确定字段。点赞评价的是主观满意度,任务完成描述业务结果,人工纠错提供了更具体的失败证据。把它们全塞进一个“质量分”,后续很难解释变化。名称、值类型和口径也要保持稳定,避免同一个概念先后使用 like=1satisfied=truegood

要把前端反馈接回 Trace,后端返回答案时需要同时返回稳定的 Trace ID。前端提交评价时带回这个 ID,平台才能把 Score 挂到正确对象上。在 Langfuse 当前 Browser SDK 文档中,点赞/点踩示例使用 BOOLEAN1/0

await langfuse.score({
  traceId,
  id: `response-rating-${traceId}`,
  name: "response_rating",
  value: 0,
  dataType: "BOOLEAN",
  comment: "引用内容与问题无关",
});

浏览器端只能使用 Public Key,不能暴露 Secret Key。稳定的 Score id 也有实际用途:用户改变选择时可以更新同一条记录,避免一个请求被重复计数。工单关闭、任务完成等发生在服务端的结果,应由后端 SDK 或 API 写入,并关联原 Trace、Observation、Session 或实验对象。

这里有一个接口版本差异需要单独记住。上面的 0/1 写法来自 Browser SDK 的 User Feedback 示例;Scores API v3 的 BOOLEAN 值类型是 false/true。读取 v3 API 或改用其他 SDK 时,要按该接口的类型定义转换,不能把示例代码原样搬过去。Scores API v3 还通过 subject.kind 区分 Score 关联的是 Trace、Observation、Session 还是 Experiment。

接入反馈后,先做一条端到端验证:发起测试问题,提交点踩,再打开对应 Trace,确认 Score 名称、值、评论和关联对象都正确。随后用当前接口实际保存的负向值筛选记录。若 Trace ID 丢失、名称漂移或重复写入,Dashboard 上的反馈趋势不会可信。

发布、观察和回退

现在可以回到开头的 Prompt 变更。团队按 Prompt 版本筛选生产 Trace,发现点踩主要集中在新版本;逐条阅读后又发现,问题并非“要求引用”本身,而是检索步骤返回了宽泛材料,新 Prompt 强制模型把这些材料写进答案。短期可以把 production 标签移回旧版本,恢复原行为;接着修正检索或引用规则,再发布下一版。

回退只是止损,不会自动回答新旧方案谁更好。用户反馈本身也有偏差:点踩者可能更愿意表达,低反馈率不能代表沉默用户满意,重试还可能由网络或交互设计引起。它是一组需要解释的证据,不是最终质量结论。

验收时确认三件事:每次运行能查到实际 Prompt 版本,每条反馈能回到被评价的结果,异常版本可以通过标签回退。负面样本随后可以进入 Dataset,在发布前接受重复比较。

参考资料


系列目录:AI 应用可观测性与评估

上一篇:AI 又慢又贵,钱到底花在哪一步?

下一篇:90 分的 AI,为什么用户还是不满意?