AI 推理监控体系:大模型服务的 SLI/SLO 设计与异常检测
一、大模型服务的可观测性盲区:延迟正常不代表服务正常
传统微服务的监控以延迟和错误率为核心指标,但大模型服务引入了新的维度。一个推理请求可能返回 200 状态码、延迟在正常范围内,但生成的结果完全不可用——幻觉、截断、格式错误。这种"静默故障"在传统监控体系下完全不可见。
更隐蔽的问题是 Token 消耗的异常。某个 Prompt 模板的变更可能导致输出 Token 数翻倍,直接导致成本飙升,但延迟和错误率指标毫无变化。大模型服务的监控必须覆盖四个维度:可用性(请求是否成功)、延迟(响应是否及时)、质量(输出是否可用)、成本(Token 消耗是否合理)。
二、AI 推理监控的四层指标体系
大模型服务的监控指标分为四层,从基础设施到业务语义逐层递进。
flowchart TB
subgraph L1[第一层:基础设施指标]
A1[GPU 利用率]
A2[显存使用率]
A3[请求队列深度]
end
subgraph L2[第二层:服务可用性指标]
B1[请求成功率]
B2[P50/P95/P99 延迟]
B3[首 Token 延迟 TTFT]
end
subgraph L3[第三层:推理质量指标]
C1[输出截断率]
C2[格式合规率]
C3[拒绝回答率]
end
subgraph L4[第四层:成本效率指标]
D1[Token 消耗速率]
D2[每请求 Token 成本]
D3[缓存命中率]
end
L1 –> L2 –> L3 –> L4
style L1 fill:#e8eaf6
style L2 fill:#e0f2f1
style L3 fill:#fff3e0
style L4 fill:#fce4ec
首 Token 延迟(TTFT,Time To First Token)是大模型服务独有的关键指标。它衡量从请求发出到第一个 Token 返回的时间,直接影响用户感知的"响应速度"。TTFT 高但总延迟低,说明模型推理快但排队久;TTFT 低但总延迟高,说明流式输出慢。两者对应完全不同的优化方向。
三、生产级监控代码实现
3.1 推理指标采集器
@Service
public class InferenceMetricsCollector {
private final MeterRegistry registry;
private final Counter requestTotal;
private final Counter requestSuccess;
private final Counter requestFailed;
private final Timer inferenceLatency;
private final Timer ttftTimer;
private final DistributionSummary tokenOutput;
private final DistributionSummary tokenInput;
public InferenceMetricsCollector(MeterRegistry registry) {
this.registry = registry;
this.requestTotal = Counter.builder("llm.request.total")
.description("总请求数").register(registry);
this.requestSuccess = Counter.builder("llm.request.success")
.description("成功请求数").register(registry);
this.requestFailed = Counter.builder("llm.request.failed")
.tag("reason", "error").register(registry);
this.inferenceLatency = Timer.builder("llm.inference.latency")
.description("推理总延迟")
.publishPercentiles(0.5, 0.95, 0.99)
.register(registry);
this.ttftTimer = Timer.builder("llm.inference.ttft")
.description("首 Token 延迟")
.publishPercentiles(0.5, 0.95, 0.99)
.register(registry);
this.tokenOutput = DistributionSummary.builder("llm.token.output")
.description("输出 Token 数").register(registry);
this.tokenInput = DistributionSummary.builder("llm.token.input")
.description("输入 Token 数").register(registry);
}
/**
* 记录一次推理调用的完整指标
*/
public void recordInference(InferenceRecord record) {
requestTotal.increment();
if (record.isSuccess()) {
requestSuccess.increment();
} else {
requestFailed.increment();
}
// 记录延迟分布
inferenceLatency.record(record.getTotalLatency(),
TimeUnit.MILLISECONDS);
// 记录 TTFT
if (record.getTtftMs() > 0) {
ttftTimer.record(record.getTtftMs(), TimeUnit.MILLISECONDS);
}
// 记录 Token 消耗
tokenInput.record(record.getInputTokens());
tokenOutput.record(record.getOutputTokens());
// 按模型分标签记录成本
Counter.builder("llm.cost.total")
.tag("model", record.getModel())
.tag("tenant", record.getTenantId())
.register(registry)
.increment(calculateCost(record));
}
private double calculateCost(InferenceRecord record) {
// 根据模型和 Token 数计算成本(元)
double inputCostPer1k = ModelPricing.getInputCost(record.getModel());
double outputCostPer1k = ModelPricing.getOutputCost(record.getModel());
return (record.getInputTokens() * inputCostPer1k
+ record.getOutputTokens() * outputCostPer1k) / 1000;
}
}
3.2 输出质量检测器
@Service
public class OutputQualityDetector {
private final MeterRegistry registry;
/**
* 检测推理输出的质量问题
* 在流式响应完成后异步执行
*/
public QualityReport detect(String requestId, String model,
String prompt, String output) {
QualityReport report = new QualityReport(requestId, model);
// 1. 截断检测:输出是否被 max_tokens 截断
if (isTruncated(output)) {
report.addIssue(QualityIssue.OUTPUT_TRUNCATED);
Counter.builder("llm.quality.truncated")
.tag("model", model)
.register(registry).increment();
}
// 2. 格式合规检测:JSON 输出是否可解析
if (expectsJson(prompt) && !isValidJson(output)) {
report.addIssue(QualityIssue.FORMAT_INVALID);
Counter.builder("llm.quality.format_invalid")
.tag("model", model)
.register(registry).increment();
}
// 3. 拒绝回答检测:模型是否拒绝回答
if (isRefusal(output)) {
report.addIssue(QualityIssue.REFUSAL);
Counter.builder("llm.quality.refusal")
.tag("model", model)
.register(registry).increment();
}
// 4. 重复检测:输出是否存在大量重复内容
if (hasRepetition(output)) {
report.addIssue(QualityIssue.REPETITION);
Counter.builder("llm.quality.repetition")
.tag("model", model)
.register(registry).increment();
}
return report;
}
private boolean isTruncated(String output) {
// 截断特征:末尾不完整(未以句号、换行等结束)
if (output.length() < 10) return false;
char lastChar = output.charAt(output.length() – 1);
return lastChar != '。' && lastChar != '.' && lastChar != '\\n'
&& lastChar != '`' && lastChar != '"';
}
private boolean hasRepetition(String output) {
// 检测连续重复的句子或段落
String[] sentences = output.split("[。.!?!?]");
if (sentences.length < 3) return false;
int duplicateCount = 0;
Set<String> seen = new HashSet<>();
for (String sentence : sentences) {
String trimmed = sentence.trim();
if (trimmed.length() > 10 && !seen.add(trimmed)) {
duplicateCount++;
}
}
return duplicateCount > sentences.length * 0.2;
}
}
3.3 SLO 告警规则配置
# Prometheus 告警规则 – AI 推理服务
groups:
– name: llm_inference_slo
rules:
# SLO: 99% 的请求在 30 秒内完成
– alert: LLMInferenceLatencySLOViolation
expr: |
histogram_quantile(0.99,
rate(llm_inference_latency_seconds_bucket[5m])
) > 30
for: 5m
labels:
severity: warning
annotations:
summary: "推理 P99 延迟超过 SLO"
description: "模型 {{ $labels.model }} 的 P99 延迟为 {{ $value }}s"
# SLO: 首Token延迟 < 5s
– alert: LLMTTFTSLOViolation
expr: |
histogram_quantile(0.95,
rate(llm_inference_ttft_seconds_bucket[5m])
) > 5
for: 3m
labels:
severity: warning
# SLO: 输出截断率 < 5%
– alert: LLMTruncationRateHigh
expr: |
rate(llm_quality_truncated_total[10m])
/ rate(llm_request_total[10m]) > 0.05
for: 10m
labels:
severity: info
# 成本告警:每小时 Token 消耗超过预算
– alert: LLMCostBudgetExceeded
expr: |
increase(llm_cost_total[1h]) > 100
labels:
severity: critical
四、AI 监控体系的落地困境
质量检测的延迟代价:输出质量检测(格式校验、重复检测)需要完整响应后才能执行,无法在流式输出过程中实时判断。对于长文本生成,质量报告可能延迟数十秒。建议将质量检测设为异步任务,不阻塞响应返回,但需确保质量告警能及时触发。
Token 计量的精度差异:不同模型供应商的 Token 计数方式不同。OpenAI 使用 BPE 分词,国内模型可能使用不同的分词器。同一文本在不同模型下的 Token 数可能相差 20% 以上。跨模型的成本对比必须基于同一分词标准,否则结论不可靠。
SLO 目标设定的博弈:延迟 SLO 和成本 SLO 天然矛盾。降低延迟需要更多 GPU 并发,增加成本;控制成本需要限制并发,增加排队延迟。建议为不同业务场景设定差异化的 SLO——实时对话要求 TTFT < 2s,批量处理允许 TTFT < 30s。
幻觉检测的工程难题:输出质量检测中的"幻觉"是最难自动化的指标。当前可行的方案是:对关键业务场景(如医疗、法律),用第二个模型对输出进行事实性校验,但这会使推理成本翻倍。非关键场景建议依赖用户反馈(点赞/踩)作为幻觉信号。
五、总结
AI 推理监控的核心是将"请求成功"细化为"请求成功且输出可用且成本合理"。本文的四层指标体系为:基础设施(GPU/显存)→ 服务可用性(延迟/TTFT)→ 推理质量(截断/格式/幻觉)→ 成本效率(Token/费用)。SLO 建议设定三个核心目标:P99 延迟 < 30s、TTFT P95 < 5s、输出截断率 < 5%。落地时需重点关注 Token 计量的跨模型一致性,以及质量检测的异步化实现。
补充落地建议:围绕“AI 推理监控体系:大模型服务的 SLI/SLO 设计与异常检测”继续推进时,应把验证标准写成可执行清单,而不是停留在经验判断。性能类方案要给出基准数据,架构类方案要给出故障隔离方式,AI 类方案要给出输出质量和人工兜底策略。每一次迭代都应回答三个问题:收益是否可量化,失败是否可回滚,维护成本是否被团队接受。
如果短期资源有限,可以先保留最关键的观测指标,包括处理耗时、失败率、资源占用和人工介入次数。等这些指标稳定后,再扩展自动化能力。这样的节奏更慢,但风险更低,也更符合生产级技术文章强调的工程可验证性。

