· 1 分钟阅读

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:

  1. Planner 先生成排查计划。
  2. Executor 按计划一步一步调用工具。
  3. 每一步把证据写入状态。
  4. 最后 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 才更像一个工程项目,而不是简单聊天页面。