工程师喜欢做的一件事是:遇到 Bug,打开对话框,把几百行日志或几十个函数的代码一股脑粘进去,然后问"这是什么问题?"。运气好的时候模型能给出有用的线索,更多时候得到的是"这段代码看起来没有明显错误"或者一个完全偏离方向的猜测。这不是模型不够聪明,这是因为你的使用方式根本就不对。

一、"把日志扔给模型"为什么不管用?

直接把原始日志或代码上下文扔给模型,核心问题有两个:信息过载和信息缺失,而且通常两个问题同时存在。

1.1 信息过载与信息缺失并存

原始日志里有 90% 的内容是正常运行的噪音——健康检查、心跳日志、常规请求记录。模型需要从这堆噪音里识别出真正异常的几行,而这个"识别"过程本身就消耗了大量上下文窗口,还不一定准确。另一方面,日志通常只包含"发生了什么",缺少"当时的系统状态是什么"——哪些服务在运行、最近有没有部署变更、请求量是否异常。没有这些背景信息,模型的分析就是猜。

1.2 上下文爆炸与结构化预处理

一个典型的生产 Bug 场景:服务报错,你打开日志文件,几千行。你的本能反应是"全给模型看",但这会触发上下文窗口的瓶颈,而且大多数信息是无关的。更糟糕的是,代码和日志混在一起时,模型在两类信息之间跳来跳去,分析质量会显著下降。

正确的做法是在把信息交给模型之前做结构化预处理:错误信息单独提取、相关代码单独提取、系统状态单独描述。这就是 Bug 定位 Skill 存在的价值——它定义了"应该提供什么信息、以什么结构提供",让每次 Bug 分析都从一个干净的起点开始,而不是把混乱留给模型处理。工程师的"前期整理成本"降低了,模型的"分析质量"自然就上去了。

二、Bug 定位 Skill 的结构化设计

2.1 五步分析框架

Bug 定位不是单步操作,它是一个有明确逻辑顺序的分析过程。把它压缩成一步会让模型在没有充分信息的情况下跳到结论——这是"把日志扔给模型"失败的另一个根本原因。五步框架把分析过程显式化:信息采集 → 异常识别 → 根因假设 → 修复方案 → 验证建议。每一步有明确的输入和输出,前一步的输出是后一步的输入。

信息采集:从输入中提取关键信息,整理成标准化的 Bug 上下文。输出:错误类型、错误位置、复现条件、相关代码段。

异常识别:从错误信息和代码中识别直接异常点(症状)和潜在异常点(可疑位置)。输出:症状描述 + 可疑点列表。

根因假设:基于症状和可疑点,生成 2-3 个根因假设,每个假设附上支撑证据(来自输入信息)和置信度评估。不要只给一个假设——单一假设的自信输出在 Bug 分析里往往是最危险的,它会让工程师停止思考其他可能性。

修复方案:针对每个根因假设,提供对应的修复方向(不一定是完整代码,重要的是修复逻辑和关键改动点)。

验证建议:如何验证修复是否有效——具体的测试用例、监控指标变化、边界条件检查。

2.2 结构化输入的设计

Skill 的输入设计是控制信息质量的关键。不是让用户"把日志扔进来",而是引导用户提供已结构化的信息:

inputs:
  error_message:
    type: string
    description: "错误消息或异常堆栈(仅错误相关部分,不包含正常日志)"
    required: true
  relevant_code:
    type: string
    description: "与错误直接相关的代码段(函数/方法级别,不超过 100 行)"
    required: false
  system_context:
    type: object
    description: "系统上下文:runtime(运行环境)、recent_changes(最近变更)、error_frequency(错误频率)"
    required: false
  reproduction_steps:
    type: string
    description: "复现步骤(如果已知)"
    required: false
  language_runtime:
    type: string
    description: "编程语言和运行时,如 'Python 3.11 / FastAPI'"
    required: false

relevant_code 是 optional 而非 required,因为运维场景下工程师可能只有日志没有代码访问权限。Skill 应该在没有代码的情况下仍然能运行,只是分析深度有所降低——这个降级行为应该在 Skill 的 Notes 里明确说明,而不是静默地降质量。

三、完整 Skill 实现与使用示例

3.1 完整 SKILL.md 示例

---
name: bug-investigator
version: "1.0"
description: "结构化 Bug 定位与修复建议。五步分析框架,输出根因假设列表和针对性修复方案"
author: devops-tools
---

# Bug Investigator

## Overview
引导工程师提供结构化的 Bug 上下文,执行五步分析
(信息采集→异常识别→根因假设→修复方案→验证建议),
输出可操作的根因分析报告。不替代工程师决策,但显著加速根因定位过程。

## Inputs

| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| error_message | string | 是 | 错误消息或异常堆栈(仅错误相关部分) |
| relevant_code | string | 否 | 直接相关代码段(函数/方法级别,≤100行) |
| system_context | object | 否 | 运行环境、最近变更、错误频率 |
| reproduction_steps | string | 否 | 已知复现步骤 |
| language_runtime | string | 否 | 编程语言和运行时,如"Python 3.11 / FastAPI" |

## Steps

### Step 1: 信息采集与标准化
从输入中提取并整理:
- 错误类型(异常类名 / HTTP 状态码 / 系统信号)
- 错误位置(文件名 + 行号,若可从堆栈中识别)
- 直接触发条件(从 reproduction_steps 或 error_message 上下文推断)
- 最近变更标记(若 system_context.recent_changes 非空,标记为高关注项)

输出标准化 Bug 上下文卡片,供后续步骤使用。

### Step 2: 异常识别
基于标准化上下文,识别:
- 直接症状:错误消息直接指向的代码位置或操作
- 潜在可疑点:与错误类型高度相关的常见根因位置
  (如 NPE 通常来自未判 null 的对象访问;连接超时通常来自连接池耗尽或下游服务不可用)

若提供了 relevant_code,在代码中标注可疑行(用行号)。

### Step 3: 根因假设生成
生成 2-3 个根因假设,按置信度降序排列。每个假设格式:

假设 N(置信度:高/中/低):
- 根因描述:[具体的技术描述]
- 支撑证据:[来自输入信息的具体依据]
- 典型触发场景:[这类根因通常在什么条件下出现]

不要生成没有证据支撑的假设。如果信息不足以支撑假设,明确说明需要哪些额外信息。

### Step 4: 修复方案
针对每个根因假设,提供修复方向:
- 关键改动点(具体到函数/配置项层面)
- 修复逻辑说明
- 关键改动的代码片段或伪代码(若有)
- 副作用提示(此修复可能引入的新问题)

### Step 5: 验证建议
提供具体的验证方案:
- 功能验证:如何确认 Bug 已修复(具体测试用例)
- 回归验证:需要检查的相关功能点
- 监控验证:修复上线后观察哪些指标(错误率、延迟、资源使用)
- 边界条件:需要特别测试的边界场景

## Output Format

输出结构化 JSON,示例:

{
  "bug_context": {
    "error_type": "NullPointerException",
    "error_location": "UserService.java:142",
    "trigger_condition": "用户未完成邮箱验证时调用 getProfile()"
  },
  "hypotheses": [
    {
      "id": "H1",
      "confidence": "高",
      "root_cause": "user.getProfile() 在 emailVerified=false 时返回 null,调用方未做 null 检查",
      "evidence": "堆栈指向 line 142 的 .getName() 调用;user 对象来自可能为 null 的 profileCache",
      "fix_direction": "在 line 140 添加 null 检查,或在 getProfile() 中保证非 null 返回"
    }
  ],
  "verification": {
    "test_cases": ["以未验证邮箱的用户调用 getProfile API,验证不再触发 NPE"],
    "metrics_to_watch": ["NullPointerException 异常率", "getProfile 接口 5xx 率"]
  }
}

## Error Handling
error_message 为空时拒绝执行并返回输入要求说明。
信息严重不足时,在 hypotheses 字段中说明需要补充的信息,而不是生成无依据的猜测。

## Notes
此 Skill 辅助定位,不替代工程师判断。修复方案需经过代码审查后再上线。
对于涉及安全漏洞的 Bug(如 SQL 注入、XSS),会在输出中添加 security_flag 标记。

3.2 一个实际使用场景

假设你有一个 Python FastAPI 服务,某个接口偶发 500 错误,错误消息是 AttributeError: 'NoneType' object has no attribute 'user_id',堆栈指向 payment_service.py 第 89 行。正确的使用方式是:把这个错误堆栈作为 error_message 传入,把第 85-95 行的相关代码作为 relevant_code 传入,在 system_context 里注明"昨天下午 3 点部署了 payment_service 的新版本,错误从部署后开始出现"。

有了这些结构化输入,Skill 的分析会直接指向:最近部署的变更引入了某个未处理 None 的代码路径,H1 置信度高。而如果你只是把错误消息扔进去,模型能给你的只是"可能是某个对象为 None,建议添加 None 检查"——这种废话你自己也能想到,用不着 AI。结构化输入的差异就是这么大。

四、总结

Bug 定位 Skill 的价值在于用结构强制信息质量。不是让模型更聪明,而是让提问更结构化。五步分析框架确保分析过程完整,结构化输入确保信息质量,多假设输出确保不会在信息不足时过度自信。对于开发和运维工程师来说,这个 Skill 真正有用的时刻,是凌晨两点生产环境报警、脑子转不动的时候——一个有框架的分析流程,比"把日志扔给模型祈祷出奇迹"可靠得多。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐