生成式 AI 可观测性:LLM 调用追踪、Token 成本监控、质量与安全评估

传统应用的可观测性(Metrics/Logs/Traces)在 LLM 应用面前依然成立,但要新增三个 LLM 特有的观测维度:Token 与成本(每次调用消耗多少、花了多少钱)、模型质量(回答对不对、是否幻觉、是否符合预期)、模型安全(提示注入、有害内容、PII 泄露)。大模型是"黑盒",它的行为 …

传统应用的可观测性(Metrics/Logs/Traces)在 LLM 应用面前依然成立,但要新增三个 LLM 特有的观测维度:Token 与成本(每次调用消耗多少、花了多少钱)、模型质量(回答对不对、是否幻觉、是否符合预期)、模型安全(提示注入、有害内容、PII 泄露)。大模型是"黑盒",它的行为是概率性的——同一提示词每次输出都不同,这决定了 GenAI 可观测性不能只看"延迟和错误码",还要看语义层面的质量与安全。本指南系统构建 GenAI 应用可观测体系:LLM 调用追踪、OTel GenAI 语义约定、成本用量监控、质量评估(LLM-as-Judge)、RAG 评估、安全监控、漂移检测与反馈回路,最后给出完整架构。

一、GenAI 应用需要观测什么

1.1 传统维度 + LLM 特有维度

传统(继承自常规应用):
  · 延迟:首 Token 延迟(TTFT)、总生成时间
  · 错误:超时、限流、模型不可用
  · 流量:调用量、QPS、并发

LLM 特有(新增):
  · Token:输入/输出 token 数(= 成本)
  · 成本:按模型按次核算金额
  · 质量:回答正确性、幻觉率、相关性
  · 安全:提示注入、有害内容、PII 泄露
  · 模型行为:温度、top_p、版本变化

ℹ️ 核心洞察:LLM 应用可观测性 = 传统可靠性监控 + 语义质量监控。前者回答"服务是不是通的",后者回答"回答靠不靠谱"——两者缺一不可。

1.2 三类观测对象

① LLM 调用本身:每次 generate/chat 的输入输出、token、耗时
② 编排链路:Agent 的每一步(工具调用、记忆检索、子任务)
③ 业务效果:用户满意度、转化率、回答采纳率(与业务指标联动)

二、LLM 调用追踪

2.1 Span 设计

一次 LLM 调用的 Span 结构:
  Span: llm / openai.chat / anthropic.complete
    · attributes: gen_ai.provider, gen_ai.model
    · attributes: gen_ai.request.temperature, max_tokens
    · events: message(input / output,含 token 计数)
    · span metrics: token 数、耗时、成本

RAG 流程的 Span 链:
  parent: 用户请求
   ├─ 检索(embedding 调用)
   ├─ 知识库查询(DB)
   ├─ 上下文组装
   └─ LLM 生成(llm span)

Agent 流程:
  parent: Agent 决策
   ├─ 记忆检索
   ├─ 工具调用(tool span)
   └─ LLM 再次决策(loop)

2.2 OTel GenAI 语义约定

OTel GenAI 语义约定(genai conventions):
  gen_ai.provider                 # openai / anthropic / ...
  gen_ai.model                    # gpt-4o / claude-3-5-sonnet
  gen_ai.request.temperature
  gen_ai.request.max_tokens
  gen_ai.request.model
  gen_ai.response.id
  gen_ai.response.finish_reason    # stop / length / tool_calls
  gen_ai.usage.input_tokens
  gen_ai.usage.output_tokens
  gen_ai.operation.name            # chat / embeddings / complete

Span 事件(记录输入输出内容):
  gen_ai.prompt                     # 输入消息
  gen_ai.completion                 # 输出消息

2.3 手动埋点示例(Python)

# genai_tracing.py — 手动为 LLM 调用打 span
from opentelemetry import trace
from opentelemetry.semconv.ai import GenAIAttributes

tracer = trace.get_tracer("genai.app")

@tracer.start_as_current_span("llm.chat")
def chat_with_model(user_query: str) -> str:
    span = trace.get_current_span()
    span.set_attribute(GenAIAttributes.PROVIDER, "openai")
    span.set_attribute(GenAIAttributes.MODEL, "gpt-4o")
    span.set_attribute(GenAIAttributes.OPERATION, "chat")

    response = model.chat(user_query)
    usage = response.usage   # token 统计

    span.set_attribute(GenAIAttributes.USAGE_INPUT_TOKENS, usage.prompt_tokens)
    span.set_attribute(GenAIAttributes.USAGE_OUTPUT_TOKENS, usage.completion_tokens)
    span.add_event("gen_ai.completion", {"text": response.content})
    return response.content

2.4 SDK 集成(LangChain / OpenAI)

# OpenAI SDK 自动埋点(借助 OpenAI OTel 集成)
from openai import OpenAI
from openai_opentelemetry import enable_tracing

enable_tracing()          # 自动为每个 API 调用创建 span
client = OpenAI()

# LangChain 自动埋点
from langchain_core.callbacks import tracing_v2_enabled
with tracing_v2_enabled("my-app"):
    result = chain.invoke({"question": "..."})

三、LLM 指标与告警

3.1 关键指标定义

# LLM 核心指标(通过 span metrics / 埋点上报到 Prometheus)
genai_llm_call_total{provider, model, operation}             # 调用量
genai_llm_token_input_total{model}                           # 输入 token
genai_llm_token_output_total{model}                          # 输出 token
genai_llm_cost_usd_total{model}                              # 成本($)
genai_llm_first_token_latency_seconds{model}                 # TTFT
genai_llm_total_latency_seconds{model}                       # 总延迟
genai_llm_error_total{provider, code}                        # 错误
genai_llm_quality_score{model, metric}                       # 质量分
genai_llm_toxic_total                                          # 有害输出
genai_llm_prompt_injection_total                               # 注入攻击

3.2 告警规则示例

groups:
  - name: genai.rules
    rules:
      # 错误率
      - alert: LLMErrorRateHigh
        expr: |
          sum(rate(genai_llm_error_total[5m]))
          / sum(rate(genai_llm_call_total[5m])) > 0.05
        for: 5m
      # 成本突增(预算控制)
      - alert: LLMCostSpike
        expr: |
          sum(rate(genai_llm_cost_usd_total[1h])) > 10
        labels:
          severity: warning
      # TTFT 超阈值
      - alert: LLMFirstTokenSlow
        expr: |
          histogram_quantile(0.95,
            rate(genai_llm_first_token_latency_seconds_bucket[5m])
          ) > 5
        for: 3m

四、Token 成本监控

4.1 成本归因

成本可观测维度:
  · 按模型(gpt-4o vs claude vs 本地)
  · 按服务/场景(客服、写作、推荐)
  · 按用户/租户(多租户成本分摊)
  · 按时间(日/周趋势)

成本 = Σ(token_in × 输入单价 + token_out × 输出单价)
  → 输出 token 往往更贵(5-10x)

4.2 成本计算埋点

# cost_metrics.py — 按模型单价计算成本
MODEL_PRICES = {
    "gpt-4o":         {"input": 0.0025, "output": 0.010},   # $/1K tokens
    "claude-3-5-sonnet": {"input": 0.003, "output": 0.015},
    "llama-3.1-70b":  {"input": 0.0002, "output": 0.0003},
}

def report_cost(model, input_tokens, output_tokens):
    price = MODEL_PRICES[model]
    cost = (input_tokens / 1000) * price["input"] \
         + (output_tokens / 1000) * price["output"]
    # 上报到 Prometheus counter
    prometheus_counter("genai_llm_cost_usd_total",
                       value=cost, labels={"model": model})
    return cost

4.3 预算治理

成本治理手段:
  · 每日预算 + 告警(费用超过当日预算 80% 触发)
  · 按租户配额(限额即停)
  · 模型路由:低成本任务走便宜模型
  · 语义缓存:命中缓存免调用
  · 降采样:对评测性调用按比例抽样

五、质量评估(LLM-as-Judge)

5.1 评估维度

LLM 输出质量评估维度:
  · 正确性(factual correctness)
  · 相关性(relevance to query)
  · 忠实度(faithfulness,是否基于给定上下文)
  · 连贯性(coherence)
  · 安全性(harmfulness)
  · 可读性(format)

评估方式:
  · LLM-as-Judge:用强模型打弱模型的输出(生产高频)
  · 规则/正则:硬性约束(格式、关键词)
  · 人工抽样:定期标注校准

5.2 生产在线评估

# judge.py — LLM-as-Judge 在线评估
from openai import OpenAI
judge = OpenAI()

JUDGE_PROMPT = """
你是质量评估员。给定用户问题与 AI 回答,输出 1-5 分:
- 正确性: {1..5}
- 相关性: {1..5}
- 忠实度: {1..5}(是否基于提供的上下文,不臆造)
返回 JSON: {"correctness": x, "relevance": x, "faithfulness": x}
"""

def evaluate_response(query, context, answer):
    resp = judge.chat.completions.create(
        model="gpt-4o-mini",
        response_format={"type": "json_object"},
        messages=[
            {"role": "system", "content": JUDGE_PROMPT},
            {"role": "user", "content":
             f"问题: {query}\n上下文: {context}\n回答: {answer}"},
        ],
    )
    scores = json.loads(resp.choices[0].message.content)
    # 上报质量分指标
    for metric, val in scores.items():
        prometheus_histogram("genai_llm_quality_score",
                             value=val, labels={"metric": metric})
    return scores

5.3 质量告警

# 平均质量分低于阈值(如 4.0)
avg(genai_llm_quality_score{metric="faithfulness"}[1h]) < 4.0
# 低分率占比
sum(genai_llm_quality_score{metric="correctness"} < 3)
/ count(genai_llm_quality_score{metric="correctness"}) > 0.05

六、RAG 评估

6.1 RAG 特有的观测点

RAG 链路观测:
  · 检索命中率:检索出的文档与问题相关度
  · 上下文利用率:回答是否真的用了检索内容
  · 引用可验证性:回答引用的文档是否存在
  · 检索延迟与失败
  · 向量库相关指标(embedding 调用、相似度分布)

关键问题:
  · "回答对但没引用" → 检查上下文是否真正注入
  · "引用了但答错" → 检索相关性差 / 文档冲突
  · "无引用乱答" → 上下文丢失 / 组装 bug

6.2 指标与追踪

def rag_pipeline(question):
    # 检索 span
    with tracer.start_as_current_span("rag.retrieve"):
        docs = vector_store.similarity_search(question, k=5)
        span.set_attribute("rag.retrieved_docs", len(docs))
        span.set_attribute("rag.top1_score", docs[0].score if docs else 0)
    # 组装 + 生成
    return generate(question, context=docs)

# 指标:
#   rag_retrieval_hit_rate        # 检索有结果的比例
#   rag_context_relevance          # 检索相关度(judge 评估)
#   rag_citation_accuracy          # 引用正确率

6.3 RAG 质量告警

# 检索命中率骤降
sum(rate(rag_retrieval_hit_rate_total[5m])) < 0.8
# 引用准确率下降
avg(rag_citation_accuracy[1h]) < 0.9

七、安全监控

7.1 LLM 安全观测维度

安全观测四类:
  ① 提示注入攻击:输入含注入指令(间接/直接)
  ② 有害内容:输出涉黄暴恐/歧视/仇恨
  ③ PII 泄露:输入或输出含敏感个人信息
  ④ 数据外泄:训练数据在输出中被复现(越狱)

检测手段:
  · 输入/输出过滤(关键词、分类器)
  · LLM-as-Judge 安全评估(违规检测)
  · 模型安全套件(Guardrails)

7.2 注入检测埋点

def detect_injection(user_input: str) -> bool:
    # 规则 + 模型双重检测
    rule_hit = any(kw in user_input.lower()
                   for kw in ["ignore previous", "you are now",
                              "system prompt", "jailbreak"])
    model_verdict = guardrail.check(user_input)
    if rule_hit or model_verdict.is_violation:
        prometheus_counter("genai_prompt_injection_total",
                           labels={"source": "user_input"})
        return True
    return False

7.3 安全告警与响应

# 注入攻击率
sum(rate(genai_prompt_injection_total[5m])) > 0.01
# PII 泄露
sum(rate(genai_pii_exposure_total[5m])) > 0
响应动作:
  · 拦截输入(不调用模型)
  · 过滤输出(替换/截断)
  · 记录攻击样本(安全分析)
  · 限流封禁(高频来源 IP/用户)

八、漂移检测与反馈回路

8.1 模型漂移观测

漂移检测:
  · 输出分布漂移(回答风格/长度变化)
  · 输入分布漂移(用户问题类型变化)
  · 质量分趋势下滑(长期)
  · 模型版本变更对比(升级前后 A/B)

方法:
  · 质量分滑窗均值 + 趋势
  · 输出长度/置信度分布
  · 用户行为反馈(点赞/点踩率)

8.2 反馈回路

# 用户反馈采集 → 修正评估集 → 回归测试
def collect_feedback(response_id, rating, comment=""):
    # 存反馈样本库(eval set)
    store_feedback(response_id, rating, comment)
    # 低分样本定期加入评测集
    if rating <= 2:
        eval_set.add(response_id)
    # 触发告警:低分率上升
    track_low_rating_ratio()

8.3 离线评估与发布门禁

GenAI 发布门禁(类似测试门禁):
  1. 黄金评测集(golden set)跑分
  2. 质量分达标(正确性/相关性 ≥ 阈值)
  3. 安全测试通过(注入/有害样本 0 泄露)
  4. 成本增量可接受
  5. 线上灰度 A/B,观测质量分与用户反馈

→ 把"观测数据"变成"上线决策依据"

九、完整 GenAI 可观测性架构

9.1 架构蓝图

应用(SDK/Agent) ──► OTel Collector ──► 后端
    │ 埋点:                        │
    │  · LLM 调用 span               ├─► Tempo(追踪)
    │  · token/成本 metric            ├─► Prometheus(指标)
    │  · 访问日志                    ├─► Loki(日志)
    │  · 质量/安全评估                └─► 评估平台(judge 结果)
    ▼
 评估服务(LLM-as-Judge / Guardrails)
    └─► 质量分 / 安全分 上报

可视化:Grafana(指标/成本/质量面板)+ Tempo(链路)
告警:错误率、成本、TTFT、质量分、安全事件
反馈回路:线上评分 → 评测集 → 回归门禁

9.2 面板设计

GenAI 观测面板(Grafana):
  · 总览:调用量、QPS、总成本、平均质量分
  · 模型对比:各模型延迟/成本/错误
  · Token 趋势:输入/输出/按服务拆分
  · 质量:正确性/相关性/忠实度时间序列
  · 安全:注入/有害/PII 事件
  · 链路:Top 慢调用、失败 Trace

9.3 落地清单

□ LLM 调用统一埋点(SDK 自动 + 手动补业务语义)
□ Token/成本指标上报(按模型/服务/租户)
□ 质量评估(LLM-as-Judge + 规则 + 人工抽样)
□ 安全检测(注入/有害/PII/外泄)
□ RAG 指标(检索命中、引用准确)
□ 漂移检测 + 用户反馈回路
□ 发布门禁(golden set + 安全 + 成本)
□ 告警(错误/成本/TTFT/质量/安全)

总结:GenAI 可观测性决策表

维度观测对象手段
可靠性调用量、延迟、错误OTel span + Prometheus
成本Token 用量、费用埋点 + 单价表
质量正确性/相关性/忠实度LLM-as-Judge
安全注入/有害/PIIGuardrails + 检测
RAG检索命中/引用准确链路埋点
演进漂移、反馈评测集 + 门禁

GenAI 可观测性把传统"三支柱"延伸到了语义世界——你不但要知道服务是通是堵,还要知道模型答得对不对、贵不贵、有没有泄露风险。这套体系让 LLM 应用从"黑盒冒险"变成"可验证的工程":每次上线前用评测集把关,上线后用指标/质量/安全实时观测,再把线上反馈回流到评测集形成闭环。落地时抓住五件事:埋点(LLM 调用 span)、记价(Token 成本)、打分(LLM-as-Judge)、护线(安全 Guardrails)、闭环(反馈→门禁)。做完这五步,你的 LLM 应用就有了与传统应用同等的可靠性与治理能力。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「Observability」更多文章

  1. 可观测性成本治理:采样降噪、数据生命周期与存储成本优化实战
  2. 服务网格可观测性:Istio 遥测、Kiali 拓扑与全链路追踪实战
  3. Prometheus 长期存储与集群化:Thanos 与 Mimir 架构对比与实战