AI自动生成故障复盘报告:提示词工程与代码实战 📅 发布时间:2026/8/27 5:36:52 👁 浏览次数: 最近和几个团队聊故障复盘大家共同的心声是故障恢复不是终点写完复盘报告才算结束。而写报告这件事往往比处理故障本身还折磨人。故障期间的时间线分散在告警平台、聊天记录、变更记录和临时开的会议里要手动对齐、补充背景、分析根因、梳理行动项一份像样的复盘报告通常要花上一两个小时遇到复杂故障甚至要半天。这篇文章要解决的问题很直接能不能把整理故障复盘这件事交给 AI 来做我们只需要把零散的故障材料丢给大模型让它自动生成一份结构完整、有根因分析、有行动项的复盘报告。文章会从方案设计、提示词编写、代码实现到落地部署讲清楚完整链路后端开发、运维、SRE 都可以直接照着搭一套自己的故障报告生成工具。1. 为什么需要 AI 辅助写故障复盘报告1.1 手动整理故障复盘报告的真实痛点故障复盘也叫事后分析或 Postmortem是线上事故处理流程中非常重要的一环。它的目的不是追责而是通过记录故障的来龙去脉找到系统设计和运维流程中的薄弱点避免同类问题再次发生。但实际操作中写复盘报告面临不少问题。第一信息散落收集成本高。一次故障涉及的素材包括告警平台的通知记录、监控图表的时间点、变更系统的操作记录、值班同学的排查笔记、群里几十条讨论消息。要把这些素材对齐到一个统一的时间线本身就是一件费时费力的事情。第二表达要求高很多人不知道怎么写。复盘报告不是流水账它需要按时间线叙述、分析直接原因和深层原因、评估影响范围、提出可执行的改进项。很多技术同学处理故障很在行但一写报告就容易写成“发现告警→排查→恢复”的三句话总结信息密度不够领导不满意后续团队也没法从中沉淀经验。第三复盘不及时质量打折扣。故障恢复后团队通常要立刻投入下一个任务复盘报告往往被拖到第二天甚至更晚才写。时间隔得越久细节丢失得越多报告质量越低。第四个体经验差异影响报告质量。有经验的 SRE 写的复盘报告结构清晰、根因分析到位、行动项具体可执行而新手写的报告经常抓不住重点。这种差异导致团队的知识沉淀不稳定。1.2 AI 写复盘报告能做到什么程度聊到这里很多人会问AI 生成的报告靠谱吗会不会胡编乱造根因分析会不会不准这里需要明确一个边界AI 不是替代工程师做根因分析而是替代工程师做信息整理和文档生成。换句话说根因结论可以来自工程师的判断也可以来自 AI 基于已有材料日志、告警、时间线的归纳分析但 AI 的作用更多是“把零散材料变成结构化报告”而不是凭空推断故障原因。具体来说AI 能完成这些工作把无序的时间线整理成按时间排序的故障经过。根据输入的材料归纳影响范围例如接口超时率、错误率、受影响用户量。基于输入的时间线和变更记录给出根因分析的第一版草稿。自动生成报告框架包括故障概述、处理过程、根因分析、后续行动项。将报告输出为 Markdown、JSON 等结构化格式方便归档和集成到内部平台。在实际落地中AI 生成的是“草稿版报告”或“结构化底稿”人工只需审核、修正和补充判断整体耗时可以从两小时压缩到二十分钟甚至更短。1.3 适用场景与边界AI 写复盘报告适合以下场景线上服务故障、接口异常、数据库问题等有明确时间线和处理过程的故障。有告警记录、日志片段、变更记录、群聊记录等数字痕迹的系统。团队需要定期输出复盘报告给管理层审阅的场景。需要将复盘报告归档到知识库形成历史故障库的场景。不太适合的场景也要说清楚完全没有任何记录材料、只靠回忆的故障AI 无法生成有效内容。涉及高度敏感的根因判断需要人工深度介入AI 只能提供结构化框架。材料中包含大量无法脱敏的机密信息且模型托管在第三方平台时需要先做脱敏或选择私有化部署。理解了 AI 写复盘报告的价值和边界之后下面进入可落地的方案设计。2. 整体方案设计2.1 技术选型思路整套方案的核心本质上是“大模型 提示词工程 结构化输入输出”。技术选型上需要注意几点大模型接口优先选择兼容 OpenAI 接口规范的大模型服务这样代码可以复用切换模型时只改配置即可。无论是使用官方 API还是国内大模型平台提供的 OpenAI 兼容网关代码层面都保持一致。编程语言Python 最合适生态成熟适合快速开发脚本和工具。输出格式采用“先输出 JSON再转 Markdown”的两段式设计。JSON 方便程序解析和后续入库Markdown 方便人工阅读和归档。输入设计输入采用 JSON 文件包含故障标题、时间范围、影响范围、时间线、日志片段等字段便于结构化管理。2.2 系统流程整个流程可以用下面这个流程来理解收集故障素材 ↓ 整理为结构化 JSON 输入 ↓ 构造提示词含输入材料和分析要求 ↓ 调用大模型接口获取结构化 JSON 结果 ↓ 解析结果渲染为 Markdown 复盘报告 ↓ 人工审核补充后归档第一步的素材收集可以通过脚本自动完成例如从监控平台导出告警时间线从聊天记录导出讨论内容。本文重点演示从结构化 JSON 到最终报告这一步素材收集部分给到可扩展的思路。2.3 输入输出规范设计输入 JSON 需要包含以下字段{ incident_id: 故障编号, title: 故障标题, start_time: 故障开始时间, end_time: 故障恢复时间, detection_source: 故障发现来源, impact_scope: 影响范围和影响程度, timeline: [ { time: 时间点, event: 发生的事情 } ], logs: 关键日志片段或告警内容 }输出部分我们要求大模型返回如下结构的 JSON{ summary: 故障概述, timeline: 处理时间线文字描述, root_cause: 根因分析, impact: 影响评估, recovery: 恢复措施, action_items: [行动项1, 行动项2], lessons: 经验教训 }定义好输入输出协议后核心工作就变成了两件事写好提示词写好调用代码。3. 环境准备与依赖安装3.1 运行环境本文示例在以下环境中验证通过版本仅作参考需要根据你的实际环境调整操作系统Linux / macOS / Windows 均可Python 版本推荐 3.9 及以上大模型接口兼容 OpenAI 接口规范的服务本文以通用的 OpenAI 兼容接口为例如果你的团队不方便直接调用外部大模型 API也可以将 base_url 指向内网部署的模型网关或本地推理服务代码逻辑完全相同。3.2 安装 Python 依赖创建虚拟环境后安装以下依赖python3 -m venv .venv source .venv/bin/activate pip install openai如果你的环境网络受限可以使用国内镜像源安装pip install openai -i https://pypi.tuna.tsinghua.edu.cn/simple为了读取配置和测试连通性建议同时安装 python-dotenvpip install python-dotenv3.3 准备 API 密钥和配置文件在项目根目录创建.env文件存放模型服务的相关配置LLM_API_KEYyour-api-key-here LLM_BASE_URLhttps://your-llm-endpoint.example.com/v1 LLM_MODELyour-model-name这里要注意不要把 API 密钥提交到 Git 仓库。项目中应添加.gitignore把.env文件忽略掉。代码中通过dotenv加载配置import os from dotenv import load_dotenv load_dotenv() api_key os.getenv(LLM_API_KEY) base_url os.getenv(LLM_BASE_URL) model os.getenv(LLM_MODEL)这样做的好处是模型地址、模型名称都通过配置管理代码不需要改动。4. 核心代码实现下面进入核心代码部分。整个代码文件可以放在generate_postmortem.py中包含数据读取、提示词构建、模型调用、结果解析和 Markdown 渲染几个模块。4.1 定义加载输入数据的函数首先实现从 JSON 文件读取故障素材的功能import json def load_incident_data(file_path: str) - dict: 从 JSON 文件加载故障输入数据。 :param file_path: 输入 JSON 文件路径 :return: 故障数据字典 with open(file_path, r, encodingutf-8) as f: data json.load(f) return data这个函数很简单但把输入和代码解耦了。后续团队可以开发自动化的素材采集脚本把采集结果直接写成这个 JSON 格式代码无需改动。4.2 编写提示词模板提示词是这套方案能不能出效果的关键。好的提示词要让大模型明确理解三件事它的角色是什么、输入材料是什么、输出格式是什么。SYSTEM_PROMPT 你是一名经验丰富的 SRE网站可靠性工程师擅长整理故障复盘报告。 你的任务是基于用户提供的故障材料生成一份结构完整、客观准确的故障复盘报告。 要求 1. 严格基于用户提供的材料不要编造材料中不存在的事实。 2. 根因分析部分区分直接原因和深层原因如果材料不足以判断请明确说明需要进一步调查。 3. 行动项必须具体、可执行不要写模糊的改进建议。 4. 输出必须采用 JSON 格式包含以下字段 summary, timeline, root_cause, impact, recovery, action_items, lessons 5. action_items 是字符串数组。 .strip() def build_user_prompt(incident_data: dict) - str: 构造用户提示词将故障数据序列化后传给模型。 return json.dumps(incident_data, ensure_asciiFalse, indent2)这里有几个设计细节角色设定为“SRE 工程师”能引导大模型使用运维和故障处理的语言风格。明确要求“不要编造材料中不存在的事实”在一定程度上降低幻觉。要求区分直接原因和深层原因提升根因分析的深度。输出格式用 JSON 约束方便后续程序解析。4.3 调用大模型生成报告调用部分封装成一个函数负责调用大模型接口并返回原始文本结果from openai import OpenAI import os from dotenv import load_dotenv load_dotenv() def generate_postmortem(incident_data: dict, model: str None) - str: 调用大模型接口生成故障复盘 JSON 文本。 :param incident_data: 故障输入数据 :param model: 模型名称默认从环境变量读取 :return: 大模型返回的原始文本 client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) if model is None: model os.getenv(LLM_MODEL) user_prompt build_user_prompt(incident_data) response client.chat.completions.create( modelmodel, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_prompt}, ], temperature0.2, response_format{type: json_object}, ) return response.choices[0].message.content温度设置为 0.2是为了让输出更稳定、更贴近材料内容减少随机发挥。response_format{type: json_object}是 OpenAI 兼容接口中常见的 JSON 输出模式如果你使用的模型网关不支持该参数可以去掉这个参数然后在解析层增加容错处理。4.4 解析模型返回结果模型返回的内容理论上已经是 JSON 字符串但为了避免个别情况下出现格式问题需要在解析层做一次容错处理import json def parse_llm_response(raw_text: str) - dict: 解析大模型返回的文本提取 JSON 数据。 如果直接解析失败尝试提取文本中的 JSON 块。 try: return json.loads(raw_text) except json.JSONDecodeError: pass # 容错处理尝试截取第一个 { 到最后一个 } 之间的内容 start raw_text.find({) end raw_text.rfind(}) if start ! -1 and end ! -1 and end start: try: return json.loads(raw_text[start:end 1]) except json.JSONDecodeError: raise ValueError(模型返回内容无法解析为 JSON) else: raise ValueError(模型返回内容中未找到 JSON 数据)这个容错逻辑很重要。虽然大模型接口开了 JSON 模式但有些场景下模型仍然会在 JSON 前后附加说明文字。通过截取花括号区间可以有效规避这种问题。4.5 渲染为 Markdown 报告拿到结构化 JSON 后就可以渲染成 Markdown 格式的复盘报告了。这里用最朴素的方式实现不引入多余依赖def render_markdown(result: dict) - str: 将结构化结果渲染为 Markdown 格式的故障复盘报告。 action_items result.get(action_items, []) items_text \n.join(f- {item} for item in action_items) markdown f # 故障复盘报告 ## 1. 故障概述 {result.get(summary, 暂无)} ## 2. 处理时间线 {result.get(timeline, 暂无)} ## 3. 根因分析 {result.get(root_cause, 暂无)} ## 4. 影响评估 {result.get(impact, 暂无)} ## 5. 恢复措施 {result.get(recovery, 暂无)} ## 6. 后续行动项 {items_text} ## 7. 经验教训 {result.get(lessons, 暂无)} return markdown.strip()在主函数中串联完整流程def main(): incident_data load_incident_data(incident.json) raw_text generate_postmortem(incident_data) result parse_llm_response(raw_text) with open(postmortem.md, w, encodingutf-8) as f: f.write(render_markdown(result)) print(复盘报告已生成postmortem.md) if __name__ __main__: main()到这里一个最小可用的 AI 故障复盘报告生成脚本就完成了。5. 完整运行演示5.1 准备示例数据在项目目录下创建incident.json内容如下{ incident_id: INC-2025-0107-001, title: 订单服务超时率升高故障, start_time: 2025-01-07 14:32:00, end_time: 2025-01-07 15:10:00, detection_source: Prometheus 告警order-service 超时率超过 20%, impact_scope: 订单查询接口超时率上升至 35%累计约 12 分钟受影响请求约 5 万次暂未造成数据丢失, timeline: [ { time: 14:30, event: 发布系统上线 order-service v2.3.1 版本变更内容为数据库连接池参数调整 }, { time: 14:32, event: Prometheus 告警触发order-service 超时率超过 20% }, { time: 14:38, event: 值班同学确认告警开始排查发现数据库连接池使用率达到 100% }, { time: 14:45, event: 初步怀疑是连接池配置过小紧急将连接池最大连接数从 50 调整到 100 }, { time: 14:52, event: 连接池使用率下降但超时率仍在 15% 左右继续排查慢查询 }, { time: 15:00, event: 定位到一条 SQL 未走索引全表扫描拖垮数据库紧急添加索引 }, { time: 15:10, event: 超时率恢复至 0.5% 以下故障解除 } ], logs: 2025-01-07 14:45:12 [order-service] ERROR slow query: SELECT * FROM orders WHERE user_id U12345 AND status PAID扫描行数 12800000耗时 3.2s }这份示例数据模拟了一次由慢查询和连接池配置不当共同导致的故障包含时间线、影响范围和日志片段足够让 AI 生成一份有深度的报告。5.2 运行脚本在项目目录下执行python generate_postmortem.py正常情况下控制台输出复盘报告已生成postmortem.md5.3 结果说明生成的postmortem.md大致结构如下# 故障复盘报告 ## 1. 故障概述 2025-01-07 14:32 至 15:10 期间订单服务 order-service 超时率异常升高至 35% 持续时间约 38 分钟。根因与数据库慢查询未走索引及连接池参数配置过小有关。 故障恢复后已补充数据库索引并对连接池参数进行调优。 ## 2. 处理时间线 14:30 发布系统上线 order-service v2.3.1 版本变更内容为数据库连接池参数调整。 14:32 Prometheus 告警触发超时率超过 20%。 14:38 值班同学确认告警开始排查。 14:45 将连接池最大连接数从 50 调整到 100。 14:52 连接池使用率下降但超时率仍偏高。 15:00 定位到一条未走索引的 SQL紧急添加索引。 15:10 超时率恢复至 0.5% 以下故障解除。 ## 3. 根因分析 直接原因订单查询 SQL 未走索引导致全表扫描产生大量慢查询占满数据库连接池。 深层原因连接池参数配置过小在慢查询突增时无法提供足够的数据库连接 发布变更前未覆盖慢查询压测场景导致问题直到线上才暴露。 ## 4. 影响评估 订单查询接口超时率最高达 35%持续约 12 分钟受影响请求约 5 万次 未造成数据丢失用户可感知到查询变慢或超时。 ## 5. 恢复措施 调整 order-service 连接池最大连接数 定位慢查询 SQL 并补充索引 监控超时率恢复至 0.5% 以下确认服务稳定。 ## 6. 后续行动项 - 对订单表高频查询字段补充索引并在测试环境验证执行计划。 - 完善连接池参数压测发布前增加慢查询审查。 - 增加慢查询日志告警慢查询超过阈值时及时通知值班人。 - 复盘本次变更评审流程增加数据库变更的 SQL Review 环节。 ## 7. 经验教训 数据库连接池参数调整类变更风险较高需要在测试环境进行压测验证。 线上故障排查时慢查询日志的及时查看能显著缩短定位时间。可以看到AI 根据输入的时间线和日志自动归纳出了直接原因、深层原因和后续行动项。其中“连接池参数配置不当”“发布前未覆盖慢查询压测”等分析在材料中是有依据的而非凭空编造。这里要强调AI 生成的报告仍然建议人工审核。尤其是行动项中的“完善连接池参数压练”等内容需要真实负责该系统的工程师确认是否合理。6. 进阶结合历史故障库做增强复盘6.1 为什么需要历史故障召回单次调用大模型生成的复盘报告只能基于当前这一次故障的材料。实际工程中很多故障是有相似先例的。比如“连接池被打满”这个根因可能在三个月前就出现过一次。如果能在生成当前复盘报告时自动参考历史相似故障的处理经验和行动项报告会更贴近团队实际情况行动项也会更具参考价值。这个场景正是 RAG检索增强生成的典型应用。思路如下把历史故障复盘报告向量化存入向量数据库写当前故障报告时先用当前故障的文本去检索最相似的几条历史报告把它们作为参考材料一起发送给大模型。6.2 最小实现思路实现一个最小可用的版本不需要引入复杂的向量数据库先用内存计算或者本地 JSON 文件存储即可。大致流程历史故障报告 - 文本向量化 - 存入向量索引 当前故障材料 - 向量化 - 相似度检索 - 取 TopK 将参考历史和当前材料一起构造 prompt - 调用大模型6.3 向量化与检索代码片段为了演示下面给出一个基于sentence-transformers和numpy的最小示例。如果你使用的是其他 embedding 模型可以替换模型名称。from sentence_transformers import SentenceTransformer import numpy as np # 加载 embedding 模型 model SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) # 历史故障报告文本列表 history_texts [ 数据库连接池打满导致订单服务超时根因是慢查询未走索引, 缓存击穿导致商品接口响应变慢根因是热点 key 过期, 磁盘空间不足导致日志写入失败根因是日志轮转策略失效, ] # 向量化历史报告 history_embeddings model.encode(history_texts) def search_similar(query: str, top_k: int 2): 检索与当前故障描述最相似的历史报告。 query_embedding model.encode([query])[0] scores [] for idx, hist_emb in enumerate(history_embeddings): score np.dot(query_embedding, hist_emb) / ( np.linalg.norm(query_embedding) * np.linalg.norm(hist_emb) ) scores.append((idx, float(score))) scores.sort(keylambda x: x[1], reverseTrue) return [(history_texts[idx], score) for idx, score in scores[:top_k]]得到相似历史报告后在构建用户提示词时把它们追加到输入材料中并增加一句以下是团队历史故障复盘中的相似案例请参考其中的经验和行动项结合本次故障材料生成报告。这一步能显著提升报告的落地价值但需要注意向量检索的相似度并不完全等于业务相关性建议在提示词中明确要求模型“仅参考与当前场景强相关的历史经验不要生硬照搬”。7. 常见问题与排查思路在实际使用过程中可能会遇到下面这些问题我整理成表格方便快速对照。问题现象常见原因解决思路模型返回内容无法解析为 JSON模型未稳定输出 JSON或接口不支持response_format去掉 JSON 模式参数在解析层做花括号截取兜底报告内容空泛缺少细节输入材料信息不足或时间线粒度太粗补充日志片段、告警详情、变更记录细化时间线根因分析出现明显错误模型基于不充分的材料进行了推测在提示词中明确“材料不足时标注需要进一步调查”行动项不具体提示词约束不足增加“行动项必须具体可执行包含改动对象和验证方式”请求超时或报错模型服务负载高或超时时间设置过短在创建客户端时增加timeout参数例如timeout60生成的报告包含敏感信息输入材料未脱敏在送入模型前对 IP、用户名、密钥等字段做脱敏处理模型总是忽略某些字段输出字段较多时偶发遗漏在提示词中列出字段模板并说明“必须包含全部字段”这里重点说两个高频问题。第一个是 JSON 解析问题。即使开启了 JSON 输出模式部分模型在长文本生成时仍然可能出现 JSON 不完整的情况。此时可以在代码中增加重试机制如果解析失败重新调用一次模型并将上次失败作为上下文反馈给模型让它修正输出。第二个是报告“看起来合理但实际不可执行”的问题。这是大模型生成的通病。解决办法是把行动项验收标准写进提示词例如“对于每个行动项必须包含负责角色或团队建议、改动模块、验证方式。”这样生成的内容会更贴近可执行的状态。8. 最佳实践与工程建议8.1 提示词工程建议提示词要围绕“角色、材料、约束、输出格式”四个维度来写。角色设定能引导语言风格和思考方式例如 SRE、技术负责人、数据库管理员。材料部分要标明哪些是事实材料哪些是待分析内容。约束部分要明确禁止编造强调“只在材料充分时下结论”。输出格式要精确到字段级别最好给一个示例模板。另外提示词版本管理也很重要。多一个空格、多一句约束生成结果可能差别很大。建议把提示词模板放在独立文件中管理或至少使用变量替换而不是硬编码在业务代码里。8.2 数据安全与合规调用外部大模型接口生成故障报告时输入数据可能包含线上系统信息、用户数据、内部 IP、代码片段等。在进入模型前务必做脱敏处理。建议搭建一个脱敏模块将 IP 地址替换为x.x.x.x。将用户名替换为user_***。将数据库连接串中的密码替换为***。将内部域名替换为internal.example.com。如果团队对数据安全要求极高可以采用私有化部署的大模型或者使用内网模型网关确保数据不出内网。8.3 输出质量保障AI 生成的复盘报告不能直接作为最终交付物。建议建立三层审核机制故障处理人审核确认时间线、恢复措施与实际一致。技术负责人审核确认根因分析准确、行动项可执行。归档审核确认格式规范、敏感信息已脱敏。在工程层面可以增加“报告生成后自动校验必填字段”的逻辑如果root_cause、action_items为空则自动重新生成或告警提示。8.4 工程化落地建议从脚本到工具还有一段工程化的路要走。几点建议供参考接入公司内部的事故管理平台。当故障状态变更为“已恢复”时自动生成复盘报告草稿。把输入数据的采集自动化。从监控告警平台、变更平台拉取时间线自动组装成 JSON。将生成的报告上传到内部文档系统或知识库支持检索和复用。定期用历史报告反哺提示词。把团队认可的优质报告作为 few-shot 示例能持续提升生成质量。不建议一开始就追求复杂的自动化链路。先把“手动输入 JSON → 生成报告”跑通再逐步增加采集、脱敏、归档等功能这样风险更可控。9. 总结与下一步学习方向本文围绕“AI 自动生成故障复盘报告”这个场景完整演示了一套可落地的技术方案。核心包括设计结构化输入输出协议、编写高质量提示词、调用大模型接口生成报告、解析结果并渲染为 Markdown以及通过 RAG 增强参考历史经验。下一步如果你想继续深入可以关注几个方向提示词工程进阶与 few-shot 设计、RAG 检索增强在实际工程中的性能优化、大模型应用的安全防护与数据脱敏、以及 AI Agent 在多步骤任务编排中的使用。如果你只是想快速解决当下的问题那么把本文第 4 节的代码跑通接入你们自己的故障材料就已经能省下一大半写复盘的时间。比起追求复杂的架构先让一个简单的工具在团队里用起来往往更重要。