LLM 应用的可观测性要关注哪些数据?

进阶实践约 6 分钟读完

一句话回答

传统服务看请求量、错误率和延迟就够了,LLM 应用还要能回答:模型这次看到了什么、回答了什么、花了多少钱、用户满不满意。每次模型调用都要记录输入输出、模型和参数、token 用量和费用、首 token 延迟和总耗时、错误和结束原因;RAG 和 Agent 还要记录检索结果和每次工具调用,并关联用户反馈。这些数据里有用户隐私,要脱敏、控制访问权限,并设置保留期限。

详细解析

每次模型调用记录什么

类别 字段 用途
标识 trace ID、会话 ID、用户 ID(哈希后)、功能入口、Prompt 版本 串起一次请求;按功能、版本统计
输入输出 完整的消息列表(系统提示可以只记版本号)、输出内容、结束原因 复现问题、分析失败案例
模型和参数 供应商、带版本的模型名、temperature、最大输出长度、提供的工具列表 对比不同配置,追踪上游模型的变化
用量和费用 输入 token、输出 token、缓存命中的 token(部分供应商会返回)、折算的费用 成本分析、异常消耗告警
性能 首 token 延迟(TTFT)、总耗时、输出速度、排队和重试次数 用户体验和容量规划
错误 错误类型(限流、超时、上下文超长、被内容审核拦截)、是否重试成功、是否降级到备用模型 稳定性

结束原因很有用:正常结束、达到长度上限被截断、被内容过滤、发起了工具调用,各自对应不同的问题。

链路上的中间结果和用户反馈

模型调用之外,链路上的其他步骤也要记录:

  • RAG:改写后的查询、召回的文档 ID 和分数、重排后的顺序、最终放进上下文的片段
  • Agent 和工具调用:每一步的工具名、参数、返回结果(太长时记摘要)、耗时、是否出错,以及总步数
  • 后处理:结构化输出的校验结果、内容审核的结果

这些步骤要用同一个 trace ID 串成一棵树,才能看清一次请求的全过程(见 链路追踪)。用户反馈也要挂到对应的 trace 上:

  • 显式反馈:点赞、点踩(附带原因选项:不准确、没回答问题、太长……)、文字反馈
  • 隐式信号:重新生成、复制回答、修改后再用、换个说法再问、中途停止生成、放弃会话、转人工
  • 关联到 trace ID 之后,从一个点踩就能直接看到当时的输入、检索结果和输出;只有少数用户会主动反馈,要结合隐式信号一起看

隐私和保留期限

  • 写入前脱敏:手机号、身份证号、邮箱这类格式固定的信息用规则替换;姓名、地址需要实体识别模型或专门的脱敏服务
  • 分级保存:统计指标长期保留;完整的输入输出只保留一段时间(按合规要求定),查看要有权限控制和审计
  • 用户要求删除数据时,日志里的内容也要能删
  • 使用第三方观测平台时,确认数据存储在哪里,必要时选择自托管(更多见 敏感信息泄露)

看板和告警

看板按功能、模型、Prompt 版本拆分,常看这几类:

  • 流量:请求量、活跃用户
  • 性能:首 token 延迟和总耗时的 P50、P95、P99
  • 稳定性:按类型统计的错误率、重试率、降级率
  • 成本:每天的 token 和费用、每次请求和每个用户的平均费用、消耗最多的用户
  • 质量:点踩率、重新生成率、截断率、JSON 解析失败率、抽样评分(见 上线后怎么发现效果变差)

常见的告警:错误率或限流比例突增;P95 延迟超过阈值;每小时的费用超过预算,或者单个用户消耗异常(可能被滥用,或者程序陷入了循环);截断比例突增(往往是 Prompt 改动让输出变长了)。

代码示例

一条调用日志的示例(数值仅为示意):

JSON
{
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "feature": "kb_qa",
  "prompt_version": "kb-answer@v12",
  "model": "provider/model-2026-01-01",
  "params": { "temperature": 0.2, "max_tokens": 800 },
  "usage": { "input_tokens": 3120, "output_tokens": 286, "cached_tokens": 2048 },
  "latency_ms": { "ttft": 820, "total": 4630 },
  "finish_reason": "stop",
  "retrieved_ids": ["doc-12#3", "doc-40#1"],
  "feedback": null
}

写入日志前先脱敏:

TypeScript
// 规则只能覆盖格式固定的信息,姓名、地址要用实体识别模型
const RULES: [RegExp, string][] = [
  [/(?<!\d)1[3-9]\d{9}(?!\d)/g, '[手机号]'],
  [/(?<![\dXx])\d{17}[\dXx](?![\dXx])/g, '[身份证号]'],
  [/[\w.+-]+@[\w-]+(\.[\w-]+)+/g, '[邮箱]'],
]

export function redact(text: string) {
  return RULES.reduce((t, [pattern, label]) => t.replace(pattern, label), text)
}

面试官可能追问

全量记录输入输出,存储成本太高怎么办?

指标全量统计,完整内容按比例采样;出错、点踩、费用异常的请求全量保留。长而固定的系统提示只记版本号,检索到的文档只记 ID。按冷热分层存储,过期自动删除。

流式输出时,首 token 延迟和 token 用量怎么统计?

首 token 延迟是从发出请求到收到第一个内容片段的时间,在服务端和客户端分别测量,两者的差就是网络和中间层的开销。token 用量通常在流的最后一个事件里返回,有的接口要在请求里显式开启才会返回。用户中途停止时,要记录已生成的部分,并确认上游请求也被取消了(见 停止生成)。

怎么把成本算到具体的用户和功能上?

每次调用都带上用户 ID、租户、功能入口这些标签,按标签聚合 token 和费用。Agent 的一次任务包含多次模型调用和工具调用,要按 trace 汇总成"一次任务的成本"。这些数据也是配额和计费的依据。

易错点

  • 只记录最终输出,不记录检索和工具调用的中间结果,出了问题无法复现
  • 不记录 Prompt 版本和带版本号的模型名,改动前后没法对比
  • 明文保存用户隐私,或者日志永久保留
  • 只看平均延迟,不看 P95 和首 token 延迟

AI 模拟面试官

用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮

登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录

这道题你掌握了吗?

选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。

学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。