欢迎光临
我们一直在努力

AI 应用的可观测性:LangFuse + Prometheus 监控 LLM 全链路

文章目录

    • 一、LLM 应用的可观测性四支柱
    • 二、LangFuse:LLM 调用级追踪
      • 2.1 快速接入:@observe 装饰器
      • 2.2 手动记录自定义步骤
      • 2.3 LangFuse Dashboard 解读
      • 2.4 Prompt 版本管理与 A/B 测试
    • 三、Prometheus:聚合级指标监控
      • 3.1 自定义指标暴露
      • 3.2 指标命名规范
    • 四、Grafana Dashboard 搭建
      • 4.1 面板配置
      • 4.2 Dashboard JSON 配置(可直接导入)
    • 五、告警规则:从"事后复盘"到"事前预警"
      • 5.1 核心告警规则
      • 5.2 告警触发流程
    • 六、实战:为 RAG 系统接入全链路可观测性
      • 6.1 可观测性增强版 RAG 服务
      • 6.2 完整观测链路验证
    • 七、可观测性体系建设路线图

传统 API 的监控三件套是"QPS + 延迟 + 错误率"——但 LLM 应用还需要第四件:Token 消耗和成本。模型调用按 token 计费,一个失控的循环或一个低效的 Prompt 可能在几天内烧掉数千元预算。更可况,LLM 的输出具有不确定性,同样的输入可能产生截然不同的结果,这让传统的"正确/错误"二元监控失效。本文聚焦 LLM 应用特有的可观测性挑战,用 LangFuse 实现调用级追踪,用 Prometheus + Grafana 实现聚合级监控,构建一套双轨并行的生产级观测方案。


一、LLM 应用的可观测性四支柱

LLM 应用的可观测性体系需要回答四类问题:单次请求发生了什么(Traces)、系统整体表现如何(Metrics)、每次交互的详细记录(Logs)、以及花了多少钱(Costs)。这四个维度不是孤立存在的,而是相互关联、逐层下钻的关系。

#mermaid-svg-ok2DlROf3fKLyHMP{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ok2DlROf3fKLyHMP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ok2DlROf3fKLyHMP .error-icon{fill:#552222;}#mermaid-svg-ok2DlROf3fKLyHMP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ok2DlROf3fKLyHMP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ok2DlROf3fKLyHMP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ok2DlROf3fKLyHMP .marker.cross{stroke:#333333;}#mermaid-svg-ok2DlROf3fKLyHMP svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ok2DlROf3fKLyHMP p{margin:0;}#mermaid-svg-ok2DlROf3fKLyHMP .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ok2DlROf3fKLyHMP .cluster-label text{fill:#333;}#mermaid-svg-ok2DlROf3fKLyHMP .cluster-label span{color:#333;}#mermaid-svg-ok2DlROf3fKLyHMP .cluster-label span p{background-color:transparent;}#mermaid-svg-ok2DlROf3fKLyHMP .label text,#mermaid-svg-ok2DlROf3fKLyHMP span{fill:#333;color:#333;}#mermaid-svg-ok2DlROf3fKLyHMP .node rect,#mermaid-svg-ok2DlROf3fKLyHMP .node circle,#mermaid-svg-ok2DlROf3fKLyHMP .node ellipse,#mermaid-svg-ok2DlROf3fKLyHMP .node polygon,#mermaid-svg-ok2DlROf3fKLyHMP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ok2DlROf3fKLyHMP .rough-node .label text,#mermaid-svg-ok2DlROf3fKLyHMP .node .label text,#mermaid-svg-ok2DlROf3fKLyHMP .image-shape .label,#mermaid-svg-ok2DlROf3fKLyHMP .icon-shape .label{text-anchor:middle;}#mermaid-svg-ok2DlROf3fKLyHMP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ok2DlROf3fKLyHMP .rough-node .label,#mermaid-svg-ok2DlROf3fKLyHMP .node .label,#mermaid-svg-ok2DlROf3fKLyHMP .image-shape .label,#mermaid-svg-ok2DlROf3fKLyHMP .icon-shape .label{text-align:center;}#mermaid-svg-ok2DlROf3fKLyHMP .node.clickable{cursor:pointer;}#mermaid-svg-ok2DlROf3fKLyHMP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ok2DlROf3fKLyHMP .arrowheadPath{fill:#333333;}#mermaid-svg-ok2DlROf3fKLyHMP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ok2DlROf3fKLyHMP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ok2DlROf3fKLyHMP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ok2DlROf3fKLyHMP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ok2DlROf3fKLyHMP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ok2DlROf3fKLyHMP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ok2DlROf3fKLyHMP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ok2DlROf3fKLyHMP .cluster text{fill:#333;}#mermaid-svg-ok2DlROf3fKLyHMP .cluster span{color:#333;}#mermaid-svg-ok2DlROf3fKLyHMP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ok2DlROf3fKLyHMP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ok2DlROf3fKLyHMP rect.text{fill:none;stroke-width:0;}#mermaid-svg-ok2DlROf3fKLyHMP .icon-shape,#mermaid-svg-ok2DlROf3fKLyHMP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ok2DlROf3fKLyHMP .icon-shape p,#mermaid-svg-ok2DlROf3fKLyHMP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ok2DlROf3fKLyHMP .icon-shape .label rect,#mermaid-svg-ok2DlROf3fKLyHMP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ok2DlROf3fKLyHMP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ok2DlROf3fKLyHMP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ok2DlROf3fKLyHMP :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

用户请求

Traces 单次请求全链路

Span: 检索

Span: 重排序

Span: LLM 生成

Span: 后处理

Metrics 聚合指标

Counter: Token 总量

Histogram: 延迟分布

Gauge: 成本累计

Logs 详细日志

trace_id 关联

Costs 费用分析

按模型/用户/项目分组

支柱监控对象典型问题工具
Traces 单次请求的完整链路 为什么这个用户的请求花了 15 秒?检索和生成各占多久? LangFuse, Jaeger
Metrics 聚合后的统计指标 QPS 是多少?P99 延迟是否超过阈值?Token 消耗日环比如何? Prometheus, StatsD
Logs 每次交互的详细文本 模型输出了什么?Prompt 内容是什么?用户反馈如何? ELK, Loki
Costs 费用明细与预算追踪 本月 GPT-4 调用花了多少钱?哪个用户的消耗最高? LangFuse, 自建计费系统

Traces 和 Metrics 的关系可以用"显微镜 vs 望远镜"来理解:Traces 把单次请求放大到每个子步骤的耗时和输入输出,用于根因定位;Metrics 把一段时间内的所有请求聚合为趋势曲线,用于容量规划和异常检测。Logs 则是最原始的记录,通常通过 trace_id 与 Traces 关联,实现"从异常指标 → 异常 Trace → 详细日志"的下钻路径。


二、LangFuse:LLM 调用级追踪

LangFuse 是一个开源的 LLM 可观测性平台(由德国团队开发),支持 SaaS 托管和自部署两种模式。它的核心概念围绕三个对象展开:Trace(一次完整请求的顶层容器)、Span(一个逻辑步骤,如检索/生成)、Generation(一次 LLM 调用,自动记录输入/输出/Token 数/延迟)。

2.1 快速接入:@observe 装饰器

LangFuse 的 Python SDK 提供 @observe() 装饰器,只需三行代码即可自动追踪函数的执行:

from langfuse.decorators import observe
from langfuse import Langfuse

langfuse = Langfuse(
public_key="pk-lf-…",
secret_key="sk-lf-…",
host="https://cloud.langfuse.com" # 或自建地址
)

@observe()
def retrieve_documents(query: str):
# 检索逻辑
docs = vector_db.search(query, top_k=5)
return docs

@observe()
def generate_answer(query: str, context: list):
prompt = f"基于以下上下文回答问题:\\n{context}\\n\\n问题:{query}"
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content

@observe()
def rag_pipeline(query: str):
docs = retrieve_documents(query)
answer = generate_answer(query, docs)
return answer

# 调用
result = rag_pipeline("Python 异步编程最佳实践")

上述代码执行后,LangFuse 会自动创建一个 Trace,包含两个 Span(retrieve_documents 和 generate_answer)。generate_answer 内部的 OpenAI 调用会被自动识别为 Generation,记录输入 Prompt、输出文本、输入 token 数、输出 token 数、模型名称、延迟等完整信息。

2.2 手动记录自定义步骤

对于装饰器无法覆盖的场景(如异步代码、多线程、或需要自定义元数据的步骤),可以使用低级别 API 手动创建 Span 和 Generation:

from langfuse import Langfuse

langfuse = Langfuse()

def custom_rag_pipeline(query: str):
# 创建顶层 Trace
trace = langfuse.trace(
name="rag_query",
metadata={"user_id": "user_123", "session_id": "sess_456"}
)

# 记录检索步骤
retrieval_span = trace.span(
name="document_retrieval",
input={"query": query, "top_k": 5}
)
docs = vector_db.search(query, top_k=5)
retrieval_span.end(output={"documents": [d[:100] for d in docs], "count": len(docs)})

# 记录重排序步骤
rerank_span = trace.span(name="reranking")
scored_docs = cross_encoder.rerank(query, docs)
rerank_span.end(output={"top_doc_score": scored_docs[0]["score"]})

# 记录 LLM 生成步骤
generation = trace.generation(
name="llm_generation",
model="gpt-4o",
input=prompt,
metadata={"temperature": 0.7}
)
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)
generation.end(
output=response.choices[0].message.content,
usage={
"input": response.usage.prompt_tokens,
"output": response.usage.completion_tokens
}
)

# 给 Trace 打总分
trace.score(name="response_quality", value=0.9)

return response.choices[0].message.content

手动记录的优势在于精确控制每个步骤的输入输出内容。例如检索步骤可以记录实际召回的文档摘要(而非完整文本,避免存储过大),重排序步骤可以记录最高分的文档得分(用于评估检索质量),Generation 可以记录 temperature 等生成参数(用于后续调优)。

2.3 LangFuse Dashboard 解读

LangFuse 的 Web Dashboard 提供四个核心视图:

视图功能使用场景
Traces 列表 按时间倒序展示所有请求,支持按延迟/成本/状态过滤 发现异常请求(如耗时 > 10s 或成本 > $0.1)
Trace 详情 时间瀑布图展示各步骤耗时,以及输入/输出文本 根因分析:哪一步骤拖慢了整体响应?
Metrics 概览 Token 消耗趋势、延迟分布、成本累计的聚合图表 容量规划:QPS 增长是否需要扩容?
Scores 评分 用户反馈(thumbs up/down)或自动化评估分数的统计 质量监控:好评率是否下降?

Trace 的时间瀑布图是最具诊断价值的视图。一个典型的 RAG 请求瀑布图可能呈现如下形态:

检索 (Embedding) |██████| 120ms
检索 (ANN Search) |████████| 180ms
重排序 |████████████████| 450ms
LLM 生成 |████████████████████████| 1200ms
后处理 |██| 50ms
总耗时 2000ms

从这个瀑布图可以直观看出:LLM 生成占总耗时的 60%,是优化重点;重排序占 22.5%,可以考虑减少精排候选数;检索仅占 15%,暂时不是瓶颈。这种基于真实数据的优化方向判断,比凭经验猜测要可靠得多。

2.4 Prompt 版本管理与 A/B 测试

LangFuse 内置 Prompt Management 功能,允许在 UI 中编辑 Prompt 模板,通过 SDK 拉取指定版本,从而实现 Prompt 的版本控制和 A/B 测试:

# 从 LangFuse 拉取最新版本的 Prompt
prompt = langfuse.get_prompt("rag_system_prompt", version=3)

# 使用 Prompt 模板
compiled_prompt = prompt.compile(context=context, query=query)

# 记录使用了哪个版本的 Prompt
trace.generation(
name="llm_call",
model="gpt-4o",
input=compiled_prompt,
prompt=prompt # 自动关联 Prompt 版本
)

Prompt 版本管理的工程价值在于:当线上发现某个版本的 Prompt 效果下降(通过 Scores 监控),可以快速回滚到上一个稳定版本,而不需要修改代码重新部署。A/B 测试则可以在小流量上验证新 Prompt 的效果,确认后再全量切换。


三、Prometheus:聚合级指标监控

LangFuse 擅长调用级追踪,但聚合级监控(如"过去一小时的 QPS 是多少")需要时序数据库的支持。Prometheus 是云原生生态的事实标准,通过拉取(pull)模式收集指标,配合 Grafana 可视化,构成完整的监控体系。

3.1 自定义指标暴露

使用 prometheus_client 库在 Python 应用中暴露 LLM 相关指标:

from prometheus_client import Counter, Histogram, Gauge, start_http_server
import time

# Token 消耗计数器(按模型和标签分组)
llm_tokens_total = Counter(
"llm_tokens_total",
"Total tokens consumed by LLM calls",
["model", "token_type", "user_id"]
)

# 请求延迟直方图(按模型分组,分桶记录)
llm_request_duration_seconds = Histogram(
"llm_request_duration_seconds",
"LLM request duration in seconds",
["model", "endpoint"],
buckets=[0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 30.0]
)

# 成本累计仪表盘(按模型分组)
llm_cost_total = Gauge(
"llm_cost_total",
"Cumulative LLM API cost in USD",
["model"]
)

# 启动指标暴露服务
start_http_server(8000)

# 模型调用时记录指标
COST_PER_1K_TOKENS = {
"gpt-4o": {"input": 0.005, "output": 0.015},
"gpt-4o-mini": {"input": 0.00015, "output": 0.0006},
"deepseek-chat": {"input": 0.00014, "output": 0.00028}
}

def call_llm(model: str, prompt: str, user_id: str):
start = time.time()

response = client.chat.completions.create(model=model, messages=[...])

duration = time.time() start
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens

# 记录 Token 消耗
llm_tokens_total.labels(model=model, token_type="input", user_id=user_id).inc(input_tokens)
llm_tokens_total.labels(model=model, token_type="output", user_id=user_id).inc(output_tokens)

# 记录延迟
llm_request_duration_seconds.labels(model=model, endpoint="/chat").observe(duration)

# 记录成本
cost = (input_tokens / 1000) * COST_PER_1K_TOKENS[model]["input"] + \\
(output_tokens / 1000) * COST_PER_1K_TOKENS[model]["output"]
llm_cost_total.labels(model=model).inc(cost)

return response

上述代码暴露了三个核心指标:

  • llm_tokens_total:Counter 类型,只增不减,适合统计累计 Token 消耗。按 model、token_type(input/output)、user_id 分组,可以回答"GPT-4o 今天输出了多少 Token"或"用户 A 本月消耗了多少 Token"这类问题。
  • llm_request_duration_seconds:Histogram 类型,将延迟分桶记录。Prometheus 会自动计算 P50/P95/P99 分位数,无需额外代码。
  • llm_cost_total:Gauge 类型,记录累计成本。虽然 Counter 也可以,但 Gauge 更适合可能重置的场景(如按天清零统计)。

3.2 指标命名规范

Prometheus 指标命名遵循 namespace_subsystem_metric_unit 的格式。LLM 应用的推荐命名约定:

指标名称类型说明
llm_tokens_total Counter Token 消耗总量
llm_request_duration_seconds Histogram 请求延迟
llm_request_errors_total Counter 错误请求数(按错误类型分组)
llm_cost_total Gauge 累计成本(USD)
llm_active_requests Gauge 当前进行中的请求数
llm_prompt_version_info Gauge Prompt 版本信息(值为 1,label 包含版本号)
rag_retrieval_count Counter 检索召回文档数
rag_rerank_score Histogram 重排序得分分布

四、Grafana Dashboard 搭建

Prometheus 存储指标,Grafana 负责可视化。一个完整的 LLM 监控 Dashboard 至少应包含四个面板:

#mermaid-svg-kbrm8soXoVQjnrSN{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kbrm8soXoVQjnrSN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kbrm8soXoVQjnrSN .error-icon{fill:#552222;}#mermaid-svg-kbrm8soXoVQjnrSN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kbrm8soXoVQjnrSN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kbrm8soXoVQjnrSN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kbrm8soXoVQjnrSN .marker.cross{stroke:#333333;}#mermaid-svg-kbrm8soXoVQjnrSN svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kbrm8soXoVQjnrSN p{margin:0;}#mermaid-svg-kbrm8soXoVQjnrSN .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-kbrm8soXoVQjnrSN .cluster-label text{fill:#333;}#mermaid-svg-kbrm8soXoVQjnrSN .cluster-label span{color:#333;}#mermaid-svg-kbrm8soXoVQjnrSN .cluster-label span p{background-color:transparent;}#mermaid-svg-kbrm8soXoVQjnrSN .label text,#mermaid-svg-kbrm8soXoVQjnrSN span{fill:#333;color:#333;}#mermaid-svg-kbrm8soXoVQjnrSN .node rect,#mermaid-svg-kbrm8soXoVQjnrSN .node circle,#mermaid-svg-kbrm8soXoVQjnrSN .node ellipse,#mermaid-svg-kbrm8soXoVQjnrSN .node polygon,#mermaid-svg-kbrm8soXoVQjnrSN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kbrm8soXoVQjnrSN .rough-node .label text,#mermaid-svg-kbrm8soXoVQjnrSN .node .label text,#mermaid-svg-kbrm8soXoVQjnrSN .image-shape .label,#mermaid-svg-kbrm8soXoVQjnrSN .icon-shape .label{text-anchor:middle;}#mermaid-svg-kbrm8soXoVQjnrSN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kbrm8soXoVQjnrSN .rough-node .label,#mermaid-svg-kbrm8soXoVQjnrSN .node .label,#mermaid-svg-kbrm8soXoVQjnrSN .image-shape .label,#mermaid-svg-kbrm8soXoVQjnrSN .icon-shape .label{text-align:center;}#mermaid-svg-kbrm8soXoVQjnrSN .node.clickable{cursor:pointer;}#mermaid-svg-kbrm8soXoVQjnrSN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kbrm8soXoVQjnrSN .arrowheadPath{fill:#333333;}#mermaid-svg-kbrm8soXoVQjnrSN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kbrm8soXoVQjnrSN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kbrm8soXoVQjnrSN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kbrm8soXoVQjnrSN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kbrm8soXoVQjnrSN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kbrm8soXoVQjnrSN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kbrm8soXoVQjnrSN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kbrm8soXoVQjnrSN .cluster text{fill:#333;}#mermaid-svg-kbrm8soXoVQjnrSN .cluster span{color:#333;}#mermaid-svg-kbrm8soXoVQjnrSN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kbrm8soXoVQjnrSN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kbrm8soXoVQjnrSN rect.text{fill:none;stroke-width:0;}#mermaid-svg-kbrm8soXoVQjnrSN .icon-shape,#mermaid-svg-kbrm8soXoVQjnrSN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kbrm8soXoVQjnrSN .icon-shape p,#mermaid-svg-kbrm8soXoVQjnrSN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kbrm8soXoVQjnrSN .icon-shape .label rect,#mermaid-svg-kbrm8soXoVQjnrSN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kbrm8soXoVQjnrSN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kbrm8soXoVQjnrSN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kbrm8soXoVQjnrSN :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Grafana Dashboard

QPS 面板

Token 消耗趋势

P50/P95/P99 延迟

成本累计

Prometheus

LLM 应用

4.1 面板配置

面板一:QPS(每秒查询数)

# 过去 5 分钟的 QPS
rate(llm_tokens_total[5m])

# 按模型分组的 QPS
sum by (model) (rate(llm_tokens_total[5m]))

面板二:Token 消耗趋势

# 每分钟 Token 消耗
sum by (token_type) (rate(llm_tokens_total[1m]))

# 输入 vs 输出 Token 比例
sum(rate(llm_tokens_total{token_type="output"}[5m]))
/
sum(rate(llm_tokens_total{token_type="input"}[5m]))

输出/输入 Token 比例是一个容易被忽视的指标。正常情况下,LLM 的输出 Token 数应该小于或接近输入 Token 数。如果这个比例突然飙升(如从 0.5 涨到 5.0),可能意味着模型在输出冗长的重复内容,需要检查 Prompt 或模型参数。

面板三:延迟分位数

# P50 延迟
histogram_quantile(0.50,
sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model)
)

# P99 延迟
histogram_quantile(0.99,
sum(rate(llm_request_duration_seconds_bucket[5m])) by (le, model)
)

面板四:成本累计与预算

# 累计成本
llm_cost_total

# 日成本增长速率
rate(llm_cost_total[1d])

# 预算使用率(假设月预算 $1000)
llm_cost_total / 1000

4.2 Dashboard JSON 配置(可直接导入)

{
"dashboard": {
"title": "LLM Application Monitoring",
"panels": [
{
"title": "QPS by Model",
"type": "timeseries",
"targets": [{
"expr": "sum by (model) (rate(llm_tokens_total[5m]))",
"legendFormat": "{{ model }}"
}]
},
{
"title": "Token Consumption (Input vs Output)",
"type": "timeseries",
"targets": [
{"expr": "sum(rate(llm_tokens_total{token_type='input'}[5m]))", "legendFormat": "Input"},
{"expr": "sum(rate(llm_tokens_total{token_type='output'}[5m]))", "legendFormat": "Output"}
]
},
{
"title": "Latency P50/P95/P99",
"type": "timeseries",
"targets": [
{"expr": "histogram_quantile(0.50, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le))", "legendFormat": "P50"},
{"expr": "histogram_quantile(0.95, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le))", "legendFormat": "P95"},
{"expr": "histogram_quantile(0.99, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le))", "legendFormat": "P99"}
]
},
{
"title": "Cumulative Cost (USD)",
"type": "stat",
"targets": [{"expr": "sum(llm_cost_total)", "legendFormat": "Total"}]
}
]
}
}


五、告警规则:从"事后复盘"到"事前预警"

监控的价值不在于看漂亮的 Dashboard,而在于异常发生时及时通知。Prometheus AlertManager 支持灵活的告警规则配置。

5.1 核心告警规则

# llm_alerts.yml
groups:
name: llm_cost_alerts
rules:
# 告警1:Token 消耗日环比突增 > 50%
alert: TokenUsageSpike
expr: |
(
sum(rate(llm_tokens_total[1h]))
/
sum(rate(llm_tokens_total[1h] offset 24h))
) > 1.5

for: 15m
labels:
severity: warning
annotations:
summary: "Token 消耗突增"
description: "过去 1 小时 Token 消耗比昨日同期增长 {{ $value | humanizePercentage }}"

# 告警2:P99 延迟 > 10s
alert: HighLatencyP99
expr: |
histogram_quantile(0.99,
sum(rate(llm_request_duration_seconds_bucket[5m])) by (le)
) > 10

for: 5m
labels:
severity: critical
annotations:
summary: "LLM P99 延迟过高"
description: "P99 延迟达到 {{ $value }}s,超过 10s 阈值"

# 告警3:错误率 > 5%
alert: HighErrorRate
expr: |
sum(rate(llm_request_errors_total[5m]))
/
sum(rate(llm_request_duration_seconds_count[5m])) > 0.05

for: 5m
labels:
severity: critical
annotations:
summary: "LLM 错误率过高"
description: "过去 5 分钟错误率 {{ $value | humanizePercentage }}"

# 告警4:日成本超过预算的 80%
alert: DailyCostThreshold
expr: |
sum(increase(llm_cost_total[1d])) > 800

labels:
severity: warning
annotations:
summary: "日成本接近预算上限"
description: "今日累计成本 ${{ $value }},预算 $1000/天"

# 告警5:输出/输入 Token 比例异常
alert: AbnormalOutputRatio
expr: |
(
sum(rate(llm_tokens_total{token_type="output"}[15m]))
/
sum(rate(llm_tokens_total{token_type="input"}[15m]))
) > 3

for: 10m
labels:
severity: warning
annotations:
summary: "输出 Token 比例异常"
description: "输出/输入 Token 比例达到 {{ $value }},可能触发冗长生成长"

5.2 告警触发流程

Slack/钉钉

AlertManager

Prometheus

LLM 应用

Slack/钉钉

AlertManager

Prometheus

LLM 应用

#mermaid-svg-opaIp0kQO233ZIST{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-opaIp0kQO233ZIST .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-opaIp0kQO233ZIST .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-opaIp0kQO233ZIST .error-icon{fill:#552222;}#mermaid-svg-opaIp0kQO233ZIST .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-opaIp0kQO233ZIST .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-opaIp0kQO233ZIST .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-opaIp0kQO233ZIST .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-opaIp0kQO233ZIST .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-opaIp0kQO233ZIST .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-opaIp0kQO233ZIST .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-opaIp0kQO233ZIST .marker{fill:#333333;stroke:#333333;}#mermaid-svg-opaIp0kQO233ZIST .marker.cross{stroke:#333333;}#mermaid-svg-opaIp0kQO233ZIST svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-opaIp0kQO233ZIST p{margin:0;}#mermaid-svg-opaIp0kQO233ZIST .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-opaIp0kQO233ZIST text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-opaIp0kQO233ZIST .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-opaIp0kQO233ZIST .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-opaIp0kQO233ZIST .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-opaIp0kQO233ZIST .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-opaIp0kQO233ZIST #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-opaIp0kQO233ZIST .sequenceNumber{fill:white;}#mermaid-svg-opaIp0kQO233ZIST #sequencenumber{fill:#333;}#mermaid-svg-opaIp0kQO233ZIST #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-opaIp0kQO233ZIST .messageText{fill:#333;stroke:none;}#mermaid-svg-opaIp0kQO233ZIST .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-opaIp0kQO233ZIST .labelText,#mermaid-svg-opaIp0kQO233ZIST .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-opaIp0kQO233ZIST .loopText,#mermaid-svg-opaIp0kQO233ZIST .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-opaIp0kQO233ZIST .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-opaIp0kQO233ZIST .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-opaIp0kQO233ZIST .noteText,#mermaid-svg-opaIp0kQO233ZIST .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-opaIp0kQO233ZIST .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-opaIp0kQO233ZIST .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-opaIp0kQO233ZIST .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-opaIp0kQO233ZIST .actorPopupMenu{position:absolute;}#mermaid-svg-opaIp0kQO233ZIST .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-opaIp0kQO233ZIST .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-opaIp0kQO233ZIST .actor-man circle,#mermaid-svg-opaIp0kQO233ZIST line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-opaIp0kQO233ZIST :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

loop

[每 15s 抓取]

loop

[每 30s 评估]

暴露 /metrics

检查告警规则

触发 TokenUsageSpike

分组/抑制/静默

发送告警通知

on-call 工程师响应

AlertManager 的三个核心功能:

  • 分组(Group):同一类告警合并为一条通知,避免告警风暴。例如 10 个模型实例同时触发高延迟告警,只会收到一条"多个实例延迟异常"的通知。
  • 抑制(Inhibit):高优先级告警抑制低优先级告警。例如"服务宕机"告警触发时,抑制"P99 延迟高"的告警(因为服务已经不可用了)。
  • 静默(Silence):在维护窗口期间静默特定告警。例如部署新版本时,临时静默"错误率升高"的告警 30 分钟。

六、实战:为 RAG 系统接入全链路可观测性

将前文构建的 RAG 问答系统接入 LangFuse + Prometheus + Grafana 的完整观测体系。

6.1 可观测性增强版 RAG 服务

from fastapi import FastAPI
from pydantic import BaseModel
from langfuse.decorators import observe, langfuse_context
from prometheus_client import Counter, Histogram, Gauge, make_asgi_app
import time

app = FastAPI()

# 挂载 Prometheus metrics 端点
metrics_app = make_asgi_app()
app.mount("/metrics", metrics_app)

# 定义 Prometheus 指标
llm_tokens = Counter("rag_tokens_total", "Token consumption", ["model", "type"])
llm_latency = Histogram("rag_latency_seconds", "Request latency", ["step"])
rag_cost = Gauge("rag_cost_usd", "Cumulative cost", ["model"])

COST_RATE = {"gpt-4o": 0.01, "gpt-4o-mini": 0.000375}

class QueryRequest(BaseModel):
question: str
user_id: str

class QueryResponse(BaseModel):
answer: str
sources: list
cost_usd: float
latency_ms: float

@observe()
def retrieve(query: str):
with llm_latency.labels(step="retrieval").time():
docs = chroma_collection.query(query_texts=[query], n_results=5)
return docs["documents"][0]

@observe()
def generate(query: str, context: list, model: str = "gpt-4o"):
prompt = f"上下文:{context}\\n问题:{query}"

with llm_latency.labels(step="generation").time():
response = openai_client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}]
)

# 记录指标
input_tok = response.usage.prompt_tokens
output_tok = response.usage.completion_tokens
llm_tokens.labels(model=model, type="input").inc(input_tok)
llm_tokens.labels(model=model, type="output").inc(output_tok)

cost = (input_tok + output_tok) * COST_RATE[model] / 1000
rag_cost.labels(model=model).inc(cost)

# 更新 LangFuse 当前 Observation 的 metadata
langfuse_context.update_current_observation(
metadata={"user_id": langfuse_context.current_observation.user_id}
)

return response.choices[0].message.content, cost

@app.post("/chat")
@observe() # 自动追踪整个请求链路
def chat(req: QueryRequest):
start = time.time()

# 更新 Trace 的 user_id
langfuse_context.update_current_trace(
user_id=req.user_id,
metadata={"endpoint": "/chat"}
)

docs = retrieve(req.question)
answer, cost = generate(req.question, docs)

latency = time.time() start

return QueryResponse(
answer=answer,
sources=docs[:3],
cost_usd=round(cost, 6),
latency_ms=round(latency * 1000, 2)
)

6.2 完整观测链路验证

启动服务后,可以通过以下路径验证观测链路是否正常工作:

验证步骤方法预期结果
Prometheus 指标 curl localhost:8000/metrics 返回 rag_tokens_total、rag_latency_seconds 等指标
LangFuse Trace 访问 LangFuse Dashboard 每条 /chat 请求生成一条 Trace,包含检索和生成两个 Span
Grafana 面板 导入 Dashboard JSON 四个面板正常显示 QPS、Token、延迟、成本
告警测试 触发异常高 Token 消耗 AlertManager 发送 Slack/邮件通知

七、可观测性体系建设路线图

#mermaid-svg-GoxTiPrN7qm8Aug7{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GoxTiPrN7qm8Aug7 .error-icon{fill:#552222;}#mermaid-svg-GoxTiPrN7qm8Aug7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GoxTiPrN7qm8Aug7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .marker.cross{stroke:#333333;}#mermaid-svg-GoxTiPrN7qm8Aug7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GoxTiPrN7qm8Aug7 p{margin:0;}#mermaid-svg-GoxTiPrN7qm8Aug7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster-label text{fill:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster-label span{color:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster-label span p{background-color:transparent;}#mermaid-svg-GoxTiPrN7qm8Aug7 .label text,#mermaid-svg-GoxTiPrN7qm8Aug7 span{fill:#333;color:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .node rect,#mermaid-svg-GoxTiPrN7qm8Aug7 .node circle,#mermaid-svg-GoxTiPrN7qm8Aug7 .node ellipse,#mermaid-svg-GoxTiPrN7qm8Aug7 .node polygon,#mermaid-svg-GoxTiPrN7qm8Aug7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .rough-node .label text,#mermaid-svg-GoxTiPrN7qm8Aug7 .node .label text,#mermaid-svg-GoxTiPrN7qm8Aug7 .image-shape .label,#mermaid-svg-GoxTiPrN7qm8Aug7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-GoxTiPrN7qm8Aug7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .rough-node .label,#mermaid-svg-GoxTiPrN7qm8Aug7 .node .label,#mermaid-svg-GoxTiPrN7qm8Aug7 .image-shape .label,#mermaid-svg-GoxTiPrN7qm8Aug7 .icon-shape .label{text-align:center;}#mermaid-svg-GoxTiPrN7qm8Aug7 .node.clickable{cursor:pointer;}#mermaid-svg-GoxTiPrN7qm8Aug7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .arrowheadPath{fill:#333333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GoxTiPrN7qm8Aug7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GoxTiPrN7qm8Aug7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GoxTiPrN7qm8Aug7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster text{fill:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 .cluster span{color:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GoxTiPrN7qm8Aug7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GoxTiPrN7qm8Aug7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-GoxTiPrN7qm8Aug7 .icon-shape,#mermaid-svg-GoxTiPrN7qm8Aug7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GoxTiPrN7qm8Aug7 .icon-shape p,#mermaid-svg-GoxTiPrN7qm8Aug7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GoxTiPrN7qm8Aug7 .icon-shape .label rect,#mermaid-svg-GoxTiPrN7qm8Aug7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GoxTiPrN7qm8Aug7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GoxTiPrN7qm8Aug7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GoxTiPrN7qm8Aug7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

阶段1:基础追踪

LangFuse @observe记录延迟+Token+成本

阶段2:聚合监控

Prometheus 指标QPS/延迟/成本

阶段3:可视化

Grafana Dashboard四面板布局

阶段4:智能告警

AlertManager成本/延迟/错误率

阶段5:质量评估

LangFuse Scores用户反馈+Ragas

闭环优化

阶段时间投入覆盖范围价值
阶段1 2 小时 单次请求追踪 能看到单次请求发生了什么
阶段2 4 小时 系统级聚合指标 能看到系统整体健康度
阶段3 4 小时 可视化面板 团队共享监控视图
阶段4 4 小时 自动告警 异常自动通知,缩短 MTTR
阶段5 8 小时 质量评估闭环 从"监控发生了什么"到"评估做得好不好"

从阶段1到阶段5的演进,本质上是从"被动观测"到"主动优化"的跃迁。阶段1-2 告诉你系统是否在正常工作,阶段3-4 让你在异常时第一时间响应,阶段5 则帮助你持续改进系统质量。

前文关于模型部署(ONNX Runtime + FastAPI)和向量数据库(Chroma/Milvus/Qdrant)的内容,为本文的 RAG 可观测性实战提供了底层服务基础。LangFuse 的调用追踪与 MLflow 的实验追踪形成互补——前者关注线上推理,后者关注线下训练,两者共同构成 AI 应用的全生命周期可观测体系。


如果这篇文章对 LLM 可观测性的建设思路有所帮助,欢迎点赞和关注专栏。此前关于模型部署服务化、向量数据库选型以及 RAG 检索增强的内容,也与本文的实战场景紧密相关,可以结合起来阅读。

赞(0)
未经允许不得转载:171主机测评 » AI 应用的可观测性:LangFuse + Prometheus 监控 LLM 全链路
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址