资讯动态

AI 服务质量定义:SLO 要把推理延迟、可用率和准确率都算进去|TaoToken 统一 Key 通道下的落地拆解

发布时间:2026/10/18 8:02:50 来源:尧图企业网站定制
1. 为什么 99.9% 可用率救不了你的 AI 服务很多团队第一次给大模型推理服务定 SLO都是照搬 Web 服务那套HTTP 2xx 比例 ≥ 99.9%P99 延迟 ≤ 2s然后接个 Prometheus 告警就完事。上线第一周大盘全绿第二周用户开始投诉回答驴唇不对马嘴你打开监控一看——可用率 99.95%延迟 P99 1.8s一切正常。问题出在哪出在 AI 推理服务的成功和 Web 服务的成功根本不是一回事。一个请求返回 200 OKbody 里是一段语法通顺但事实错误的回答从 HTTP 状态码看它是成功的从用户角度看它是失败的。如果你的 SLO 只盯状态码这类失败在你的监控体系里是完全隐形的。我见过一个客服问答场景HTTP 层可用率 99.97%但抽样人工评估发现 12% 的回答存在事实性错误——这 12% 的用户流失大盘上一个数字都没动。所以 AI 服务质量定义必须是三维的推理延迟用户等多久、可用率服务能不能稳定返回、准确率回答对不对。这三个维度里任何一个塌了用户感知到的服务质量就是塌的。SLO 的意义不是让大盘好看而是让服务质量这件事从口号变成可采集、可告警、可复盘的工程指标。这篇文章面向的是正在给推理服务做可观测性建设的工程师或者被模型上线后质量怎么量化卡住的团队。我会把三维 SLO 拆成可落地的指标定义、可复制的采集配置、可执行的压测与故障注入验证步骤并且用 TaoToken 统一 Key 通道作为接入层示例——因为多模型、多 Key 的场景下SLO 采集点放在统一网关层比散落在各业务代码里靠谱得多。先明确一个边界SLO 是内部目标不是对外合同。SLA 没达到要赔钱SLO 没达到说明你需要改进。把准确率的 SLO 写成对外承诺是给自己挖坑因为准确率本身就是一个需要持续校准的近似值。这个区别后面会展开。2. TaoToken 统一 Key 通道把 SLO 采集点收敛到一层2.1 为什么 SLO 采集要放在统一通道三维 SLO 落地最大的工程障碍不是指标定义是采集点分散。如果你的业务代码里直接调各家模型 SDK延迟埋点、成功率统计、准确率回传要写三遍模型换一个版本埋点逻辑就得跟着改。更麻烦的是多租户场景付费用户和免费用户走不同 Key你想按租户维度看 SLO得在每个调用点打标签。TaoToken 在这里的角色是统一 Key/API 通道所有模型调用走同一个 Base URL用同一套 Key 管理模型 ID 作为参数传入。对 SLO 建设的价值在于——你可以在这一层统一做请求日志、延迟打点、状态归类业务代码只需要关心调哪个模型、传什么参数不用关心埋点。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点统一是 https://taotoken.net/api 这个地址不加 UTM 参数直接用于配置。模型对话调试可以在 https://taotoken.net/api-keys 之外的对话入口先验证但生产接入建议直接看文档https://taotoken.net/doc 。2.2 三件套Base URL Key Model ID不管你用 OpenAI 兼容 SDK、Cline、还是 Claude Code接入都是三件套。以 OpenAI Python SDK 为例from openai import OpenAI client OpenAI( base_urlhttps://taotoken.net/api, api_keysk-你的TaoTokenKey, # 在 console 的 API Keys 页面生成 ) resp client.chat.completions.create( modelclaude-sonnet-4-5, # Model ID 按文档里的可用列表填 messages[{role: user, content: 用一句话解释 SLO 和 SLA 的区别}], streamTrue, )这里三个参数缺一不可base_url指向统一通道api_key是你在 console 生成的 Keymodel是具体模型 ID。SLO 采集就挂在这个 client 外面包一层——记录发起时间、首 Token 时间、结束时间、HTTP 状态、以及业务侧的成功判定。2.3 在通道层做三维打点我建议在业务代码和 SDK 之间加一个薄封装把三维事件一次性记录import time, json, logging def call_with_slo(client, model, messages, tenant_id, streamTrue): t0 time.time() ttft None status ok try: resp client.chat.completions.create( modelmodel, messagesmessages, streamstream ) chunks [] for chunk in resp: if ttft is None: ttft time.time() - t0 # 首 Token 时间 if chunk.choices and chunk.choices[0].delta.content: chunks.append(chunk.choices[0].delta.content) e2e time.time() - t0 answer .join(chunks) # 业务侧准确率判定这里用规则/评估模型示例用长度兜底 accuracy_ok len(answer.strip()) 0 logging.info(json.dumps({ tenant: tenant_id, model: model, ttft_ms: round(ttft * 1000, 1) if ttft else None, e2e_ms: round(e2e * 1000, 1), http_ok: True, accuracy_ok: accuracy_ok, })) return answer except Exception as e: logging.error(json.dumps({ tenant: tenant_id, model: model, http_ok: False, error: str(e)[:200], })) raise这段代码的关键点ttft单独记录因为流式场景下用户感知的是第一句话出现前的等待P99 端到端延迟达标不代表 TTFT 达标accuracy_ok是业务侧判定可以接自动评估也可以先用规则兜底tenant标签让后续能按租户维度聚合 SLO。3. 可复制的三维 SLO 配置指标、告警、燃尽率3.1 指标定义与目标值先把三维 SLO 的指标和目标值定下来。下面这张表可以直接抄进你的 SLO 文档维度指标目标窗口说明延迟P99 端到端延迟≤ 5s30 天滚动达标率 ≥ 99%延迟P95 TTFT≤ 500ms30 天滚动流式场景单独设可用率HTTP 2xx 率≥ 99.9%30 天滚动传统口径可用率推理成功率≥ 99.5%30 天滚动排除 200 但推理失败准确率自动评估通过率≥ 基线 95%30 天滑动均值需人工校准准确率用户点赞率≥ 90%30 天滚动有反馈入口才可用注意推理成功率和HTTP 2xx 率是两个指标。前者要排除返回 200 但内容为空、被安全策略拦截、JSON 解析失败这些情况。实现方式是在封装层做业务判定判定失败时打http_okTrue, inference_okFalse。3.2 Prometheus 告警规则配置把上面的指标暴露成 Prometheus 格式后告警规则可以这样写。假设你的指标名是ai_slo_events_total带dimension、indicator、resultgood/bad标签groups: - name: ai-slo-burn-rate rules: # 延迟维度P99 达标率低于 99% - alert: AISLO_Latency_BurnRateHigh expr: | ( sum(rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e,resultbad}[1h])) / sum(rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e}[1h])) ) 0.01 for: 10m labels: severity: P1 dimension: latency annotations: summary: 延迟 SLO 燃尽率过高 description: 过去 1 小时 P99 延迟达标率 {{ $value | humanizePercentage }}低于目标 99% # 可用率维度推理成功率低于 99.5% - alert: AISLO_Availability_BurnRateHigh expr: | ( sum(rate(ai_slo_events_total{dimensionavailability,indicatorinference_success,resultbad}[1h])) / sum(rate(ai_slo_events_total{dimensionavailability,indicatorinference_success}[1h])) ) 0.005 for: 5m labels: severity: P1 dimension: availability annotations: summary: 可用率 SLO 燃尽率过高 # 准确率维度自动评估通过率低于基线 95% - alert: AISLO_Accuracy_BurnRateHigh expr: | ( sum(rate(ai_slo_events_total{dimensionaccuracy,indicatorauto_eval,resultbad}[6h])) / sum(rate(ai_slo_events_total{dimensionaccuracy,indicatorauto_eval}[6h])) ) 0.05 for: 30m labels: severity: P2 dimension: accuracy annotations: summary: 准确率 SLO 偏离基线准确率告警的窗口要拉长6h且for时间要长30m因为准确率本身波动大短窗口容易误报。延迟和可用率可以敏感一些。3.3 燃尽率计算与 Grafana 面板燃尽率Burn Rate是 Google SRE 的核心概念燃尽率 (目标 - 当前达标率) / 错误预算其中错误预算 1 - 目标。燃尽率 1 表示正在以超过预算的速度消耗错误配额燃尽率 14.4 表示一天烧掉一个月的 2% 预算该触发 P1。在 Grafana 里可以用一个变量面板展示三维燃尽率# 延迟维度燃尽率 ( 0.99 - ( sum(rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e,resultgood}[30d])) / sum(rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e}[30d])) ) ) / (1 - 0.99)三个维度各放一个 Stat 面板阈值设 1黄和 14.4红。这样一眼就能看出哪个维度在烧预算。3.4 多租户分组如果你的服务有付费/免费分层SLO 要按租户聚合。在打点时就带上tenant标签PromQL 里用by (tenant)分组sum by (tenant) ( rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e,resultgood}[1h]) ) / sum by (tenant) ( rate(ai_slo_events_total{dimensionlatency,indicatorp99_e2e}[1h]) )付费用户的延迟目标可以设得更严比如 P99 ≤ 3s免费用户放宽到 8s。SLO 不是全局一个数是按租户分层的。4. 验证请求与成功结果压测 故障注入4.1 用脚本压测验证延迟 SLO配置写完不代表 SLO 达标得压。写一个并发压测脚本模拟真实流量分布import asyncio, time, statistics from openai import AsyncOpenAI client AsyncOpenAI( base_urlhttps://taotoken.net/api, api_keysk-你的TaoTokenKey, ) async def one_request(i): t0 time.time() ttft None try: stream await client.chat.completions.create( modelclaude-sonnet-4-5, messages[{role: user, content: f第 {i} 个压测请求请简短回答}], streamTrue, ) async for chunk in stream: if ttft is None: ttft time.time() - t0 return {ttft: ttft, e2e: time.time() - t0, ok: True} except Exception as e: return {ttft: None, e2e: time.time() - t0, ok: False, err: str(e)[:100]} async def main(): results await asyncio.gather(*[one_request(i) for i in range(200)]) ok [r for r in results if r[ok]] ttfts sorted(r[ttft] for r in ok if r[ttft]) e2es sorted(r[e2e] for r in ok) print(f成功率: {len(ok)}/{len(results)} {len(ok)/len(results):.2%}) print(fP95 TTFT: {ttfts[int(len(ttfts)*0.95)]*1000:.0f}ms) print(fP99 E2E: {e2es[int(len(e2es)*0.99)]*1000:.0f}ms) asyncio.run(main())跑完看三个数成功率是否 ≥ 99.5%P95 TTFT 是否 ≤ 500msP99 E2E 是否 ≤ 5s。任何一个不达标说明你的 SLO 目标定得太乐观或者通道层有瓶颈。4.2 故障注入验证可用率 SLO可用率 SLO 的验证靠故障注入。故意制造几类故障看告警是否按预期触发第一类把api_key改错模拟 401。预期http_okFalse可用率告警在 5 分钟内触发。第二类把model改成不存在的 ID模拟 404/400。预期推理成功率下降但 HTTP 层可能返回 4xx要确认你的打点把这类归到inference_okFalse。第三类在封装层注入随机延迟time.sleep(random.uniform(0, 8))模拟后端慢。预期延迟燃尽率上升P99 告警触发。第四类注入随机空响应模拟200 但内容为空。预期准确率维度下降但可用率维度不受影响——这验证了三维是独立的。4.3 成功结果长什么样一次完整的验证跑下来你应该看到压测脚本输出的成功率 ≥ 99.5%P95 TTFT 在 300–500ms 区间P99 E2E 在 3–5s 区间故障注入时对应维度的告警在预期时间内触发Grafana 三维燃尽率面板在正常流量下都 1注入故障后对应维度跳到 1。如果这些都符合你的三维 SLO 就是可验证的工程指标不是口号。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth5.1 401 Unauthorized最常见的报错。原因通常是 Key 没传对、Key 过期、或者 Base URL 写错导致请求打到了别的服务。排查顺序先确认base_url是https://taotoken.net/api注意结尾没有多余斜杠再确认api_key是从 console 的 API Keys 页面复制的完整字符串最后确认这个 Key 没有在别处被删除。如果用的是环境变量打印一下os.environ.get(OPENAI_API_KEY)[:8]看前几位对不对。5.2 local proxy failed / connection refused这个报错通常出现在你本地配了代理但代理没起来或者 SDK 读到了系统代理环境变量。排查检查HTTP_PROXY、HTTPS_PROXY、ALL_PROXY这几个环境变量如果指向一个没运行的本地端口清掉它们。在 Python 里可以显式传http_client绕过系统代理。注意这里说的是清理无效的本地代理配置不是让你去搭什么通道。5.3 reading choices / NoneType object is not subscriptable这个报错说明你拿到的响应里choices是空的或 None。常见原因流式请求里某个 chunk 的choices为空正常跳过即可或者非流式请求返回了错误结构。修复方式是在解析时加判空if chunk.choices and chunk.choices[0].delta.content: chunks.append(chunk.choices[0].delta.content)如果你在非流式场景遇到这个先打印完整resp看结构多半是模型 ID 不对导致返回了错误体。5.4 OAuth / Claude Code 接入报错用 Claude Code 接入时如果报 OAuth 相关错误通常是因为配置里混用了官方登录态和 API Key 模式。Claude Code 走 API Key 模式时需要设置三个环境变量export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的TaoTokenKey export ANTHROPIC_MODELclaude-sonnet-4-5三件套齐了再启动。如果之前登录过官方账号先清掉~/.claude下的凭据缓存避免 OAuth 态和 Key 态冲突。Cline 的 MCP 配置同理在 settings 里填 Base URL、Key、Model ID 三项不要只填 Key。5.5 准确率 SLO 的好天气偏误这不是报错但是最常见的 SLO 陷阱流量平稳时准确率 SLO 总是绿的一到大促或模型升级就崩。建议在 SLO 报告旁边附上混沌实验期间的三维达标率。平静期的 99% 不如压力下的 95% 有说服力。6. 把 SLO 变成可复盘的工程指标三维 SLO 落地到最后拼的不是指标定义多漂亮是复盘时能不能拿出数据。我建议每周做一次 SLO 复盘看三件事哪个维度的燃尽率最高、哪个租户的 SLO 最差、哪次告警是误报。误报要调阈值真报要追根因。准确率维度的校准别偷懒。自动评估分Rouge-L、模型评估只是近似值每月随机抽 200 条做人工标注算一下自动评估和人工评判的偏差用这个偏差修正你的 SLO 基线。不做校准的准确率 SLO三个月后就会变成一个没人信的装饰数字。如果你还没开始搭这套体系建议从延迟和可用率两个维度先跑起来采集点放在 TaoToken 统一通道这一层业务代码零侵入。等这两个维度稳定了再上准确率。接入文档在 https://taotoken.net/doc API Key 在 https://taotoken.net/api-keys 生成模型对话调试入口可以先用 https://taotoken.net/api 配合 SDK 直接跑通。长期做编码 Agent 和多模型调度的团队可以看 Coding Plan 的通道方案把 SLO 采集和 Key 管理一起收敛。基础设施不需要漂亮话。它需要的是当你看着监控大盘时每一个绿色的指标背后都有一个经得起推敲的定义。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑