当前位置: 首页 > article >正文

AI应用可观测性工程:像监控微服务一样监控你的LLM应用

LLM 应用进入生产后“为什么这次回答质量差”、哪次调用导致成本飙升这些问题如果没有完整的可观测性体系根本无法回答。本文构建 LLM 应用的完整监控体系。LLM 应用监控的独特挑战传统微服务监控关注的是响应时间、错误率、吞吐量。这些对 LLM 应用同样重要但 LLM 应用还有其特殊性非确定性输出同样的输入每次输出可能不同无法用传统方式对比正确性。Token 成本计量每次调用的成本与输入输出 Token 数直接相关需要细粒度追踪。长链路调用一个用户请求可能触发多次 LLM 调用RAG 查询 生成 验证需要追踪完整链路。输出质量评估不像 HTTP 200/500 那样黑白分明LLM 输出质量是连续变量需要专门的评估机制。## 核心监控指标体系### 性能指标pythonfrom prometheus_client import Histogram, Counter, Gauge, Summaryimport time# LLM 专用指标LLM_REQUEST_DURATION Histogram( llm_request_duration_seconds, Total duration of LLM requests, [model, operation], # 按模型和操作类型标注 buckets[0.5, 1.0, 2.5, 5.0, 10.0, 30.0, 60.0])LLM_TTFT Histogram( llm_ttft_seconds, Time to first token, [model], buckets[0.1, 0.25, 0.5, 1.0, 2.5, 5.0])LLM_TOKEN_USAGE Counter( llm_tokens_total, Total tokens consumed, [model, type] # type: input/output)LLM_COST_TOTAL Counter( llm_cost_usd_total, Total cost in USD, [model])LLM_QUALITY_SCORE Histogram( llm_quality_score, Quality score of LLM responses (0-1), [model, use_case], buckets[0.1, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 1.0])ERROR_COUNT Counter( llm_errors_total, Total number of LLM errors, [model, error_type])### 统一的可观测性装饰器pythonimport functoolsimport uuidfrom contextlib import asynccontextmanagerfrom typing import AsyncGeneratorclass LLMObservabilityMiddleware: def __init__(self, tracer, logger, metrics_client): self.tracer tracer self.logger logger self.metrics metrics_client def observe(self, model: str, operation: str, use_case: str default): 装饰器为 LLM 调用添加完整的可观测性 def decorator(func): functools.wraps(func) async def wrapper(*args, **kwargs): request_id str(uuid.uuid4()) start_time time.time() # 开始 Span with self.tracer.start_as_current_span( f{operation}, attributes{ llm.model: model, llm.operation: operation, llm.request_id: request_id, llm.use_case: use_case, } ) as span: try: result await func(*args, **kwargs) duration time.time() - start_time # 记录成功指标 LLM_REQUEST_DURATION.labels( modelmodel, operationoperation ).observe(duration) # 提取 Token 使用量如果有 if hasattr(result, usage): usage result.usage LLM_TOKEN_USAGE.labels( modelmodel, typeinput ).inc(usage.prompt_tokens) LLM_TOKEN_USAGE.labels( modelmodel, typeoutput ).inc(usage.completion_tokens) # 计算成本 cost self._calc_cost(model, usage) LLM_COST_TOTAL.labels(modelmodel).inc(cost) span.set_attribute(llm.input_tokens, usage.prompt_tokens) span.set_attribute(llm.output_tokens, usage.completion_tokens) span.set_attribute(llm.cost_usd, cost) self.logger.info( llm_request_success, request_idrequest_id, modelmodel, durationduration, operationoperation ) return result except Exception as e: ERROR_COUNT.labels( modelmodel, error_typetype(e).__name__ ).inc() span.record_exception(e) self.logger.error( llm_request_error, request_idrequest_id, errorstr(e), error_typetype(e).__name__ ) raise return wrapper return decorator def _calc_cost(self, model: str, usage) - float: 根据模型和Token数计算成本 PRICING { gpt-4o: {input: 0.005 / 1000, output: 0.015 / 1000}, gpt-4o-mini: {input: 0.00015 / 1000, output: 0.0006 / 1000}, claude-3-5-sonnet: {input: 0.003 / 1000, output: 0.015 / 1000}, } pricing PRICING.get(model, {input: 0, output: 0}) return (usage.prompt_tokens * pricing[input] usage.completion_tokens * pricing[output])# 使用示例middleware LLMObservabilityMiddleware(tracer, logger, metrics)middleware.observe(modelgpt-4o, operationchat_completion, use_casecustomer_service)async def chat_with_customer(messages: list): return await openai_client.chat.completions.create( modelgpt-4o, messagesmessages )## 分布式链路追踪对于复杂的 RAG 或 Multi-Agent 系统需要追踪完整的调用链pythonfrom opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter# 初始化 OpenTelemetryprovider TracerProvider()provider.add_span_processor( BatchSpanProcessor(OTLPSpanExporter(endpointhttp://jaeger:4317)))trace.set_tracer_provider(provider)tracer trace.get_tracer(llm-app)async def rag_pipeline_with_tracing(user_query: str, user_id: str): 完整的 RAG 管道带完整链路追踪 with tracer.start_as_current_span(rag_pipeline) as root_span: root_span.set_attribute(user.id, user_id) root_span.set_attribute(query.text, user_query[:200]) # 1. 检索阶段 with tracer.start_as_current_span(retrieval) as retrieval_span: docs await retrieve_documents(user_query) retrieval_span.set_attribute(retrieval.doc_count, len(docs)) retrieval_span.set_attribute(retrieval.top_score, docs[0].score if docs else 0) # 2. 重排序阶段 with tracer.start_as_current_span(reranking) as rerank_span: reranked_docs await rerank_documents(user_query, docs) rerank_span.set_attribute(reranking.kept_count, len(reranked_docs)) # 3. 生成阶段 with tracer.start_as_current_span(generation) as gen_span: response await generate_answer(user_query, reranked_docs) gen_span.set_attribute(generation.model, gpt-4o) gen_span.set_attribute(generation.output_tokens, response.usage.completion_tokens) return response## LLM Ops智能异常检测pythonimport numpy as npfrom collections import dequeclass LLMQualityMonitor: def __init__(self, window_size: int 100, alert_threshold: float 0.7): self.quality_window deque(maxlenwindow_size) self.alert_threshold alert_threshold self.baseline_quality None def record_quality_score(self, score: float, metadata: dict None): 记录单次质量评分 self.quality_window.append({ score: score, timestamp: time.time(), metadata: metadata or {} }) # 建立基线前100次 if len(self.quality_window) 100 and self.baseline_quality is None: scores [r[score] for r in list(self.quality_window)[:100]] self.baseline_quality np.mean(scores) # 检测质量下降 if self.baseline_quality and len(self.quality_window) 20: recent_scores [r[score] for r in list(self.quality_window)[-20:]] recent_avg np.mean(recent_scores) if recent_avg self.baseline_quality * self.alert_threshold: self._trigger_quality_alert( currentrecent_avg, baselineself.baseline_quality ) def _trigger_quality_alert(self, current: float, baseline: float): 触发质量告警 degradation_pct (1 - current / baseline) * 100 print(f⚠️ LLM质量告警相比基线下降 {degradation_pct:.1f}%) print(f 基线均值: {baseline:.3f}) print(f 当前均值: {current:.3f}) # 发送告警到监控系统 # alert_manager.send_alert(...)## 成本异常检测pythonclass CostAnomalyDetector: 检测异常的 LLM 调用成本 def __init__(self): self.hourly_costs {} self.daily_budget 100.0 # USD self.hourly_alert_threshold 10.0 # USD def record_cost(self, cost_usd: float, model: str, user_id: str): hour_key int(time.time() / 3600) if hour_key not in self.hourly_costs: self.hourly_costs[hour_key] {} user_key f{user_id}:{model} self.hourly_costs[hour_key][user_key] ( self.hourly_costs[hour_key].get(user_key, 0) cost_usd ) # 检查小时预算 total_hour_cost sum(self.hourly_costs[hour_key].values()) if total_hour_cost self.hourly_alert_threshold: print(f⚠️ 小时成本告警{total_hour_cost:.2f} USD) # 检测单个用户的异常高消耗 user_hour_cost self.hourly_costs[hour_key].get(user_key, 0) if user_hour_cost 5.0: # 单用户每小时超5美元 print(f⚠️ 用户异常消耗告警{user_id} 在过去1小时花费 {user_hour_cost:.2f} USD)## Grafana Dashboard 配置yaml# grafana-dashboard.yaml关键面板配置panels: - title: LLM请求延迟P50/P95/P99 type: graph targets: - expr: histogram_quantile(0.5, llm_request_duration_seconds_bucket) legend: P50 - expr: histogram_quantile(0.95, llm_request_duration_seconds_bucket) legend: P95 - expr: histogram_quantile(0.99, llm_request_duration_seconds_bucket) legend: P99 - title: Token消耗趋势 type: graph targets: - expr: rate(llm_tokens_total[5m]) * 300 legend: Token/5min - title: 每小时成本USD type: stat targets: - expr: increase(llm_cost_usd_total[1h]) - title: 输出质量评分分布 type: histogram targets: - expr: llm_quality_score_bucket - title: 错误率 type: graph targets: - expr: rate(llm_errors_total[5m]) legend: {{error_type}}## 告警规则yaml# alertmanager-rules.yamlgroups: - name: llm-application rules: - alert: LLMHighLatency expr: histogram_quantile(0.95, llm_request_duration_seconds_bucket) 10 for: 5m labels: severity: warning annotations: summary: LLM P95延迟超过10秒 description: 过去5分钟P95延迟为 {{ $value }}s - alert: LLMHighErrorRate expr: rate(llm_errors_total[5m]) / rate(llm_request_duration_seconds_count[5m]) 0.05 for: 2m labels: severity: critical annotations: summary: LLM错误率超过5% - alert: LLMCostBudgetAlert expr: increase(llm_cost_usd_total[1h]) 50 labels: severity: warning annotations: summary: 1小时LLM成本超过50美元## 生产监控体系总结完整的 LLM 可观测性体系包含四个层次指标层MetricsPrometheus Grafana监控性能、成本、错误率追踪层TracingOpenTelemetry Jaeger追踪复杂链路日志层Logging结构化日志记录每次请求的完整上下文质量层Quality自动化评估持续监控输出质量趋势 从零到完整体系推荐三个阶段1. 先建立成本监控防止意外费用2. 再接入性能追踪排查慢请求3. 最后建立质量评估持续改进输出可观测性投入是 LLM 应用成熟度的重要标志它让你从出了问题才知道变为问题发生时已知道。

相关文章:

AI应用可观测性工程:像监控微服务一样监控你的LLM应用

LLM 应用进入生产后,“为什么这次回答质量差?”、"哪次调用导致成本飙升?"这些问题如果没有完整的可观测性体系,根本无法回答。本文构建 LLM 应用的完整监控体系。LLM 应用监控的独特挑战传统微服务监控关注的是&#x…...

AI低代码产品,从“拖拽搭应用“到“对话即开发“,其中最关键的能力是什么?

作为一名在企业数字化一线摸爬滚打了10多年的项目负责人。这些年,我亲眼见证了低代码从小众工具变成企业标配的全过程。在2026年的当下,AI大模型现已全面融入低代码产品的底层,"对话生成应用"也已从概念名词变为了实际应用。但与此…...

主芯片LP3717BTT+LP3568C,5V3.1A过认证适配器⽅案(电路原理图)

LP3717BTT LP3568C 是一套 5V/3.1A(15.5W)隔离型反激电源方案,主打"过认证、高效率、低温度"。LP3717BTT 是原边 PWM 控制器,LP3568C 是次级同步整流芯片,两者配合实现高精度恒压输出,板端效率可…...

AI API 中转站完全指南:从 Claude、GPT 到“满血”“翻车”,一次搞懂整个 AI API 圈子

如果你刚开始接触 AI API,大概率会在各种开发者群、论坛或者教程里看到一堆让人摸不着头脑的词,比如“满血”“阉割”“翻车”“官转”“上车”“池子”“逆向”等等。很多新人第一次看这些内容的时候,基本都是每个字都认识,但连在…...

C 语言通讯录(终版)|新手踩坑全总结 + 最终可运行代码博客简介

系列回顾 本系列三篇完整闭环: 第一篇(基础版):从零实现增删查改 文件存储,踩遍新手所有坑(格式符乱码、文件闪退、输入死循环);第二篇(优化版)&#xff1…...

天勤策略钉钉告警:交易信号与异常通知怎么分流

前言 策略上云之后,我和同事最怕两件事:一是真出事了没人知道,二是没事也被钉钉刷屏刷到麻木。最早接推送时图省事,在 wait_update 里每次 last_price 变就发一条,一个活跃品种白天能几百条,两天之后群里全…...

LEFT JOIN 中 ON 与 WHERE 过滤的差异

在 MySQL 数据库开发中,LEFT JOIN(左外连接)是一个最常被误用的语法。许多开发者往往习惯性地将所有过滤条件一股脑地往 ON 后面塞,或者为了排版好看将条件全部扔到 WREHRE 里面。 这种模糊的逻辑在普通内连接(INNER J…...

宇树go2机械狗远程操控联网问题

用手机“Unitree Go”app的wifi模式,让狗和电脑连接同一个wifi,使其处于同一个局域网下。要求wifi名和密码无中文。然后在本地电脑powershell输入ipconfig查询本机局域网网段,确认机械狗同一网段 IP 地址。终端执行命令:ssh unitr…...

如何找到最适合你的私有化IM?

跳出公有云的舒适区,决心搭建私有化IM,并不是一件能一蹴而就的事。市面上打着私有化旗号的软件鱼龙混杂,有的安装环境要求极高,有的功能华而不实。如何在复杂的选型迷雾中,找到最适合组织基因的那一款?你可…...

一幅精细绝伦的[城市或地点]微缩模型

提示词: 一幅精细绝伦的[城市或地点]微缩模型,无缝搭建于质朴的木桌之上,仿佛整个场景都是实时手工制作而成。场景囊括了[城市或地点]最具标志性的地标、建筑、街道、交通、文化元素和氛围,周围环绕着密 地址:https://…...

淮南家长必看:淮南哪里学少儿编程靠谱?原来这样选才不踩坑。

说实话,很多淮南家长送孩子学编程,心里是没底的。因为编程不像钢琴、画画,能当场弹一首或画一张给你看。孩子到底学了啥、学得怎么样,家长往往两眼一抹黑。今天我不推荐任何一家机构,只跟你分享三个普通人一眼就能看懂…...

2026年最佳手机阅读器推荐:付费也值得的精品选择

在数字时代,阅读方式正在发生深刻变革。随着电子书、在线文章和多媒体内容的兴起,人们越来越倾向于通过智能手机进行阅读。然而,并非所有的阅读器都能提供优质的阅读体验。今天,我们将聚焦于一款即便付费也绝对物超所值的手机阅读…...

DDD 中的代码组织:按技术层分 vs 按领域模块分,哪种才是正解?

前言 在实践领域驱动设计(DDD)时,你可能见过两种截然不同的代码组织方式:一种是传统的按技术层划分文件夹,另一种是按业务模块划分文件夹。两种写法的人都声称自己在做 DDD,那到底哪种更合理?本…...

从CDP“3A”到千亿美元目标:联想集团的创新路径与AI原生转型

在全球产业链加速重构、人工智能技术范式快速迭代的背景下,中国企业的创新能力正成为各界关注的焦点。当被问及“哪些中国企业创新做得不错”时,有一家科技企业凭借其在绿色低碳、供应链协同以及混合式人工智能领域的系统性突破,给出了具有说…...

油雾净化设备哪家技术更专业

在机械加工、五金锻造、热处理等工业生产场景中,机床切削、乳化液喷淋、高温加工会持续产生大量工业油雾。悬浮在车间内的油雾不仅会腐蚀生产设备、污染生产环境,还会刺激人体呼吸道,危害操作人员身体健康,同时超标排放还会违反环…...

解密Palantir系列一:1. 决策的三元闭环

解密Palantir系列一:1. 决策的三元闭环 第一性问题企业真正缺的是更多数据,还是让数据变成正确行动的闭环?很多人第一次理解 Palantir,会把它归类成“大数据公司”“AI 公司”“可视化工具”或“咨询公司”。这些说法都只碰到了一…...

如何做好费用率数据分析?巧用费用率研判企业盈利现状

企业经营发展过程中,盈利水平高低直接决定长远发展实力,而费用率数据是看透企业真实盈利水平最直观、最核心的指标。很多经营者在日常管理中,往往只看重账面营收的增长,却忽略了费用率数据的深层分析与解读,最终出现营…...

(QBuffer配合 QDataStream)二进制序列化

QByteArray arr; QBuffer buf(&arr); buf.open(QIODevice::WriteOnly); QDataStream out(&buf); out << QString(“hello”) << 123; // 序列化 // 反序列化 buf.seek(0); QDataStream in(&buf); QString s; int n; in >> s >> n;...

VMware虚拟机安装及配置

密码 # 设置 root 用户密码 sudo passwd root修改国内镜像源 在 Ubuntu 24.04 之前&#xff0c;Ubuntu 的软件源配置文件路径为 /etc/apt/sources.list&#xff1b;从 Ubuntu 24.04 开始&#xff0c;Ubuntu 的软件源配置文件变更为 DEB822 格式&#xff0c;路径为 /etc/apt/so…...

专业做绝对值编码器的服务商

在工业自动化领域&#xff0c;绝对值编码器是不可或缺的关键组件。它能够直接输出轴或直线运动的“绝对位置”&#xff0c;断电后位置信息不会丢失&#xff0c;每次上电都能立刻知道当前的精确坐标&#xff0c;这使得其在各种精密应用中具有无可替代的优势。本文将通过具体数据…...

《从 0 实现 SGLang》第 1 篇 · LLM 推理引擎到底在做什么

千行代码&#xff0c;一步步搭出一个现代 LLM 推理引擎&#xff0c;吃透大模型推理的每一项关键技术。 本阶段目标 — 最简推理实现 用最朴素的方式把端到端推理跑通&#xff1a;先搭起整体框架&#xff0c;再逐个模块替换为完整实现。整个阶段共 5 篇短文&#xff1a; 序号…...

2026年必看:六款热门AI编程工具横评,Trae与Cursor怎么选

2026年必看&#xff1a;六款热门AI编程工具横评&#xff0c;Trae与Cursor怎么选AI编程工具正从辅助插件进化为全流程开发核心&#xff0c;2026年市场进入智能体协作新阶段。本文精选6款主流AI编程工具&#xff0c;从核心功能、协作模式、适配场景等维度深度解析&#xff0c;帮开…...

第一学期结果

关注 1.从安涛老师前三期视频中了解了方向2.从b站了解了555的内部结构3.仿真。4.低通滤波器的基本原理&#xff1a;一、核心定义只允许低频信号顺利通过&#xff0c;阻挡、衰减高频信号的电路。 你电路里作用&#xff1a;滤掉方波里的高频谐波&#xff0c;留下低频基波&#xf…...

2026.5.21【MIPI D-PHY】一、D-PHY 简介

一、简介 MIPI&#xff1a;全称移动行业处理器接口&#xff08;Mobile Industry Processor Interface&#xff09;。MIPI是由MIPI联盟发起的为移动应用处理器制定的开放标准。 MIPI可分为物理层和逻辑层两大部分。 MIPI按照物理层&#xff08;Physical Standard&#xff09;划分…...

由一次构建 OpenEuler 22.03 dnf源所了解到的

零、说在前面今天在安装 Milvus 的时候&#xff0c;因为部分插件下载过慢&#xff0c;需要重建国内 yum/dnf 源&#xff0c;按照常规的方式重建后报出了一些奇怪的报错。通过这些报错让我了解到了 OpenEuler 22.03 的不同版本在构建 yum/dnf 源的时候是存在区别的。因此将我的处…...

Delft3D建模、水动力模拟方法及地表水环境影响评价:岸线绘制与导入、非结构化计算网格生成、水下地形数据处理等前处理操作;水动力与污染物对流扩散模拟的参数设置、边界条件设定及模型率定验证

查看原文>>>https://mp.weixin.qq.com/s/_CiPDK_oXaAGxVfu2qk6ew 前言 本文以地表水数值模拟软件Delft3D 4.03.00操作为主要内容&#xff0c;强调地表水水动力建模、基础资料的获取、边界条件设定、模型率定和验证、数据分析和处理等关键环节。通过对案例模型的实操…...

Token聚合平台 vs 传统云 vs AI原生云,AI推理应用怎么选?

在大模型能力深度融入生产环境的当下&#xff0c;后端 AI 架构的选择往往决定了应用的生死。从早期的“调用一个接口”到如今复杂的智能体&#xff08;Agent&#xff09;工作流&#xff0c;开发团队在底座选型上面临着两条截然不同的演进路径&#xff1a;一条是追求便利与极致轻…...

windows VS2026 编译32位 onnxRuntime

打开命令行终端&#xff0c;执行以下命令克隆官方仓库并初始化子模块&#xff08;--recursive 参数非常重要&#xff0c;否则会因为缺少依赖导致编译失败&#xff09;&#xff1a;git clone --recursive https://github.com/microsoft/onnxruntime.git进入目录&#xff1a;cd o…...

影刀RPA 从0到1:自动化系统架构收敛与工程化演进总结

影刀RPA 从0到1&#xff1a;自动化系统架构收敛与工程化演进总结 作者&#xff1a;林焱 写到这里。 这个系列其实已经慢慢进入后半段了。 前面聊了很多内容。 包括&#xff1a; 浏览器池 节点集群 Redis 队列 调度系统 容灾恢复 日志监控 性能治理 很多人刚开始接…...

2026年想做美缝施工?专业靠谱的美缝施工究竟哪家好?

在装修领域&#xff0c;美缝施工虽看似是小工程&#xff0c;却对家居整体美观度和实用性影响重大。然而&#xff0c;美缝行业乱象丛生&#xff0c;让众多业主在选择美缝施工团队时犯了难。2026年若想做美缝施工&#xff0c;怎样才能选到专业靠谱的团队呢&#xff1f;下面为大家…...