你的LLM应用一上线就黑盒,怎么知道哪里贵、哪里慢、哪里错
很多AI产品开发者把精力全花在prompt和模型选型上,上线之后反而心里没底。用户反馈”有点慢”,你连慢在哪一步都说不清;账单月底翻倍,你想不起来到底哪个功能在烧钱。传统监控工具对LLM应用基本失灵,因为它们看不到token、cost、单次推理延迟这些关键信号。
这篇文章不讲道理,直接给你一套能落地的LLM可观测性方案:要监控哪些信号、用OpenTelemetry怎么做无侵入埋点、一个可以抄的token成本统计代码。
为什么要给LLM应用专门做可观测性
普通API的监控看的是QPS、错误率、P99延迟。但LLM应用多了一个普通后端没有的维度:你的接口正确性取决于模型输出,而模型输出是概率性的,还可能受上下文长度、rate limit、缓存命中率影响。
OpenTelemetry官方文档里专门讲了一课:LLM应用要重点盯三件事——用量和成本、推理延迟、限流。延迟这一点尤其重要,因为同一个prompt在不同的输入下返回时间可能差好几倍。OpenTelemetry的LLM可观测性文档建议用trace记录RAG应用里检索和生成的全过程,再配合metrics看聚合数据。
这套思路已经很成熟。Langfuse官方介绍里说自己每月处理90B+条观测数据,被21家财富500强使用,10万+工程师在它上面构建。这说明大型团队早就把LLM可观测性当成标配了,不是你产品做大了才需要。
监控哪些信号,一张清单说清楚
别一上来就堆十几个指标。先把下面这五个盯住,就够你发现80%的问题。
- token用量和成本。每个请求的输入输出token,乘上单价就是成本。这是你对账、做成本优化(比如降级到便宜模型)的依据。
- 端到端延迟。从用户发请求到拿到回复的总时长,以及拆开看:检索耗时、LLM调用耗时、流式首token耗时。
- rate limit与重试。外部模型接口可能限流,命中限流会导致功能降级。要记录限流次数和重试次数。
- 输出质量信号。离线很难测,但能测的都要记:截断次数、空回复、格式解析失败、自定义的bad response标记。
- 缓存命中率。prompt缓存或多租户共享缓存,命中能省一大笔钱,必须看得见数字。
用OpenTelemetry做无侵入埋点
最省事的方式是用开源的自动埋点库,比如OpenLIT,它能自动给OpenAI、Anthropic这些SDK加上trace,不用你手写一堆埋点代码。OpenLIT把LLM相关的span上报到OpenTelemetry标准后端(Prometheus存metrics、Jaeger存traces),再用Grafana做可视化。
这套组合的好处是标准统一:traces和metrics都走OTel协议,换后端不锁死。下面是加trace的最小代码,Node环境直接用OpenLIT SDK:
import { OpenTelemetry } from '@openlit/sdk';
// 一行初始化,自动为OpenAI/Anthropic等SDK加埋点
const telemetry = new OpenTelemetry();
telemetry.init({
serviceName: 'my-ai-app',
traceBatch: true,
disableBatch: false,
});
初始化之后,你调用OpenAI SDK的每个请求都会自动生成一条span,包含model、prompt tokens、completion tokens、延迟这几个关键字段。你不用改业务代码,就能在Jaeger里看到完整的调用链。
官方推荐的Go/Java/Python都有对应SDK,思路上完全一致:先初始化,再正常调SDK。想迁移到Langfuse自托管或别的平台,改的是export端,不是你的代码。
手写一个token成本统计,不用等平台
如果不想引入整套平台,也可以写个轻量中间件,把每次调用的成本和延迟记录到日志或时序库里。下面这段Python用OpenAI SDK,配合一个简单的记账函数就能跑:
import time, json
from openai import OpenAI
# 单价按 token 计价,不同模型价格不同,写进配置
MODEL_PRICES = {
"gpt-4o-mini": {"input": 0.00015, "output": 0.0006}, # 每千tokens美元
}
client = OpenAI()
COST_LOG = open("llm_cost.log", "a")
def chat_with_track(model, messages):
t0 = time.perf_counter()
resp = client.chat.completions.create(model=model, messages=messages)
dt = time.perf_counter() - t0
usage = resp.usage
price = MODEL_PRICES[model]
cost = (usage.prompt_tokens * price["input"] +
usage.completion_tokens * price["output"]) / 1000
COST_LOG.write(json.dumps({
"model": model,
"prompt_tokens": usage.prompt_tokens,
"completion_tokens": usage.completion_tokens,
"latency_s": round(dt, 3),
"cost_usd": round(cost, 6),
"ts": time.time(),
}) + "\n")
return resp
这套代码解决的是最刚需的问题:每次调用花了多少钱、用了多久。把日志导进Prometheus或者写个简单的汇总脚本,就能按天/按模型做成本报表。别小看这几行,很多小团队连自己的token成本都说不清楚。
从排查到评估的一小步
光有埋点还不够,数据要能用起来。你至少该每周看一次三个汇总:总成本变化趋势、P95延迟走势、rate limit命中次数。成本突然上涨,优先查是不是缓存失效;延迟变高,拆开看是检索慢还是模型慢;限流多了,检查是不是并发没控好。
再进一步,可以把用户行为和观测数据打通。比如把”这条回复被点赞/被举报”和生成它的trace关联起来,用真实反馈给模型输出质量打标。这一步做通,你就从”能看见”变成了”能评估”,这才是LLM可观测性的最终价值。
我不是让你第一周就把全套体系搭起来。先把五个核心信号和那个成本统计跑通,跑两周,你对自己的AI应用心里就有底了。剩下的,等数据开口说话再补。
