news 2026/8/22 11:20:19

AI全栈知识15:AI应用的可观测性 - Token监控与成本控制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI全栈知识15:AI应用的可观测性 - Token监控与成本控制

AI全栈知识15:AI应用的可观测性 - Token监控与成本控制

写在前面

你维护一个普通微服务,监控很简单:QPS、延迟、错误率、CPU、内存。这些指标稳定可预测,每次请求消耗的资源基本一致。

AI服务不一样。同一个接口,用户问"你好"可能消耗100个Token,问"帮我写一份完整的K8s部署方案"可能消耗5000个Token。每次请求的成本完全不可预测。

如果不做好监控,你可能遇到:

  • 月底收到一张天价账单,不知道钱花在哪
  • 某个用户在刷量,Token一直在烧但没人发现
  • Agent陷入死循环,一个请求消耗了几万Token
  • 用户投诉"AI好慢",但你看CPU利用率才30%

这篇帮你建立AI服务的完整可观测性体系。


AI服务跟普通服务的监控区别

普通微服务的监控

指标固定、成本可预测: - QPS:每秒处理多少请求 - 延迟:每个请求多少毫秒 - 错误率:多少请求报错 - 资源:CPU/内存使用率 特点:每次请求消耗的资源差不多

AI服务多出来的监控

指标波动大、成本不可预测: - Token消耗:每次请求不一样(100~10000+) - 首Token延迟:用户等多久看到第一个字 - 生成速度:每秒输出多少Token - 成本(元):直接跟钱挂钩 - 调用轮次:Agent跑了几轮 - 模型选择:用了哪个模型(大小模型成本不同)
维度普通微服务AI服务
成本模型固定(服务器费/月)变动(按Token计费)
延迟构成单一(处理时间)复合(首Token+生成)
请求成本差异几乎一样差100倍(简单问题vs复杂问题)
失败模式崩溃/超时额外有:死循环/Token爆炸/模型拒绝
成本归因按服务分摊需按团队/功能/用户归因

核心指标一:Token消耗

为什么Token是最重要的指标

Token = 钱。调用大模型API按Token计费:

通义千问qwen-turbo: 输入:0.003元/千Token 输出:0.006元/千Token GPT-4o: 输入:0.01元/千Token 输出:0.03元/千Token

一个请求如果消耗5000 Token(输入3000+输出2000),用GPT-4o就花了0.09元。看着不多,100个用户每人每天10次 = 90元/天 = 2700元/月。

如果有个Agent死循环消耗了50000 Token,一次请求就花掉将近1元。不监控根本发现不了。

需要记录的Token指标

# 每次请求记录token_metrics={"request_id":"req-xxx","user_id":"user-001","function":"customer_service",# 哪个功能"model":"qwen-turbo",# 用了哪个模型"prompt_tokens":1500,# 输入Token"completion_tokens":800,# 输出Token"total_tokens":2300,# 总Token"cost_yuan":0.0093,# 换算成钱"rounds":3,# Agent跑了几轮}

Prometheus打点

fromprometheus_clientimportCounter,Histogram# Token总量TOKENS_TOTAL=Counter('ai_tokens_total','Total tokens consumed',['model','function','token_type']# 按模型、功能、输入/输出分类)# 每次请求的Token数分布TOKENS_PER_REQUEST=Histogram('ai_tokens_per_request','Tokens per request',['model','function'],buckets=[100,500,1000,2000,5000,10000,20000,50000])# 使用时TOKENS_TOTAL.labels(model='qwen-turbo',function='customer_service',token_type='prompt').inc(1500)TOKENS_TOTAL.labels(model='qwen-turbo',function='customer_service',token_type='completion').inc(800)TOKENS_PER_REQUEST.labels(model='qwen-turbo',function='customer_service').observe(2300)

核心指标二:延迟(TTFT + 生成速度)

两段延迟

AI服务的延迟跟普通服务不一样,分两段:

用户发送问题 ↓ [等待...] ← TTFT(Time To First Token):首Token延迟 ↓ 用户在这段时间里看到的是空白/loading 开始输出第一个字 ↓ [持续输出中...] ← 生成速度:每秒输出多少Token ↓ 用户看到文字在一个一个往外蹦 输出完毕 ← 总延迟(End-to-End Latency)

为什么要分开看

指标影响什么用户感受
TTFT用户等多久开始看到回答TTFT>3秒用户就觉得卡了
生成速度文字蹦出来的快慢<10 tokens/s像打字机,>30基本感知不到
总延迟完整回答出来要多久Agent多轮可能几十秒

用户体验主要看TTFT。哪怕总回答需要10秒,只要0.5秒就开始出字,用户感觉就很快(流式输出的优势)。

Prometheus打点

TTFT=Histogram('ai_time_to_first_token_seconds','Time to first token',['model','function'],buckets=[0.1,0.3,0.5,1.0,2.0,3.0,5.0,10.0])GENERATION_SPEED=Histogram('ai_generation_tokens_per_second','Token generation speed',['model'],buckets=[5,10,20,30,50,100])E2E_LATENCY=Histogram('ai_request_duration_seconds','End-to-end request latency',['model','function'],buckets=[1,2,5,10,20,30,60])

核心指标三:成本归因

问题

月底Token账单来了,总共花了5000元。老板问:钱花在哪了?哪个团队花的?哪个功能最烧钱?

如果没有成本归因,你只能说"总共花了5000"。有了归因,你能说:

本月Token成本归因: 客服机器人:3200元(64%)← 最大头 内部知识搜索:1100元(22%) 运维Agent:500元(10%) 测试/开发调试:200元(4%)

怎么做

在每次API调用时打上标签(团队、功能、环境):

classCostTracker:def__init__(self):self.records=[]defrecord(self,team,function,model,tokens,cost):self.records.append({"timestamp":datetime.now(),"team":team,# 哪个团队"function":function,# 哪个功能"model":model,# 什么模型"tokens":tokens,# 消耗多少Token"cost":cost,# 花了多少钱})defdaily_report(self):"""生成每日成本报告"""# 按团队/功能汇总...

Prometheus Label设计

# 关键:通过label区分来源COST_YUAN=Counter('ai_cost_yuan_total','Total cost in yuan',['team','function','model','environment'])# 使用时COST_YUAN.labels(team='customer_service',function='chat_bot',model='qwen-turbo',environment='production').inc(0.009)

Grafana里就能按team筛选,看每个团队的花费趋势。


核心指标四:调用链追踪

为什么需要

Agent可能调了5轮LLM、3个工具,最后给了一个错误答案。不记录调用链,你不知道是第几轮出的问题。

一次Agent请求的完整调用链

{"trace_id":"trace-abc123","request_id":"req-001","user_input":"帮我查查order-service为什么报错","total_duration_ms":8500,"total_tokens":4500,"total_cost_yuan":0.018,"rounds":[{"round":1,"action":"llm_call","model":"qwen-turbo","prompt_tokens":800,"completion_tokens":50,"duration_ms":1200,"decision":"call tool: get_unhealthy_pods"},{"round":2,"action":"tool_call","tool":"get_unhealthy_pods","duration_ms":300,"result":"order-service-xxx: CrashLoopBackOff"},{"round":3,"action":"llm_call","model":"qwen-turbo","prompt_tokens":1200,"completion_tokens":60,"duration_ms":1500,"decision":"call tool: get_pod_logs"},{"round":4,"action":"tool_call","tool":"get_pod_logs","duration_ms":500,"result":"OutOfMemoryError..."},{"round":5,"action":"llm_call","model":"qwen-turbo","prompt_tokens":1800,"completion_tokens":200,"duration_ms":2000,"decision":"final_answer"}]}

有了这个,出问题时能精确定位:第几轮、调了什么、结果是什么、Token花在哪了。

接入方式

可以用OpenTelemetry或自己写日志。核心是每次LLM调用和工具调用都带上同一个trace_id:

importuuidclassRequestTracer:def__init__(self):self.trace_id=str(uuid.uuid4())self.rounds=[]deflog_llm_call(self,round_num,model,prompt_tokens,completion_tokens,duration_ms,decision):self.rounds.append({"round":round_num,"action":"llm_call","model":model,"prompt_tokens":prompt_tokens,"completion_tokens":completion_tokens,"duration_ms":duration_ms,"decision":decision,})deflog_tool_call(self,round_num,tool_name,duration_ms,result_preview):self.rounds.append({"round":round_num,"action":"tool_call","tool":tool_name,"duration_ms":duration_ms,"result":result_preview[:200],# 只存前200字})

核心指标五:异常检测

AI服务独有的异常场景

异常现象原因告警条件
Token暴涨单次请求>20000 TokenAgent死循环/用户输入超长文本单次>阈值
成本突增今日花费已超预算80%流量突增/被刷量/模型选错了日成本>阈值
延迟飙升TTFT从0.5s变成5s模型过载/并发太高P99>阈值
拒绝率升高模型频繁返回无法回答安全策略误杀/Prompt有问题拒绝率>10%
空回答模型返回空字符串模型异常/Token用完空回答率>5%
重复调用同一用户短时间大量请求恶意刷量/前端bug每分钟>20次

告警规则(Prometheus AlertManager)

groups:-name:ai_service_alertsrules:# Token单次暴涨-alert:HighTokensPerRequestexpr:ai_tokens_per_request>20000for:0mlabels:severity:warningannotations:summary:"单次请求Token异常高"# 日成本超预算-alert:DailyCostExceededexpr:sum(increase(ai_cost_yuan_total[24h]))>200for:5mlabels:severity:criticalannotations:summary:"今日AI成本已超200元"# TTFT延迟飙升-alert:HighTTFTexpr:histogram_quantile(0.99,ai_time_to_first_token_seconds)>5for:5mlabels:severity:warningannotations:summary:"首Token延迟P99超过5秒"# 用户刷量-alert:UserRateLimitexpr:sum(rate(ai_tokens_total[1m])) by (user_id)>50000for:2mlabels:severity:warningannotations:summary:"某用户Token消耗速率异常"

Grafana面板设计

推荐面板布局

第一行:概览 - 今日总Token消耗 + 今日总成本(大数字显示) - 当前QPS - 当前活跃用户数 第二行:延迟 - TTFT P50 / P95 / P99 趋势图 - 生成速度 (tokens/s) 趋势图 - 请求总延迟分布 第三行:Token详情 - Token消耗趋势(按功能/团队分色) - 每次请求Token分布(直方图) - 输入Token vs 输出Token比例 第四行:成本 - 每日成本趋势(柱状图) - 成本按团队归因(饼图) - 成本按模型归因(饼图) - 预算消耗进度条 第五行:异常 - 单次高Token请求列表 - 错误/拒绝率趋势 - Agent平均轮次趋势

PromQL示例

# 今日总Token sum(increase(ai_tokens_total[24h])) # 今日总成本(元) sum(increase(ai_cost_yuan_total[24h])) # TTFT P99 histogram_quantile(0.99, rate(ai_time_to_first_token_seconds_bucket[5m])) # 按团队的Token消耗速率 sum(rate(ai_tokens_total[5m])) by (team) # Agent平均轮次 avg(ai_agent_rounds_per_request)

成本控制实战

预算管理

classBudgetManager:def__init__(self,daily_budget_yuan=200,monthly_budget_yuan=5000):self.daily_budget=daily_budget_yuan self.monthly_budget=monthly_budget_yuan self.daily_spent=0self.monthly_spent=0defcheck_budget(self,estimated_cost):"""请求前检查预算"""ifself.daily_spent+estimated_cost>self.daily_budget:returnFalse,"今日预算已用完"ifself.monthly_spent+estimated_cost>self.monthly_budget:returnFalse,"本月预算已用完"returnTrue,"OK"defon_request_complete(self,actual_cost):"""请求完成后记录花费"""self.daily_spent+=actual_cost self.monthly_spent+=actual_cost# 达到80%告警ifself.daily_spent>self.daily_budget*0.8:send_alert("今日预算已使用80%")

省钱策略

策略做法节省比例
大小模型路由简单问题用小模型,复杂问题用大模型30-50%
Prompt精简去掉冗余的System Prompt10-20%
缓存相同问题直接返回缓存结果视场景20-80%
限流每用户每分钟限制请求次数防止异常消耗
设Token上限max_tokens限制输出长度防止超长回答
选择合适模型不是所有场景都需要最贵的模型50-90%

缓存示例

importhashlibclassResponseCache:def__init__(self,ttl_seconds=3600):self.cache={}self.ttl=ttl_secondsdefget_cache_key(self,model,messages):"""相同的输入生成相同的key"""content=f"{model}:{str(messages)}"returnhashlib.md5(content.encode()).hexdigest()defget(self,model,messages):key=self.get_cache_key(model,messages)ifkeyinself.cache:entry=self.cache[key]iftime.time()-entry["time"]<self.ttl:returnentry["response"]# 命中缓存,省TokenreturnNonedefset(self,model,messages,response):key=self.get_cache_key(model,messages)self.cache[key]={"response":response,"time":time.time()}

完整监控架构

AI应用(打点) │ ├── Prometheus指标(Token/延迟/成本/错误率) │ ↓ │ Prometheus Server │ ↓ │ Grafana(面板展示) │ ↓ │ AlertManager(告警通知) │ ├── 调用链日志(每轮详情) │ ↓ │ ELK / Loki(存储查询) │ ↓ │ Kibana / Grafana(搜索回溯) │ └── 成本报表 ↓ 定时任务(每日/每周汇总) ↓ 发送到钉钉/邮件

面试怎么说

如果被问"AI服务怎么做监控":

"AI服务跟普通微服务最大的区别是每次请求成本不固定,所以监控要重点关注Token消耗和成本。

我的监控体系分五个维度:

  • Token消耗:按模型、功能、团队打标签,能做成本归因
  • 延迟:分首Token延迟(TTFT)和总延迟,用户体验主要看TTFT
  • 成本:每日预算管控,达到80%告警,达到100%限流
  • 调用链:Agent的每轮LLM调用和工具调用都记录,出问题能回溯
  • 异常检测:单次Token暴涨、用户刷量、死循环都有告警规则

技术栈用Prometheus打点 + Grafana面板 + AlertManager告警,调用链用ELK或Loki。

还有一些省钱手段:大小模型路由(简单问题用小模型)、响应缓存、Prompt精简。我们落地后Token成本降了约40%。"


延伸思考

问题答案
自部署vLLM也需要监控Token吗需要。虽然不按Token付费,但Token数影响延迟和吞吐,是容量规划的依据
怎么估算一次请求的成本输入Token × 输入单价 + 输出Token × 输出单价。大部分API返回usage字段
监控数据存多久明细日志保留7-30天,聚合指标保留3-6个月做趋势分析
小公司需要做这么完整吗不用。先做Token总量+日成本+TTFT这三个最核心的,其他慢慢补
OpenTelemetry支持AI监控吗社区在推LLM Observability标准,LangSmith和LangFuse是专门做AI调用链的工具

小结

本篇核心收获:

  1. AI服务监控核心差异:每次请求成本不固定,Token=钱
  2. 五大监控维度:Token消耗、延迟(TTFT+总延迟)、成本归因、调用链、异常检测
  3. TTFT比总延迟更重要:用户体验看首字输出速度
  4. 成本归因必须做:按团队/功能打标签,知道钱花在哪了
  5. 异常检测防止烧钱:Token暴涨、死循环、刷量都要有告警
  6. 省钱手段:大小模型路由+缓存+Prompt精简+限流

下一篇预告

AI全栈知识16:AI应用架构设计 - 从单体到平台

下一篇进入架构设计:

  • OneAPI网关层设计
  • 应用层(RAG/Agent)的分层
  • 模型层(vLLM)的部署策略
  • 从单应用到AI平台的演进路径

参考链接

  • Prometheus Client Python
  • OpenTelemetry LLM Observability
  • LangFuse(AI调用链追踪)
  • LangSmith(LangChain官方追踪)
  • vLLM Metrics文档
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 11:18:14

技术驱动下的零边际成本趋势:AI、自动化与能源如何重塑未来经济

这次我们来看一个关于技术发展趋势的讨论话题&#xff1a;“未来一切或将免费”。这个观点由埃隆马斯克提出&#xff0c;并非一个具体的开源项目或软件工具&#xff0c;但它触及了人工智能、自动化、能源等前沿技术发展的核心逻辑。对于开发者、创业者和技术爱好者而言&#xf…

作者头像 李华
网站建设 2026/8/22 11:16:25

数学建模实战:基于GAM与ACE指数分析全球变暖对飓风活动的影响

1. 项目背景与核心问题拆解2017年第六届数学建模国际赛&#xff08;小美赛&#xff09;的A题&#xff0c;将我们带入了一个极具现实意义和挑战性的科学前沿领域&#xff1a;飓风与全球变暖的关系。这道题之所以经典&#xff0c;不仅因为它结合了气象学、统计学和数学建模&#…

作者头像 李华
网站建设 2026/8/22 11:16:00

HoRain云--Sklearn 数据预处理

数据预处理是机器学习项目中的一个关键步骤&#xff0c;它直接影响模型的训练效果和最终性能。 在进行机器学习建模时&#xff0c;数据预处理是至关重要的一步&#xff0c;它帮助我们清洗和转换原始数据&#xff0c;以便为机器学习模型提供最佳的输入。 数据预处理涉及多个步…

作者头像 李华
网站建设 2026/8/22 11:15:16

HoRain云--DeeSeek Harness 防御性编程:结果报告、清理与凭据

这一篇讲五个最重要的防御性编程模式&#xff1a;结果报告、dispose 停稳、凭据擦除、链接删除、回调隔离。一句话&#xff1a;这些模式防止「一个简单的边界情况把整个 Agent 搞挂」。先看对照图下面的图把坏示例与好示例并排对比&#xff0c;每条都来自真实的缺陷类别。官方把…

作者头像 李华
网站建设 2026/8/22 11:14:04

Path of Building 上手五步:把流放之路的配装从猜变成算

Path of Building 上手五步&#xff1a;把流放之路的配装从猜变成算 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding 配一个新角色的时候&#xff0c;你大概率卡在这种时刻…

作者头像 李华