同一支 PR 送進 LinkedIn 的審查系統後,會同時被好幾組彼此不知情的模型看過一遍——兩組以上不約而同抓到同一段程式碼,直接算高信心;只有一組抓到,也不會被丟掉,而是回頭再驗證一次。
同一支 PR,LinkedIn 派好幾組 AI 分頭審
LinkedIn 對「用 AI 審查一支 PR」的做法,是同時派出好幾組彼此獨立的 model-and-harness 組合各自審查、再讓重疊的發現互相印證。一個典型的一週裡,這套系統審了 79,000 多次、涵蓋 40,000 多支 PR,任務完成率 99.1%,建議的整體採用率是 63.9%。對正在評估要不要導入 AI code review 的團隊來說,這幾個數字本身沒什麼參考價值——真正值得拆解的是背後那套「多組獨立審查、靠重疊判斷信心」的架構,跟只挑一個模型接上 CI 相比,差在哪裡、代價又是什麼。這篇要拆的是這套系統怎麼組出來、去重與交叉驗證怎麼判斷一個發現值不值得留下,客製化規則怎麼分層,以及那些漂亮數字背後自己承認的量測邊界。
同一份 diff,好幾組模型各自看一遍
這套系統的核心是一個 orchestrator:一支 PR 進來,它同時派出好幾個獨立的審查 subagent 去看同一份 diff,收集回來的發現做去重與交叉驗證。LinkedIn 把每個 subagent 定義成「a distinct model-and-harness pairing wrapped in its own context-retrieval, prompting, and output-filtering logic」——模型本身、抓取上下文的方式、輸出過濾的邏輯,都各自獨立成一套。「harness」在這裡指的是包住模型的那一整圈工程:怎麼把 repo 的相關檔案抓進 context、怎麼組 prompt、模型吐回來的原始輸出又怎麼過濾成一則可讀的 review comment。這些 subagent 彼此看不到對方的輸出,審查過程是真正平行、互不干擾的——跟「同一個模型跑兩輪、取交集」不同,這裡引入的是好幾種真正獨立的判斷來源。
為什麼要這麼麻煩?LinkedIn 的理由很直接:「a single AI model and harness carries inherent biases from its training data, leading to consistent blind spots」——單一模型跟它的執行環境綁在一起用,盲點是固定的、可預期的,漏掉的那一類問題永遠漏掉,加開幾次審查也不會多看到什麼。解法不是換一個更強的模型,而是換一批訓練背景不同的模型一起看:「Different pairings bring different training backgrounds, architectures, and reasoning styles, chosen for complementary trade-offs between precision and recall rather than redundant overlap」。重點在「complementary」——挑選這幾組 pairing 時,目標是找訓練背景不同、強弱項也彼此互補的模型搭配起來。precision 與 recall 本來就是一組取捨,一個 pairing 偏向少報但準、另一個偏向多報但雜,讓兩種取捨並存,才有東西可以互相印證。
播放看四組模型獨立掃描同一份 diff · 10 行程式碼
模擬示意,非 LinkedIn 實際遙測:四組獨立 model-and-harness 各自掃過同一份十行 diff,…
四組獨立模型各自掃過同一份 diff,抓到同一行的模型數只要達到兩個以上,那一行就直接判定為高信心;只有一組模型抓到的發現則被送回原模型再核一次,核不過就丟掉。
下面這個小工具用模擬示意四組模型各自掃過同一份十行的 diff:同一條時間軸上,四種顏色的標記各自落在它們覺得有問題的行上,重疊出現的那一行會先轉為高信心,單獨出現的則被送去覆核。四組模型跑完全部需要的時間,取決於最慢的那一組——這是平行架構天生要付的代價,跟單一模型比起來,端到端的延遲不會是零成本,多派一組模型換來的是判斷來源變多。重疊本身怎麼變成一個判斷依據,是下一段要談的機制。
兩個獨立模型看到同一件事,才算數
多組模型各自審完之後,真正的工作才開始:把重複的發現去重、把可疑的發現交叉驗證。LinkedIn 的說法是:「When two independently reasoning models flag the same code pattern, that convergence carries information」——兩個彼此不知道對方存在的模型,各自獨立推理出同一個結論,這件事本身就是訊號。系統把這種重疊直接當成高信心發現處理,不用再等第三方確認。反過來說,架構上可以推論:收斂機制只被拿來過濾「真的有問題」的訊號,不會反過來被當成「程式碼一定沒事」的證明——畢竟每一組模型各自的召回率都不是百分之百,沒被標記,不代表那裡真的乾淨。
只被一組模型抓到的發現不會被直接丟棄,也不會被直接放行——系統會把它丟回第一個模型驗證,回頭問一次原本的模型「你確定嗎」,通過這一輪覆核才進入最終輸出。這個設計把「單一模型的判斷」跟「單一模型的最終輸出」分開處理:一個模型第一次給出的答案不算數,它得在被要求重新檢視之後仍然堅持,才算通過。交叉驗證同時也在做另一件事:過濾掉「suggestions that are cosmetic, already addressed in a subsequent commit, or inconsistent with the repo's established patterns」——裝飾性的建議、已經在後續 commit 被處理掉的問題、跟 repo 既有慣例衝突的意見,都在這一關被擋下來,不會流到人類審查者手上。對寫程式的人來說,這一關的實際效果是少收到「這裡可以改成更 idiomatic 的寫法」這種可有可無的留言,留下的多半是重疊出現、或是覆核後仍然成立的發現。
點按鈕看兩條獨立評估曲線疊合 · 疊合處判定為高信心
切換單一模型/多模型審查 · 同一段程式碼的結果對照
工程師實際會看到的變化,是一支 PR 底下可能同時出現好幾則留言,而不是一個模型一次講完。這一段架構沒有明講、但可以直接從機制推出來的是:如果好幾則留言講的是同一件事,通常代表這件事的信心比較高;只出現一次的留言,代表它已經通過覆核才被放行——這是讀留言時能用的線索,LinkedIn 原文沒有這樣寫,是從架構推導出來的合理判斷。
這套去重與驗證的邏輯,代價是算力:同一份 PR 要跑好幾組模型,單一發現還要多跑一輪覆核。LinkedIn 顯然判斷這個代價值得付——單一模型的盲點是系統性的,加開一組訓練背景不同的模型,換來的是「重疊」這個可以外部驗證的訊號。這也是為什麼「重疊」被拿來當判斷依據,而不是「信心分數」這種模型自己回報的數字:模型自己說「我有 90% 把握」是它自己的判斷,兩個獨立模型不約而同做出同一個判斷,才是外部可驗證的訊號。這個選擇也解釋了為什麼前面要強調 pairing 之間必須「complementary」而不是「redundant」:如果四組模型訓練背景相近、盲點也相近,重疊出現的機率確實會提高,但提高的理由是大家一起漏看或一起誤判——挑選 pairing 這一步做得好不好,直接決定「重疊」這個訊號到底可不可信。
規則分三層:全域、repo、情境
多組模型互相印證,解決的是「單一模型會漏東西」的問題;但就算所有模型都判斷正確,它們給出的標準也未必是這個團隊要的標準。LinkedIn 的說法很直白:「no model, no matter how capable, can replace the encoded knowledge of your team's specific codebase」——模型再強,也不知道這個團隊三年前為什麼決定不用某個 pattern、這個 repo 的命名慣例為什麼跟隔壁團隊不一樣。這句話等於承認一件事:前面兩段講的多模型收斂機制,處理的是「這段程式碼有沒有問題」,不處理「這個團隊認為什麼才算問題」,後者得靠另一套機制補上。
解法是把客製化拆成三層:全域/組織層級的規則,套用在所有 repo 上;Repository 層級的規則,處理個別程式庫的架構慣例;還有一個 Custom Rules subagent,直接整合進 orchestration 層,跟模型審查者並列跑,處理需要情境判斷的規則。三層各自負責不同範圍,理由是:「a single rule file can't encode organization-wide policy or repository-level architectural rules, nor can it use case-specific guidance independently」——想用一份規則檔案同時涵蓋組織政策、repo 架構、還有臨場判斷,結果通常是規則寫得又籠統又難維護,改一次全部得重新確認有沒有互相打架。分成三層之後,改組織政策不用動到 repo 規則,換一個 repo 也不用重寫全域規則,各自的維護範圍縮小了。三層規則彼此衝突時最後聽誰的,LinkedIn 沒有進一步說明——這是這篇資料沒有覆蓋到的地方,是留白:三層各自負責的範圍雖然清楚,界線重疊時該由哪一層拍板,文章沒有寫明。
三層規則不是互相取代的關係,而是疊加:組織政策一直都在,repo 規則在它之上加一層,情境判斷再疊上去。拿掉任一層,底下那層的判斷仍然成立,只是少了上面那層的補充——這跟前面的多模型架構是同一種設計邏輯:讓不同來源的判斷疊加起來。對想導入類似系統的團隊,這裡其實是一個一開始就要想清楚的設計決定:規則要不要分層、分幾層,直接決定後面要不要一直重寫同一份規則檔案。如果團隊手上已經有一份散落在 wiki、Slack 討論串、資深工程師腦子裡的 code review 慣例,這三層架構等於提供了一個現成的分類方式:哪些其實是公司層級的政策、哪些是這個 repo 特有的習慣、哪些只在特定情境下才成立——先把這幾類分開,才有辦法決定接下來要不要真的把規則餵給一套多模型審查系統。
63.9% 採用率背後的 90.1%
把架構說完,回到數字。LinkedIn 給的規模數字是:一個典型的一週裡,這套系統審了 79,000 多次、涵蓋 40,000 多支 PR,任務完成率 99.1%;建議的整體採用率是 63.9%。運作速度上,PR 事件進來後「in under 5 seconds」就會排入佇列,審查在「~90 seconds」內啟動,大多數審查「end-to-end in under 10 minutes」完成——這個時間拿來跟一般團隊等人類第一次審查的時間相比,差距明顯;99.1% 跟 63.9% 這兩個數字問的其實是不同層次的問題:完成率問的是系統有沒有順利跑完整套審查流程、產出建議,跟建議本身好不好無關;採用率問的是產出來的建議裡有多少真的被寫進合併的程式碼。一套系統可以完成率很高、但採用率很低——代表它很穩定地跑完流程,只是給出來的建議大多不被工程師買單;反過來,完成率低但採用率高,代表它偶爾跑不完,跑完的部分品質倒是不差。LinkedIn 兩個數字都拿出來,等於同時交代了「可靠度」跟「品質」兩件事。單一 worker host 可以同時審查最多 12 支 PR。合理的推測是,12 這個數字反映的是單一 host 的資源上限——同時開好幾組模型審查,對外部模型 API 的併發連線數、CPU 與記憶體都會被同時吃掉,這是水平擴充可以解決的問題,加開 host 就能墊高總處理量;但 LinkedIn 沒有說明實際瓶頸卡在哪一項資源,這一段是推測,不是原文的說法。99.1% 的完成率換句話說也代表有 0.9% 沒有完成,LinkedIn 沒有進一步說明那一小部分審查中間發生了什麼事,也沒有交代這 0.9% 是穩定發生還是偶發個案,這是這篇能找到的資料邊界。同樣地,單一 host 最多同時審 12 支 PR 這個數字,究竟是刻意保留餘裕的保守設定、還是已經逼近硬體極限,LinkedIn 也沒有交代——對正在評估類似架構的團隊來說,這正是規劃容量時該先問清楚、而不是照抄一個數字的地方。
播放看排隊、啟動、執行三段時間的真實比例 · 5 秒 / 90 秒 / 10 分鐘
但採用率這個數字本身也有它的量測邊界。LinkedIn 是拿「1727 PRs and 5230 rigorously sampled comments for a 7-day window」去算,而不是全量統計——這是一個獨立抽樣出來的樣本,跟前面 79,000 多次審查、40,000 多支 PR 的全量規模不是同一個統計口徑,兩個數字談的是不同層次的東西,不能直接放在一起比。這批抽樣留言裡,只有 90.1% 屬於「high-confidence evaluation」——有清楚證據可以判定一條建議後來真的被寫進合併程式碼的比例是九成,另外約一成屬於中低信心判定。LinkedIn 自己的講法是:「90.1% high-confidence evaluation rate validates both our methodology and the quality of suggestions themselves」——把這句話反過來讀,等於承認量測方法本身有一成的盲區:63.9% 這個數字,站得住腳的把握主要來自那九成可判定的樣本。
這一段量測邊界不是要否定 63.9% 這個數字,而是提醒:一套把「重疊即高信心」當成核心邏輯的系統,量測自己成效時同樣得面對「多少判斷有清楚證據、多少沒有」這個一模一樣的問題。信心分數這件事,套在審查建議上是設計,套在自己的成效數字上,一樣得老實承認邊界在哪裡。對照著看,整篇拆下來其實是同一個原則被套用了三次:模型審查靠重疊建立信心、規則框架靠分層建立範圍、連量測方法自己也靠「多少樣本有清楚證據」畫出可信的邊界,不會把一個平均數字當成對全部案例都成立的答案。
這套架構解鎖了什麼:一份 PR 不必再賭在單一模型的判斷上——好幾組獨立審查者疊出的重疊訊號,加上分層的規則框架,讓自動建議在幾分鐘內就能帶著較高的可信度,送到人類手上。