ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于OpenTelemetry与原始提示词构建GenAI应用可观测性实践

基于OpenTelemetry与原始提示词构建GenAI应用可观测性实践 这类工具最值得先看的不是功能列表而是能不能在普通环境里稳定跑起来以及它到底解决了监控里的哪个具体痛点。从标题来看这是一个结合了 OpenTelemetryOtel追踪、原始提示词raw prompts来为生成式 AIGenAI应用生成有界Bounded指标的工具。它瞄准的不是简单的“能跑通”而是如何从海量的、非结构化的 AI 调用中提取出可量化、可告警、能反映业务健康度的核心指标。对于正在或计划在生产环境部署 GenAI 应用比如大模型对话、文生图、代码生成的团队来说最大的挑战往往不是模型本身而是“看不见”。一次调用慢是模型问题还是网络问题提示词改了几个字为什么成本飙升了五倍用户抱怨回答质量下降到底有多少比例的请求真的变差了传统的应用监控如请求延迟、错误率在这里完全不够用你需要能穿透“黑盒”把提示词、模型响应、token 消耗、成本这些维度关联起来看。这个项目我们姑且称它为otel-genai-metrics的思路很直接利用已经广泛采用的 OpenTelemetry 来收集追踪数据然后通过解析原始的提示词和响应自动生成一系列有业务意义的指标。它的价值在于把监控的粒度从“一次 HTTP 调用”细化到了“一次 AI 对话的内部构成”并且试图为“效果”这种主观感受找到可测量的代理指标。我建议先从最小样例开始理解它的数据流和指标定义再考虑是否要集成到你的 CI/CD 或告警流水线里。下面按实际落地顺序拆一遍。1. 先理解“有界指标”和“原始提示词”到底监控什么很多人一看到“GenAI metrics”会想到吞吐量、延迟但这只是基础。这个工具关注的是更深层的、与提示词工程和模型行为直接相关的指标。所谓“有界”Bounded我理解是指标有明确的、合理的上下界或判断标准不是无限增长的计数器而是能直接反映“好”或“坏”的状态。1.1 核心监控维度成本、质量与稳定性根据 OpenTelemetry 在可观测性领域的常见实践和 GenAI 的特点这类工具通常会从以下几个维度生成指标成本与效率类genai.token.usage每次调用消耗的 Prompt Tokens 和 Completion Tokens。这是计算费用的直接依据。genai.cost.estimated根据 token 使用量和模型单价估算的单次调用成本。genai.request.duration从发送提示词到收到完整响应的总耗时。genai.time_to_first_token从请求发出到收到第一个 token 的时间反映模型“思考”速度。质量与效果类这是难点和重点genai.response.length响应内容的长度字符数或 token 数。异常短或异常长的响应可能意味着模型截断或“胡言乱语”。genai.prompt.length提示词的长度。过长的提示词可能影响性能且增加成本。基于原始提示词的衍生指标这是标题中raw prompts的关键。例如可以检查响应是否包含特定关键词如“抱歉我无法回答”、是否以 JSON 格式返回、是否遵循了指令。这需要工具能解析提示词中的指令。毒性/安全性评分通过简单的规则或轻量级模型对响应内容进行安全扫描标记潜在风险。稳定性与错误类genai.request.error模型 API 调用失败如网络错误、鉴权失败、模型过载。genai.rate_limit触发速率限制的次数。genai.content.filter被模型自身安全过滤器拦截的请求数。1.2 为什么必须关联“原始提示词”如果不看提示词很多指标没有意义。比如response.length很低可能是因为模型生成了简洁的答案也可能是因为你的提示词是“只回答是或否”。只有把响应和触发它的提示词关联起来你才能判断这次高成本是因为提示词本身写了上千字的上下文吗这次响应质量差是因为提示词语义模糊还是模型本身的问题某个用户或某个功能模块的提示词模式是否存在优化空间以降低成本因此这个工具的核心能力之一是从 Otel 的 Span 属性或事件中提取出本次调用的完整提示词和响应文本并以此为基础进行计算。2. 环境准备与数据采集打通 Otel 链路工具本身可能是一个 Collector 的处理器Processor、一个导出器Exporter或者一个独立的后处理服务。无论形态如何前提是你的 GenAI 应用已经接入了 OpenTelemetry。2.1 基础 Otel 集成假设你的应用是一个 Python 服务使用 OpenAI SDK。你需要先集成 Otelpip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation openai在你的应用初始化代码中设置 Otel SDK 和导出器例如导出到控制台或 Jaegerfrom opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.instrumentation.openai import OpenAIInstrumentor # 设置全局 TracerProvider trace.set_tracer_provider(TracerProvider()) tracer_provider trace.get_tracer_provider() # 添加一个简单的控制台导出器生产环境请用 OTLP 导出到 Collector span_processor BatchSpanProcessor(ConsoleSpanExporter()) tracer_provider.add_span_processor(span_processor) # 自动注入 OpenAI 调用的追踪 OpenAIInstrumentor().instrument()这样每次调用openai.ChatCompletion.create都会自动创建一个 Span并包含一些基础属性如openai.request.model、openai.response.id等。2.2 关键一步将提示词和响应记录为 Span 属性或事件默认的 Instrumentation 可能不会记录完整的提示词和响应因为可能很大。为了生成有意义的指标你必须手动将messages提示词和response.choices[0].message.content响应添加到 Span 中。from opentelemetry import trace tracer trace.get_tracer(__name__) def chat_with_gpt(messages): with tracer.start_as_current_span(openai_chat_completion) as span: # 1. 将原始提示词记录为 Span 属性注意可能很长需考虑采样或截断 # 生产环境中可以考虑只记录提示词的哈希或关键特征或采用采样策略。 span.set_attribute(genai.prompt.messages, str(messages)) span.set_attribute(genai.prompt.length, sum(len(m[content]) for m in messages if m.get(content))) try: response openai.ChatCompletion.create( modelgpt-3.5-turbo, messagesmessages, temperature0.7, ) content response.choices[0].message.content # 2. 将原始响应记录为 Span 属性 span.set_attribute(genai.response.content, content) span.set_attribute(genai.response.length, len(content)) span.set_attribute(genai.usage.prompt_tokens, response.usage.prompt_tokens) span.set_attribute(genai.usage.completion_tokens, response.usage.completion_tokens) span.set_attribute(genai.usage.total_tokens, response.usage.total_tokens) # 3. 你也可以记录自定义事件 span.add_event(genai.completion.received, attributes{model: response.model}) return content except Exception as e: # 4. 记录错误状态 span.set_status(trace.Status(trace.StatusCode.ERROR, str(e))) span.record_exception(e) raise现在你的 Otel 追踪数据里就包含了生成指标所需的“原材料”。3. 部署与配置指标生成器假设otel-genai-metrics是一个 Otel Collector 的配置组件。你的数据流会是这样应用 - OTel SDK - OTel Collector (otel-genai-metrics处理器) - 指标后端 (Prometheus) 追踪后端 (Jaeger/Tempo)。3.1 配置 Collector你需要编写一个otel-collector-config.yaml文件。关键是在processors部分使用这个工具这里以概念性配置示例receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: # 假设这个工具作为一个名为 genai-metrics 的处理器 genai-metrics: # 配置指标提取规则 metrics: - name: genai.cost.estimated type: gauge description: Estimated cost per request in USD # 从 span 属性中提取 token 数乘以模型单价需配置 value_src: attributes[genai.usage.total_tokens] unit: USD # 假设配置了 gpt-3.5-turbo 的单价示例值 model_pricing: gpt-3.5-turbo: 0.000002 # 每 token 价格 - name: genai.response.toxicity.score type: gauge description: Toxicity score of the response (0-1) # 这可能调用一个内置的轻量级文本分类模型对 attributes[genai.response.content] 进行分析 value_src: analyze_toxicity(attributes[genai.response.content]) unit: 1 # 指定从哪些 Span 中提取通过属性过滤例如所有包含 genai.prompt.messages 的 Span span_filter: include: match_type: strict attributes: - key: genai.prompt.messages batch: # 批处理处理器通常放在最后 exporters: prometheus: endpoint: 0.0.0.0:8889 namespace: genai jaeger: endpoint: jaeger:14250 tls: insecure: true service: pipelines: traces: receivers: [otlp] processors: [genai-metrics, batch] # 在批处理前运行我们的指标提取器 exporters: [jaeger] metrics: receivers: [otlp] processors: [batch] exporters: [prometheus]注意以上配置是概念性的实际工具的配置语法需要查阅其文档。核心思想是在processors中这个工具会消费 Span 数据根据规则生成新的指标数据这些新指标会进入metricspipeline 被导出到 Prometheus。3.2 运行与验证启动 Collector./otelcol-contrib --configotel-collector-config.yaml触发你的 GenAI 应用发起几次对话请求。检查指标访问http://localhost:8889/metrics你应该能看到类似genai_cost_estimated、genai_response_length这样的自定义指标。在 Grafana 中可视化将 Prometheus 作为数据源添加到 Grafana然后创建仪表盘。可以创建以下面板成本面板sum(rate(genai_cost_estimated[5m]))显示近5分钟每秒的成本估算。响应质量面板avg(genai_response_toxicity_score)显示平均毒性分数histogram_quantile(0.95, rate(genai_response_length_bucket[5m]))显示响应长度的95分位数。Token 使用面板rate(genai_usage_prompt_tokens_total[5m])和rate(genai_usage_completion_tokens_total[5m])对比提示和补全的 token 消耗速率。4. 定义有效的指标与告警规则工具能生成指标但哪些指标值得关注阈值怎么设这需要结合业务。4.1 从“可观测”到“可行动”的指标不要盲目监控所有东西。优先关注能直接驱动决策的指标指标名称类型计算方式示例告警阈值建议行动genai_cost_per_requestGaugeattributes[“genai.usage.total_tokens”] * model_price单次请求 $0.01检查是否提示词过长或模型选错genai_prompt_lengthHistogramattributes[“genai.prompt.length”]p95 4000字符优化提示词考虑是否需拆分或总结上下文genai_response_contains_rejectionCounter响应内容匹配“抱歉”、“无法回答”等关键词比率该Counter/总请求 10%审查提示词是否触发模型安全策略或需调整指令genai_time_to_first_tokenHistogramSpan 事件时间差p99 10s检查模型区域、网络或模型负载genai_request_error_ratioRatiostatus_codeERROR的Span数 / 总Span数 1%检查API密钥、配额、网络稳定性4.2 在 Prometheus 中配置告警根据上表在 Prometheus 的alert.rules.yml中配置groups: - name: genai_alerts rules: - alert: HighGenAICostPerRequest expr: genai_cost_per_request 0.01 for: 5m labels: severity: warning annotations: summary: 单次GenAI请求成本过高 (实例 {{ $labels.instance }}) description: 请求 {{ $labels.trace_id }} 估算成本为 {{ $value }} 美元请检查提示词长度和模型选择。 - alert: HighGenAIRejectionRate expr: rate(genai_response_contains_rejection_total[10m]) / rate(genai_requests_total[10m]) 0.1 for: 5m labels: severity: warning annotations: summary: GenAI请求拒绝率过高 description: 过去10分钟内超过10%的请求被模型拒绝。请审查提示词内容。5. 生产环境考量与避坑指南把这样一个系统跑起来只是第一步要让它稳定可靠地服务于生产还需要考虑以下几个现实问题。5.1 数据体积与采样策略完整的提示词和响应内容可能非常大尤其是长上下文对话。全量记录所有 Span 的原始文本会对传输、存储和处理造成巨大压力。对策关键属性采样只在特定情况下记录完整内容。例如仅当请求耗时超过阈值、或消耗 Token 数异常、或响应中包含错误关键词时才将genai.response.content作为属性记录。摘要记录不记录全文而是记录哈希值、长度、关键特征如是否包含JSON、情绪倾向分数。otel-genai-metrics工具本身可能就提供这种特征提取功能。在 Collector 层过滤配置span_filter只处理你关心的服务或特定属性的 Span。5.2 指标基数爆炸如果你把每个不同的提示词都作为一个独立的标签如prompt_hash会导致指标基数急剧膨胀拖垮 Prometheus。对策对标签进行聚合不要使用高基数的原始值作为指标标签。例如用提示词的长度区间prompt_length_range”1k”, “1k-4k”, “4k”代替具体的长度值。使用模型、接口路径、用户类型等低基数维度作为主要标签。利用直方图Histogram和摘要Summary对于响应时间、长度、成本等连续值使用这些类型它们能自动进行分桶聚合避免为每个值创建单独的时间序列。5.3 敏感信息与合规性提示词和响应中可能包含用户个人信息PII、商业机密等敏感数据。将这些数据明文发送到可观测性后端存在风险。对策客户端脱敏在应用层OTel SDK添加处理器在将敏感数据设置为 Span 属性前进行脱敏或替换如用“ ”替换所有邮箱地址。Collector 端处理如果工具支持配置规则在计算指标后丢弃原始文本属性只保留数值结果。加密与访问控制确保可观测性后端如 Tempo, Jaeger的存储和访问是加密且受严格权限控制的。5.4 工具集成与维护成本引入一个新的处理器意味着多一个维护点。你需要关注版本兼容性otel-genai-metrics与你的 Otel Collector 版本是否兼容。配置复杂度指标提取规则会随着业务变化而调整这部分配置的管理如是否纳入 GitOps需要规划。性能影响在 Collector 中运行复杂的文本分析如毒性检测会增加处理延迟和资源消耗。对于高流量场景可能需要评估性能或考虑抽样分析。6. 替代方案与扩展思路如果这个工具还不成熟或者你的场景特殊可以考虑以下替代或补充方案6.1 应用层直接上报指标最直接的方式是在你的业务代码中在调用 AI 模型后直接使用 Prometheus 客户端库上报自定义指标。from prometheus_client import Counter, Histogram, Gauge GENAI_COST Gauge(genai_cost_estimated_usd, Estimated cost per request) GENAI_PROMPT_LEN Histogram(genai_prompt_length_chars, Length of prompts, buckets[100, 500, 1000, 2000, 5000]) GENAI_REJECTION Counter(genai_response_rejection_total, Count of rejected responses) # 在调用后 GENAI_COST.set(estimated_cost) GENAI_PROMPT_LEN.observe(len(prompt)) if 抱歉 in response: GENAI_REJECTION.inc()优点简单直接没有中间环节性能好。缺点监控逻辑与业务代码耦合无法利用已有的追踪数据进行关联分析。6.2 使用日志分析与 Metric 提取将包含提示词和响应的结构化日志JSON 格式发送到 Loki 或 Elasticsearch。然后使用 LogQL 或 Elasticsearch 的聚合功能在查询时生成临时指标或者使用像loki-metric-query这样的工具定期将日志聚合为指标写入 Prometheus。优点日志系统通常已经存在无需大幅改造。可以保留完整的原始数据供事后深度调查。缺点实时性较差计算聚合指标对日志后端有查询压力不适合做高频实时告警。6.3 扩展工具能力自定义分析脚本如果otel-genai-metrics支持插件或自定义函数你可以扩展它例如业务特定检查检查响应是否是一个有效的 SQL 语句对于 SQL 生成场景。代码质量评分对生成的代码进行简单的语法检查或风格评分。与基准答案对比在测试环境中将模型响应与标准答案进行相似度比较需预先准备测试集。这个方案真正落地时最该盯住的不是功能列表而是数据采集的完备性、指标定义的业务相关性以及整个管道在高压下的稳定性。我建议先在一个非关键服务上试点用真实的流量跑几天重点观察 Collector 的资源消耗、生成指标的正确性以及这些指标是否真的能帮你发现过去发现不了的问题。如果只是学习用默认配置跑通数据流就达到了目的如果要长期用于生产就必须把数据采样、标签管理、敏感信息处理和告警调优这些工程细节提前考虑清楚。
返回列表