RAG初探:让 AIOps Agent 学会查询历史故障
2026/7/23 14:18:29 网站建设 项目流程

RAG,全称 Retrieval-Augmented Generation,检索增强生成。先查询最新的知识,如果有合适,就基于这些知识回答;如果没有,再用历史的知识回答

RAG 的思路是:用户提问的时候,先去知识库里捞几条相关文档,把这些文档和问题一起拼进 prompt,再让 LLM 基于这些"事实"来回答。相当于给LLM配置了一个内部资料包

先看代码结构
blog/code/
├── main.py # 主流程:分词检索 + prompt 拼装 + LLM 调用
└── knowledge_base.py # 知识库:存放运维文档
knowledge_base.py
这个文件很简单,就是一个 Python 列表,每个元素是一条运维文档,包含 title 和 content 两个字段:

docs = [
{
“title”: “Nginx 504 排查手册”,
“content”: “Nginx 504 通常表示网关等待上游服务响应超时,需要检查 upstream 服务耗时、业务服务日志、数据库慢查询和连接池。”
},
{
“title”: “订单服务历史故障”,
“content”: “订单服务曾经因为数据库连接池耗尽,导致 /api/orders 接口大量超时,最终在 Nginx 中表现为 504。”
},
# …
]
在真实生产里,这里可以换成从 Confluence、内部 Wiki、Elasticsearch 里拉取的文档,甚至是历史故障复盘记录。这个 Demo 用硬编码列表,是为了让整个流程零依赖、能直接跑。

main.py

_tokenize 函数负责把文本拆成 token:
def _tokenize(text: str):
text = text.lower()
tokens = re.findall(r"[a-z0-9]+“, text) # 英文/数字按词切分
chinese_parts = re.findall(r”[\u4e00-\u9fff]+", text)
for part in chinese_parts:
if len(part) == 1:
tokens.append(part)
else:
tokens.extend(part[i:i + 2] for i in range(len(part) - 1)) # 中文按 2 字片段切
return set(tokens)
retrieve 函数用关键词命中次数给文档打分,取 top_k,用集合求交集来算相关度,简单粗暴但在小型知识库里够用
def retrieve(query: str, top_k: int = 2):
query_tokens = _tokenize(query)
results = []
for doc in docs:
text = doc[“title”] + " " + doc[“content”]
doc_tokens = _tokenize(text)
score = len(query_tokens & doc_tokens) # 交集大小 = 相关度
if score > 0:
results.append({…})
results.sort(key=lambda x: x[“score”], reverse=True)
return results[:top_k]
整条 RAG 链路在 main 里串起来:

用户问题

retrieve() ← 关键词检索,拿 top_k 文档

build_prompt() ← 把文档 + 问题拼成 prompt

call_llm() ← 发给 LLM,拿回答

打印结果
以 “订单服务出现大量 504,应该怎么排查?” 为例跑一遍,控制台输出大致如下:

=== 检索到的文档 ===

  • Nginx 504 排查手册,score=4
  • 订单服务历史故障,score=3

=== 构造出来的 Prompt ===
你是一个 Kubernetes 运维分析 Agent。

文档标题:Nginx 504 排查手册
文档内容:Nginx 504 通常表示…

文档标题:订单服务历史故障
文档内容:订单服务曾经因为数据库连接池耗尽…

=== LLM 最终回答 ===
根据知识库,建议优先排查以下几点:

  1. 检查订单服务数据库连接池是否耗尽(历史上曾出现此问题)
  2. 查看 Nginx upstream 日志确认超时节点
  3. 确认 Pod 实例数和 CPU/内存状态

    LLM 的回答里会引用到"历史上连接池耗尽"这条,这就是 RAG 发挥作用的地方——纯靠通用知识是不会提这条的

如果匹配的文档有5000字,那全部都要塞给llm吗?
假设有 100 个故障案例文档,每个文档 5000 字,那就是50w字的,全部发给llm,不但提高了回答成本,回答速度也会大大降低,造成了大量浪费

如果内容太长,放进大模型上下文会浪费 token。并且里面主题太杂,内容检索可能不知道这篇文档到底主要讲什么

所以文档选取的时候,一般选取最相关的top5,并且文档需要拆分成更小的chunk,类似这种:

标题:订单服务大量 504

现象:

  • Nginx 出现大量 504
  • upstream_response_time 超过 60s
  • Pod CPU/内存正常
  • Redis、MySQL、Kafka 连接正常

排查过程:

  1. 查询 Nginx 日志,确认是 upstream timeout
  2. 查询业务日志,发现调用三方接口耗时异常
  3. 查询 Prometheus,Pod 资源无明显瓶颈
  4. 查询链路追踪,确认耗时集中在 external-api span

根因:
三方接口响应慢,导致业务线程阻塞,Nginx 等待超时。

处理:

  • 临时调大线程池
  • 降级三方接口
  • 增加超时控制
  • 增加熔断策略

关键词:
504, upstream timeout, external api, thread blocked, nginx
这已经是一个完整知识单元:现象 → 排查过程 → 根因 → 处理方案

chunk和文档有什么关系
简单来说,完整的文档就相当于一本书,一个chunk就是某页或者某一小节,查资料时只摘抄相关小节,而不是读完整本书,和 RAG 用 chunk 逻辑完全一致

chunk向量化
原始文档切割后的成为不同的chunk,通过embedding 模型转换成一段向量,而提出的问题也会被转换成一段向量,用户问题向量和所有 chunk 向量看哪个最相似,最终返回最相似的几个 chunk,提交给llm

例如:

chunk:订单服务大量 504,Pod 正常,Redis MySQL 正常,最终是三方接口慢导致线程阻塞,转换成向量:[0.012, -0.233, 0.891, 0.056, …]

用户问题:订单接口大量 504,但是 Pod 和数据库都正常,怎么排查?,也转换成向量:[ 0.021564, -0.156489, 0.089451, …]

然后向量库会比较两者的向量,看哪个最相似,返回相似的chunk,提交给llm

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询