一套 OpenAI 兼容脚本測出差距
把同一個 SDK 指到兼容端點,循環兩個 model ID,就能在你的真實任務上直接比出差距。

以前我還要手動切環境、改 wrapper、複製 prompt;現在我只換 model ID,就能把兩個模型丟進同一條任務鏈路比出差距。
我這幾年最煩的一件事,就是模型評測常常被做成一場自我感動。圖表畫得很漂亮,分數也像那麼回事,結果一落到我自己的任務上,還是看不出到底該換誰。更慘的是,很多團隊嘴上說自己用的是 OpenAI 兼容接口,真到實作時卻在手動切環境變數、改一堆 if/else、重跑一輪又一輪。最後你拿到的不是模型差異,而是流程噪音。這次把我拉回來的,是這篇知乎對比文:Kimi K3 與 GLM-5.2 性能實測:2.8 倍價差背後的能力差距有多大。我看到它的第一反應不是「誰比較強」,而是「這種比法才對味」。
觸發我拆這套方法的核心,是它把 Kimi、GLM 這種模型放到同一個兼容端點思路裡看。你如果用的是 Kimi、智譜 AI 這類服務,再搭配 OpenAI API 規格 和 openai-python,其實根本不用把對比做成遷移專案。把 SDK 指到同一個 endpoint,然後在兩個 model ID 上循環,這事本來就該是一次字串替換,而不是一次架構重寫。
把模型對比縮成一個開關
訂閱 AI 趨勢週報
每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。
不會寄垃圾信,隨時可取消。
把 SDK 指到同一端點,循環兩個 model ID,你就能在同一條任務上看出模型差異。
翻譯一下就是:你不要先為了對比去改業務程式,再補一層適配,再加一堆額外抽象,最後才開始跑。這樣你永遠分不清楚,結果差是因為模型差,還是因為你自己把流程改壞了。最穩的做法,是把模型切換壓到最小,只讓 model ID 變動,其他全部固定。

我以前很愛把評測做得很重。每個模型一個分支,每個環境一套設定,最後跑完之後,我自己都不太敢相信數字。後來我才發現,真正有用的對比,長得都很樸素:同一段輸入、同一個 endpoint、同一套 timeout、同一組 sampling 參數,唯一變的就是 model。這個「唯一變數」很無聊,但它很值錢,因為它把噪音砍掉了。
實操寫法很簡單:先把你的呼叫入口收斂成一個函數,參數只留 endpoint、api key、model、prompt 和少量控制項。別讓評測腳本順手承擔「順便修一下業務」的責任。評測腳本只做一件事:記錄模型在你真實任務上的表現。
- 固定輸入,不要一邊測一邊改 prompt。
- 固定 sampling 參數,尤其是 temperature 和 max_tokens。
- 固定日誌欄位,至少要有 model、latency、usage、error。
SDK 要像開關,不要像補丁堆
我最怕看到的,就是為了兼容兩個模型,程式裡長出一堆 if/else。今天是 Kimi,明天是 GLM,後天又來一個別家,你的呼叫層就開始變成補丁堆。OpenAI 兼容接口真正有價值的地方,就是它應該讓你把切換成本壓到很低,而不是把你拖進新的抽象地獄。
也就是說,你應該用同一套 client,靠配置切 model,不靠複製程式碼切邏輯。把 endpoint 指向 https://api.ofox.io/v1,再在 request 裡替換 model ID,這種做法對 OpenAI API 來說本來就很自然。你如果用 Python,直接看 openai-python 的寫法就夠了,別自己發明一套模型適配層,最後適配層比模型還難維護。
我之前就遇過這種事。團隊想在同一個摘要任務上比較兩個模型,最開始有人提議各寫一套 wrapper,說這樣每個模型都能「用自己最舒服的方式」接。聽起來很合理,實際上完全毀掉對比意義。後來我硬是把入口統一,大家突然就只能討論輸出品質,而不是 wrapper 差異。這種改法很土,但很有效。
實操寫法:把模型名做成配置項,別寫死在程式裡。最簡單就是讀環境變數,例如 MODEL_ID=kimi-k3 或 MODEL_ID=glm-5.2。然後在迴圈裡跑兩個值,輸出到同一個結果檔。你會發現,切換成本低了之後,大家才會願意反覆測,而不是只跑一次就宣布差不多。
- endpoint 固定,model 可變。
- request body 固定,只有 model 欄位不同。
- 結果統一落盤,後面才好做 diff。
usage 和延遲,才是你真正要付錢的地方
很多人聊模型評測,只盯著「答對沒答對」。我懂,因為肉眼最容易判斷的就是輸出文本。但如果你做的是生產任務,只看內容對不對遠遠不夠。usage 和延遲才是真正會進帳單、會影響使用者體感的東西。

翻成白話就是:A 模型可能少犯一點錯,但 token 用得更多、反應也更慢;B 模型可能答案稍微差一點,但整體吞吐更高、成本更低。你最後選誰,不是看誰單次輸出比較討喜,而是看誰在你的約束裡更划算。這也是我覺得那篇對比值得看的地方,它不是只講誰比較聰明,而是把價差、能力、調用成本放在一起看。
我以前也被這件事打過臉。我們做過一個分類任務,當時只看輸出正確率,結果選了個看起來很順眼的模型。上線後才發現,它的輸出比較長,重試率也高,最後整條流程成本比另一個模型更難看。那時我才真正理解,便宜不等於省錢,貴也不等於浪費,關鍵是你有沒有把整條鏈路算進去。
實操寫法:每次呼叫都把 usage 物件存下來,別只存 content。再記錄端到端延遲,不要只看模型生成時間。最好連重試次數、超時次數也一起記,不然你會把「偶爾卡住」誤判成「平均性能差」。
result = client.responses.create(
model=model_id,
input=prompt,
)
print({
"model": model_id,
"latency_ms": elapsed_ms,
"input_tokens": result.usage.input_tokens,
"output_tokens": result.usage.output_tokens,
"total_tokens": result.usage.total_tokens,
"text": result.output_text,
})單次運行不是草率,是最低成本證據
我知道有人會說,單次運行不夠嚴謹,應該多輪、多樣本、做統計顯著性。我不反對,但很多團隊的問題根本不是統計不夠,而是連最小可用證據都沒有。先做單次運行對比,至少能回答一個很現實的問題:在我的真實輸入上,這兩個模型會怎麼表現。
也就是說,單次運行不是最後結論,它是篩選器。它能幫你把明顯不合適的模型先踢出去,省得你後面花一堆時間在不值得的候選上。你不需要先把評測系統做成論文,才有資格開始選型。很多時候,先跑十條真實樣本,比先搭兩天框架更有用。
我以前就吃過這個虧。為了一個任務,我們先花好幾天搭自動化評測集,結果最後才發現,兩個模型在最基本的指令遵循上就差很大。要是我一開始先跑幾條真實樣本,根本不會把後面的精力浪費在那個候選上。說白了,單次運行的價值不是證明誰贏,而是快速排除誰不行。
實操寫法:拿你最常見的 5 到 10 條真實輸入,先做一次人工可讀的對比。每條都跑同樣的 prompt、同樣的參數、同樣的 endpoint。不要為了公平去用脫離業務的合成題。你要測的是你的任務,不是論文題。
2.8 倍價差,要先換算成自己的單位成本
標題裡最容易抓眼球的,就是 2.8 倍價差。但我其實不太在意這個數字本身,我在意的是:你有沒有把它換算成自己的單位成本。模型貴 2.8 倍,不代表一定不值;模型便宜很多,也不代表一定更適合。
翻成白話就是:把 token 成本、失敗重試成本、人工複核成本和延遲成本一起算。很多團隊只看 API 單價,結果上線後才發現,便宜模型把後面的流程拖慢了,人工補救成本更高。那就不是省錢,是把錢搬到別的地方而已。Kimi、智譜 AI 這類已經提供兼容接口的服務,真正該比的不是誰名字更大聲,而是誰更適合你的工作流。
我自己的做法很土:先把流程拆成生成、校驗、重試、落庫、人工介入五段,然後看每個模型在這些環節裡的綜合成本。這樣你就不會只盯著「每百萬 token 多少錢」,而是會看「我這條鏈路一週到底燒多少錢」。這個角度一換,很多原本吵很兇的選型問題會安靜很多。
實操寫法:做一張最簡單的成本表,列四項:輸入 token、輸出 token、平均延遲、失敗率。再把它們映射成你自己的錢,比如每 1000 次調用的總成本。這樣你看的就不是標價,而是整條鏈路的真實花費。
- 不要只看 API 標價。
- 把重試和人工返工算進去。
- 用你的真實任務算單位成本。
真正有用的腳本,應該像工具,不像論文
如果一個對比腳本需要你讀半小時文件、改十個地方、再祈禱環境沒問題,那它基本就失去意義了。我更喜歡那種很硬的東西:輸入一段 prompt,跑兩個 model ID,吐出結構化結果,完事。越少花活,越能重複使用。
也就是說,你的腳本應該能被同事直接拿去跑,而不是只有你自己知道怎麼用。最好一條命令就能切模型,一條命令就能導出結果,一條命令就能看 diff。這樣對比才會從偶爾做一次的儀式,變成每次選型都能順手做的動作。
我最喜歡的評測腳本都很無聊。沒有花俏 UI,沒有複雜資料庫依賴,甚至沒有多餘抽象層。它們之所以好用,正是因為它們只解決一個問題:讓我快速知道哪個模型更適合這次任務。
實操寫法:把腳本拆成三層。第一層負責發請求;第二層負責記錄結果;第三層負責輸出報告。不要讓這三層互相纏在一起。你以後要加新模型,只需要改配置,不需要改執行邏輯。
可抄的模板
#!/usr/bin/env python3
import os
import time
import json
from openai import OpenAI
ENDPOINT = os.getenv("OPENAI_BASE_URL", "https://api.ofox.io/v1")
API_KEY = os.getenv("OPENAI_API_KEY")
MODELS = [
os.getenv("MODEL_A", "kimi-k3"),
os.getenv("MODEL_B", "glm-5.2"),
]
PROMPTS = [
"把這段內容整理成 3 點重點。",
"請用繁中輸出,並保留原始名詞。",
]
OUT = os.getenv("OUT_FILE", "model_compare.jsonl")
client = OpenAI(api_key=API_KEY, base_url=ENDPOINT)
with open(OUT, "a", encoding="utf-8") as f:
for prompt in PROMPTS:
for model_id in MODELS:
start = time.time()
record = {
"endpoint": ENDPOINT,
"model": model_id,
"prompt": prompt,
}
try:
resp = client.responses.create(
model=model_id,
input=prompt,
)
elapsed_ms = round((time.time() - start) * 1000, 2)
usage = getattr(resp, "usage", None)
record.update({
"ok": True,
"latency_ms": elapsed_ms,
"input_tokens": getattr(usage, "input_tokens", None),
"output_tokens": getattr(usage, "output_tokens", None),
"total_tokens": getattr(usage, "total_tokens", None),
"output_text": getattr(resp, "output_text", None),
})
except Exception as e:
elapsed_ms = round((time.time() - start) * 1000, 2)
record.update({
"ok": False,
"latency_ms": elapsed_ms,
"error": str(e),
})
f.write(json.dumps(record, ensure_ascii=False) + "\n")
f.flush()這版我會直接放進 repo,名字就叫 model_compare.py。如果你想再往前一步,我會加上 CSV 匯出、固定 seed、以及把每次結果 hash 起來,避免你之後看不出是不是同一份輸入。你也可以再接 pandas 做平均延遲、token 均值和失敗率統計,這些都很直白,沒必要搞得像研究計畫。
原始思路來自這篇知乎文章:Kimi K3 與 GLM-5.2 性能實測:2.8 倍價差背後的能力差距有多大。我這裡做的是把它拆成可執行的方法和可直接複製的腳本;具體模型結論、實測細節和原文表述,請以原作者發布內容為準。