Grok 4.3 自动化分类300个Issue的深度实测与关键教训:自动化远没想象中简单
几个月前接手了一个中等规模的开源项目维护,最头疼的不是代码,而是 GitHub 上快破三百的积压 Issue。功能请求、Bug 反馈、使用咨询混在一起,每次手动打标签都要耗掉半个下午。当时第一个念头是:找个 AI 模型来分类,应该很快搞定。结果折腾了两天才找到一个“勉强算稳定”的方案。
先说结论:Grok 4.3 做 Issue 分类确实比预期要好,尤其是在理解上下文含糊的英文描述时。但它也容易“过度推断”——把一个写着“希望支持某个配置项”的功能请求硬判成 Bug,因为描述里带了一句“升级后不 work 了”。这恰好说明:模型能理解字面意思,但很难还原提交者真正的意图。
实际动手之前,先用域名为 ouai.me 的聚合站点做了个小对比。同一批 Issue 描述分别喂给 ChatGPT、Claude 和 Grok,发现 Grok 对长文本里的因果链条抓得更准,但 ChatGPT 的分类更保守、更“安全”。既然目标是减少漏判严重 Bug,最终选了 Grok 4.3 来做初筛,同时自己加了一层人工确认。
最初的简单 Prompt,效果很“飘”
一开始写的 Prompt 非常随意,大致是:
请阅读以下 GitHub Issue 内容,判断它属于:Bug 报告、功能请求、使用咨询、或无效/重复。只返回分类名称。
结果 Grok 把一条“希望 CLI 支持 --config 参数”的请求直接标成了 Bug,理由是原文里有句“以前用着好好的,新版本没了”。后来翻提交记录才发现,那个参数原本就是实验性的,文档里写明了随时可能移除。
显然,让模型单靠一条简短指令做判断是不靠谱的。Issue 里经常混杂着用户的情绪、误解,甚至非英语的机器翻译腔,模型很容易被带偏。
改进后的两步式 Prompt
把流程拆成两步:先让模型提取事实,再让它分类。第一步的 Prompt 变成这样:
你是一个开源项目的 Issue 分类助手。请阅读以下 Issue 内容(包含标题和正文),提取出三个关键信息:
- 用户遇到的具体现象或期望;
- 涉及的组件或功能模块;
- 是否有明确的报错信息或复现步骤。
只输出以上三点,不要添加判断。
拿到事实摘要后,再让它跑第二步:
基于上述提取的信息,将 Issue 归类为以下之一:Bug 报告、功能请求、使用咨询、无效/重复。
分类规则:
- Bug 报告:行为与文档或预期不符,有具体的报错或异常行为;
- 功能请求:期望新增或修改某个特性,没有提到异常行为;
- 使用咨询:询问“怎么实现”“是否支持”等,没有明确说“出错了”;
- 无效/重复:仅包含无意义内容,或与已有 Issue 高度重复。
只返回分类名称,不要解释。
这套 Prompt 上线后,分类的准确率从最初不到 60% 提到了 85% 左右。剩下那 15% 的问题,主要集中在“边界案例”上:比如用户既描述了异常行为,又顺带提了一个新功能需求。这种混合型 Issue,模型仍然倾向于只选一个标签。
用历史数据做了一次量化验证
为了心里有数,把过去一年里手动分类的 500 条 Issue 拿出来,让 Grok 4.3 盲跑了一遍,然后和人工标签对比。结果如下:
| 类别 | 人工数量 | Grok 准确数 | 准确率 | 典型误判 |
|---|---|---|---|---|
| Bug 报告 | 230 | 212 | 92.2% | 把严重性低的日志输出异常判为使用咨询 |
| 功能请求 | 145 | 118 | 81.4% | 描述里带“报错”二字的都被归为 Bug |
| 使用咨询 | 80 | 73 | 91.3% | 部分英文长难句被归到“无效” |
| 无效/重复 | 45 | 32 | 71.1% | 未能识别出高度相似的重复 Issue |
数据很诚实:Bug 类准确率最高,因为报错日志本身就是强信号;功能请求准确率最低,因为模型对“用户情绪性表达”的过度解读很难完全消除。而这恰恰是开源项目里最需要人工判断的部分——有些功能请求虽然措辞激烈,但本身是合理的。
半自动工作流的落地形态
综合下来,没让 Grok 直接去改 GitHub 的标签,而是把它嵌到了一个 Python 脚本里,每次跑完只生成一个建议标签文件,由维护者每天早上花十分钟过一遍。脚本结构大概这样:
import requests
def classify_issue(title, body):
# 第一步:提取事实
facts_prompt = f"""你是一个开源项目的 Issue 分类助手...
标题:{title}
正文:{body}"""
facts = call_grok_api(facts_prompt)
# 第二步:基于事实分类
classify_prompt = f"""基于以下事实,分类:
{facts}"""
label = call_grok_api(classify_prompt)
return label.strip()
# 读取未打标签的 Issue
for issue in get_unlabeled_issues():
suggested = classify_issue(issue.title, issue.body)
write_suggestion(issue.number, suggested)真正节省的时间不在“分类”这一步,而在“快速了解每个 Issue 的核心内容”。以往得逐条通读,现在脚本跑完会附带一个事实摘要,扫一眼就能判断分类是否合理。阅读时间从两小时压缩到了二十分钟。
几个值得留意的边界
幻觉问题:在测试过程中,Grok 4.3 出现过一两次“编造报错信息”的情况。某个 Issue 根本没提供日志,模型的提取结果里却出现了一行根本不存在的错误信息。所以强制要求第一步的输出只基于原文,不能联想。这一步人工抽查还不能省。
隐私和合规:这里处理的是公开仓库的 Issue,数据本来就是对所有人可见的。如果是公司内部项目的 Issue 或需求文档,建议在发送给外部模型前完成脱敏,或者直接考虑本地部署方案。
不要用 AI 做价值判断:模型可以告诉你“这条 Issue 看起来是个 Bug”,但它判断不了“这个 Bug 值不值得现在修”。优先级、排期、社区影响,这些仍然是维护者的事。
回头来看,这次尝试最值得记下的不是 Grok 4.3 本身的能力,而是那个“两步式拆解”的思路:把推断和判断拆开,让模型只做它擅长的前半段,后半段交给规则和人工。这个原则放到需求分析、文档整理甚至测试用例生成上,其实也一样适用。别指望一步到位,也别把最终决定权交出去——这是花了两个下午换来的一条经验。
