大模型用于根因分析(RCA)时,一个常见误区是把效果不佳归因于“模型不会推理”。越来越多工程师提出了另一种判断:现代 LLM 已经具备分析故障因果链的基本能力,真正困难的是在调用模型之前,把指标、日志、调用链、部署事件和服务依赖整理成一份准确、紧凑、带时间关系的上下文。
Coroot 针对 11 个模型开展的实验,为这一判断提供了早期证据。它并不意味着 RCA 已经变成一个简单的提示词问题,而是提示团队重新分配工程投入:与其反复寻找“更聪明”的模型,不如先检查遥测关联管道是否向模型交付了足够可靠的事实。
模型看到的不是生产系统,而是一段输入
值班工程师分析事故时,通常会同时查看多类信息:
- 哪些服务在什么时间出现错误率或延迟突增;
- 异常请求经过了哪些上游和下游服务;
- 故障窗口内是否发生部署、配置修改或扩缩容;
- 日志中的异常是否与指标拐点处于同一时间段;
- 数据库、消息队列或第三方 API 是否出现资源饱和。
LLM 不会天然获得这些信息。若输入只有一句“支付接口变慢,请分析根因”,模型只能依赖通用经验补齐空白,最终给出数据库慢查询、网络抖动、线程池耗尽等看似合理却无法验证的猜测。
因此,RCA 上下文至少需要保留四种关系:
- 时间关系:异常开始、变更发生和恢复发生的时间顺序。
- 拓扑关系:服务之间真实的调用方向,而不是一份静态服务清单。
- 信号关系:指标峰值、日志错误和异常 trace 是否指向同一组件。
- 基线关系:当前值相对正常窗口究竟偏离了多少。
这也是“上下文工程”与简单拼接日志的区别。前者在构建可供推理的证据结构,后者只是在消耗 token。
遥测关联管道才是新的核心组件
一个面向 LLM 的 RCA 管道,可以拆成以下步骤:
Metrics / Logs / Traces / Deploy Events
|
v
时间归一化与实体解析
|
v
服务拓扑和请求链关联
|
v
异常检测、去重与证据排序
|
v
RCA Context Package
|
v
LLM
这里最容易出问题的通常不是最后一次模型调用,而是前面的数据处理:服务名在日志中写成 checkout,在指标标签中写成 checkout-api;部署事件使用本地时间,trace 使用 UTC;采样策略恰好丢掉了错误请求;一次连锁故障产生数千条重复异常,挤掉了真正关键的配置变更。
高质量上下文包不必包含全部遥测数据,但应该让每一项重要结论都能追溯到证据。一个实用的数据结构可以包含:
- 事故窗口与正常基线窗口;
- 服务依赖图及受影响路径;
- 按时间排序的关键事件;
- 每项异常的当前值、基线值和变化幅度;
- 代表性日志与 trace ID;
- 已知缺失数据和采样限制。
最后一项尤其重要。告诉模型“该服务没有 trace”与“trace 显示该服务正常”是完全不同的事实。
可以这样实践:生成一个最小 RCA 上下文包
下面是一个可直接运行的 Python 示例。它不依赖真实可观测性平台,而是演示如何把部署事件、指标异常和日志按时间整理成模型可消费的 Markdown。假设各数据源已经统一为 UTC,并且服务名称已经完成映射;接入生产环境时,需要把示例列表替换为 Prometheus、日志平台、追踪系统和部署系统的查询结果。
将代码保存为 build_rca_context.py,然后运行 python build_rca_context.py:
from datetime import datetime, timezone
INCIDENT = {
"start": "2025-03-08T10:00:00Z",
"end": "2025-03-08T10:20:00Z",
"symptom": "checkout API p95 latency exceeded 2 seconds",
}
EVENTS = [
{
"time": "2025-03-08T09:57:00Z",
"kind": "deployment",
"service": "pricing",
"detail": "version changed from 2.4.1 to 2.5.0",
},
{
"time": "2025-03-08T10:02:00Z",
"kind": "metric",
"service": "pricing",
"detail": "database pool wait p95 rose from 12 ms to 840 ms",
},
{
"time": "2025-03-08T10:03:00Z",
"kind": "trace",
"service": "checkout -> pricing",
"detail": "pricing span accounted for 91% of request latency; trace_id=abc123",
},
{
"time": "2025-03-08T10:04:00Z",
"kind": "log",
"service": "pricing",
"detail": "connection acquisition timeout, 137 occurrences in 5 minutes",
},
]
DEPENDENCIES = [
"web -> checkout",
"checkout -> pricing",
"pricing -> postgres",
]
LIMITATIONS = [
"Only 10% of successful requests are traced.",
"PostgreSQL statement-level telemetry is unavailable.",
]
def parse_time(value: str) -> datetime:
return datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(timezone.utc)
def build_context() -> str:
ordered = sorted(EVENTS, key=lambda event: parse_time(event["time"]))
lines = [
"# Incident context",
"",
f"- Window: {INCIDENT['start']} to {INCIDENT['end']}",
f"- User-visible symptom: {INCIDENT['symptom']}",
"",
"## Service dependencies",
*[f"- {item}" for item in DEPENDENCIES],
"",
"## Correlated timeline",
]
for event in ordered:
lines.append(
f"- {event['time']} | {event['kind']} | "
f"{event['service']} | {event['detail']}"
)
lines.extend(["", "## Data limitations"])
lines.extend(f"- {item}" for item in LIMITATIONS)
return "\n".join(lines)
if __name__ == "__main__":
print(build_context())
生成上下文后,可以把它与下面的提示词一起提交给所选模型:
你是一名生产事故分析工程师。仅根据提供的事故上下文完成分析。
请输出:
1. 最可能的根因,并引用对应的时间、服务和遥测证据;
2. 从根因到用户症状的因果链;
3. 两个仍然合理的替代解释;
4. 为确认或排除每个解释需要执行的查询;
5. 当前证据的缺口。
规则:
- 不要把时间相关性直接表述为因果关系。
- 没有证据时明确写“未知”。
- 将结论分为“已观察事实”“推断”和“待验证假设”。
这个例子刻意要求模型输出替代解释和验证查询。RCA 的目标不应只是生成一个听起来确定的答案,而是压缩调查范围,并给值班人员提供下一步可执行动作。
评估时别只看答案是否命中
Coroot 的多模型实验可以视为早期信号,但团队在自己的系统中仍需要建立评测集。生产故障类型、遥测完整度和服务拓扑差异很大,一个模型在公开或预设案例中表现良好,不代表它能处理本地环境中的命名混乱与数据缺失。
建议用历史事故复盘构造测试样本,并分别衡量:
- 根因候选是否覆盖复盘确认的原因;
- 引用的证据是否真实存在,时间是否一致;
- 模型有没有把相关性夸大为因果性;
- 缺少关键遥测时,是否明确表达不确定性;
- 建议的验证命令是否可执行、是否可能扩大事故;
- 更换模型后,结果改善来自推理能力还是上下文长度变化。
还应保留人工审批边界。模型可以建议回滚、重启或调整连接池,但不应仅凭概率性判断直接执行高风险操作。上下文中也可能包含密钥、用户数据和内部拓扑,进入外部模型前必须完成脱敏和访问控制。
采用前的工程检查表
把 LLM 接入 RCA 流程之前,可以检查以下问题:
- 所有遥测源是否使用统一时间和稳定的服务标识;
- 是否能将指标、日志和 trace 关联到同一事故窗口;
- 部署与配置变更是否进入时间线;
- 上下文是否包含正常基线,而不只是异常值;
- 是否标记采样率、数据缺口和查询失败;
- 模型输出能否回链到原始证据;
- 自动化动作是否设置权限、审批和回滚机制;
- 是否用历史事故持续回归测试上下文管道与模型。
AI 根因分析的竞争重点,可能不再只是模型排行榜上的推理分数。决定系统是否可信的,往往是模型调用之前那条不显眼的管道:它能否把分散的遥测转换成时间一致、拓扑清楚、证据可追溯的事故叙述。模型负责提出解释,而上下文工程决定这些解释有没有事实基础。