簡短回答是否定的,但詳細回答能為你節省數小時
一次完整的費根審查需要一名主持人、一名朗讀員、兩到四名審查員,以及作者本人。團隊以每小時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 是團隊三週前改了契約,卻忘了更新下游程式碼。
大型語言模型會標記未處理的例外。但它注意不到:例外處理缺失是因為作者假設資料庫 transaction會自動回復,而這個假設在團隊使用的特定隔離層級下並不成立。
這些都是意圖層面的缺陷。它們需要領域知識、歷史背景,以及追問「作者預設了哪些並不成立的事情」的能力。大型語言模型無法接觸到團隊那些未文件化的假設。它沒有上季度架構決策的記憶。它也無法對著需求文件看出程式碼實作的是錯誤的需求。
費根審查正是為了捕捉這類缺陷而設計的。人類審查員帶來不同的心智模型和不同的上下文。當他們對程式碼應該做什麼產生分歧時,他們假設之間的縫隙就是真正 bug 藏身的地方。
大型語言模型只有一種心智模型,而且它是在公開程式碼上訓練的,不是在你的程式碼庫上。
真正的權衡:覆蓋度 vs. 理解深度
大型語言模型預審給你的是覆蓋度。它逐行閱讀、逐個函式檢查,永遠不會被 Slack 通知分散注意力。它是完美的狹義審查員。
人類審查給你的是理解深度。它把程式碼連接到規格說明,把規格說明連接到資料庫 Schema,再把 Schema 連接到上個 Sprint 計畫會上變更的業務規則。這是發現程式碼之外缺陷的唯一途徑。
這個權衡不是人 vs. 機器,而是深 vs. 廣。
如果你用大型語言模型取代審查團隊,你會發現更多語法層面的缺陷,同時漏掉更多意圖層面的缺陷。淨結果取決於哪種 bug 正在拖垮你。如果你的生產事故大多是空指標解引用和資源洩漏,大型語言模型能幫上忙。如果你的事故大多是錯誤業務邏輯和遺漏的邊界情況,大型語言模型只會給你虛假的安全感。
實務中如何執行混合審查
這裡有一個實用的工作流程:讓大型語言模型做它擅長的事,同時把只有人類才能做的事留給人類團隊。
會前,用大型語言模型預審腳本跑一遍程式碼。把輸出連同原始程式碼一起發給每位人類審查員。要求他們在個人準備階段逐一驗證或駁回大型語言模型的每條發現。這會迫使他們去審視那些本來可能一掃而過的行。
會議中,朗讀員仍然大聲複述程式碼。審查員仍然提出問題。但現在他們是從一份已經過分類整理的機械缺陷清單出發。會議時間可以從兩小時縮短到九十分鐘,或者團隊可以在同樣的時間窗口內審查更多程式碼。
主持人增加一項新職責:追蹤大型語言模型的準確率。記錄大型語言模型標記的缺陷中有多少是真的、有多少是誤報、以及有多少人類獨有的缺陷被大型語言模型漏掉了。經過三四次審查,你就會知道檢查清單提示詞是否需要調校。
這正是美國國家航空暨太空總署在1990年代試驗工具輔助審查時採用的流程。自動檢查器找到了簡單的缺陷,把難的留給人類。人類表現更好,因為他們沒有因為找出簡單缺陷而精神疲憊。
結論
大型語言模型無法取代完整的審查團隊,因為審查不僅僅是讀程式碼。它是一個結構化的社會過程,旨在揭示作者假設與程式碼實際行為之間的落差。
大型語言模型能做到的是,透過卸除機械性負擔來提升人類團隊的效率。它可以扮演第五個角色:在人類到來之前就已經打掃好戰場的不知疲倦的預審員。
如果你因為審查太貴而跳過它,大型語言模型不會讓它變成免費。但它可以讓審查變短。這往往就夠了。
常見問題
什麼是費根審查?
一種由麥可·費根於1976年在IBM發明的六階段結構化評審流程。它使用明確定義的角色(主持人、朗讀員、審查員、作者)、強制的個人準備以及限時會議,在測試之前發現缺陷。它始終能回報60%到90%的缺陷清除率。
大型語言模型能取代人類程式碼審查員嗎?
對於那些最重要的缺陷,不能。大型語言模型能捕獲機械性問題,如缺少空指標檢查和資源洩漏。但它會漏掉意圖層面的缺陷,如對上游契約的錯誤假設、缺失的業務邏輯、程式碼與需求之間的不匹配。
如何將大型語言模型整合進費根審查?
在準備階段使用大型語言模型。針對檢查清單執行它,在會前把輸出交給人類審查員,並要求他們驗證每條發現。這能縮短會議時間、提升人類專注度,同時不剝奪人類判斷。
什麼樣的大型語言模型檢查清單提示詞才有效?
具體性。泛泛的提示詞只會產生泛泛的輸出。有效的提示詞會點名精確的缺陷類別,要求結構化JSON輸出,禁止提出修復方案,並要求給出精確的行號和變數名。檢查清單應當匹配你的語言和團隊最常漏掉的缺陷。
挑一個檔案試試
選一個在上個月引發過生產事故的檔案。寫一份包含五種具體缺陷類型的檢查清單,這些缺陷類型是你的團隊關心的。用上面的腳本配合這份檢查清單跑一遍。把輸出交給兩位沒有寫過這個檔案的工程師。
比較大型語言模型的發現與人類的發現。統計重疊部分,統計各自漏掉的部分。那個差距就是你的答案。