监控与可观测性:LLM 应用的生产管理
一个 LLM 产品上线后,怎么知道它"行不行"?慢了、错了、贵了、被攻击了?这一篇讲监控栈。
L7-05 我们讲了”怎么部署 LLM”—— 这一篇讲”部署后怎么监控”。
传统 web 服务的监控经验不够 LLM 用—— LLM 产生的”质量问题” 大多数监控工具看不见。
没监控 = 黑盒 = 出事不知道。 生产 LLM 应用必备监控栈。
LLM 监控的三个维度
不同于传统服务的监控分层:
维度 1:技术指标(基础)
和普通 web 一样——
- 延迟 (P50 / P95 / P99)
- 吞吐 (QPS)
- 错误率 (5xx)
- 可用性 (uptime)
维度 2:LLM 特有指标
LLM 特别需要监控的:
- Token 用量(input + output 分开)
- Cache 命中率
- 每个请求的成本
- 不同模型的使用比例
- 失败 + 重试次数
维度 3:质量指标(最难)
- 输出质量(用户的 thumbs up/down)
- 幻觉率
- 拒绝率(合理 vs 过度)
- 风格一致性
- 业务关键指标(转化率 / 留存等)
第三维度最难—— 需要持续做”质量评估”(详见 L4-08)。
监控数据收集
必备的日志
每次 LLM 调用应记录:
log_entry = {
# 基础
"request_id": uuid(),
"timestamp": now(),
"user_id": user_id,
"session_id": session_id,
# LLM 调用
"model": "gpt-4o",
"endpoint": "/chat",
"prompt_tokens": response.usage.prompt_tokens,
"completion_tokens": response.usage.completion_tokens,
"total_cost_usd": calculate_cost(...),
# 性能
"latency_ms": elapsed_ms,
"ttft_ms": time_to_first_token,
"cache_hit": cache_hit_bool,
# 质量
"prompt": prompt[:1000], # 注意敏感信息
"response": response[:1000],
"fingerprint": response.fingerprint, # OpenAI 提供,用于一致性追踪
# 错误
"error": None, # 或错误详情
"retry_count": 0,
# 业务
"feature": "summarization",
"user_tier": "pro",
"experiment_group": "B",
}
log_to_db(log_entry)
全栈日志 —— 是后续所有监控的基础。
用户反馈
# 用户给 thumbs up/down
@app.post("/feedback")
def feedback(request_id, rating, comment=""):
log_feedback({
"request_id": request_id,
"rating": rating, # 1-5 或 thumbs
"comment": comment,
"timestamp": now(),
})
每个请求都有直接质量反馈—— 后续分析模型质量的金矿。
监控工具选择
| 工具 | 用途 | 推荐度 |
|---|---|---|
| LangSmith(LangChain) | 完整 LLM 应用追踪 | ⭐⭐⭐⭐⭐ |
| Helicone | 监控 + 成本 | ⭐⭐⭐⭐ |
| Phoenix(Arize) | 开源 LLM 可观测 | ⭐⭐⭐⭐ |
| Langfuse | 开源跟踪 + 评估 | ⭐⭐⭐⭐ |
| Weights & Biases (Weave) | 实验跟踪 + LLM | ⭐⭐⭐ |
| OpenAI Dashboard | 自家 token 用量 | ⭐⭐⭐(限于 OpenAI) |
| Datadog LLM Observability | 企业级 | ⭐⭐⭐⭐ |
起步推荐:Langfuse(开源、免费)或 LangSmith(功能强)。
用 LangSmith 例子
from langsmith import traceable
@traceable
def my_rag_pipeline(query):
# 1. 检索
docs = vector_db.search(query)
# 2. 拼 prompt
prompt = build_prompt(query, docs)
# 3. LLM
response = llm.invoke(prompt)
return response
# 调用 = 自动追踪
result = my_rag_pipeline("How does AI work?")
LangSmith UI 自动显示:
- 每步的输入 / 输出
- 每步的延迟
- 每步的 cost
- 总质量评分
监控仪表板
实战常见的仪表板组件:
实时指标面板
当前 QPS: 42
当前 P95 延迟: 2.3s
今日 token: 12.5M
今日成本: $156
缓存命中率: 48%
活跃用户数: 890
时序图
- 24 小时 QPS 趋势
- 错误率随时间
- 成本随时间
- P50 / P95 / P99 延迟随时间
模型对比
模型分布:
├── gpt-4o-mini (70%) → 简单查询
├── gpt-4o (25%) → 复杂任务
└── claude-3-opus (5%) → 兜底
成本分布:
├── gpt-4o-mini (15%)
├── gpt-4o (60%)
└── claude-3-opus (25%)
> mini 量大但便宜,opus 量小但贵。
错误分类
错误类型分布:
├── 超时 (40%)
├── 内容过滤 (25%)
├── token 超限 (15%)
├── API 限流 (10%)
└── 其它 (10%)
针对性优化——超时多 = 缩短 prompt / 换模型。
告警
监控不是看——是自动告警:
关键告警规则
- name: high_error_rate
condition: error_rate > 5% for 5 minutes
severity: critical
notify: pagerduty
- name: cost_spike
condition: hourly_cost > $100
severity: warning
notify: slack
- name: latency_degradation
condition: P95 > 5s for 10 minutes
severity: warning
notify: slack
- name: cache_dropout
condition: cache_hit_rate < 20% for 30 minutes
severity: info
notify: email
- name: user_satisfaction_drop
condition: thumbs_down_rate > 10% for 1 hour
severity: critical
notify: pagerduty
所有 LLM 服务必须有这些。
质量监控
最难也最重要—— LLM 输出质量怎么持续监控?
方法 1:用户反馈
最直接—— 但有偏:
- 不满意的用户更可能点 down
- 默默不满的不反馈
- 反馈延迟(可能产品已上线很久才反馈)
方法 2:定期抽样 + 人工 review
# 每 100 个请求抽 1 个,让运营 review
def sample_for_review(request_id, response):
if random() < 0.01:
send_to_review_queue(request_id, response)
适合:高价值场景(客服、医疗、金融)。 坏处:贵 + 慢。
方法 3:LLM-as-Judge
用另一个 LLM 自动评分:
def auto_evaluate(prompt, response):
judge_prompt = f"""
Rate this response on:
1. Helpfulness (1-5)
2. Accuracy (1-5)
3. Safety (1-5)
Prompt: {prompt}
Response: {response}
Return JSON.
"""
return gpt4_judge(judge_prompt)
适合:大量自动评估。 坏处:判断有偏(详见 L4-08)。
方法 4:业务指标
最终极—— 直接看业务:
- 客服 bot:CSAT 分数、问题解决率
- 写作助手:导出率、用户保存率
- 翻译:编辑距离(用户改了多少)
这是质量的”金标准”—— 但反馈周期长。
实战:四种方法组合用——互相补充。
安全监控
LLM 特别需要安全监控:
检测异常 prompt
def check_suspicious_prompt(prompt):
flags = []
# 长度异常
if len(prompt) > 50000:
flags.append("excessive_length")
# 已知 jailbreak 模式
if any(pattern in prompt.lower() for pattern in JAILBREAK_PATTERNS):
flags.append("jailbreak_pattern")
# PII 泄露
if contains_pii(prompt):
flags.append("pii_leak")
return flags
检测异常输出
def check_output(response):
# 检测有害内容
if contains_harmful(response):
log_alert("harmful_output", response)
return None # 拒绝返回
# 检测 PII 泄露
if contains_pii(response):
return redact_pii(response)
return response
用户行为模式
监控:
- 同一用户频繁调用 → 可能滥用 / 爬虫
- 同一 user 激活多个工具 → 可能在攻击 Agent
- prompt 出现”system” 等 LLM 内部词 → 可能 prompt injection
所有异常都自动 log + 告警。
一个工程模板
完整的”LLM 监控栈”:
┌─────────────────────────────────────┐
│ 用户请求 │
└─────────────┬───────────────────────┘
↓
┌─────────────────────────────────────┐
│ 请求中间件(input 检查 + 日志) │
└─────────────┬───────────────────────┘
↓
┌─────────────────────────────────────┐
│ LLM 调用(with tracing) │
│ - LangSmith / Langfuse SDK │
└─────────────┬───────────────────────┘
↓
┌─────────────────────────────────────┐
│ 响应中间件(output 检查 + 日志) │
└─────────────┬───────────────────────┘
↓
┌─────────────────────────────────────┐
│ 存储 │
│ - 日志 → BigQuery / ClickHouse │
│ - Metrics → Prometheus │
│ - Traces → Jaeger / OpenTelemetry │
└─────────────┬───────────────────────┘
↓
┌─────────────────────────────────────┐
│ 分析 + 告警 │
│ - Grafana 仪表板 │
│ - AlertManager │
│ - 业务 dashboard │
└─────────────────────────────────────┘
一些反思
”LLM 监控比 web 监控复杂 10×”
为什么?
- 质量 没有简单数字(vs HTTP 200/500)
- 成本 每个请求不同(vs 固定)
- 状态 多模态 + 多模型 + multi-step
- 变化 模型 / prompt 经常迭代
LLMOps 是个新职业—— 类似 DevOps 之于传统 web。 但更复杂。
“不监控的代价”
- 错误不能及时发现 → 用户流失
- 成本失控 → 月底报表心梗
- 安全事件 → 媒体新闻
- 质量下降 → 慢性流失(看不见)
“早期省下的监控时间,后期会用 10× 修复成本还回来”。
“起步建议”
如果你刚做 LLM 产品—— Week 1 就上监控:
- 用 Langfuse / LangSmith(免费档够用)
- 加基础告警(错误率、延迟)
- 用户 thumbs up/down
别等到上线后 才意识到要监控—— 那时数据已经丢了。
“What gets measured gets managed” —— Peter Drucker
LLM 应用——
- 不监控质量 → 质量退化没人知道
- 不监控成本 → 成本失控
- 不监控延迟 → 用户体验差
- 不监控安全 → 出大事
监控不是”奢侈品”—— 是 LLM 工程的最低要求。
下一篇推荐:L7-08 模型生命周期管理 或 L7-09 LLMOps 完整流程。
读到这里说明你认真在学 🎯
订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。
讨论区
· 用 GitHub 账号登录评论src/components/Comments.astro 顶部填入
仓库 ID 和分类 ID(见组件注释里的配置步骤)。