大模型接入CI:失败用例自动根因分析,飞书报告90秒直达

发布时间:2026/10/26 6:21:14

大模型接入CI:失败用例自动根因分析,飞书报告90秒直达 每天早上到工位的第一件事不再是打开邮箱而是点开 CI 流水线页面像做侦探一样逐个翻失败用例。看一眼日志翻一下这次提交的代码变更猜一个原因在群里 对应的开发然后祈祷他不是在开会。这套流程我干了整整一年终于在某天早上爆发了——那天有 17 个失败用例我花了快三个小时才归完因而其中有 12 个其实是同一个根因。所以我做了个决定把大模型接进 CI。测试用例失败之后自动收集失败堆栈、相关日志、这次提交涉及的代码变更交给大模型做根因分析再把分析结果和修复建议整理成消息卡片直接推到飞书群里。整个过程在流水线里新增一个阶段完成测试挂了以后大约 90 秒内群里就会收到一份带“疑似根因”和“修复建议”的报告。这篇文章就把整个落地的过程完整拆一遍重点讲清楚三件事失败用例的上下文怎么采集和裁剪、大模型的 Prompt 怎么设计才能让归因靠谱、飞书的机器人消息怎么接得又稳又不烦人。适合被 CI 失败用例反复折磨的测试开发、SRE、以及想在 DevOps 流程里引入 AI 能力但不知道从哪下手的同学。1. 为什么我决定把大模型塞进 CI 流水线1.1 每天早上的手工归因真的做不动了先交代一下背景。我们的 CI 是自建的 GitLab Runner每天合并请求触发流水线跑完单元测试、接口测试、前端构建之后测试报告会归档成一个 JUnit XML 文件。单测和集成测试加起来大概 3000 多个用例高峰期每天要执行七八次全量流水线失败用例少则两三个多则十几个。这些失败用例聚在一起就是每天早上最折磨人的活。手工归因为什么累因为大多数失败用例的日志都是“看起来很像”的。比如一个接口超时可能是服务没起来可能是数据库连接池满了也可能就是某段代码引入了死循环。你得先看堆栈再翻这次 MR 改了哪些文件猜测是不是改动引起的然后打开对应服务的日志确认。每个用例平均要花 5 到 10 分钟十几个失败用例就是一两个小时。更气人的是同一批失败的用例往往来自同一个根因比如测试环境部署出了问题但你手动看的时候根本不知道这一点只能一个个重复劳动。我当时最强烈的需求是能不能在流水线跑完的同时就有一份报告告诉我“这些用例为什么失败相互之间有没有关联可能是谁改的代码导致的”。哪怕准确率不是 100%也能把 80% 的重复劳动省掉。1.2 我为什么不选“规则脚本 关键字匹配”的老路一开始我确实想过用正则和规则脚本做。比如抓到NullPointerException就归因为空指针抓到Connection refused就归因为服务不可用抓到TimeoutException就归因为超时。这类方案实现起来很快但有两个过不去的坎。第一个坎是规则库的维护成本。你永远预料不到下一次失败是以什么姿势出现的。上周是 Redis 连接池耗尽这周是某个 JSON 字段为 null 导致反序列化失败下周可能又是某个第三方 SDK 的版本兼容问题。每出现一种新模式就得改一次规则而且规则写多了以后相互之间还会冲突同一个堆栈能匹配上三个规则你根本不知道信谁。第二个坎是跨模块根因很难通过关键字发现。A 服务改了接口字段B 服务的消费方没有适配导致 B 服务的用例在 CI 里挂掉——日志里可能根本没有 A 服务的任何痕迹纯靠关键字匹配完全归因不出来。而大模型的语义理解能力恰好擅长解决这个问题它可以综合“失败堆栈 本次提交的变更内容 相关历史日志”来做跨模块推断输出一段带逻辑的归因解释。这是我选择大模型路线的最核心原因我要的不是一个应急 keyword 匹配器而是一个能读懂“改动之间的关联关系”的分析助手。1.3 方案目标与边界自动归因不等于自动修复想清楚目标才能不被带偏。我给这个项目定的目标是在 CI 测试失败后的 2 分钟内给出每个失败用例的疑似根因、影响范围、修复建议并把报告推送到飞书群。同时必须控制成本不能每次流水线都调用大模型只有失败用例才走分析链路。但我也给自己划了一条边界自动归因不等于自动修复。大模型的输出只是给开发一个起点而不是替代开发和测试的判断。所以卡片消息里我会把大模型的分析和原始日志、用例链接放在一起让人能快速下钻验证。这个边界很重要否则你会陷入“模型说的是错的但没人发现”的新风险里——后面我会详细说我们是怎么用数据评估这个风险的。2. 全链路架构拆解流水线里多出来的“分析环节”2.1 完整链路一句话描述整个方案在 CI 里新增了一个post-test-analysis阶段挂在测试任务之后。链路可以概括成六个步骤测试任务结束后归档 JUnit XML 报告和测试日志。分析任务解析 JUnit XML筛选出失败用例。对每个失败用例采集失败堆栈、相关代码变更、对应服务的错误日志片段。把这些上下文拼接成 Prompt调用大模型。大模型返回结构化的 JSON 结果包含根因分类、详细分析、修复建议。脚本把结果打包成飞书消息卡片发到指定的群。如果一句话说清楚测试挂了流水线自动触发一个分析程序程序把“失败现场”打包喂给大模型再把模型的分析写成报告发出来。下面我把几个关键节点的细节展开讲。2.2 数据采集从 JUnit XML 到 git diff数据采集是整个方案里最容易被低估的环节。Prompt 写得再好喂进去的数据不对输出质量也上不去。我按四类数据来做采集数据来源说明采集方式JUnit XML失败用例的类名、方法名、失败信息、堆栈解析testsuites/testcase/failure节点控制台日志失败服务在测试前后的错误日志读取日志文件按时间范围抽取git diff本次 MR 或 commit 涉及的文件变更通过 GitLab API 或git diff命令最近提交信息关联的 commit message辅助定位git log这里有个经验不要直接把整个堆栈倒进去大部分堆栈里 80% 是没用的框架调用。我会先做一层裁剪只保留从项目自己的包名开始的栈帧过滤掉java.lang.reflect、sun.*、org.springframework.test这些框架层。裁剪后的堆栈长度通常能压缩到原来的三分之一信息密度反而更高。2.3 调用大模型的成本与控制策略大模型的调用成本是团队会直接质疑的点我必须把这件事量化出来。我们的用量其实非常克制只有失败用例才触发调用正常通过的用例完全不涉及。以每天 10 次全量流水线、每次平均 2 个失败用例来算一天的调用量大约 20 次左右。模型选型上我一开始试了旗舰款效果确实最好但单价太高。后来换成了通用款把 Prompt 调好之后归因质量差别并不大。我们的实际配置是输入上下文控制在 4000 个 token 左右输出限制在 800 个 token单次成本约 0.02 元。按这个量级算下来一个月的大模型调用成本不到 15 元。这个成本对比人工归因两三小时的时间成本来说基本可以忽略。如果你的团队没有 API 预算也可以部署私有化模型。我们后来在另外一条业务线就用了私有化部署的版本效果接近只是响应速度稍微慢一点。这块完全取决于你们的合规要求和预算。3. 归因质量的关键上下文怎么采集Prompt 怎么设计3.1 只给堆栈远远不够上下文要拼得“像人一样看”大模型归因质量的高低不在于模型有多强而在于你有没有把“人平时会看的信息”完整地给它。我之前第一版 Prompt 只把失败堆栈丢进去模型输出的归因基本就是复述堆栈什么“空指针异常导致”没有任何增量信息属于典型的“正确废话”。后来我重新设计思路把自己平时手工归因时会看的信息完完整整地列出来包括四块。第一块是失败用例的完整上下文用例名、所属模块、失败阶段。第二块是裁剪后的堆栈和关键日志片段尽量保留错误出现前后的 30 行日志。第三块是本次提交涉及的代码变更这里尤其要注意不要只给文件清单要把具体改了哪一行、原始代码是什么样的都带上。因为很多失败就是改了一行引起的。第四块是历史数据这个用例过去 7 天的通过情况以及最近一次修改过相关代码的 commit。在实际操作中我发现第三块的贡献最大。很多用例失败是因为改了公共方法、改了数据库表结构、改了接口字段而这些在堆栈里根本看不出来只有结合代码变更才能定位。比如有一次一个用例报错是“字段 user_type 不匹配”堆栈看了半天看不出问题但结合同一批提交里改了实体类、把用户类型从 String 改成了 Integer一眼就明白了。3.2 Prompt 模板与输出约束Prompt 我建议直接走“角色设定 数据 输出约束”三段式结构。角色设定很重要它会显著改变模型的输出风格。在模型内部我是这么写的你是一名资深的测试工程师和代码审查专家。你的任务是分析 CI 流水线中的失败用例定位可能导致失败的根因。你需要结合失败堆栈、日志片段、代码变更上下文推断失败原因并给出可执行的修复建议。 以下是本次失败用例的相关信息 失败用例 名称{testCaseName} 所属模块{moduleName} 失败类型{failureType} /失败用例 失败堆栈 {stackTrace} /失败堆栈 相关日志 {logSnippet} /相关日志 本次代码变更 {diffContent} /本次代码变更 请严格遵守以下输出格式只输出 JSON不要输出任何多余文字 { root_cause_category: AMBIGUOUS_ERROR, root_cause_summary: 一句话根因摘要, detailed_analysis: 详细的分析过程说明你看到了哪些证据、哪些证据支持你的推断, confidence: 0.85, suggested_fix: 具体的修复建议尽量指出涉及的文件和修改方式, related_files: [文件路径1, 文件路径2] }输出约束这里我给了一个枚举值root_cause_category这个设计很关键。我们预定义了几类根因CODE_CHANGE、ENV_ISSUE、TEST_CODE_BUG、DATA_ISSUE、DEPENDENCY_CHANGE、AMBIGUOUS_ERROR。有了枚举值后面做数据统计、错误分类、以及跟开发拉通时的沟通成本都会大幅降低。confidence字段用来给每个失败案例打一个置信度低于 0.5 的结果我们会在报告里标记为“仅供参考”提醒开发不要过度采信。3.3 输出校验与失败兜底大模型返回的结果不能直接用至少要做两层校验。第一是 JSON 格式校验。模型偶尔会输出多余的 Markdown 包裹或者解释文字我们必须用代码严格解析json.loads失败就进入重试或降级逻辑。第二是字段合法性校验比如confidence必须在 0 到 1 之间root_cause_category必须是枚举值里的一个related_files里的文件路径必须存在。这一步能过滤掉相当一部分模型的胡言乱语。我在这块吃过一个亏有一次模型返回的 JSON 里多了一个尾随逗号直接导致json.loads抛异常整个分析任务挂掉群消息没发出来。后来我改用两步解析策略先用正则提取最外层花括号的 JSON 快再做json.loads实在解析失败就发一条“解析失败请看原始报告”的降级消息同时附带原始日志链接。这样至少保证人不会漏掉失败信息。4. 飞书端的工程细节从 Webhook 到消息卡片4.1 自定义机器人 Webhook 接入飞书这边的接入方式挺简单我们在飞书群里添加一个自定义机器人拿到 Webhook 地址。要注意的是机器人有两种安全设置可选关键字校验和签名校验。我强烈建议你用签名校验因为只用关键字校验的话任何往这个群里发消息的程序只要带上关键字就能发安全边界太松散。签名校验的逻辑需要在代码里实现把当前时间戳、密钥、时间戳拼接成字符串做 HMAC-SHA256 签名用 base64 编码后拼到请求参数里。下面是我用 Python 实现的签名代码import base64 import hashlib import hmac import time def gen_sign(secret, timestamp): string_to_sign f{timestamp}\n{secret} hmac_code hmac.new( string_to_sign.encode(utf-8), digestmodhashlib.sha256 ).digest() return base64.b64encode(hmac_code).decode(utf-8) timestamp str(int(time.time())) sign gen_sign(secret, timestamp) # 请求 URL 需要带上 timestamp 和 sign url f{webhook_url}?timestamp{timestamp}sign{sign}这里有一个容易踩的坑签名里的时间戳必须用请求发出的当前时间而且飞书那边会检测时间戳偏差超过一小时会拒绝请求。如果服务器时间不准或者把时间戳缓存了就会收到签名过期的错误。我第一次是从模板消息里手动带时间戳去测发现怎么都调不通排查了半天才意识到是自己本地时间比对逻辑写错了。4.2 卡片消息的模板与按钮交互飞书机器人支持文本消息和交互卡片两种形态。我强烈建议直接用卡片。原因很简单卡片可以结构化展示根因摘要、置信度、修复建议和链接按钮读起来不费劲。我们实际的卡片结构是这样组织的标题测试失败分析报告 - {项目名} - {构建号}正文正文总失败数、分布统计按根因类别、一句话总结。二级标签每个失败用例单独列出来包含用例名、错误类型、根因类别卡、置信度条、一句话摘要。底部按钮查看完整报告、跳转 CI 流水线。卡片消息的结构可以写成 JSON 模板Python 里用字典拼出来最后调飞书的interactive类型消息接口。要注意卡片里的字段是有长度限制的长文本不要一股脑全怼进去特别是堆栈这种超长内容放到详情页比如 CI 日志页或我们内部的一个报告页面卡片里只放摘要和链接。4.3 群报告怎么做到“一屏看完”分实际使用中开发们最关心的不是单个用例的归因细节而是“这轮失败总体上是什么原因”“我负责的模块有没有问题”。所以报告一定要有聚合视图。我的做法是在卡片顶部加一段“聚合结论”由大模型对整轮失败先做一次汇总分析比如“本次 8 个失败用例中5 个与 user-service 的接口字段变更有关2 个是测试环境数据库连接池耗尽1 个待确认。”这个聚合结论对开发来说价值最大它能立刻帮人建立整体认知。为了做到这一点我在流水线里的分析脚本会先单独调用一次“汇总调用”把所有失败用例的归因结果聚合到一起再让大模型生成综合结论。这次调用因为输入比较浓缩成本非常低但收益很大。实践下来开发拿到卡片后判断“是否紧急处理”的时间从平均 5 分钟降到了 30 秒。另外关于“飞书机器人发送表格”这个需求我也试过。如果想让报告里的失败用例以表格形式展示可以用飞书的附件表格或卡片表格。我最后采用的是卡片自带的“表格组件”把用例名、模块、根因类别、置信度、修复建议这几列塞进去。这个组件在手机端飞书上滚动有点卡但在 PC 端体验很好。如果你要展示的列太多考虑做一个跳转链接指向云文档或内部页面别硬塞卡片。5. 实测效果、踩坑记录与还能怎么扩展5.1 跑了一个季度的真实数据这个方案上线到现在跑了差不多一个季度我把关键数据列一下。平均每天分析 15 个失败用例大模型归因的整体准确率在 68% 左右。这里说的“准确率”是指模型输出根因类别与人工最终确认的一致率。听起来不算惊艳但要注意原来我们没有归因现在至少 68% 的结果可直接参考另外还有一部分是“部分正确”方向对了但细节不对。如果只看“方向正确”的话大概在 84%。最明显的效率提升在于跨模块根因的发现。以前手工归因跨模块问题经常要找到对应开发问一圈才能确定现在模型往往会在一开始就指出“user-service 的接口变更可能影响了 mobile-api 的消费方用例”减少了大量沟通成本。数据统计也验证了一个判断ENV_ISSUE类占比最高大约 38%主要就是测试环境不稳定、数据库连接数打满、依赖服务未就绪这几类。这类根因在过去纯手工归因时最容易被忽略因为大家都习惯把锅甩给“测试代码写得不好”而模型会基于日志里的证据给出相对客观的归属。5.2 三个印象最深的坑第一个坑是超时。我们调用大模型的 API 平均响应时间在 15 秒左右但偶尔会飙到 60 秒以上。刚开始没有设置超时分析阶段直接卡了 8 分钟严重影响流水线总时长。后来我做了双层保护代码层设 25 秒超时超时则跳过该用例并把“分析超时”写进报告流水线层设 3 分钟总超时过了就强制失败但保证消息一定发出。这样最坏情况也不会让 CI 无限阻塞。第二个坑是上下文溢出。有一次某个模块的 MR 改了 200 多个文件git diff生成的内容有几万行直接把模型输入上下文撑爆了。解决办法是给 diff 加限制只保留测试用例直接相关的文件、以及被测试用例依赖的公共模块文件每个文件的 diff 最多取前 80 行。超出部分我会在 Prompt 里写“XX 文件变更过大已截断重点看其余文件”。第三个坑是误报。模型有几次把ENV_ISSUE错误地归因为CODE_CHANGE导致开发组在完全没有问题的代码里反复排查。后来我在 Prompt 里加了一条约束“如果日志中存在超时、连接重试、资源不足等环境类证据优先归类为 ENV_ISSUE除非你能明确指出具体代码变更与本失败存在直接因果链。”这一改之后ENV 类的误报率降了不少。这说明大模型归因的边界需要我们靠经验去对齐Prompt 迭代是持续的事。5.3 下一步可以做的方向现在这个系统解决的是“失败之后告诉你怎么回事”但还没做到“失败之前拦住它”。我接下来的规划有两个方向。第一个是把分析结果沉淀成知识库。每次确认真实的根因之后可以把这轮失败用例、归因结果、最终确认结论存起来形成历史样本库。后续大模型再归因时可以先用相似度在样本库里检索历史案例找到最接近的 1-2 条作为 Few-shot 示例喂给模型。这个方向如果跑通准确率应该还能再上一个台阶。第二个方向是把归因结果和 MR 改动自动关联。比如当模型判断是代码变更引起的失败时可以直接在飞书卡片里生成一个“建议退回此 MR”的按钮人工确认后一键触发操作。这个涉及权限和流程审批不会做成全自动但可以把“定位到责任人”和“建议操作”这两段流程打通。这个系统整体已经变成我们团队早上的“值班助手”了。工程师来上班第一件事不是翻 CI而是看一眼群里的自动报告10 秒就知道昨天的失败是什么情况。按我个人的体验这类实践最值得投入的点在于它没有改变工程师原有的工作习惯只是把最费时的“信息收集和初步判断”这部分自动化了而把最终判断权留给了人。这才是 AI 接进开发流程里我觉得最舒服的姿势。
延伸阅读

更多相关文章

2026/10/26 6:21:14

Nvidia收购Slurm:AI与HPC融合的技术革新

1. 项目概述:Nvidia收购Slurm的战略布局2023年Nvidia对Slurm工作负载管理器的收购在HPC和AI领域引发广泛关注。作为长期从事高性能计算系统开发的工程师,我认为这次收购绝非简单的商业行为,而是Nvidia构建完整AI基础设施生态的关键一步。Slur…

2026/10/26 6:21:14

行为数据分析:从多模态数据到心理过程解码

1. 项目概述:当数据科学遇见心理学十年前我刚接触行为数据分析时,需要手动记录被试者的反应时数据,用Excel做简单的t检验。如今看到眼动仪、可穿戴设备和脑电设备产生的海量时序数据,才真正理解什么叫"行为数据的复杂性"…

2026/10/26 6:16:13

跨模态安全攻防:现状、挑战与防御策略

1. 跨模态安全攻防的现状与挑战多模态技术正在重塑人机交互的边界,但很少有人注意到其中潜藏的安全暗流。去年某国际AI顶会上展示的对抗样本攻击实验让我印象深刻——攻击者仅需在音频中插入特定噪声,就能让多模态系统将"打开门锁"误识别为&qu…

2026/10/26 7:26:18

LSTM与GEE在东非植被监测中的应用与实践

1. 项目概述:当LSTM遇上GEE的东非植被监测去年在肯尼亚实地考察时,当地牧民向我展示了一本记录了30年牧场变化的笔记本。泛黄的纸页上手绘的植被分布图与气候记录,让我意识到时间序列数据对生态研究的重要性。这正是我们使用Google Earth Eng…

2026/10/26 7:26:18

UE5字典动画技术解析与优化实践

1. UE5字典动画技术解析与应用实践在虚幻引擎5(UE5)的动画系统开发中,字典(Dictionary)数据结构扮演着关键角色。不同于传统编程中的简单键值存储,UE5的字典系统深度整合了蓝图可视化编程和动画资源管理&am…

2026/10/26 7:26:18

端到端测试体系搭建:从设计到稳定的完整实践指南

我做了这么多年测试和工程效能,几乎在每个团队都见过同一个场景:周五下午,CI流水线里e2e测试又红了一片,开发群里开始互相,点开报告一看,不是hover没生效就是元素加载慢半拍。有人顺手点了"重跑"…

2026/10/26 7:26:18

MV-UMI:跨载体机器人学习的技术突破与应用

1. 论文核心思想解析:MV-UMI如何实现跨载体学习这篇论文提出的MV-UMI(Multi-View Universal Machine Interface)系统,本质上是在解决机器人学习领域的一个关键瓶颈:如何让不同形态的机器人共享学习经验。想象一下&…

2026/10/26 7:26:18

Selenium WebDriver协议与浏览器自动化核心技术解析

## 1. Selenium核心架构解析:从浏览器操作到代码执行的完整链路当你在IDE中写下driver.find_element(By.ID, "username").send_keys("test")这行代码时,Selenium在后台完成了从HTTP请求到浏览器DOM操作的全链路协同。这套诞生于2004…

2026/10/26 7:21:18

物理层与数据链路层排障:从错包计数到VLAN抓包

一台机器白天跑得好好的,晚上业务高峰就开始丢包,ping时通时断,延迟从 0.3ms 跳到 200ms 再掉回来。第一反应是查 IP 冲突、查路由、查防火墙策略,查了一整圈没问题,最后拔下网线换了一根,好了。这类事我碰…

2026/10/26 0:20:20

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/26 1:53:47

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/26 0:20:17

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/26 0:00:48

Nested Learning:解决AI灾难性遗忘的分层记忆架构

1. 为什么AI需要"记忆"能力?在传统深度学习模型中,我们常遇到一个根本性问题:模型在处理新任务时,往往会完全遗忘之前学到的知识。这种现象被业界称为"灾难性遗忘"(Catastrophic Forgetting)。想象一下&#…

2026/10/26 0:00:48

企业级大模型应用:OCR预处理、Dify编排与DeepSeek落地实战

1. 这不是“用大模型”,而是重构工作流的起点“大模型的应用和工具”——这八个字现在被贴在无数技术分享、招聘JD、内部立项书的标题栏里,但绝大多数人点进去后看到的,是零散的API调用示例、几个开源UI截图、或者一句“接入LLM就能降本增效”…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑