简短回答是否定的,但详细回答能为你节省数小时
一次完整的费根审查需要一名主持人、一名朗读员、两到四名审查员,以及作者本人。团队以每小时125行的速度,花费两小时审查大约250行代码。这意味着一次小小的改动就要消耗八到十二人时。
大语言模型可以在不到一秒内读完250行代码。它可以执行检查清单、标记可疑模式,并在任何人打开文件之前就生成一份结构化的缺陷记录。
这并不意味着它能取代整个团队。而是说,团队不应该在大语言模型做完功课之前就开始开会。
大语言模型在费根审查中真正能做什么
费根审查有四个明确的角色。每个角色的职责与大语言模型能力之间的映射关系各不相同。
主持人负责规划审查、把关准入条件,并确保会议不跑题。大语言模型可以生成检查清单、在审查前验证测试是否通过、并根据行数估算时间。但它无法判断一屋子工程师是不是正在滑向设计争论。主持人的角色是社会性的,而大语言模型不具备社会性。
朗读员在会议中大声复述代码,迫使整个团队以理解的速度而非扫读的速度去消化逻辑。大语言模型可以总结代码,但它无法让一屋子人慢下来。朗读员的真正价值在于社会约束力。大语言模型没有这种约束力。
审查员通过对照检查清单和领域知识来发现缺陷。这是大语言模型最擅长的地方。它比任何人都更快地发现空指针解引用、资源泄漏、未处理的错误路径和差一错误。它不会疲倦,也不会因为某个枯燥的辅助函数看起来安全就跳过它。
作者负责回答问题并修复缺陷。大语言模型无法取代作者,因为它没有写这段代码,也无法验证作者的意图。
所以现实的答案不是”取代”,而是”角色替代”。大语言模型可以充当不知疲倦的预审员,在人类进入会议室之前就完成审查员角色中那些机械性的部分。
大语言模型真正有帮助的地方:准备阶段
费根审查中最重要的阶段是准备阶段。每位审查员在会议前都要单独研读材料。研究表明,准备阶段发现的缺陷约占整个流程发现缺陷的一半。如果大语言模型能大幅强化这一阶段,人类的会议就会变得更短、更犀利。
这里有一个实用的做法。向大语言模型投喂代码、一份针对你所用语言量身定制的检查清单,以及一个强制要求结构化输出的提示词。把大语言模型的输出作为人类审查员的起点,而不是替代。
提示词比模型更重要。像”帮我审一下这段代码”这样模糊的请求只会给你泛泛而谈的陈词滥调。而带有检查清单和输出格式的结构化提示词,才能给你可操作的缺陷。
下面是一个使用兼容OpenAI接口的API来运行基于大语言模型的预审的Python脚本。它读取源文件,应用费根式检查清单,并输出结构化的缺陷记录。
#!/usr/bin/env python3
"""
LLM pre-inspection for Fagan-style review.
Produces structured defect log from a checklist.
"""
import argparse
import os
from pathlib import Path
def build_prompt(code: str, filepath: str, language: str) -> str:
checklist = {
"python": [
"Missing null/None checks before dereferencing",
"Unclosed file handles or missing context managers",
"Bare except clauses that swallow exceptions",
"Mutable default arguments in function signatures",
"Race conditions in shared mutable state",
"Missing input validation on public functions",
],
"typescript": [
"Non-null assertions (e.g., !) without justification",
"Missing await on async calls",
"Any types that should be narrowed",
"Unhandled promise rejections",
"Missing input validation on public functions",
],
"rust": [
"Unwrap or expect without comment explaining invariants",
"Missing error propagation where Result is returned",
"Unsafe blocks without safety comments",
"Clone on large data structures in hot paths",
"Missing input validation on public functions",
],
}
items = checklist.get(language, checklist["python"])
checklist_text = "\n".join(f" - {item}" for item in items)
return (
"You are a Fagan inspection assistant. Review the following code "
"against the checklist. For each defect found, output a JSON object "
"with keys: line, category, severity (minor/major/critical), description. "
"If no defect is found for a checklist item, omit it. "
"Be specific about line numbers and exact variable names. "
"Do not suggest fixes. Fagan inspections only log defects, they do not solve them.\n\n"
f"File: {filepath}\n"
f"Language: {language}\n\n"
"Checklist:\n"
f"{checklist_text}\n\n"
"Code:\n```\n"
f"{code}\n"
"```\n\n"
"Output strict JSON array of defects only. No markdown, no preamble."
)
def inspect_file(filepath: str, api_key: str, base_url: str) -> list:
"""Run LLM pre-inspection and return parsed defect list."""
from openai import OpenAI
path = Path(filepath)
code = path.read_text()
# Infer language from extension
ext_map = {
".py": "python",
".ts": "typescript",
".tsx": "typescript",
".rs": "rust",
}
language = ext_map.get(path.suffix, "python")
client = OpenAI(api_key=api_key, base_url=base_url)
response = client.chat.completions.create(
model=os.environ.get("INSPECTION_MODEL", "gpt-4.1-mini"),
messages=[
{"role": "system", "content": "You are a precise code inspection tool."},
{"role": "user", "content": build_prompt(code, filepath, language)},
],
temperature=0.2,
max_tokens=2048,
)
raw = response.choices[0].message.content.strip()
# Some models wrap JSON in markdown fences. Strip them.
if raw.startswith("```json"):
raw = raw[7:]
if raw.startswith("```"):
raw = raw[3:]
if raw.endswith("```"):
raw = raw[:-3]
raw = raw.strip()
import json
try:
defects = json.loads(raw)
if not isinstance(defects, list):
return []
return defects
except json.JSONDecodeError:
print("Warning: LLM returned non-JSON output:")
print(raw[:500])
return []
def main():
parser = argparse.ArgumentParser(description="LLM pre-inspection for Fagan review")
parser.add_argument("files", nargs="+", help="Source files to pre-inspect")
parser.add_argument("--api-key", default=os.environ.get("OPENAI_API_KEY"))
parser.add_argument(
"--base-url",
default=os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1"),
)
args = parser.parse_args()
if not args.api_key:
raise SystemExit("Error: set OPENAI_API_KEY or pass --api-key")
all_defects = []
for f in args.files:
defects = inspect_file(f, args.api_key, args.base_url)
all_defects.extend({"file": f, **d} for d in defects)
if not all_defects:
print("No defects flagged by LLM pre-inspection.")
return
print(f"LLM pre-inspection found {len(all_defects)} defect(s):\n")
for d in all_defects:
print(
f"[{d['severity'].upper()}] {d['file']}:{d.get('line', '?')} "
f"({d['category']}) {d['description']}"
)
if __name__ == "__main__":
main()
用 pip install openai 安装 OpenAI SDK,设置好 API 密钥,然后运行 python inspect.py src/auth.py。该脚本会输出一份结构化缺陷记录,人类审查员可以把它当作起始检查清单。
这不是审查本身。这只是准备工作。发现的缺陷仍然需要人类判断。
大语言模型会漏掉什么:真正值钱的缺陷
最昂贵的缺陷不是语法错误,而是错误的假设。
大语言模型能发现缺少的空指针检查。但它发现不了:空指针的情况本不该发生,因为上游服务保证了该字段的存在;真正的 bug 是团队三周前改了契约,却忘了更新下游代码。
大语言模型会标记未处理的异常。但它注意不到:异常处理缺失是因为作者假设数据库事务会自动回滚,而这个假设在团队使用的特定隔离级别下并不成立。
这些都是意图层面的缺陷。它们需要领域知识、历史背景,以及追问”作者默认了哪些并不成立的事情”的能力。大语言模型无法接触到团队那些未文档化的假设。它没有上季度架构决策的记忆。它也无法对着需求文档看出代码实现的是错误的需求。
费根审查正是为了捕捉这类缺陷而设计的。人类审查员带来不同的心智模型和不同的上下文。当他们对代码应该做什么产生分歧时,他们假设之间的缝隙就是真正 bug 藏身的地方。
大语言模型只有一种心智模型,而且它是在公开代码上训练的,不是在你的代码库上。
真正的权衡:覆盖度 vs. 理解深度
大语言模型预审给你的是覆盖度。它逐行阅读、逐个函数检查,永远不会被 Slack 通知分散注意力。它是完美的狭义审查员。
人类审查给你的是理解深度。它把代码连接到规格说明,把规格说明连接到数据库 Schema,再把 Schema 连接到上个 Sprint 计划会上变更的业务规则。这是发现代码之外缺陷的唯一途径。
这个权衡不是人 vs. 机器,而是深 vs. 广。
如果你用大语言模型取代审查团队,你会发现更多语法层面的缺陷,同时漏掉更多意图层面的缺陷。净结果取决于哪种 bug 正在拖垮你。如果你的生产事故大多是空指针解引用和资源泄漏,大语言模型能帮上忙。如果你的事故大多是错误业务逻辑和遗漏的边界情况,大语言模型只会给你虚假的安全感。
实践中如何运行混合审查
这里有一个实用的工作流程:让大语言模型做它擅长的事,同时把只有人类才能做的事留给人类团队。
会前,用大语言模型预审脚本跑一遍代码。把输出连同原始代码一起发给每位人类审查员。要求他们在个人准备阶段逐一验证或驳回大语言模型的每条发现。这会迫使他们去审视那些本来可能一扫而过的行。
会议中,朗读员仍然大声复述代码。审查员仍然提出问题。但现在他们是从一份已经过分类整理的机械缺陷清单出发。会议时间可以从两小时缩短到九十分钟,或者团队可以在同样的时间窗口内审查更多代码。
主持人增加一项新职责:追踪大语言模型的准确率。记录大语言模型标记的缺陷中有多少是真的、有多少是误报、以及有多少人类独有的缺陷被大语言模型漏掉了。经过三四次审查,你就会知道检查清单提示词是否需要调优。
这正是美国国家航空航天局在1990年代试验工具辅助审查时采用的流程。自动检查器找到了简单的缺陷,把难的留给人类。人类表现更好,因为他们没有因为找出简单缺陷而精神疲惫。
结论
大语言模型无法取代完整的审查团队,因为审查不仅仅是读代码。它是一个结构化的社会过程,旨在揭示作者假设与代码实际行为之间的落差。
大语言模型能做到的是,通过卸除机械性负担来提升人类团队的效率。它可以扮演第五个角色:在人类到来之前就已经打扫好战场的不知疲倦的预审员。
如果你因为审查太贵而跳过它,大语言模型不会让它变成免费。但它可以让审查变短。这往往就够了。
常见问题
什么是费根审查?
一种由迈克尔·费根于1976年在IBM发明的六阶段结构化评审流程。它使用明确定义的角色(主持人、朗读员、审查员、作者)、强制的个人准备以及限时会议,在测试之前发现缺陷。它始终能报告60%到90%的缺陷清除率。
大语言模型能取代人类代码审查员吗?
对于那些最重要的缺陷,不能。大语言模型能捕获机械性问题,如缺少空指针检查和资源泄漏。但它会漏掉意图层面的缺陷,如对上游契约的错误假设、缺失的业务逻辑、代码与需求之间的不匹配。
如何将大语言模型整合进费根审查?
在准备阶段使用大语言模型。针对检查清单运行它,在会前把输出交给人类审查员,并要求他们验证每条发现。这能缩短会议时间、提升人类专注度,同时不剥夺人类判断。
什么样的大语言模型检查清单提示词才有效?
具体性。泛泛的提示词只会产生泛泛的输出。有效的提示词会点名精确的缺陷类别,要求结构化JSON输出,禁止提出修复方案,并要求给出精确的行号和变量名。检查清单应当匹配你的语言和团队最常漏掉的缺陷。
挑一个文件试试
选一个在上个月引发过生产事故的文件。写一份包含五种具体缺陷类型的检查清单,这些缺陷类型是你的团队关心的。用上面的脚本配合这份检查清单跑一遍。把输出交给两位没有写过这个文件的工程师。
比较大语言模型的发现与人类的发现。统计重叠部分,统计各自漏掉的部分。那个差距就是你的答案。