Spring AI 场景下的 RAG 与运维 Agent 设计复盘
这篇结合自动化运维 Agent 项目,记录我对 RAG、ReAct、Plan-Execute、上下文记忆和流式输出的理解。
做自动化运维 Agent 这个项目时,我一开始想得比较简单:用户把告警信息发给系统,大模型分析一下,然后给出排查建议。后来发现,如果只是这样,其实很像一个“会聊天的搜索框”,离真正有用的运维辅助系统还有距离。
运维场景的难点在于,信息来源很多,而且大部分信息都不在模型参数里。比如服务依赖关系、历史故障、内部 SOP、最近发布、日志、指标、链路追踪,这些都需要系统自己去查。模型的作用更像是“调度和总结”,而不是凭空知道答案。
所以这个项目里,我把核心能力分成几块:RAG 知识库、工具调用、多轮对话、ReAct 快速问答、Plan-Execute 系统排障,以及 SSE 流式输出。
为什么不能只靠大模型回答
通用大模型知道很多技术概念,但不知道我们自己的系统。比如它可以解释 Kafka rebalance,也可以讲 Redis 缓存击穿,但它不知道“订单服务上周五那次超时是因为哪个 SQL 没加索引”。
如果用户问:
order-service 今天 18:00 开始超时率上升,可能是什么原因?
模型如果不查日志和指标,只能给一些通用建议,比如“检查数据库、检查网络、检查下游依赖”。这些建议不是错,但不够有用。
所以 Agent 必须能查真实信息:
- 查知识库:有没有类似历史故障。
- 查日志:有没有错误堆栈。
- 查指标:CPU、内存、连接池、接口耗时有没有变化。
- 查发布:最近是否上线过新版本。
- 查链路:是否某个下游接口变慢。
这也是我理解的运维 Agent 和普通聊天机器人的区别。
RAG 在这里负责补内部知识
RAG 主要解决“模型不知道内部知识”的问题。比如历史故障复盘、排障手册、服务说明文档,都可以进入知识库。
我觉得运维知识库不能只按固定长度切块,因为故障文档一般有完整结构:
故障现象
影响范围
排查过程
根因
解决方案
预防措施
如果切块把根因和解决方案拆开,模型拿到的上下文就会断。比较好的做法是尽量按标题和语义切分,并给 chunk 加上服务名、文档类型、时间、权限等元数据。
检索结果最好也不要直接塞给模型,而是带上来源。这样最终回答时可以写:
参考了《order-service 连接池耗尽故障复盘》中的排查记录。
这会比模型直接给建议可信很多。
ReAct 适合短问题
ReAct 的模式是模型一边思考一边调用工具。它适合处理比较短的问题,比如:
- “帮我查一下订单服务最近 10 分钟 ERROR 日志。”
- “这个错误码在知识库里有没有记录?”
- “根据这段日志解释一下可能原因。”
这类任务链路不长,模型调用一两个工具就能回答。用 ReAct 会比较灵活,用户追问时也自然。
但 ReAct 不太适合复杂排障。因为模型可能一直在循环里查来查去,也可能漏掉关键步骤。
Plan-Execute 适合系统排障
如果是 P1 告警,我更倾向于 Plan-Execute:
- Planner 先生成排查计划。
- Executor 按计划一步一步调用工具。
- 每一步把证据写入状态。
- 最后 Reporter 生成报告。
比如告警是“接口超时率升高”,计划可能是:
1. 查询最近 10 分钟错误日志。
2. 查询接口 P95/P99 延迟。
3. 查询数据库连接池指标。
4. 查询最近 30 分钟发布记录。
5. 检索历史故障知识库。
6. 汇总可能根因。
这个流程比让模型自由发挥更稳。每一步查了什么、结果是什么,都能记录下来。以后排查 Agent 自己的问题也方便。
上下文记忆不能无限堆
多轮对话必须有记忆,不然用户追问“那刚才那个服务呢?”模型会不知道“那个服务”是谁。
但记忆不能无限堆。历史消息太多会占 token,也会把无关信息带进来。我觉得可以把记忆分成两类:
- 短期记忆:最近几轮对话。
- 任务状态:当前告警、已查工具、关键证据、未完成步骤。
短期记忆可以用 Spring AI 的 Chat Memory 思路管理,任务状态则更适合放在自己的工作流 State 里。
比如当前状态里保存:
{
"service": "order-service",
"alert": "timeout rate increased",
"checkedTools": ["logs", "metrics"],
"keyEvidence": ["HikariPool exhausted"],
"nextStep": "query_recent_deployments"
}
这样模型不用从长聊天记录里重新猜上下文。
SSE 流式输出改善体验
运维场景里等待很难受。如果用户提交一个告警,系统半天没反应,即使后端还在查,也会让人觉得卡住了。
所以我会用 SSE 做流式输出。不是说模型一定要马上给最终答案,而是先告诉用户:
已收到告警,正在查询错误日志...
日志查询完成,发现数据库连接池耗尽相关错误...
正在查询最近发布记录...
这种过程反馈会让用户知道系统在做事,也方便人工提前判断方向。
还没完全解决的问题
如果真实上线,我觉得还有几个难点:
- 工具调用失败时怎么自动降级。
- 多个工具结果互相矛盾时怎么处理。
- RAG 检索不到内容时怎么避免模型硬编。
- 高风险操作怎么做人类确认。
- 如何评估 Agent 生成报告的质量。
这些问题不是写一个 Demo 就能解决的,但在项目复盘里可以讲清楚自己的设计思路。
小结
Spring AI 可以让 Java 后端比较自然地接入大模型、RAG、记忆和工具调用。但运维 Agent 的重点不只是“接入模型”,而是让模型能基于真实系统信息行动。
我现在更愿意把它理解成一个后端系统:RAG 提供知识,工具提供实时数据,Plan-Execute 控制流程,记忆保存上下文,SSE 改善体验,权限和人工确认控制风险。这样设计出来的 Agent 才更像一个工程项目,而不是简单聊天页面。