「跑得起來」跟「真的幹完活」是四件事
同一個 API 相容的 endpoint,在工具呼叫、回合控制、context 和快取上都不一樣。一份 4,165 個回合的單人經驗報告,把「模型有回應」「工具真的執行」「程式碼通過檢查」拆成四層,也量到委派給本地 Nemotron 工人時,每次驗證成功反而貴 8.6 倍。文末有一張能直接拿去用的驗收清單。
數字全部來自 arXiv 2610.34241v1。那是作者自己的工程紀錄,不是受控實驗;「我認為」的部分我會標出來。
先講一個畫面
「模型有回應了。」這是最容易騙過驗收的一句話。API 回 200、文字讀得懂,但工具可能根本沒被呼叫出去。
2026 年 7 月,Vaibhav Jain 把幾台筆電串起來,跑一個單機放不下的模型。聊天可以,當 coding agent 用卻慢到不能用;每次重啟,32B 的權重要在 Wi-Fi 上傳五分鐘(8.7 GB)。最後他收掉分散式,改成單機。
這件事的重點不是「分散式不行」。是他從那時候開始發現:模型跑得起來,跟它能不能幫你幹完活,是四件不同的事。
這篇要拆的就是那四層,還有驗收單上通常漏掉的那一欄。
一個模型權重檔(checkpoint)載得進去,丟一句話會回話,然後呢?你叫它去看一個檔案、呼叫一個工具、維持一段長 session、守住一個 repo 的介面約定。這些它可能全部做不到,而你的 API 還是回你 200。
問題出在「相容」這兩個字。同一個號稱相容的 endpoint,後面可能是完全不同的東西。工具呼叫的格式、一輪對話怎麼結束、context 怎麼被改寫、快取有沒有重用,四件事都可以不一樣。
只要有一件不一樣,你在 A 模型上驗過的流程,換到 B 模型就會壞。而且通常不會給你錯誤訊息。
這篇是一份單人經驗報告的導讀。論文是 arXiv 2610.34241,作者是獨立研究者,紀錄的時間橫跨 2026 年 7 月到 10 月,跑過 vLLM、SGLang、llama.cpp 和 MLX。
它做的事很樸素:把「能跑」拆成四層,再用 45 場有隱藏檢查的實驗,告訴你第四層要怎麼驗、代價在哪裡。
四層,不是一個開關
作者把「模型有沒有用」拆成四層:
- 服務得起來:checkpoint 載得進去,送一句話有東西回來。
- 文字連貫:回得出人話,讀得懂,能回答問題。
- 工具被解析並執行:它說「我要讀這個檔案」,client 真的收到,真的去讀。
- 通過獨立行為檢查:產出的程式碼,在另一個不屬於它的檢查器裡,真的把事做對。
論文裡有一句話是整篇的骨架:
一個 endpoint 可以滿足前三層,卻在第四層全錯。而且如果第三層過不了,你根本量不到第四層。
(這是作者的話,我照原意翻。)
| 層級 | 你要問的問題 | 通過之後,你還不知道什麼 |
|---|---|---|
| 1 服務 | 載得進去、有回應嗎? | 回的是不是人話 |
| 2 連貫 | 讀得懂、講得出道理嗎? | 它會不會真的動手 |
| 3 工具 | 工具呼叫被解析、被執行了嗎? | 執行完的結果對不對 |
| 4 驗證 | 產出通過獨立的行為檢查了嗎? | 這一層過了,才叫「幹完活」 |
這四層不是「程度」的差別,是四道不同的門。第一層過了,不代表第二層;第二層過了,也不代表它會動手。很多人停在第二層就以為快成功了,因為它講得有模有樣。
你平常在驗收單上看到的三個層級,大概是這樣對應。「模型有回應」是第 1 層加第 2 層;「程式跑起來」是第 3 層;「測試通過」是第 4 層。
但「測試通過」要看是誰的測試。廠商自己寫的測試過了,你可能還停在第 3 層;第 4 層的檢查,得是別人寫的、在驗收前就凍結的。
我把第 1、2 層拆開,是因為它們的失敗長得很像、原因完全不同。一個是服務沒通;一個是通了,但只會講話。
(如圖 1)
同一個 API,不同的協議
作者把 Claude Code 接上自己寫的 gateway,後面接不同的模型。他原本想的是「換一個 endpoint 而已」,實際上的感覺,比較像換一個工作習慣完全不同的人。
有的模型照工具契約做。有的用文字描述它「打算執行這個指令」。有的會把它覺得不順的介面改掉,例如把一個本來穩定的函式簽名重寫成它喜歡的樣子。這些不是模型笨,是它跟你的 client 對「工具」這件事的理解不一樣。
他統計了 gateway 上的真實請求。Gemma 4 有 492 個帶工具的請求,其中 294 個解析出 tool_calls。144 個以 stop 結束、沒有 tool call;還有 54 個沒有存到解析結果。
那個 144 不能全部算失敗。正常收尾也會是 stop,沒有 tool call 可能只是任務做完了。這是本文的第一個陷阱:「沒有工具呼叫」本身不是錯誤訊號,要看當下該不該有。
還有更直接的。Gemma 4 的存檔輸出裡有 8 個 <|tool_call> 前綴的畸形呼叫,解析器完全沒接住。GPT-OSS-120B 走 SGLang(一種推論伺服器)時,tool_choice=required 會跟它自己的工具格式(Harmony)打架,得降成 auto。工具回合的輸出上限也要放寬,不然 reasoning 和 tool JSON 會一起被截斷。
回合控制是另一半。對話的識別碼(session identifier)不見、工具呼叫繞圈、thinking channel 對不上。任何一個都會讓對話「看起來還在跑,其實已經迷路」。
最值得記下來的是這一段:API 格式(schema)檢查全部通過,接上真的 Claude Code 之後還是壞。
一次是 client 的工作目錄沒有被放進 request,模型只能猜路徑。一次是 streaming 的工具參數被當成「替換」而不是「附加」,參數被切斷,模型收到一個殘缺的呼叫。
這兩個都不會出現在單元測試裡。它們要你真的把 client 接上去,跑一次完整流程才會出現。
作者的診斷問題很簡單:工具失敗的時候,是模型不會用,還是中間某個環節把呼叫弄丟了?
如果是後者,就修在源頭:模型的 template、parser 規則、serve flag、request 翻譯。而不是在 gateway 上不斷補丁。他後來的做法是把 gateway 縮成薄的翻譯層,只做協議與安全檢查。上游失敗就往外傳,不要讓一個失敗的 stream 看起來像正常結束。
「能被設定」不等於「真的跑起來、被評測過」。這句話對採購很有用:供應商說「支援」,通常只代表它能被設定。
對話看起來連續,其實中間斷了
第三層過了,還有一個更隱形的問題:對話。
對你來說,那是一段連續的對話。對 runtime 來說,它是三樣東西:token 前綴(對話開頭的固定內容)、KV cache(算過的注意力狀態)、執行 slot。你看到的「連續」,它不一定看得到。
作者留下 4,165 個 gateway 回合、623 個除錯工作的紀錄。其中 85 筆是冷前綴:完全沒有重用,30,000 到 36,000 個 input token。280 筆是高重用:至少 90% 重用、少於 2,000 個新 token。
首字延遲的中位數:冷前綴 69.4 秒,高重用 2.8 秒。
差了約 25 倍。
但這裡要很小心。作者自己標了「觀察性資料」:兩組工作的組成不同、不是隨機分配、沒有配對。所以不能寫成「快取讓速度快 25 倍」。能說的是:前綴有沒有被重用,跟你的體感差距很大,而且大到不像是雜訊。
(如圖 2)
機制很樸素。推論後端可以重用「完全相同的 token 前綴」的 KV 狀態。所以只要前綴變了,整段 context 就要重算一次 prefill(把前綴重新算過)。哪怕只是前面多一個時間戳、換一個 system banner、工具定義的順序不同、JSON 序列化方式不一樣。
你改的是一個 banner;你付的是整段 context。
還有一種更冤的:旁支請求。coding agent 的流量不是只有主對話,還有生成標題、權限確認這類小請求。如果後端只有一個可重用的執行 slot,一個旁支請求就可能把主對話的駐留狀態擠掉。
他的紀錄裡,65 個被歸類為 auxiliary 的請求,有 44 個沒有快取重用。在高重用的紀錄中,auxiliary 的首字延遲中位數是 12.2 秒(13 筆),主請求是 2.7 秒(267 筆)。
長對話超過某個長度時,系統會把它壓成摘要(compaction)。這裡也有類似的假象:他刻意把壓縮門檻調低,在 12 次測試裡,子代理壓縮觸發了 6 次。這 6 次任務全部沒有完成,而且其中一筆還被標成 PASS。
「壓縮發生了」不是「工作完成了」。這兩件事在 log 裡長得很像。
所以他把 session 連續性當成應用的責任,而不是後端的參數:
- 訊息序列盡量 append-only,除非真的需要改前面的內容。
- 已經送出的工具訊息,不要為了美觀重新序列化。
- streaming 的 tool JSON 和最後的完整版本要一致。
- 每回合的 metadata 不要動到被凍結的 system 前綴。
- 保住 session affinity(下一回合要回到同一個執行位置)。穩定的 prompt 不夠,slot 換了就沒有那份快取。
快取不是後端參數,是應用的紀律。
第四層才算驗收
接下來是這篇論文真正做實驗的地方。當部署、協議、session 都處理到可以跑範圍明確的任務之後,問題才真正出現。一個開源的小模型,能不能交出通過檢查的程式碼?
設計是這樣:五類 TypeScript 任務,報價、按比例分攤、客戶、拆分、零件;每類每種跑三次,總共 45 場。三種條件是:直接寫;優化委派(父層只寫規格、審查並套用工人的產出);可分批的委派。最後一種允許父層把工作拆成連續幾包,但只有少數場次真的拆。
父層(負責規劃與審查的那一層)固定是 Claude Code 加 Claude Opus 5.5。工人(被委派實作的那顆模型)是量化過的 Qwen3-Coder 30B-A3B。每一場都用任務專屬的隱藏行為檢查判定,不看 agent 自己說「我完成了」。
結果:直接寫 15/15;優化委派 12/15;可分批的委派 14/15。
這三個數字不能排名。每一格只有三次,信賴區間是重疊的;作者也明說,這些資料不足以建立一般的成功率差異。能說的是:工人真的交得出東西。30 場委派裡,26 場驗證通過,而且都保留了工人寫的程式碼。但不是每次。
另外,那 14/15 不是「批次比較好」的證據。15 場裡只有 5 場真的用到批次呼叫,其餘是單次委派。論文自己說這是「批次標記的適應式策略」,不是批次與非批次的對照。
第二組更嚴格。15 個任務,各跑三次,直接與委派各 45 場。工人產出的檔案要先通過一份固定的介面契約,才能進父層審查。
直接寫 45/45。委派給 Nemotron Cascade 2 工人 12/45,其中 11 場是工人真的替換成功,1 場是父層改寫後才通過。Qwen3-Coder 工人 0/45。
這個 45/45 也要保留一點判斷空間。題目是為這份研究準備的,而且只有五類、每類三題;論文沒有做難度分層。
| 實驗 | 直接寫 | 委派給工人 |
|---|---|---|
| 45 場試驗 | 15/15 | Qwen3-Coder 12/15(優化委派)、14/15(可分批) |
| 第二組(15 任務 × 3) | 45/45 | Nemotron 12/45(11 場是工人替換);Qwen 0/45 |
| 第二組,中斷算失敗 | 37/45 | Nemotron 8/45 |
這裡有一個必須寫出來的細節:有 16 場因為訂閱額度用完、連模型都沒有呼叫就中斷,後來被替換掉。這 16 場是直接組 8 場、Nemotron 組 8 場。替換之後,直接組多拿到 8 場成功,Nemotron 組多拿到 4 場。
如果把原本中斷的 16 場算成失敗,數字會變成 37/45 與 8/45。
作者兩個都寫了。這些是排程中斷,不是推論失敗。但如果你要拿這個數字去說服人,兩種算法都要看得到。
還有一件事要誠實講。五個任務的定義和隱藏測試,是在 AI 協助下產生的。合併後的測試檔,在第一場評估前大約 39 秒才建立,而且直到最後一場跑完才第一次進版控。
作者沒有把這件事藏起來。他能主張的是:45 場存下來的任務指令和可見檢查完全一致。事後比對的分數標籤,也和評分程式(scorer)對得上。但他不能宣稱這是一個有獨立事前快照的 benchmark。
第一組的測試流程(harness)也有限制。父層的 constraints 欄位沒有被轉給工人。gateway 會丟掉重複的 system message、截斷超過 1,800 字元的訊息。41 個重建的工人 prompt 裡,有 2 個各少了約 220 字元,都在失敗的場次。
所以「工人不聽指令」這個結論要打折。有些失敗是工人不會,有些是它根本沒收到完整的指令。
那 0/45 呢?那不是「這顆模型什麼都做不到」的意思。那 45 場沒有 direct 對照組,父層接受與套用沒有重播,兩個研究的父層快取狀態也沒有重置。作者自己把它限定成「這批任務、這份契約、這個工人設定」的結果。
驗證是第四層,不是第三層的副產品。
可是帳單反過來了
直覺是這樣的:前沿模型的輸出 token 很貴,本地小模型便宜。那把實作委派給本地工人,不就省錢了嗎?
問題是委派不是免費。父層要寫規格、要看工人做了什麼、要判斷能不能用、失敗要收拾。這些都是前沿模型的 token。
作者把成本拆成:父層 context、寫規格、審查、收拾、工人。這篇只量到前沿模型那幾項。工人端的電費、硬體、時間都沒有算進去,而且他明講「未量測不能當成零」。
第一組,每次驗證成功的成本:直接寫 $0.136;委派 $0.214(優化版)與 $0.199(另一種)。大約 1.6 倍。
第二組:直接 $0.153;Nemotron 委派 $1.313。8.6 倍。
Qwen 那組的「每次成功成本」算不出來,不是零——因為它一場都沒成功。
| 實驗 | 直接寫 | 委派 | 倍數 |
|---|---|---|---|
| 45 場試驗 | $0.136 | $0.214(優化)、$0.199(另一種) | 約 1.6× |
| 第二組(Nemotron) | $0.153 | $1.313 | 8.6× |
(成本是 API 列表價換算,含失敗場次,不含本地硬體、電費、工程時間。)
還有一個小案例。有一場收費功能的任務,工人寫的東西通過了、也被套用了,但前沿成本是 $0.1856,直接寫是 $0.1293。加上本地執行時間,實際耗時 126.4 秒對 27.4 秒。
成功替換,不等於省錢。
但這不能推成「委派一定不省錢」。作者自己引了 Scrouting 這個反例。小模型先偵察 repo、前沿模型負責修,在 266 題上解了 159 題,最強單一模型是 158 題。只差一題,成本大約五分之一。
方向相反,結果就相反。他的結論只限定在自己的委派方式:前沿模型寫規格、本地工人實作。
成本定義也很窄:用 API 列表價換算,不含本地硬體、電費、工程時間。所以「8.6 倍」不是你的總帳,是前沿那一邊的帳。
便宜的是 token,貴的是協調。
驗收腳本自己也會誤殺
這篇最實用的一段,其實不是模型,是驗收。
他的工人產出要先過一份靜態契約:import、export、公開函式的參數列表都要對得上。問題是,任務的 stub 裡有些用不到的參數前面有底線(_entries),工人實作時很自然地把它拿掉(entries)。
對一般的位置參數呼叫來說,這完全不影響行為。但契約是比對「參數名的字串」,所以直接退件。父層根本沒看到,隱藏檢查也沒跑。
後來他做了一次事後診斷。36 個「只因底線被移除」而被退的 artifacts,跳過那一條規則、原封不動套到新的任務副本,再跑原本的隱藏檢查。
19 個通過,17 個還是不行。
所以那條規則不是全錯,它同時擋掉了好東西和壞東西。差別在於:擋掉壞東西是它的工作,擋掉好東西是它的副作用。而你的流程如果只有這道門,副作用就是最終結果。
| 工人 | 只因底線被退 | 原封不動通過隱藏檢查 | 仍失敗 |
|---|---|---|---|
| Qwen3-Coder | 23 | 12 | 11 |
| Nemotron | 13 | 7 | 6 |
| 合計 | 36 | 19 | 17 |
作者沒有把這 19 個算成成功。它們沒有走完父層審查與套用流程,分數維持 Qwen 0/45、Nemotron 12/45。他也沒有因此說契約要拿掉。他提的是下一個實驗:讓工人收到具體的驗證錯誤,允許一次有界的修正。
那個實驗還沒做。
在這份契約上,比模型能力更容易出錯的,是驗收設計。
它不能證明什麼
寫到這裡應該先把邊界畫出來,不然很容易變成另一種「AI 什麼都能」或「什麼都不能」。
- 這是單人的回溯性經驗報告,不是受控實驗。工作負載隨工程進展變動。
- 樣本小:五類任務、每格三次;單一父層;單一工人設定。
- 成本只算前沿模型、用列表價換算。
- 原始紀錄沒有公開,你沒辦法自己驗算。
- 作者明說:研究沒有合併,不替模型或執行環境排名。
所以這篇能給你的不是「哪顆模型比較好」,是一張驗收框架。我認為,這份報告最有價值的地方不是那些數字,是它把「完成」拆成可以逐層檢查的東西。
這是一份可檢查的經驗,不是一張排行榜。
明天就能用的檢查表
作者在最後整理了五條實務規則。我把它們改寫成可以直接放進 PoC 文件的形式:
- 在任務邊界定義成功。 不要用「有沒有回應」驗收,用「產出有沒有通過一個不屬於它的檢查」驗收。而且要用真的 client 跑,不是用自己寫的 API 測試腳本。
- 把部署當成一份 recipe,不是一個模型名字。 checkpoint revision、量化、runtime、template、context 設定、gateway、client、可用記憶體,任何一個換了,都要重驗。
- session 連續性是應用的責任。 前綴穩定、工具訊息不要重寫、旁支請求不要搶掉主對話的狀態。
- 委派看「每次驗證成功」的成本。 不是 token 單價,也不是「這次呼叫花了多少」。
- 能用行為驗就用行為驗。 靜態檢查便宜、該留,但要知道它擋掉的是什麼。
如果你是要買的人,三個問題就夠:
- 這個 demo 停在哪一層?「它會回話」是第 2 層。
- 第 4 層你們怎麼驗?驗收腳本誰寫的、什麼時候凍結的?
- 成本怎麼算,每次呼叫,還是每次驗證成功?
我們自己的影片轉錄管線也遇過同一類問題。模型跑起來了,流程還是卡住;而且每一個環節的失敗,看起來都像「模型有點笨」。我們沒有做這種規模的量測,所以這篇只借論文的數字。本地跑大模型的記憶體取捨,之前寫在另一篇。
上一則我們談的是檔案看起來對、其實不能用;這一則是模型看起來對、其實幹不完活。
如果你要的是有人陪你把這張表填完,我們的企業 AI 導入健檢做的就是這件事。先判斷哪些工作現在就能交給 AI,哪些還不成熟。
結論:你拿哪一層當「完成」
前三層可以在一個下午示範完。載一個模型、丟幾句話、接一個 client,快的話半天。
第四層要幾週:設計任務、寫隱藏檢查、跑足夠的次數、把失敗分類、算成本。而且做完之後,你得到的通常不是「這顆模型可以」,而是「這批任務、這份契約下,它可以」。
驗收單上缺的那一欄,就是差價所在。
明天可以先做一件事:把「測試通過」寫進你的 PoC 定義,然後要求對方出示第 4 層是怎麼驗的。