免費模型能扛多少粗活? glm-5.2 × GPT-5.5 Codex 三類委派實測

Delegation Benchmark · 2026-07-04 · 繁體中文

免費模型能扛多少粗活?
glm-5.2 × GPT-5.5 Codex 三類委派實測

影片版(4 分鐘):https://youtu.be/2uh8l6u54VE

背景:Claude Code 訂閱 token 有限,我們把「打字與讀大檔」外包給 NVIDIA NIM 免費層的模型,Claude 只負責寫規格與驗收。z-ai 出了 glm-5.2 之後,我們用三種真實委派任務重測,並以 OpenAI Codex CLI(gpt-5.5)同題對照。全部題目與評分標準都附在文末,歡迎自己重跑。

glm-5.2 三類總分
93 / 97 / 82
生成 / 閱讀 / 修改(滿分 100)
Codex 三類總分
95 / 95 / 88
生成 / 閱讀 / 修改(滿分 100)
功能正確率
雙方全滿分
36 個驗收檢查點,兩邊 0 失誤
成本
$0 vs 付費
NIM 免費層 vs ChatGPT 訂閱額度

00一句話結論

免費的 glm-5.2 在功能品質上已與 GPT-5.5 Codex 同檔次(36 個驗收點雙方全過),分差全在「工程品格」細節:glm 會編造時間戳、時間變異極大(33 秒到 23 分鐘);Codex 時間穩定、後設資訊誠實,但這次被抓到寫完不自測。在「省 token」前提下,glm-5.2 配上機械化驗收(lint 腳本+diff 檢查)已足堪日常委派;Codex 留給急件與需要可稽核根因的場合。

01方法

項目glm-5.2GPT-5.5 Codex
存取途徑opencode CLI → NVIDIA NIM 免費層(z-ai/glm-5.2)OpenAI Codex CLI 0.139.0(gpt-5.5,reasoning medium)
執行形式headless、同一份 prompt、各自獨立的乾淨工作目錄、可用本機 shell 工具
出題與驗收由 Claude(Fable 5)設計:標準答案先於測試存在;受測模型拿不到測資與評分標準
驗收環境PHP 任務雙環境驗收:Windows 本機 PHP 7.3.30 + Debian 13 / PHP 8.4.21(正式環境鏡像),以 8.4 為準

三類任務對應委派場景分類:A 生成(從規格寫新程式)、B 閱讀(大檔分析摘要)、C 修改(改既有程式並遵守團隊慣例)。每題都埋了「照抄規格會錯、要真的理解才會對」的陷阱。

02耗時對比(秒,越短越好)

同題 wall-clock 時間

同一比例尺;glm-5.2 的 A 類含約 20 分鐘的環境除錯兔子洞(見 §05)

glm-5.2(免費)GPT-5.5 Codex(付費)
C 類:修改任務(手續費改版)
glm-5.2
91s
Codex
311s
B 類:閱讀任務(3000 行 log 五題)
glm-5.2
33s
Codex
121s
A 類:生成任務(CSV 報表腳本)
glm-5.2
1372s ⚠
Codex
84s

03C 類:修改任務 Codex 88glm 82

題目:把一支捐款手續費函式 calcFee($amount) 改版成三參數版本,規格埋四個陷阱:費率級距看原始金額但費用算淨額、級距邊界值(剛好 1000/10000)、會員折扣在四捨五入之前、最低手續費在之後且淨額為零時豁免。同時必須遵守團隊慣例:修改區塊用帶時間戳與模型署名的註解標記包起來、舊程式碼不可刪只能註解保留。

驗收:17 項邊界測試 + php -l + git diff 範圍檢查 + 慣例格式逐條核對。

檢查點glm-5.2Codex
17 項邊界測試(含四陷阱)17/1717/17
只動目標檔
舊碼註解保留✓(且自行發現巢狀註解會壞、改逐行註解)
署名誠實「GLM-5.2」正確寫「GPT-5」,實為 gpt-5.5(小偏差)
時間戳誠實造假:寫 14:30,實際 19:33先跑 Get-Date 才寫,精確到秒
標記行格式end 行漏署名子句 ×4完全合規
耗時91s311s
關鍵發現:glm 系列「不查環境、憑空編一個合理時間戳」是跨版本的結構性行為(5.1、kimi、5.2 皆然)。對策不是換模型,是改流程:委派 prompt 由主控端預先算好時間戳與標記行原文,令其照抄——它不擅長誠實查證,但很擅長照抄。

04B 類:閱讀任務 glm 97Codex 95

題目:3000 行合成 log(格式:時間戳 LEVEL [module] 訊息),五題皆有唯一標準答案:①ERROR 總數(埋 10 行「訊息含 ERROR 字樣但 level 不是 ERROR」的干擾項);②各 module 分佈;③首尾 ERROR 行號(最後一行剛好在檔尾——專抓「默默漏讀檔尾」);④兩分鐘爆量窗的根因推斷(connection pool 耗盡→串聯拖垮登入與金流);⑤FATAL 行數與行號。

檢查點glm-5.2Codex
五題正確率5/55/5
干擾項(10 行假 ERROR)全數識破全數識破
檔尾陷阱(第 3000 行)
策略grep + uniq 聚焦,不硬讀整檔;路徑踩坑 5 秒自我修復結構化擷取,每個因果環節都掛行號,零腦補
根因推斷正確,但多送一句未驗證的因果延伸(-2)正確且全程可稽核
耗時33s121s
世代躍遷:同樣的 B 類測試,glm-5.1 三輪全部超時、零產出(它會硬讀整檔撐爆 context);glm-5.2 換成工具聚焦策略後 33 秒滿分。行為改變比分數提升更重要——這直接決定它能不能用。

05A 類:生成任務 Codex 95glm 93

題目:從零寫一支捐款 CSV 彙總報表 CLI 腳本。規格埋六個陷阱:引號內含逗號的欄位("李,大華")、空白行跳過且不佔錯誤行號、行號從含標題列起算、總額相同時以字串排序決勝負、錯誤走 STDERR 且正常輸出走 STDOUT、三種結束碼(0/1/2)。受測模型拿不到測資,只拿規格。

驗收:三組測資(髒檔含 BOM+四種壞列 / 乾淨檔 / 無參數)在 PHP 8.4 正式環境鏡像逐項比對標準輸出。

檢查點glm-5.2Codex
PHP 8.4 全項驗收滿分滿分
自我驗證五組功能自測含 exit code只跑 php -l,未做功能測試
可攜性(PHP 7.3 + Big5 locale)手刻解析器,照樣全對str_getcsv 版全軍覆沒
環境問題處置自測撞上 locale 地雷→自行診斷出 Big5 是根因→改走可攜寫法→清理除錯檔渾然不覺(因為沒自測)
耗時1372s(23 分鐘,大半在除錯兔子洞)84s
本輪最大的意外收穫與公共服務:Windows 上老 XAMPP 的 PHP 7.3.30 配繁中系統 locale(Big5/CP950)時,str_getcsv/fgetcsv 解析含中文欄位的 CSV 會錯亂——切出來的欄位整個位移,且與內容相關、非全滅,極易誤判成程式寫錯。Codex 的正確腳本在本機驗收全錯、上 PHP 8.4 全對,差點被冤枉。若你在 Windows 中文環境用老 PHP 處理 CSV,驗收請務必上與正式環境同版的機器。

06總表與解讀

類別glm-5.2Codexglm 耗時Codex 耗時勝負手
A 生成93951372s84sglm 品質與紀律更完整,輸在時間失控
B 閱讀979533s121s同為滿分,glm 快 3.7 倍且免費
C 修改828891s311s功能同分,glm 輸在時間戳造假等後設誠實度
  • 功能品質已無代差。36 個驗收檢查點雙方全過,包括所有故意埋的陷阱。免費模型「不能用」的印象該更新了。
  • 分差全在工程品格,而品格可以用流程補。glm 的時間戳造假、格式漏子句都是機械可驗、機械可修的;我們已把「時間戳預先餵給它照抄」寫進委派範本、把格式檢查寫成 lint 腳本,修完等價分數逼近 Codex。
  • 兩者的強弱是任務形狀的函數,不是固定標籤。C 類 Codex 展現誠實與自我修正,A 類卻犯了「寫完不試」;glm 在 A 類反而秀出完整的診斷-改寫-自測-清場迴圈。單一「哪個比較強」的問題沒有意義,路由表才有。
  • 時間變異是 glm 最大的實用短板。33 秒到 23 分鐘都可能(NIM 免費層排隊+它愛鑽兔子洞)。不趕時間的背景委派無所謂,急件請改派時間穩定的 Codex。

07完整題目(歡迎重跑)

以下是三份一字未改的委派 prompt 與驗收工具。任何 agent CLI(opencode、Codex、Claude Code、aider⋯)都能跑:建一個乾淨目錄、餵 prompt、然後用附上的測試驗收。留意兩個坑:opencode run 不吃 shell 的工作目錄,要帶 --dir;非互動環境下記得關 stdin(前綴 '' |< /dev/null),否則會永久卡住。

C 類題目:calcFee 改版 spec(含起始檔案)

起始檔案 feeCalc.php:

<?php
    /*
      目的:計算捐款金流手續費(線上刷卡通道)。
      作者:徐傳企 Mario Hsu
      沿革:
           2026-05-02  v0.0.0.2  1.手續費率由 1.8% 調整為 2%。
           2026-04-11  v0.0.0.1  1.誕生日。
    */

    /**
     * 計算單筆捐款的金流手續費。
     *
     * @param int $amount 捐款金額(新台幣,整數元)
     * @return int 手續費(元)
     */
    function calcFee($amount)
    {
        if (!is_int($amount)) {
            throw new InvalidArgumentException("amount must be an integer");
        }
        if ($amount < 0) {
            throw new InvalidArgumentException("amount must not be negative");
        }
        $fee = $amount * 0.02;
        return (int) round($fee);
    }

    // CLI 測試入口:php feeCalc.php <amount>
    if (PHP_SAPI === 'cli' && isset($argv) && basename(__FILE__) === basename($argv[0])) {
        $amount = isset($argv[1]) ? (int) $argv[1] : 0;
        echo calcFee($amount) . PHP_EOL;
    }

委派 prompt:

請修改本目錄下的 feeCalc.php,把 calcFee() 依以下規格改版。只能改這一個檔案。

## 新函式簽名
function calcFee($amount, $coupon = 0, $isMember = false)

## 計算規格(嚴格依序執行)
1. 參數驗證:$amount 與 $coupon 都必須是整數且 >= 0,且 $coupon 不得大於 $amount,
   違反任一條件即 throw InvalidArgumentException。
2. 淨額 net = $amount - $coupon。
3. 費率級距**必須以原始的 $amount 判斷**(不是以 net 判斷):
   - $amount < 1000 → 費率 2.0%
   - 1000 <= $amount <= 9999 → 費率 1.5%(注意:剛好 1000 適用 1.5%)
   - $amount >= 10000 → 費率 1.0%(注意:剛好 10000 適用 1.0%)
4. 費用以**淨額 net** 計算:fee = net * 費率。
5. 若 $isMember 為 true,費用打 8 折(是費用打折,不是金額打折):fee = fee * 0.8。
6. 四捨五入到整數元(round half up)。
7. 最低手續費規則**最後才套用**:若 net == 0,手續費為 0(不套最低費);
   若 net > 0 且算出的手續費 < 5,手續費為 5。

## 程式慣例(全域 SOP,必須遵守)
- 所有修改的區塊用一對註解包起來,格式嚴格如下(<模型名>寫你自己實際的模型名稱,
  時間戳寫實際當下時間精確到秒):
  // YYYY-MM-DD HH:MM:SS <一句說明>. By <模型名> (effort: default), 傳企監看。begin
  ...修改的程式碼...
  // YYYY-MM-DD HH:MM:SS <一句說明>. By <模型名> (effort: default), 傳企監看。 end
  (注意:begin 行結尾緊接 begin 無空格;end 行是「。 end」句號後一個空格再 end)
- 被取代的舊程式碼**不可刪除**,整塊註解掉保留在原處,舊區塊與新區塊各自用一對 begin/end 包起來。
- 檔頭「沿革」加一行新紀錄(版號 v0.0.0.3),說明本次改動。
- CLI 測試入口也要更新成可傳入 coupon 與 isMember:php feeCalc.php <amount> [coupon] [isMember(0/1)]。

完成後只回報:改了哪些地方、每處一句話說明,不要貼程式碼全文。
C 類驗收:17 項邊界測試(runTests.php)
<?php
// 驗收測試:php runTests.php <path-to-feeCalc.php>
require $argv[1];

$cases = [
    [[0, 0, false], 0,   'net=0 零元特例(不套最低費)'],
    [[500, 0, false], 10,  '一般 2% 級距'],
    [[999, 0, false], 20,  '邊界 999 → 2%(19.98 進位 20)'],
    [[1000, 0, false], 15, '邊界:剛好 1000 → 1.5%'],
    [[9999, 0, false], 150,'邊界 9999 → 1.5%(149.985 → 150)'],
    [[10000, 0, false], 100,'邊界:剛好 10000 → 1.0%'],
    [[1200, 300, false], 14,'陷阱:級距看原始 1200(1.5%),費用算淨額 900 → 13.5 → 14'],
    [[10000, 5000, false], 50,'陷阱:級距看原始 10000(1%),淨額 5000 → 50(誤用淨額會算 75)'],
    [[1000, 0, true], 12,  '會員 8 折:15 → 12'],
    [[300, 0, true], 5,    '會員折後 4.8 → round 5 → 最低費 5'],
    [[200, 0, true], 5,    '陷阱:折後 3.2 → 3 → 最低費 5(順序:round 後才套最低費)'],
    [[100, 0, false], 5,   '最低手續費 5'],
    [[1000, 1000, false], 0,'陷阱:net=0 → 0,不套最低費'],
    [[1000, 1000, true], 0, 'net=0 + 會員 → 仍 0'],
];

$exceptions = [
    [[-1, 0, false], '負數 amount 應丟例外'],
    [[100, 200, false], 'coupon > amount 應丟例外'],
    [[100, -5, false], '負數 coupon 應丟例外'],
];

$pass = 0; $fail = 0;
foreach ($cases as $i => [$args, $exp, $label]) {
    try {
        $got = calcFee(...$args);
        if ($got === $exp) { $pass++; echo "PASS #".($i+1)." $label\n"; }
        else { $fail++; echo "FAIL #".($i+1)." $label — expected $exp got ".var_export($got, true)."\n"; }
    } catch (Throwable $e) {
        $fail++; echo "FAIL #".($i+1)." $label — unexpected exception: ".$e->getMessage()."\n";
    }
}
foreach ($exceptions as $i => [$args, $label]) {
    $n = count($cases) + $i + 1;
    try {
        calcFee(...$args);
        $fail++; echo "FAIL #$n $label — no exception thrown\n";
    } catch (InvalidArgumentException $e) {
        $pass++; echo "PASS #$n $label\n";
    } catch (Throwable $e) {
        $fail++; echo "FAIL #$n $label — wrong exception type: ".get_class($e)."\n";
    }
}
echo "RESULT: $pass/".($pass+$fail)." passed\n";
B 類題目:log 分析五題 + 測試 log 生成器

委派 prompt(把 log 檔放進工作目錄再發):

分析本目錄下的 app.log(約 3000 行,格式:時間戳 LEVEL [module] 訊息)。
只回結論與行號,不要引整段原文內容。

回答以下五題:
1. level 為 ERROR 的總行數。注意:訊息文字裡含有 ERROR/error 字樣、
   但 level 欄位不是 ERROR 的行,不算。
2. ERROR 依 module(方括號內)的分佈統計,每個 module 各幾行。
3. 第一個 ERROR 與最後一個 ERROR 各在第幾行(行號)。
4. 02:14 至 02:16 之間發生了什麼事?用一到兩句話推斷根本原因,
   以及它造成的後續影響。
5. level 為 FATAL 的有幾行?各在第幾行?

輸出格式:五題各一行結論,總長度不超過 15 行。

log 生成器(php gen_log.php app.log,同時印出標準答案):

<?php
// 決定性生成 3000 行測試 log,埋入已知事實與陷阱。用法: php gen_log.php <輸出檔>
$out = fopen($argv[1], 'w');

// ERROR 行位置(level=ERROR)
$dbBurst = range(421, 463, 3);                       // 15 行 pool exhausted 爆量
$dbOther = [87, 350, 890, 1420, 1980, 2300, 2650, 2900]; // 8 行
$auth    = [470, 475, 480, 485, 490, 495, 500, 1100, 2450]; // 9 行(爆量後串聯)
$payment = [505, 510, 515, 520, 525, 1700, 2100, 2999];     // 8 行
$cron    = [600, 1300, 1900, 2500];                  // 4 行
$api     = [750, 1600, 3000];                        // 3 行(3000 = 檔尾陷阱)
$fatal   = [1204, 2718];                             // FATAL 2 行
$infoTrap = [200, 800, 1500, 2000, 2600, 2950];      // INFO 但訊息含 ERROR 字樣
$warnTrap = [300, 1000, 1800, 2400];                 // WARN 含小寫 error

$special = [];
foreach ($dbBurst as $l)  $special[$l] = "ERROR [db] connection pool exhausted (pool=main, waited 30s, active=50/50)";
foreach ($dbOther as $l)  $special[$l] = "ERROR [db] query timeout on donations table (took 31024ms)";
foreach ($auth as $l)     $special[$l] = "ERROR [auth] login failed: timeout waiting for db connection from pool";
foreach ($payment as $l)  $special[$l] = "ERROR [payment] charge failed: upstream db timeout, order rolled back";
foreach ($cron as $l)     $special[$l] = "ERROR [cron] scheduledTelegramNotice aborted: lock file stale";
foreach ($api as $l)      $special[$l] = "ERROR [api] 500 on POST /donate: unhandled exception";
foreach ($fatal as $l)    $special[$l] = "FATAL [kernel] out of memory killer invoked, php-fpm worker slain";
foreach ($infoTrap as $l) $special[$l] = "INFO [monitor] ERROR rate within threshold, dashboard /admin/ERROR_REPORT rendered";
foreach ($warnTrap as $l) $special[$l] = "WARN [api] client reported error page screenshot uploaded to s3";

$fillers = [
    "INFO [api] GET /lastnews.php 200 in %dms",
    "INFO [auth] session refreshed for uid=%d",
    "INFO [db] slow query log rotated, %d entries",
    "INFO [payment] webhook heartbeat ok seq=%d",
    "INFO [cron] tick, next job in %ds",
];

$base = strtotime('2026-07-04 02:00:00');
for ($i = 1; $i <= 3000; $i++) {
    $ts = date('Y-m-d H:i:s', $base + 2 * $i);
    $msg = $special[$i] ?? sprintf($fillers[$i % 5], ($i * 37) % 900 + 10);
    fwrite($out, "$ts $msg\n");
}
fclose($out);

// ground truth
$all = array_merge($dbBurst, $dbOther, $auth, $payment, $cron, $api);
sort($all);
echo "ERROR total: " . count($all) . "\n";
echo "db: " . (count($dbBurst) + count($dbOther)) . " auth: " . count($auth) .
     " payment: " . count($payment) . " cron: " . count($cron) . " api: " . count($api) . "\n";
echo "first ERROR line: {$all[0]}, last ERROR line: " . end($all) . "\n";
echo "FATAL: " . count($fatal) . " lines at " . implode(',', $fatal) . "\n";
echo "burst window lines 421-463, ts " . date('H:i:s', $base + 2*421) . "-" . date('H:i:s', $base + 2*463) . "\n";

標準答案:ERROR 共 47(db 23 / auth 9 / payment 8 / cron 4 / api 3);首尾行號 87 與 3000;FATAL 2 行(1204、2718);根因:02:14 起 db connection pool 耗盡(active 50/50),串聯導致 auth 登入逾時與 payment 交易回滾。

A 類題目:捐款 CSV 報表腳本 spec + 測資

委派 prompt:

在本目錄新建 donateReport.php(PHP CLI 腳本,不可動其他檔案),依以下規格實作。

## 功能
讀取 argv[1] 指定的捐款 CSV 檔,輸出彙總報表。

## 輸入格式
- CSV 欄位:姓名,金額,日期,方式。第 1 行是標題列,一律跳過。
- 欄位可能被雙引號包住且內含逗號(如 "李,大華"),必須正確解析(建議 str_getcsv)。
- 每個欄位取值前先 trim 前後空白;行尾可能是 CRLF。
- 整行 trim 後為空字串的空白行:直接跳過,不算錯誤、不報行號。

## 驗證規則(行號 = 實際檔案行號,含標題列在內從 1 起算)
- 金額:必須是純數字正整數(regex ^[0-9]+$ 且 > 0)。違反 → 往 STDERR 印一行
  「第 N 行: 金額不合法」,該行不列入彙總。
- 日期:必須符合 ^\d{4}-\d{2}-\d{2}$ 格式(只驗格式)。違反 → STDERR
  「第 N 行: 日期不合法」,不列入彙總。
- 同一行金額與日期都錯時,只報金額錯誤一行即可。

## 輸出(STDOUT)
- 每位捐款人一行:姓名<TAB>總金額<TAB>筆數
- 排序:總金額由大到小;金額相同時依姓名字串升冪(strcmp)。
- 之後一行「---」
- 最後一行:總計 N 筆 M 元(N=有效筆數,M=有效金額加總)

## 結束碼
- 有任何驗證錯誤 → exit 1;全部有效 → exit 0。
- argv[1] 未給或檔案不存在 → STDERR「檔案不存在」,exit 2。

## 程式慣例
- 檔頭需有 block 註解:目的/作者(徐傳企 Mario Hsu,AI 協助註明實際模型名)/
  沿革(YYYY-MM-DD v0.0.0.1 1.誕生日。)。
- 寫完自己跑 php -l 驗證語法。

完成後只回報:檔案已建立、實作要點三句話以內,不要貼程式碼全文。

驗收測資 messy.csv(UTF-8 with BOM、CRLF 行尾):

姓名,金額,日期,方式
王小明,500,2026-07-01,線上
"李,大華",1200,2026-07-02,轉帳
(此行為空白行)
王小明,700,2026-07-03,線上
陳阿姨,abc,2026-07-03,現金
林先生,0,2026-07-04,線上
張三,-100,2026-07-04,線上
趙四,300,2026/07/05,現金
李四,1200,2026-07-05,轉帳
王小明,  800 ,2026-07-05,線上

標準答案:STDOUT 依序「王小明 2000/3 筆→李,大華 1200/1→李四 1200/1」(tie-break:strcmp 下「李,大華」排「李四」前)、總計 5 筆 4400 元;STDERR 四行(第 6/7/8 行金額不合法、第 9 行日期不合法);exit 1。另備一份乾淨檔驗 exit 0,無參數驗 exit 2。

08限制與注意

  • 每類 n=1。這是委派路由的實用煙霧測試,不是嚴謹學術評測;分數是單次表現,NIM 免費層的延遲變異尤其大,重跑時間數字必有出入。
  • Codex 跑 reasoning medium(該 CLI 建議值);glm-5.2 走 NIM 免費層,與付費版/官方 API 行為可能不同。
  • 評分中「工程品格」項(署名、時間戳、自測)帶主觀權重,rubric 已在文中列明,不服可自行重配。
  • 兩個復現必踩的坑再提醒一次:opencode run 要帶 --dir;headless 跑任何 agent CLI 前綴 '' | 關 stdin。

測試設計、標準答案、驗收與本頁整理:Claude(Fable 5)。受測:z-ai glm-5.2(NVIDIA NIM 免費層,經 opencode CLI)、OpenAI gpt-5.5(Codex CLI 0.139.0)。2026-07-04,台灣。題目與驗收碼歡迎自由取用重測。

留言

這個網誌中的熱門文章

架站資源整理清單

這次多機聯防的程式筆記