本周工作概览

这周我把PromQL查询工具从伪代码变成了可运行的实现,同时搭建了知识库检索的基础设施,并且成功跑通了第一个简单的故障分析流程——当收到“CPU使用率过高”告警时,Agent能够自动调用工具查询指标数据,结合知识库给出初步判断。

具体工作内容

PromQL查询工具的实现与调试

这周花了整整两天把PrometheusClient彻底实现。之前只是定义了接口签名,现在需要处理真实的数据连接和异常场景。我写了一个查询引擎,支持四种常用的查询模式:即时向量查询(查当前值)、范围向量查询(查一段时间变化)、标量查询和区间查询。最麻烦的是处理Prometheus返回的数据格式,它的结果可能是vector、matrix、scalar或者string,每种结构的解析方式都不一样。我写了一个统一的数据提取函数,把各种格式都转成带时间戳的数值列表,方便后续计算最大值、最小值、平均值和变化率。

测试过程中发现一个问题:当查询的时间范围跨度很大(比如过去7天)且步长很小(比如15秒)时,返回的数据点可能几千个,传给大模型会直接撑爆上下文。解决方案是在工具内部做自动降采样,当数据点超过200个时,先聚合为分钟级平均值再返回。同时返回数据的统计摘要(最大值出现时间、平均值、波动幅度)而不是原始序列,这样既保留了关键信息又控制住了token消耗。

另外一个实用功能是异常检测辅助计算。我在工具里内置了几个常用指标的计算公式,比如某个指标在过去一小时内的波动系数、是否存在突增突降、当前值偏离历史基线的程度。这些计算的结果会以文本形式附加在查询结果后面,让Agent不需要自己算就能感知异常严重程度。

知识库检索模块的搭建

知识库这部分用了Qdrant作为向量数据库(轻量级且Docker一键启动),Embedding模型选了text2vec-large-chinese,因为我们的故障案例和Runbook大多是中文写的。周三我整理了六个典型故障场景的文档:CPU飙升排查指南、内存泄漏定位方法、磁盘写满处理流程、数据库连接池耗尽、接口超时分析、服务假死诊断。每个文档都按照“故障现象—可能原因—排查步骤—常用命令—参考案例”的结构编写,然后切片成512个字符左右的段落存入向量库。

检索接口封装成一个工具函数,输入是告警描述和时间范围内的关键指标变化(比如“CPU从20%突然涨到95%,持续10分钟”),输出是向量库中语义最相似的三个故障文档片段。为了让检索更精准,我用了混合检索策略:先用向量相似度召回十个候选,再用BM25关键词匹配重新排序取前三。测试时输入“CPU负载很高”,能准确召回CPU飙升排查指南,相关性还不错。

Agent工具调用框架的选型落地

纠结了几天后决定不完全依赖LangChain的AgentExecutor,而是自己写一个轻量级的循环。原因有两个:一是LangChain的中间步骤日志太冗长,不方便前端展示“Agent正在做什么”;二是它对工具调用失败的重试机制不太符合我们的需求(我们希望失败后Agent能换个思路而不是反复试同一个工具)。我自己实现了一个简单的ReAct循环:输入告警信息后,Agent输出思考内容(当前知道什么、还缺什么信息),然后决定调用哪个工具以及传入什么参数,工具执行结果返回后继续下一轮思考,直到Agent认为可以给出结论。

这个循环的核心是提示词设计。我写了详细的系统提示,告诉Agent它有哪些工具可用(目前有查询PromQL指标、检索知识库、查询服务状态三个工具)、每个工具什么时候该用、以及思考的格式要求。为了让输出能被程序解析,要求Agent每次输出必须包含Thought(想法)和Action(动作)两个字段,Action里写明工具名称和参数JSON。刚开始测试时模型经常忘记格式,后来在提示词里加了几个例子(few-shot)之后稳定了很多。

第一个分析流程的打通

周五是个小里程碑。我手动模拟了一条告警:服务A的CPU使用率在过去15分钟内从25%上升到98%。告警进入Agent后,Agent的第一步思考是“需要确认CPU的具体变化趋势和当前值”,于是调用了PromQL查询工具,参数是指标名node_cpu_usage、时间范围过去30分钟、输出格式摘要。工具返回了“CPU在14:23分从30%开始快速上升,14:30达到95%,之后维持在90%以上波动”。

Agent的第二步思考是“CPU突增通常与进程行为变化或请求量突增有关,需要查知识库了解常见原因”,于是调用了知识库检索,输入是“CPU突然飙升排查方法”。检索返回了两个相关文档片段,提到可以先看哪个进程占用CPU高,检查是否有定时任务集中执行,以及是否被攻击或爬虫。

Agent的第三步思考是“根据已有信息,结论还不够充分,缺少进程级别的数据”,但当前版本还没有接入进程监控,所以Agent在最终输出中给出了一个带局限性的结论:可能是某类计算密集型任务或异常流量导致,建议优先检查服务日志中是否有大量请求涌入,同时登录机器执行top命令确认具体进程。

虽然这个分析还不够深,但至少验证了整个链路——告警输入、Agent自主决策调用哪些工具、工具返回结果、Agent给出合理化建议——是通的。前端同学也在同一天完成了分析过程展示页面的初版,能看到Agent的每一步思考内容和工具调用记录。

本周遇到的问题与解决

最大的坑是PromQL查询的时间戳单位问题。Prometheus内部使用毫秒时间戳,但我传入的Python datetime转成浮点秒后少了三位小数,导致查询永远返回空数据。排查了两个小时才发现,最后统一用int(dt.timestamp() * 1000)解决。第二个问题是知识库检索时切片粒度过细,512字符切出来的片段经常把一个完整的排查步骤切两半,导致检索回来的信息不完整。改成按段落分割、每段最多800字符、允许重叠100字符后改善了很多。

更多推荐