ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Deepseek+Dify打造告警分析智能体:从告警风暴到自动SQL生成

2026/10/8 15:27:58 拓冰建站 浏览量
Deepseek+Dify打造告警分析智能体:从告警风暴到自动SQL生成 简介这是一份基于Deepseek与Dify构建告警分析智能体的技术方案文档适合对运维自动化感兴趣的IT从业者尤其推荐给具备一定编程基础、熟悉告警平台的监控运维人员目标是让大模型自动完成指定时间段内的告警总结、系统状态掌握与优化建议输出。文档以“大模型插件工作流”的AI Agent落地为主线完整覆盖Dify平台安装、模型供应商接入、时间/时间戳获取工作流与自然语言转SQL查询告警并统计的工作流搭建以及基于DeepSeek-R1配置Agent、提示词编排、结构化告警报告告警概览、关键发现、建议措施输出的完整环节同时针对大模型输入长度限制给出分批处理方案强调查询数据库时使用只读账号等安全注意点。资源为单份docx文档大小约816KB已有405人学习。读者可按文中方案快速落地告警自动总结与分析能力提高故障响应效率并将提示词与工作流迁移到自身告警平台降低运维AI Agent的落地试错成本。1. 告警分析智能体运维团队为什么值得把 Deepseek 接进 Dify凌晨两点被值班同事一个电话叫醒打开告警群一看几百条未读真正要处理的只有两条——剩下全是网络抖动、磁盘 IO 瞬时拉高、某个非核心服务重试成功的噪音。这种场景干过运维监控的人都不陌生告警风暴不是不够响是太响了响到人已经分不清轻重缓急。Deepseek 加 Dify 组合成一个告警分析智能体干的活就是把「告警源头到人眼」之间的那一段脏活自动化拉取告警、清洗去重、按时间线总结、生成 SQL 去查数据最后输出一段带证据链的分析结论。最适合的是 10 人以上运维团队、每天告警量在几百条以上、但又没预算养专职算法工程师的那批人。这套方案不需要你从零训练模型也不需要重写监控体系它只是在现有监控平台和值班人之间多了一层会读会写的中间层。看懂它能解决什么接下来每一步配置才有意义。2. 搭建基础链路本地部署 Deepseek 与 Dify 对接的完整过程2.1 Dify 社区版部署与模型 Provider 配置Dify 在这套架构里承担的是「工作流编排 Agent 框架」的角色Deepseek 是底层的推理引擎。先解释为什么选这两个组合而不是直接用脚本写死监控告警的分析逻辑每天都在变SQL 查询条件、总结口径、需要关注的指标用代码写规则要改一次发布一次而 Dify 工作流把节点可视化以后运维同事改节点参数就能调整整个分析流程。Deepseek 作为大模型底座负责的是那些规则引擎写不清楚的部分——告警间的相关性判断、用什么维度去归类噪音、自然语言到 SQL 的转换。部署 Dify 社区版用 Docker Compose 最省事。官方仓库拉下来以后docker compose up -d把整套服务起起来然后进后台的 Settings —— Model Provider 里添加 Deepseek。添加时注意要填的是 Deepseek 开放平台的 API key基础 URL 填https://api.deepseek.comModel 名称填deepseek-chat或deepseek-reasoner。两个模型的分工有讲究deepseek-chat响应快、成本低适合高频的告警总结和 SQL 生成deepseek-reasoner推理链条完整但慢适合每天几次的深度根因分析。日常告警分析场景默认用deepseek-chat先把活儿跑起来成本实测下来比通用商用模型低一个量级。# docker-compose 关键环境变量片段写入 .env 文件 # NGINX_PORT 决定 Dify 后台暴露端口默认是 80改成 8080 避免与已有 Web 服务冲突 NGINX_PORT8080 # 后续接入 Deepseek 时的模型配置项先在平台控制台拿到 key 再填 # DIFY_MODEL_PROVIDER_DEEPSEEK_API_KEYsk-xxxxx # DIFY_MODEL_PROVIDER_DEEPSEEK_MODELdeepseek-chat这段配置本身不复杂坑基本都在取值上。Dify 社区版版本迭代很快不同小版本对模型 Provider 的字段要求不完全一致填错了后台会直接报告 credentials validation 失败。遇到这种校验错误先别怀疑 key 有问题优先去看容器日志里 provider 认证请求是否真的发出去很多是网络代理挡了 HTTPS 请求。2.2 告警数据接入先定 JSON 结构再做工作流告警源是 Prometheus、Zabbix 还是自研监控平台不重要重要的是你喂给智能体的告警数据结构要统一。我做这套系统时定的最小告警 JSON 结构包含五个字段alert_name告警名称、severity级别、instance实例标识、message原始告警内容、timestamp发生时间。少了severity字段大模型在总结时没法区分优先级少了timestamp后面 SQL 生成环节就不知道要查哪个时间窗口的数据。Dify 工作流的开始节点会收到这个 JSON格式上是标准的 HTTP POST body。为了让工作流内部处理更方便用一个代码节点把数据做一次解析和规整——从原始 JSON 里提取数组按timestamp升序排列再把severity字段统一映射成数字级别。规则很简单P0 紧急对应 1P1 高对应 2P2 中对应 3P3 低对应 4其他未知级别归为 9。这一步是给大模型减少理解成本也是给后续 SQL 生成节点提供稳定入参。# 代码节点告警数据标准化 def main(alert_json: str) - dict: import json alerts json.loads(alert_json) # 只保留影响分析决策的字段message 截断到 200 字符防止上下文超长 normalized [] severity_map {P0: 1, P1: 2, P2: 3, P3: 4, 紧急: 1, 严重: 2, 警告: 3} for item in alerts: severity severity_map.get(str(item.get(severity)).upper(), 9) normalized.append({ alert_name: item.get(alert_name, )[:100], severity: severity, instance: item.get(instance, )[:100], message: item.get(message, )[:200], timestamp: item.get(timestamp, ) }) # 时间升序排列方便后续大模型按时间线组织语言 normalized.sort(keylambda x: x[timestamp]) return {alerts: normalized, alert_count: len(normalized)}severity映射为什么要单独处理而不是直接丢给大模型因为监控平台之间的级别叫法不一致Prometheus 用 critical/warningZabbix 用 disaster/high/average自研平台可能直接写汉字。统一成数字之后后续判断「今天是否有 P0 级告警」这种问题就不需要大模型做模糊匹配准确率更可控。2.3 Deepseek API 直连调通先验证模型再排工作流Dify 界面把流程搭好之前第一步永远是先用 Python 脚本把 Deepseek API 直连调通。因为如果模型 API 本身都有问题在 Dify 工作流里排查会多绕一层。我的习惯是准备一个最小验证脚本放在工作目录里之后每次改模型参数都先跑一遍它。curl https://api.deepseek.com/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-your-key-here \ -d { model: deepseek-chat, messages: [ {role: system, content: 你是一个运维告警分析助手只输出 JSON。}, {role: user, content: 请把这条告警按严重程度打分CPU usage 95% on host web-01} ], temperature: 0.1, max_tokens: 500 }这个请求发出去正常情况下会返回一段 JSON 格式的响应。temperature这里设 0.1是为了让告警分析这种需要稳定输出的场景尽量少产生随机发挥。如果返回里出现 401先检查 key 有没有配错出现 429说明账号并发配额不够后面工作流里十次告警同时进来会排队需要在 Dify 的节点前加一个限流控制。真正容易忽略的是响应结构。Deepseek 的 API 返回里choices[0].message.content才是模型回复内容但有些场景下模型会很听话地输出纯文本 JSON有些场景会在 JSON 前后加 json 代码块标记。Dify 的代码节点拿到这种带标记的字符串直接json.loads会报错所以解析时代码里要做一层清洗。这个细节非常影响落地的顺畅程度我在第一次接的时候就被这个看似不起眼的问题卡了半天。import re def parse_model_response(text: str) - dict: # 去掉大模型偶尔输出的 markdown 代码块标记 text text.strip() text re.sub(r^json\s*, , text) text re.sub(r\s*$, , text) return json.loads(text)工作流里每个调用大模型的节点后面都接一个代码节点做响应清洗这个动作要养成习惯否则后续只要模型输出格式一飘整个流程就断掉。Dify 的失败重试机制能处理网络超时但处理不了这种「请求成功但内容格式不合法」的情况。3. 工作流编排从原始告警到总结报告的节点设计3.1 告警分析工作流的整体链路与节点划分Dify 工作流的核心价值不是把几个节点串起来而是明确每个节点的职责边界、输入输出schema。这套告警分析智能体我拆成六个节点开始节点接收告警 JSON、代码节点数据标准化、知识检索节点关联历史相似告警、大模型节点 1生成告警总结、大模型节点 2生成 SQL 查询语句、结束节点返回分析报告 查询 SQL。开始节点负责接收外部请求通常来自一个钉钉/企微机器人转发过来的告警内容。知识检索节点很多人会忽略但它其实是减少大模型胡说八道的关键——把过去半年处理过的告警工单和处置记录作为知识库来源检索出与当前告警最相似的历史记录作为上下文喂给总结节点。大模型看到「这个告警上次的处理方法是什么」总结就不只是复述原文而是能给出策略建议。节点之间的数据传递要提前设计。我建议每个节点输出都统一成 JSON 对象避免出现纯文本裸传。大模型节点输出总结文字 关键字段代码节点做字段校验这样出了问题能快速定位是哪个节点返回异常。Dify 的调试面板支持单节点运行这是排查问题的主要手段——先点运行整个流程再逐个节点回看中间变量。3.2 告警总结 Prompt 的核心写法与参数控制告警总结这个大模型节点的 Prompt 设计直接决定输出质量。我踩过一轮坑之后总结出了结构化 Prompt 的写法交代角色、给定任务、说明输入、列出输出要求。角色你是有 10 年经验的 SRE 值班专家。 任务梳理当前告警列表找出最需要优先处理的问题输出值班交接摘要。 输入标准化后的告警 JSON 列表按时间升序。 输出要求 1. 用 3 到 5 句话概括当前告警态势 2. 列出 Top 3 高优先级告警说明影响实例与可能原因 3. 对每一条高优先级告警给出立即可执行的动作建议 4. 只输出 JSON格式为 {summary: ..., top_alerts: [{...}], actions: [...]}这里有一个特别关键的参数temperature必须调低到 0.1 到 0.2 之间。告警总结是事实性内容不需要创造性表达温度高了措辞会飘。max_tokens也不要设太高500 到 800 足够否则模型会啰嗦地展开许多无关内容推高 token 成本。知识检索节点的召回数量设置为 3 到 5 条即可。太少,模型找不到参考节奏太多无关信息混进来反而干扰判断。Dify 知识库里每一条历史记录建议单独切成一个文档文档命名用「告警名称 日期 处置结论」这样召回时标题本身就能提供一部分信息量。3.3 中间变量处理上下文超长与节点输出的取舍告警量大到一定规模上下文超长的问题就会冒出来。Dify 工作流里大模型节点的上下文长度是有限制的超过了就会出现「提示词被截断」或「模型开始胡说」的翻车现场。我遇到过一次 500 条告警同时涌入大模型节点直接报错原因是把全部告警原文都塞给了模型。解决方案是在代码节点里做两阶段处理。第一阶段如果告警数量大于 50先按 severity 级别过滤掉 P2 及以下级别的所有告警第二阶段对剩余告警做 message 字段摘要只保留「实例 指标 阈值」三要素其余自然语言部分直接丢弃。def compact_alerts(alerts: list, max_count: int 50) - list: # 只保留 P0 和 P1P2 及以下直接丢弃控制进入模型的告警总数 high_priority [a for a in alerts if a.get(severity) in (1, 2)] high_priority.sort(keylambda x: x[timestamp]) if len(high_priority) max_count: return high_priority # 超出上限时按严重级别二次压缩每条 message 只保留最后 80 字符 for item in high_priority: item[message] item[message][-80:] return high_priority[:max_count]告警太多的时候与其全量处理不如放弃完整性保准确性。宁可只分析头部几十条高优告警也不要把所有 P2 噪音带进模型上下文导致模型注意力被稀释。Dify 工作流里每个节点处理后的中间结果也可以在调试中看到确认压缩逻辑没把关键信息切掉再进入下一轮调研。4. SQL 生成核心让 Agent 替人写查询语句4.1 项目里SQL生成能力怎么落地标题里「SQL生成」不是指智能体能写会写任意 SQL而是让 Deepseek 在给定的数据库模式下根据告警分析需求自动生成查询语句。比如一个告警说 CPU 高智能体需要自动查询监控数据库里对应主机过去两小时的 CPU 指标时间序列验证告警是否持续是否与其他指标相关。要让 SQL 生成可用有两件的必需品一是建好的数据库表结构说明二是严格限定模型只能查询哪些表。Dify 工作流里用知识库保存表结构说明每个表格建一个文档写清楚表名、字段名、类型、含义、常用的 JOIN 关系。SQL 生成节点的 Prompt 必须明确列出允许访问的表。允许访问的表 - instance_metric实例指标表字段 instance_id, metric_name, value, ts - alert_records告警记录表字段 alert_id, host, alert_type, start_time, end_time, status - incident_log处置记录表字段 incident_id, host, description, action, created_at 禁止访问表user_info, billing_info, system_config。模型看到这份 schema 列表后被提示词限定「只能使用上述表不允许猜测不存在的字段名」生成的 SQL 可用性就大幅提升。如果不加限制大模型经常编造出根本不存在的字段比如alert_records.instance_id明明叫 host模型偏偏写SELECT * FROM alert_records WHERE instance_id...执行必然报错。4.2 SQL 生成与执行验证的工作流实现SQL 生成节点完成后不能直接把生成的 SQL 交给用户执行了事。实际上应该加入一个「执行验证」的代码节点把 SQL 在测试数据库上跑一遍把结果集返回给模型做一次自校验。这个闭环能挡住大约六成错误 SQL。# 执行节点先跑通再返回 import subprocess import os def execute_sql(sql: str) - dict: # 使用只读账号连接监控数据库避免智能体生成的 SQL 误操作写数据 conn_cmd [ psql, os.environ[MONITOR_DB_URL], -v, ON_ERROR_STOP1, -c, sql ] result subprocess.run(conn_cmd, capture_outputTrue, textTrue, timeout10) if result.returncode ! 0: # 失败返回错误信息给大模型节点让它重新生成 return {status: error, message: result.stderr} return {status: ok, output: result.stdout[:2000]}这个节点里有三个细节。第一数据库连接必须使用只读账号这是为了防止智能体生成DELETE之类危险语句第二timeout设 10 秒防止查询大表时挂死工作流第三返回结果截断到 2000 字符避免把全量查询结果灌进大模型上下文导致上下文超长问题再次出现。如果返回状态为 error就把错误信息回传给大模型节点加上「请根据错误信息修正你的 SQL字段名和表名必须在允许列表中」的修正指令重新生成一次。试过三轮修正后仍然报错就放弃自动执行直接把 SQL 原文输出给用户让值班人自己判断。这个「自愈 人工兜底」的机制比让工作流无限重试要稳妥得多。4.3 查询结果结构化的输出约束SQL 执行结果集是表格形式的直接丢进大模型让它总结太吃 token 且容易丢失关键信息。我在工作流里加一步代码节点把 psql 输出的文本结果转成紧凑结构只保留最近 20 个时间点的数据和指标名称。def translate_query_output(raw_output: str) - dict: lines [line.strip() for line in raw_output.splitlines() if line.strip()] # 常见 psql 输出尾部有 rows) 记录已查询 之类的统计行去掉 lines [line for line in lines if rows not in line and not line.startswith(---)] # 提取表头与数据行 if len(lines) 2: return {fields: [], rows: [], row_count: 0} fields [f.strip() for f in lines[0].split(|)] rows [] for line in lines[1:]: values [v.strip() for v in line.split(|)] rows.append(dict(zip(fields, values))) return {fields: fields, rows: rows[-20:], row_count: len(rows) - 1}这个结构能帮大模型快速判断「这个指标在过去 20 个采样点里是持续上升还是波动」从而得出「CPU 高不是瞬时尖峰而是持续饱和」这类结论。SQL 生成节点和结果解析节点配合好才是真正帮值班人省时间的完整链路。5. 避坑与排查Dify 与 Deepseek 集成中高频踩到的五个问题这套方案流程上并不长但实际落地时每一层都有各自的坑。按我自己的踩坑经验整理几条典型问题都是现象到原因的排查记录照着对照你的环境能省不少时间。5.1 现象Dify 后台添加 Deepseek 时报 credentials validation 错误原因Dify 的 provider 校验请求走的是容器内网络如果你的 Dify 部署在 Docker 里容器里访问外网需要经过宿主机的代理。很多公司内网环境强制走代理代理对 HTTPS 证书做了替换Dify 校验的时候证书链不完整就会报错。解决先看 dify-api 容器日志docker logs dify-api | grep -i deepseek如果日志里出现 SSL 相关关键词基本可以确定是证书问题给容器传入HTTP_PROXY/HTTPS_PROXY环境变量并将代理的 CA 证书挂载到容器内还不行就临时在docker-compose.yml里把 provider 校验用的域名加入 no_proxy绕过代理直连这个排查思路不仅适用 Dify所有自托管的开源系统对接外部模型 API 都差不多的流程。5.2 现象Dify 工作流提示上下文长度超限大模型节点报错原因告警列表没有做数量控制就全量丢给了模型。当告警数量超过几百条时光是提示词文本就撑爆了模型的上下文窗口Dify 会直接终止流程并返回错误。解决在代码节点里把告警数量限制在 50 条以内P2 及以下级别直接丢弃对每条告警的 message 字段先截断再做后续处理保实例保指标保数值其他描述性文字全部砍掉如果业务上必须要处理全量告警就改成循环批处理每 20 条一批喂给大模型完后把每批摘要再汇总一次这个优化同时也压低了 token 成本。5.3 现象大模型生成的 SQL 执行报错字段名不存在原因知识库里的表结构文档写得不够完整,或者模型习惯了别的数据库命名方式生成的 SQL 里的字段名和实际表结构对不上。这种问题在大模型身上非常常见尤其当表名字段名不是常规命名时。解决工作流里加 SQL 验证节点执行失败自动拿错误信息回去让模型重新生成重试次数 2 到 3提示词里强调「严格使用知识库提供的字段名不要臆造」把知识库文档重写一遍每个字段都加上示例值大模型参考样例后生成的 SQL 更贴合5.4 现象总结内容跟告警对不上模型「自己脑补」了不存在的告警原因模型输入数据里的 instance 字段和 message 字段被截断后一些关键标识信息丢失了模型只能根据残缺内容联想还有一种情况是temperature设太高导致模型开启了幻觉。解决代码节点截断 message 时保留末尾部分而不是开头因为实例 IP、端口、阈值这些关键信息一般在末尾temperature调整到 0.1 到 0.2 之间在 Prompt 的最后用一句硬约束「所有描述必须来自输入数据禁止编造未出现的告警内容」能起到明显改善5.5 现象Dify 工作流整体运行很慢单次分析要一两分钟原因权重在于知识检索节点召回了过多文档、大模型输出 token 太长、SQL 执行节点查询了大表且没有 LIMIT 限制。三个因素叠加单次分析时间就失控了。解决知识检索的 topK 调低到 3只取最相关的内容大模型节点的max_tokens限制到 800 以内让模型勿长篇大论SQL 验证节点先在查询语句末尾强制加 LIMIT 50 的限制若监控库执行支持大幅缩短执行时间6. 进阶用法从「能跑通」到「敢上线」的工作流验证法这部分写给已经跑通基础的读者。把智能体从技术上能运行到业务上敢使用之间还差一步验证体系。我自己的做法是弄一个「模拟告警数据集」每年平台巡检里用同一批数据跑一套完整流程检查输出是否稳定。这个数据集不大20 条告警包括了 P0/P1/P2 各级别以及已知根因的典型故障场景。每次改完工作流参数我强制自己跑一遍这 20 条模拟数据并且会人工对比输出结论看有没有跑偏。温度调到 0.1 之后正常情况下同一份数据不会产生明显不同的结论。如果改了 Prompt 或节点逻辑导致输出变了就说明某一处有隐性状态没考虑到。这套做法看着简单我身边用得好的团队基本都在用。第二个能提效的进阶点是把智能体的分析结果做成「可审计」——每次分析完成后把告警源数据、生成的 SQL、查询结果、最终结论以 JSON 形式落库。后续如果误判了随时回放当时的上下文定位是模型问题、数据问题还是知识库问题。这就回到大模型应用里的一个核心话题智能体行为审计。我见过不少团队把这套审计流程省略掉等到出了事故才发现查不到任何依据。记得一次生产环境告警误判值班同事按智能体建议把某台实例重启了事后复盘的时候发现结论是把另一台机器的负载误挂到了这台机器上原因就是 SQL 生成的查询条件里没把 host 字段过滤准。从那以后我每次部署工作流都强制走一遍「模拟告警 结论审计 SQL 全记录」三步验证所有结论必须能溯源到原始告警数据否则宁可让智能体说「无法分析」也不要让它给一个没有依据的结论。这套习惯帮我少熬了无数个半夜。希望帮到你。本文还有配套的精品资源点击获取