大模型实战:搭建一张“看得懂”的大模型应用可观测看板

前面已经做了很多底层工作:

  • 对每次模型调用打了 LLMCallLog,记录耗时、token、错误类型等;
  • 给多智能体/工作流每个节点打了 Trace,能看到「一次请求走过哪些节点」;
  • 还有异常检测、自愈、A/B 实验等机制。

但如果这些信息只躺在日志或数据库里,不做一个「一眼就能看懂」的看板,日常用起来还是很痛苦:

  • 想看最近是不是变慢了,要到处 grep 日志;
  • 想知道哪条工作流最费钱,要自己写脚本算;
  • 想查某次异常请求的执行路径,更是翻半天。

这篇就从工程角度讲清楚一件事:

如何基于前面已经埋好的日志和指标,

搭一张大模型应用可观测看板

让你能在浏览器里实时看到:调用量、错误率、延迟、token、成本、节点耗时等。

我用的是「通用思路 + 偏伪代码」的方式来讲,你可以用任意监控栈(Prometheus/Grafana、ClickHouse+Superset、自写管理页)去实现。


一、先想清楚:看板上要"看什么"?

不要一上来就堆一堆图表,先列需求。

对一个大模型应用来说,最有用的几类视图通常是:

  1. 全局概览

    • 总调用量(按分钟/小时)
    • 成功率 / 错误率趋势
    • 平均延迟 / P95 延迟
    • 平均 token 数
    • 预估总费用
  2. 按场景拆分(scene 维度)​

    • 问答(qa)、总结(summary)、翻译(translate)等;
    • 每个场景的调用量、成功率、延迟、成本。
  3. 按 Agent / 工作流节点拆分

    • 哪个 Agent 被调用最多;
    • 哪个节点最慢 / 错误最多;
    • 某个复杂工作流中,各节点耗时占比。
  4. 质量相关

    • 低质量回答占比(基于前面简单规则或用户反馈);
    • RAG 命中率、检索条数分布等。
  5. 异常 & 自愈

    • 最近触发了哪些熔断 / 降级;
    • 哪些资源(模型、向量库、外部 API)出问题最频繁。

搞清这 5 类,剩下就是「怎么把它们做成图表」的问题。


二、数据打平:把日志变成"可查询事件表"

无论你是写入文件、数据库,还是时序数据库,最终都可以抽象成一张「事件表」:

复制代码
llm_calls
---------
- timestamp
- trace_id
- model
- scene
- agent
- success (bool)
- error_type (string)
- latency_ms (float)
- prompt_tokens (int)
- completion_tokens (int)
- total_tokens (int)
- estimated_cost (float)

还有一张「工作流节点 Trace 表」:

复制代码
workflow_traces
---------------
- timestamp
- trace_id
- workflow_name
- node_name
- status (success/error_xxx)
- duration_ms (float)

只要有这两张表,你要的各种图基本都能算出来。

如果你现在是把 LLMCallLog 打到日志文件里,可以写个小采集脚本(示意伪代码):

python 复制代码
import json
import sqlite3
from datetime import datetime

def ingest_logs_to_db(log_file: str, db_path: str):
    conn = sqlite3.connect(db_path)
    cur = conn.cursor()
    cur.execute("""
    CREATE TABLE IF NOT EXISTS llm_calls (
      ts TEXT,
      trace_id TEXT,
      model TEXT,
      scene TEXT,
      agent TEXT,
      success INTEGER,
      error_type TEXT,
      latency_ms REAL,
      prompt_tokens INTEGER,
      completion_tokens INTEGER,
      total_tokens INTEGER,
      estimated_cost REAL
    )
    """)

    with open(log_file, encoding="utf-8") as f:
        for line in f:
            if "[LLM_CALL]" not in line:
                continue
            data = json.loads(line.split("[LLM_CALL]", 1)[1].strip())
            cur.execute("""
              INSERT INTO llm_calls VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
            """, (
                data.get("ts") or datetime.utcnow().isoformat(),
                data.get("trace_id", ""),
                data["model"],
                data["scene"],
                data["agent"],
                1 if data["success"] else 0,
                data.get("error_type", ""),
                data["latency_ms"],
                data["prompt_tokens"],
                data["completion_tokens"],
                data["total_tokens"],
                data.get("estimated_cost", 0.0),
            ))
    conn.commit()
    conn.close()

后面你可以把 SQLite 换成 MySQL / ClickHouse / 时序库都行,思路完全一样。


三、几个关键指标的 SQL 计算示例

假设我们用的是一个支持 SQL 的存储(比如 ClickHouse 或 SQLite),下面给几个典型查询示范,你可以直接拿去做图表的数据源。

3.1 全局概览:最近 24 小时调用趋势

按 5 分钟聚合一次:

python 复制代码
SELECT
  strftime('%Y-%m-%d %H:%M:00', ts) AS bucket,
  COUNT(*) AS calls,
  SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) AS success_rate,
  AVG(latency_ms) AS avg_latency_ms,
  AVG(total_tokens) AS avg_tokens,
  SUM(estimated_cost) AS total_cost
FROM llm_calls
WHERE ts >= datetime('now', '-1 day')
GROUP BY bucket
ORDER BY bucket;

你可以据此画出:

  • 请求数折线;
  • 成功率折线;
  • 平均延迟折线;
  • 费用面积图。

3.2 按场景(scene)拆分表现

python 复制代码
SELECT
  scene,
  COUNT(*) AS calls,
  SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) AS success_rate,
  AVG(latency_ms) AS avg_latency_ms,
  AVG(total_tokens) AS avg_tokens,
  SUM(estimated_cost) AS total_cost
FROM llm_calls
WHERE ts >= datetime('now', '-1 day')
GROUP BY scene
ORDER BY calls DESC;

在看板上,你可以做一个「场景排行榜」:

  • 调用最多的前 N 个场景;
  • 哪个场景延迟异常高;
  • 哪个场景最烧钱。

3.3 按 Agent 拆分

python 复制代码
SELECT
  agent,
  COUNT(*) AS calls,
  AVG(latency_ms) AS avg_latency_ms,
  SUM(estimated_cost) AS total_cost
FROM llm_calls
WHERE ts >= datetime('now', '-1 day')
GROUP BY agent
ORDER BY calls DESC;

用这个可以诊断:

  • 哪个 Agent 是"热点";
  • 哪个 Agent 总是最慢或最贵。

3.4 工作流节点耗时分布

python 复制代码
SELECT
  workflow_name,
  node_name,
  COUNT(*) AS calls,
  AVG(duration_ms) AS avg_ms,
  percentile_95(duration_ms) AS p95_ms
FROM workflow_traces
WHERE ts >= datetime('now', '-1 day')
GROUP BY workflow_name, node_name
ORDER BY workflow_name, avg_ms DESC;

这张表特别适合做「瀑布图」或「条形图」,用来识别:

  • 某个工作流中,究竟是哪几个节点拖慢了整体。

四、在前端做一张"技术同事看了就想用"的看板

你可以用任何前端技术栈,这里给的是信息布局思路,而不是框架代码。

4.1 页面分区布局建议

可以做成四大块:

  1. 顶部:全局 KPI 概览

    • 今日调用量 / 成功率 / 平均延迟 / 预估总费用;
    • 昨日同比环比的小箭头。
  2. 左侧:时间趋势区

    • 调用量 + 成功率双轴图;
    • 延迟 P95 / 平均延迟随时间变化;
    • Token 和成本趋势。
  3. 右侧:场景 & Agent 榜单

    • 表格或条形图:
      • Top N 场景:调用量、成功率、延迟、成本;
      • Top N Agent:调用量、平均延迟、节点错误率。
  4. 底部:工作流详情 + Trace 追踪

    • 下拉选择一个工作流名;
    • 显示:
      • 各节点平均耗时、P95;
      • 最近几次异常请求的 Trace(按时间线展示)。

4.2 Trace 时间线展示的核心数据结构

后端可以给前端返回这样的结构:

python 复制代码
{
  "trace_id": "abc-123",
  "workflow": "qa_pipeline",
  "start_ts": "2026-02-07T10:00:00Z",
  "end_ts": "2026-02-07T10:00:02Z",
  "nodes": [
    {
      "name": "router",
      "start_offset_ms": 0,
      "duration_ms": 10,
      "status": "success"
    },
    {
      "name": "retrieve",
      "start_offset_ms": 10,
      "duration_ms": 100,
      "status": "success"
    },
    {
      "name": "answer",
      "start_offset_ms": 110,
      "duration_ms": 1800,
      "status": "success"
    }
  ]
}

前端只要按 start_offset_ms + duration_ms 做一个水平条形时间线,就能直观看到:

  • 整个调用花了 1.9s;
  • 其中绝大部分时间耗在 answer 节点。

五、把"异常检测 / 自愈"也挂到看板上

前一篇我们加了异常检测和自愈机制,现在可以在看板上做一块「异常面板」:

5.1 异常事件表结构

可以存一张 anomalies 表:

python 复制代码
anomalies
---------
- ts
- type          # latency / error / quality / token_burst / rag_degrade 等
- severity      # info / warning / critical
- workflow
- node
- trace_id
- message
- auto_healed   # 是否已被自愈逻辑处理

5.2 异常看板内容

  • 最近 1 小时 / 24 小时异常数量趋势;
  • 按类型的堆叠柱状图(延迟异常、错误、质量下降等);
  • 最近 N 条严重异常列表(可点进去看 Trace);
  • 自愈效果统计:
    • 多少异常被自动处理;
    • 自动处理后的平均耗时变化。

六、成本维度:用已有 token 数据做一个"成本雷达"

你前面已经在 LLMCallLog 里算了 estimated_cost,现在可以从看板上做一块「成本分析」:

6.1 按模型拆分成本

python 复制代码
SELECT
  model,
  SUM(estimated_cost) AS total_cost,
  COUNT(*) AS calls,
  SUM(estimated_cost) / COUNT(*) AS avg_cost_per_call
FROM llm_calls
WHERE ts >= datetime('now', '-7 day')
GROUP BY model
ORDER BY total_cost DESC;

适合画成:

  • 模型成本占比饼图;
  • 每次调用平均花费柱状图。

6.2 按场景拆分成本

再配合场景,就能知道:

  • 哪个场景最烧钱;
  • 哪个场景单位成本最高(每次调用花多少钱)。

这对后面做「路由策略」「模型分层」非常有参考价值。


七、落地路线:用最少工作量让看板先跑起来

推荐一个「最小可行方案」路径:

  1. 先把 LLM 调用日志 + 工作流 Trace 写进一个能跑 SQL 的存储

    • 小项目可以用 SQLite/PostgreSQL;
    • 大一点可以上 ClickHouse / TimescaleDB;
    • 如果已有监控栈(Prometheus),LLM 指标也可以直接写成时序指标。
  2. 写几个最关键的查询

    • 全局概览;
    • 按场景/Agent 拆分;
    • 节点耗时统计;
    • 异常事件列表。
  3. 用一个可视化工具快速搭一版

    • Superset / Metabase / Grafana 都可以;
    • 先不追求 UI 完美,只要团队能看到数据就行。
  4. 等大家开始用看板后,再逐步优化

    • 把最常用的视图放到首页;
    • 加筛选维度(按时间、按场景、按模型);
    • 把异常 & 自愈信息挂上去。

做到这里,你就从:

「知道有日志有指标,但用起来很费劲」

升级成:

「打开一个地址,就能看到今天大模型系统跑得怎么样,

哪个场景出问题了,哪个 Agent 该优化,

甚至知道大概花了多少钱。」

相关推荐
廖圣平13 小时前
从零开始,福袋直播间脚本研究【七】《添加分组和比特浏览器》
python
B站_计算机毕业设计之家13 小时前
豆瓣电影数据可视化分析系统 | Python Flask框架 requests Echarts 大数据 人工智能 毕业设计源码(建议收藏)✅
大数据·python·机器学习·数据挖掘·flask·毕业设计·echarts
zzz的学习笔记本13 小时前
AI智能体时代的记忆 笔记(由大模型生成)
人工智能·智能体
AGI-四顾13 小时前
文生图模型选型速览
人工智能·ai
大尚来也13 小时前
一篇搞懂AI通识:用大白话讲清人工智能的核心逻辑
人工智能
Coder_Boy_13 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例
java·人工智能·spring boot·后端·spring
风指引着方向13 小时前
动态形状算子支持:CANN ops-nn 的灵活推理方案
人工智能·深度学习·神经网络
mr_LuoWei200913 小时前
python工具:python代码知识库笔记
数据库·python
weixin_3954489113 小时前
cursor日志
人工智能·python·机器学习