想象你捂着肚子走进一家三甲医院,只对分诊台的护士丢下一句“医生,我难受”,然后转身就走。护士不知道该挂内科还是外科,不知道你疼了多久,更不知道什么情况下会加重——这台庞大的“诊治机器”根本无法启动。开源项目就是一座全年无休的“代码医院”,而 Issue 系统就是它的挂号分诊台。你提交的每一份 Issue,都像一张病历:主诉清晰、化验单齐全,医生才能快速定位病灶。所谓“化验单”,就是本文的核心主角——最小可复现示例(MRE):一段能让维护者按图索骥、亲眼看到 bug 的最小代码。这篇文章会用“看病”的故事,带你走完从挂号、开化验单、规范书写、沟通复诊到出院的完整流程,让你从“报 bug 被无视的小白”成长为“社区大佬抢着回应的贡献者”。

岗位关联

对 AI 从业者来说,高质量 Issue 报告是你调用全球开源社区智慧的“医保卡”:模型训练 OOM、推理框架崩溃、算子精度异常,都能靠一份规范的 Issue + MRE 快速得到修复,同时沉淀个人技术品牌。

目录
  1. 可视化演示
  2. 1. Issue报告基础:先学会挂号
  3. 2. 最小可复现示例:一张能看懂的化验单
  4. 3. 撰写规范技巧:病历要分结构
  5. 4. 社区沟通礼仪:别把维护者当客服
  6. 5. 问题定位排查:先当一回侦探
  7. 6. 提交与跟进:从挂号到出院
  8. 7. 优秀案例剖析:向高手学写病历
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

模拟问题描述、最小可复现示例编写与修复验证三步流程,展示规范Issue报告如何加速开源社区协作与问题定位。

本节配有交互动效(进入视口后自动加载,约 3KB)。

模式1:规范问题描述 标题+环境+复现步骤 预期vs实际行为 Issue = 期望 - 实际 描述越规范,维护者定位越快。

1. Issue报告基础:先学会挂号

走进开源项目这座“代码医院”,第一个遇到的不是医生,而是挂号台。在 GitHub、GitLab 这些平台上,Issue 就是这个挂号台:一份正式的、可追溯的、面向所有人的问题工单。你首先要搞清楚挂哪个科——Issue 按性质分为三类:bug 是“生病了”,程序行为与文档不符;feature request 是“想做个体检套餐”,请求新功能;question 是“挂个咨询号”,问用法不求改代码。挂错科,医生再高明也难下手。

挂号单上最重要的就是“主诉”,对应 Issue 的标题。主诉的黄金法则是:模块 + 操作 + 现象一句话说清。比如 [Bug] transformers 的 tokenizer 在长文本下丢失 [CLS],维护者扫一眼就知道问题出在哪。反过来,“我的模型训练不起来”这种标题,等于捂着肚子喊“我难受”——信息量为零。

挂号前还有一道工序:搜索先行。病人进医院先看导诊屏,而不是每个窗口都排一遍队。提交 Issue 前,先在 issues 列表用关键词搜索,确认没有重复问题。最后,学会使用项目的 Issue 模板和标签体系——那是医院准备好的空白病历,照着实填即可。

所以,下次写标题前,把自己当成分诊台护士:把最关键的三个词(模块、报错、场景)塞进主诉。标题写好了,你的 Issue 就赢在了起跑线上——医生还没接诊,心里已经有了初步判断。

P=1−(1−r)nP = 1 - (1-r)^{n}
标题里放的“关键词”越多、越精准,Issue 被检索到的概率越高。r 是单个关键词的命中率,n 是关键词个数。
  1. 单个关键词命中率 rr 表示标题里某个关键词(如 CUDA、OOM)被搜索或过滤命中的概率。r 介于 0 到 1 之间,与词频和项目特性有关。
    r∈(0,1)r \in (0, 1)
  2. 全部关键词落空每个词都“没命中”的概率是 (1-r),n 个词同时落空的概率就是它的 n 次方。
    (1−r)n(1-r)^{n}
  3. 至少一个命中用 1 减去“全军覆没”,就是在搜索、分类、提醒中至少被看到一次的概率。
    P=1−(1−r)nP = 1 - (1-r)^{n}

2. 最小可复现示例:一张能看懂的化验单

病人光说“我胃疼”是不够的,医生需要的是化验单、CT、过敏原测试——一份能亲手验证的客观凭证。在开源社区,这个凭证就叫最小可复现示例(Minimal Reproducible Example,MRE):把 bug 从整个项目中“提纯”出来,形成一段能让维护者在自己机器上完整复现问题的独立代码。

MRE 讲究“三要素”:可运行的输入数据(最好是几行就能构造的伪数据)、准确的环境配置(框架版本、CUDA、操作系统)、完整的复现步骤(三条以内的操作序列)。三要素缺一,化验单就不合格:没有输入,维护者不知道喂什么;没有环境,同样的代码结果天差地别;没有步骤,复现路径全靠猜。

“最小”二字是灵魂。精简技巧包括:删掉与 bug 无关的函数和依赖;把随机种子和输入硬编码写死;大文件数据集用随机张量代替;最后用“复现验证闭环”收尾——把 MRE 丢到一个全新的 conda 环境里,从零跑一遍,确认 bug 依然出现。这一步就像护士抽完血后核对姓名:确保化验的是你的血,不是别人的。

把 MRE 想成一道菜谱:主厨要复刻你的“失败菜品”,需要的是精确到克的配料表,而不是你描述“盐放多了”这种模糊体验。只要 MRE 能在陌生环境里稳定“翻车”,维护者就拿到了修复 bug 的第一手证据。

R=1−2−mR = 1 - 2^{-m}
每锁定一个关键复现条件(输入、版本、步骤……),复现概率就翻一倍。m 是“被固化的条件数”。
  1. 零条件基线当 m = 0,即只丢一句话“有问题”,复现概率 R = 0,维护者无从下手。
    R=1−20=0R = 1 - 2^{0} = 0
  2. 逐项固化每确定一项条件(比如“batch_size 固定为 32”、“用 PyTorch 2.0”),等价于在分母中减半不确定性。
    R=1−2−1=0.5R = 1 - 2^{-1} = 0.5
  3. 条件越多越确定当 m = 4,R ≈ 93.75%,四个条件锁定后,维护者几乎必然复现,后续修复就是水到渠成。
    R=1−2−4=0.9375R = 1 - 2^{-4} = 0.9375

3. 撰写规范技巧:病历要分结构

一份专业的病历,讲究“主诉、现病史、既往史”分层书写。规范的 Issue 同样要有清晰结构。首先是背景与动机:你正在做什么任务,为什么走到这一步。这行字看似可有可无,却让维护者理解你的上下文——就像医生需要知道病人是运动员还是程序员,同样的胸痛,诊断方向完全不同。

正文的核心是预期 vs 实际。明确写出“我期待发生什么”和“实际发生了什么”,并指出差异点。很多新手只写报错,不写预期,维护者看完满脑子问号:你到底觉得哪里不对?差异写清楚了,bug 的定位范围立刻缩小一半。

然后是环境信息清单:操作系统、Python 版本、框架版本(如 transformers、torch)、CUDA 版本、甚至 git commit 号。AI 项目对版本极度敏感,torch 1.13 与 2.0 的行为差异足以让同一个 bug 时有时无。最后是代码块与日志格式:用 Markdown 的三反引号包裹代码和日志,长日志不要整段贴,截取报错堆栈中关键 20 行即可。这就像化验单上的每个指标都要对应到行,而不是甩给医生一张模糊的全身照片。

把这份“加权公式”贴在显示器旁,写 Issue 时逐项对照:背景一句话、环境五六行、步骤两三步、差异一段话。结构化之后,维护者读你的病历就像看体检报告,哪里异常一目了然。

S=0.15×B+0.2×E+0.3×St+0.35×DS = 0.15 \times B + 0.2 \times E + 0.3 \times St + 0.35 \times D
信息完整度 S 由四部分加权求和:背景(B)、环境(E)、步骤(St)、差异(D)。权重代表维护者的关注优先级。
  1. 背景 B 权重 0.15背景是“为什么”,辅助理解,但不是核心证据,所以权重最低。
    0.15×B0.15 \times B
  2. 环境 E 与步骤 St环境权重 0.2,步骤权重 0.3。步骤比环境更接近“复现路径”,因此更重。
    0.2×E+0.3×St0.2 \times E + 0.3 \times St
  3. 差异 D 权重 0.35预期 vs 实际是 bug 的定义本身,权重最高。四项累加得到完整度。
    S=0.15B+0.2E+0.3St+0.35DS = 0.15B + 0.2E + 0.3St + 0.35D

4. 社区沟通礼仪:别把维护者当客服

医院的规则有一条铁律:不要对护士发火,他们不是你的私人医生。开源的维护者更是如此——绝大多数是志愿者,无偿用业余时间回答问题、修 bug。你在 Issue 里的每一句“怎么还不行?”“快修复!”,都像在急诊室对护士吼叫,只会让沟通成本飙升。

“避免重复打扰”是教养的体现。提交 Issue 后,不要每小时 ping 一次;更不要因为没人回复,就开一个一模一样的新 Issue。如果一周没有动静,可以在原 Issue 下礼貌地补充一句“请问这个问题需要更多信息吗?”。你补充的“新研究发现”(比如定位到一个更小的触发条件)远比催促更有价值,这正是“及时跟进反馈”的正确姿势。

当维护者给出了修复建议,请第一时间测试并回报结果;问题解决后,在 Issue 中明确说一句“已验证修复,感谢!”并关闭它。这份“致谢与共建”不只是礼貌——你的一次完整反馈,会成为后来者搜索时的宝贵资料,也是你从“求助者”走向“协作者”的起点。社区信任就像账户余额:每一次规范的互动都在存款,每一次催促都在取款。

沟通是有“复利”的:你每省下一轮对话,维护者就多出一份耐心给你调试。把维护者当成并肩作战的队友,而不是售后客服,你的 Issue 会得到完全不同的待遇。

Ctotal=C0+c×kC_{\text{total}} = C_0 + c \times k
一次 Issue 的总沟通成本等于固定成本 C₀ 加上每轮对话的边际成本 c 乘以轮数 k。轮数越多,大家越疲惫。
  1. 固定成本 C₀写清标题、结构、MRE 的初始投入,是不可避免的“挂号费”。
    C0C_0
  2. 边际成本 c每追加一轮“你追问、我补充”的对话,双方都要付出阅读、理解、回复的时间。
    c×kc \times k
  3. 总成本k 轮之后,总成本线性上涨。目标是把一次性说清楚,让 k 趋近于 0。
    Ctotal=C0+c×kC_{\text{total}} = C_0 + c \times k

5. 问题定位排查:先当一回侦探

优秀的病人不会直接把所有症状倒给医生,而是自己先记录发病规律:饭后疼还是运动后疼?同样,优秀的 Issue 提交者会先自己排查,把问题范围压缩到最小。排查的第一武器是二分定位法:假设你的代码有 N 行,先注释掉一半,跑一下,如果 bug 消失,说明问题在被注释的那一半;否则在另一半。重复这个过程,每次排除一半嫌疑,很快就能锁定元凶。

环境隔离验证是第二步:创建一个全新的 conda 环境,只装最小依赖,逐版本回退框架,看 bug 是否随之消失。很多 AI 项目的 bug 是“版本杂交”造成的:transformers 4.36 配 torch 2.1 正常,配 torch 2.0 就崩。日志与报错解读则是侦探的放大镜:不要只看最后一行报错,从堆栈回溯(stack trace)向上读,找出第一个“你自己的代码”出现的帧——那才是病灶所在;再把报错全文扔进搜索引擎,十有八九有人踩过同一个坑。

最后是最小化依赖:把外部库条件逐个去掉,直到 bug 必须依赖某个库才能出现。这一步和 MRE 是一体两面——排查的过程,就是 MRE 诞生的过程。你挖得越深,交给维护者的“犯罪现场”就越干净。

侦探破案靠的不是运气,而是系统性缩小范围。当你把 1024 行代码用 10 次实验锁定到 1 行,这份“破案笔记”本身,就是给维护者最好的见面礼。

k=⌈log⁡2N⌉k = \lceil \log_2 N \rceil
面对 N 个候选位置,二分定位法最多只需要约 log₂N 次对比。N=1024 时,最多 10 次就能定位。
  1. 候选规模 N把代码按区块或功能分成 N 个嫌疑单元,比如按函数、按训练循环、按数据预处理切块。
    NN
  2. 每次排除一半每次实验要么排除左半,要么排除右半,嫌疑范围减半,等价于取对数。
    log⁡2N\log_2 N
  3. 向上取整N 不一定是 2 的整数次幂,所以要向上取整保证覆盖所有情况。
    ⌈log⁡2N⌉\lceil \log_2 N \rceil

6. 提交与跟进:从挂号到出院

看病不只是挂号那一步,后续的检查、复诊、取药同样关键。Issue 也有完整的生命周期:open(挂号成功)→ triage(分诊,维护者确认是否有效)→ assigned(排到医生名下)→ fixed(开药动刀)→ closed(出院结账)。每一步都需要你作为“病人”的配合。

提交前检查好比出门前确认带齐了病历和医保卡。清单包括:标题是否包含关键信息?搜索过重复 Issue 了吗?MRE 能否在新环境复现?环境信息是否齐全?期望 vs 实际写清楚了吗?六项检查通过,再按下提交键。提交后进入观察期:及时更新进展——维护者提问必须回答,你发现的新线索(比如“把 batch_size 降到 8 就不崩”)要主动补充,这些信息会让 triage 更快做出判断。

当 bug 被修复,维护者合入 PR 后,你需要验证修复是否生效,然后关闭与后续:关闭 Issue、回复验证结果,如果顺手,还可以认领一个相关的"good first issue"开始贡献代码。从 open 到 closed,不是一次性的交付,而是一次完整的诊疗闭环。

出院时回望,你会发现整个流程中,“等待”占据了大半时间。而你能做的,就是让自己的每一份输出都足够清晰,让医生的每一次诊断都不需要重复问诊——这才是对医生最大的尊重。

E[T]=λ×μE[T] = \lambda \times \mu
Issue 的平均解决时长,约等于沟通轮次 λ 乘以每轮平均耗时 μ。想缩短总时长,就要同时减少轮次和单轮耗时。
  1. 沟通轮次 λ维护者每追问一次、你每补充一次,都算一轮。信息越完整,λ 越小。
    λ\lambda
  2. 单轮耗时 μ每一轮中,双方阅读、理解、环境切换、重新运行的平均时间。
    μ\mu
  3. 期望总时长两者相乘得到平均解决时间。MRE 与规范结构能同时压缩 λ 和 μ。
    E[T]=λ×μE[T] = \lambda \times \mu

7. 优秀案例剖析:向高手学写病历

医学生进步最快的方式,是读名医亲手写的高分病历。开源社区同样如此。高分 Issue 特征高度一致:标题一句话点明模块与症状;正文结构分层(环境、步骤、期望、实际);MRE 精简到几十行且自带伪数据;语言克制专业,不抱怨不催促。读这样的 Issue,维护者甚至会产生一种“这个作者懂行”的信任感,回复速度自然快人一等。

反例教训也很有价值:标题写“求救!”;正文是散文;截图拍屏糊成一片;代码直接甩一个包含数据集的 zip。这类 Issue 往往被维护者一句话打回:"Please provide a minimal reproducible example."——听起来是要求,其实是婉拒。常见套路模板是把 GitHub 的 issue template 字段拆解成五段:背景 / 环境 / 步骤 / 期望 / 实际,外加一个 MRE 代码块。把模板背下来,闭着眼都能写出 80 分的 Issue。

更高阶的玩法是从 Issue 到 PR:你在报告 bug 时顺带做了二分定位,相当于替维护者完成了最耗时的一步;这时如果提出“我找到了可疑函数,能否帮忙确认?”,不少维护者会主动邀请你提交修复 PR。一份高质量的 Issue,就这样变成了你开源贡献之路的敲门砖。

高手与新手的分野,不在智力而在纪律。把完整度和冗余度这两把尺子随身携带,你的每一份 Issue 都会像名医的病历一样,简洁、准确、让人愿意一读到底——而这份“让人愿意读”的能力,恰恰是开源世界里最稀缺的信任资产。

Q=S1+RQ = \frac{S}{1 + R}
Issue 质量 Q 等于信息完整度 S 除以冗余惩罚项 (1+R)。完整度越高越好,冗余度 R 越高,质量被拉低。
  1. 完整度 S来自第 3 节的加权完整度,决定“信息够不够”。
    SS
  2. 冗余惩罚 1+RR 是无关信息占比。R 越大,分母越大,质量被稀释,比如贴三天日志、整段复制项目。
    1+R1 + R
  3. 质量得分完整真实的信息是分子,冗余噪音是分母。高分 Issue = 信息全 + 噪音低。
    Q=S1+RQ = \frac{S}{1 + R}

AI 应用场景

场景一:为 Hugging Face Transformers 提交模型 bug

阶段:开源协作与问题反馈(调试闭环)

解决的问题:传统做法是在微信/知乎发帖求助,信息零散且无法沉淀;或者只贴一张报错截图,维护者无法复现。AI 工程师用规范 Issue + MRE 把不确定问题固化为可验证工单。

具体案例:你在微调 BERT 时发现中文分词结果异常。先用二分定位法确认是 BertTokenizerFast 在 max_length=512 边界处的行为,再写一个 30 行的 MRE(用随机文本 + 三行配置)提交。维护者十分钟复现,第二天就合入了修复 PR,你的名字出现在 release note 的感谢列表里。

场景二:为 vLLM 推理框架上报性能回归

阶段:性能排查与优化

解决的问题:LLM 推理框架升级后吞吐量骤降,直接报“变慢了”无法定位。AI 平台工程师用版本二分法定位到具体 commit,用 MRE 附上请求负载脚本和 benchmark 数据,让维护者一次锁定回归根因。

具体案例:你在生产环境把 vLLM 从 0.4.0 升到 0.4.2 后,TPS 从 800 掉到 400。用环境隔离法在 Docker 里逐版本回退,发现是 0.4.1 引入的 attention backend 改动。Issue 里附上压测脚本 + 环境清单,3 天内官方发布了 hotfix。

场景三:用 AI 协助撰写 Issue 与 MRE

阶段:报告生成辅助(Copilot 提效)

解决的问题:很多开发者英语表达不自信,或对日志梳理没耐心,导致报告质量低。借助 ChatGPT 等工具,可以把报错堆栈、环境信息整理成结构化 Issue,并生成 MRE 骨架。

具体案例:你让 AI 把一段 CUDA OOM 堆栈 + 环境清单重写成规范的英文 Issue 开篇,再让它生成一个“最小化数据加载”的复现脚本雏形。人工核对后提交,质量远超仓促拼凑的中式英语报告。注意:AI 生成内容必须人工验证可运行,MRE 的“可复现”红线不能交给幻觉。

Python 演示

python36 行
import platformimport sysfrom datetime import date  def get_env_info():    # 收集运行环境信息, 作为 Issue 的环境信息清单.    info = {        "os": platform.platform(),        "python": sys.version.split()[0],        "date": date.today().isoformat(),    }    for pkg in ("torch", "transformers"):        try:            module = __import__(pkg)            info[pkg] = getattr(module, "__version__", "unknown")        except ImportError:            info[pkg] = "not installed"    return info  def build_issue(title, steps, expected, actual, mre_code):    # 把各个字段组装成一份结构化 Issue 报告草稿.    env = get_env_info()    return (        title + "\n\n"        "## 环境信息\n"        "- OS: " + env["os"] + "\n"        "- Python: " + env["python"] + "\n"        "- torch: " + env["torch"] + "\n"        "- transformers: " + env["transformers"] + "\n\n"        "## 复现步骤\n" + steps + "\n\n"        "## 期望行为\n" + expected + "\n\n"        "## 实际行为\n" + actual + "\n\n"        "## 最小可复现示例\n"        "
目的:一键生成一份符合规范的结构化 Issue 报告草稿,并自动检查六个核心字段的完整度。
  1. import platform读取操作系统信息,环境清单的第一块拼图。
  2. sys.version.split()[0]提取干净的 Python 版本号,避免把 "3.10.12 (main, ……)" 整坨塞进报告。
  3. for pkg in ("torch", "transformers")自动探测 AI 项目最关心的两个框架版本,装没装都如实上报。
  4. def build_issue(...)把标题、步骤、期望、实际、MRE 组装成 Markdown 模板,顺序对应正文的“病历结构”。
  5. required = ["## 环境信息", ...]一份检查清单,对应提交前检查的六个字段。
  6. hit / len(required)输出 0-100% 的完整度分数,提醒你哪些模块还没写。

常见误区

误区我把三天的操作日志、六张截图、十段无关代码全部贴进 Issue,为什么维护者还让我“请精简一下”?

正解信息多不等于信息全。医生要的是主诉和化验单,不是你的三餐流水账。有效的“详细”是结构化完整:背景、环境、步骤、期望、实际、MRE 六件套缺一不可,而不是抒情散文。冗余信息会淹没关键信号,维护者的阅读时间按秒计费,长文直接劝退。

为何常见:初学者怕“说不清楚被追问”,本能地堆砌所有信息,以为量变会产生质变。

误区我都把报错截图发上去了,为什么还让我“提供一个可复现的最小示例”?截图还不够直观吗?

正解截图只能证明你遇到了问题,不能证明维护者能复现。报错发生在你的数据、你的版本、你的环境里,就像病人给医生看一张 CT 片,却不告诉医生这 CT 是用什么设备、什么参数拍的。MRE 才是让问题“可搬运、可验证”的凭证,截图只是凭证上的一个盖章,代替不了整张化验单。

为何常见:人脑处理图像很直观,于是误以为对方能共享你脑中的全部上下文。

误区我把整个仓库 zip 上传,附上完整数据集和训练配置,这下够“可复现”了吧?

正解最小(Minimum)才是灵魂。整个项目是飞机维修手册,维护者只需要“打火启动失败”的那一个电路。MRE 应该控制在几百行以内、用公开或合成数据、删掉所有无关逻辑。数据太大就随机生成,代码太长就二分砍半。你打包的“全家桶”只会让维护者下载半小时、排查一整天,最终礼貌地关掉 Issue。

为何常见:把“可复现”等同于“完整交付”,混淆了复现条件与业务全貌的区别。

误区我已经把 Issue 发出去了,后续就是维护者的事了。一周没动静,我再发一个催一下。

正解Issue 是对话的开始,不是交付物。维护者追问时你要及时补充;重复开 Issue、反复 ping、无意义的 “+1“,都在消耗社区信任。开源维护者平均一人维护多个项目,你的每一次高质量补充(新发现的最小触发条件、版本对比结果)都在帮他们降低诊断成本,这才是”跟进”的正确姿势。

为何常见:习惯了商业软件“一对一客服”的思维定式,缺乏对社区协作“人人为我,我为人人”本质的理解。

误区我把代码砍到 20 行了,环境就写个 "Python 3" 应该够了吧?

正解环境信息是复现的“温度计”。很多 bug 是 torch 1.13 有、2.0 没有的;GPU 型号、CUDA 版本、操作系统细节都会改变行为。环境不全,MRE 就是一张没有患者姓名和采血日期的化验单,数值再准也无法入档。规范的环境清单至少六项:OS、Python、框架版本、CUDA、GPU 型号、项目 commit 号。

为何常见:MRE 这个词把注意力全引向“代码”,人们很容易忽略与代码同等重要的环境上下文。

面试题

Q1. 在 Issue 标题中,哪种写法信息量最高?

单选题 · easy

  • A.训练模型失败怎么办
  • B.[Bug] 显存不足训练崩溃← 正确答案
  • C.我的模型不工作帮我
  • D.新版好像有点问题啊

答案:B。B 含模块(训练)+ 现象(显存不足、崩溃),并用 [Bug] 标注类型,像一句精准的主诉;A 和 C 只有模糊情绪,D 连症状都没说。维护者扫一眼标题就能决定是否点开,标题就是 Issue 的第一印象。

Q2. 缩写 MRE 中的 "M" 代表什么?

单选题 · easy

  • A.Maximum (最大值)
  • B.Minimum (最小值)← 正确答案
  • C.Model (模型)
  • D.Memory (内存)

答案:B。MRE 是 Minimal Reproducible Example,“最小”是灵魂。它不是让你把整个项目打包,而是提炼出能复现 bug 的最小代码、最小数据、最小步骤。就像过敏原测试只需要一滴血,不需要全身抽一遍。

Q3. 一份规范的最小可复现示例,应包含哪些要素?

多选题 · mid

  • A.可运行的输入数据← 正确答案
  • B.准确的环境配置← 正确答案
  • C.完整的复现步骤← 正确答案
  • D.公司内部业务代码

答案:ABC。MRE 三要素是输入数据、环境配置、复现步骤,对应“喂什么、在什么条件下、怎么操作”。D 恰恰相反——公司内部代码既不能公开,又包含大量无关逻辑,是典型的反面材料。三要素齐了,维护者才能按图索骥复现。

Q4. 提交 Issue 之前,第一步应该做什么?

单选题 · easy

  • A.直接发到讨论区
  • B.搜索重复的问题← 正确答案
  • C.私信项目维护者
  • D.在社交平台吐槽

答案:B。先搜索是否已有相同 Issue,就像看病先看导诊屏:重复挂号既浪费自己的时间,也浪费维护者的精力。若已有相同 Issue,正确做法是进去补充自己的环境信息,而不是开新帖。

Q5. 若有 1024 行代码,用二分定位法最坏需要对比几次?

单选题 · hard

  • A.大概 512 次
  • B.大概 1024 次
  • C.大概 10 次← 正确答案
  • D.大概 100 次

答案:C。二分定位法每次注释一半代码,嫌疑范围减半,最坏次数是 log₂1024 = 10。这是“每次排除一半可能”的指数级威力:1024 行只需 10 次实验,而不是逐行扫描。顺着这个思路,把排查过程写进 Issue,维护者会把你当同行。

Q6. 下列哪些属于 Issue 环境信息清单?

多选题 · mid

  • A.操作系统版本号← 正确答案
  • B.框架版本信息← 正确答案
  • C.CUDA 版本号← 正确答案
  • D.维护者的星座信息

答案:ABC。环境信息清单是复现的“温度计”:OS、框架版本、CUDA、GPU 型号、commit 号都直接影响行为,torch 1.13 与 2.0 的差异就足以造成隐性 bug。D 与工程无关,属于典型的凑数干扰项。

Q7. 关于“期望行为”与“实际行为”,正确写法是?

单选题 · hard

  • A.只写期望行为
  • B.只写实际行为
  • C.两者都写并对比← 正确答案
  • D.等维护者来追问

答案:C。bug 的定义就是“期望与实际的偏差”,只写一半等于只给医生半个症状。C 把差异直接摆出来,维护者一眼锁定问题边界;D 把成本转嫁给维护者,是新手最典型的错误。

Q8. 维护者回复了你的 Issue 并给出建议,恰当做法是?

单选题 · mid

  • A.试完建议再反馈← 正确答案
  • B.直接关闭该 Issue
  • C.再开一个新 Issue
  • D.私信感谢不再回复

答案:A。维护者的建议需要你实测验证,结果(成功或失败)都要回报,这构成诊疗闭环。B 和 C 都切断或分裂了上下文;D 的“感谢”虽好但没反馈结果,等于病情复查缺席。一次完整的反馈,比十句谢谢更有价值。

Q9. 当 Issue 一周无人回复时,哪些做法是合适的?

多选题 · extreme

  • A.礼貌性地 @ 维护者← 正确答案
  • B.补充最近的研究发现← 正确答案
  • C.直接关闭该 Issue
  • D.转发讨论到更多社区

答案:AB。一周无回复时,一次礼貌的 @ 提醒(A)是合理的;补充新发现(B)更是把“催办”变成“贡献”,大家乐于回应。C 擅自关闭把自己和社区都锁死了;D 到处转发制造噪音,透支个人信誉。

Q10. 二分定位法的核心思想是?

单选题 · mid

  • A.顺序扫描全部代码
  • B.每次排除一半可能← 正确答案
  • C.随机抽查几处代码
  • D.只查看首尾几行

答案:B。二分定位每次实验排除一半嫌疑,把问题规模指数级缩小。顺序扫描是线性复杂度,随机抽查靠运气,只看首尾则完全可能漏掉中间段。类比侦探审讯:每次问一个“是/否”问题,就能砍掉一半嫌疑人名单。