要在自己的機器上用決策模型做分類或守門,先把題目收成一題只問一件事,選項彼此互斥,並留下一個「其他」。2026-10-11 我們在一台 Mac(MLX 4-bit)與一台 NVIDIA 工作站(GGUF Q4_K_M)上跑開源的 Clef-flash,研究類型大約 1.8 秒一篇,工作站 p50 是 266 毫秒一篇;77 篇 PubMed 摘要的標籤完全相同,準確率都是 92.2%,這個數字只屬於這 77 篇。決策模型吃進一段狀態(state,待判斷的原文或 JSON)和一道事先列好選項的具型別問題,做一次前向計算,也就是把輸入算過一遍就讀出每個選項的機率,不生成自由文字,也不必再解析輸出。
本系列第 4 篇|這篇回答:要在自己的機器上用決策模型,題目和選項怎麼設計,Mac 與 NVIDIA 上怎麼跑、多快?
第 1 篇處理決策模型是什麼,第 2 篇處理原理與訓練,第 3 篇用 77 篇 PubMed 論文檢驗校準。這篇只回答題目怎麼設計、本機怎麼部署。第 5 篇才進入讓 Agent 先問再做的守門與選型。
一題只問一件事
一題只問一件事:研究類型用單獨一道 choice,工具守門拆成 action 與 high_risk 兩題,不要寫進同一個問題。
具型別的意思是,選項和回答的形狀在送出之前就定好了。文件裡的題型有三種。noul 是是非題,回傳該陳述為真的機率,數值落在 0 到 1,而且沒有 confidence 欄位。choice 從具名選項裡選一個,選項數是 2 到 255,回傳每個選項的 probabilities,另外帶一個 confidence。score 是有序等級,級距是 2 到 10,同樣回傳 probabilities 與 confidence。一次呼叫可以同時帶 1 到 64 題。Clef 與 Clef-flash 的請求與回應,形狀與 Jev 的 /v1/systemone 相同,輸入可以是文字、JSON 或影像。哪些輸入在本機路徑上可用,以部署紀錄為準,硬體那一節分開寫。
我們的決策模型用戶端有兩個內建 profile。study_type 把研究類型做成一題 choice。tool_gate 把守門拆開:action 是 choice,負責這次要採取哪一種行動;high_risk 是 noul,負責問執行之後會不會是高風險。拆開是因為這兩件事可以同時成立。若把它們塞進同一題 choice,模型只能在互斥選項裡留下一個標籤,另一件事就沒有位置;拆開之後,每個機率只對應一件事,可以各自設門檻。後兩句是我們的推論;profile 本身已經把它們做成兩題。
官方文件寫明,System One 模型不寫回覆、不產生程式碼,也不產生推理說明。原文是 "System One models do not write replies, produce code, or generate explanations of their reasoning." 題目外面不會再有一段理由說明它為什麼選這一類。區分條件必須寫進選項自己的定義,讓機率對應的是你事先寫好的那句話。
廠商自報:同一份 state 上可平行問多題,各題彼此隔離,加題幾乎不增加延遲。我們沒有在 Mac 或 NVIDIA 上重測。本機量到的秒數,都是研究類型這一個題目的時間。
有些工作不該交給它。需要寫作、摘要、萃取、開放式推理、多步規劃,或要它解釋理由時,它做不到,因為那些產出是自由文字,而它不生成自由文字。選項如果無法事先列出來,也不適合。choice 最多 255 個選項。超過時要改成兩段式,這是我們的解讀;文件寫明的是 255 這個上限。
這比較像表格每一列只留一個空格,填完再換下一列。模型這邊也是同一件事:每一題的輸出空間在發問前就關起來,它只在那個空間裡給機率。
選項怎麼列:互斥,再加一個其他
選項要彼此互斥,並保留一個「其他」類,承接不屬於前面任何一類的案例;研究類型的其他類叫做 original_research,呼叫失敗時也回落到這個標籤。
互斥是指,照你寫下的定義,一份材料只應該落進一個選項。每個選項附一句當時就能判斷的定義,profile 裡叫 criteria。定義要寫出區分條件,而不是只給一個名稱。研究類型裡用得到的例子是「明確隨機分派」,以及「沒有新的濕實驗或臨床資料」。前一句把隨機對照試驗和沒有隨機的人體研究分開,後一句把純計算工作和帶有新實驗或新臨床資料的論文分開。
若兩個定義可以同時成立,choice 仍會交回每個選項的機率,但那組機率不再回答唯一的一類是哪一個。這句是我們的推論。設計時先檢查任意兩句 criteria 會不會同時為真,會的話就改寫定義,或拆成兩題。
可以把它想成選擇題最後一格印著「以上皆非」。前面的類別都對不上時,模型有一個規定好的去處,而不是被擠進一個只是比較相近的標籤。original_research 扮演的就是這一格,定義是不屬於前八類的其他原創研究。
文件說的「不會幻覺」,指的是輸出空間事先被 schema 限制住,型別錯誤不可能發生。交回來的選項名稱一定在你列過的範圍裡。選項選得對不對仍是機率問題,要靠校準和信心門檻處理。校準是指它回報的機率接近實際命中的比例。後半句是我們的解讀,不是一份準確率保證。
呼叫失敗時,用戶端不用一個臨時發明的標籤,而是採用該 profile 事先寫好的 on_fail;study_type 的 on_fail 就是 original_research。失敗紀錄要怎麼保存,最後一節再談。
研究類型 9 類的題目怎麼寫
研究類型寫成一題 choice,列出 9 個互斥選項,每個選項附一句可判斷的定義;不屬於前八類的論文歸入 original_research。
下表是 study_type 的全部選項與判斷條件。閱讀時先看右欄能不能把左欄兩兩分開,再把左欄的代碼當成送給模型的選項名稱。criteria 的原文是英文,表裡是同一組條件的中文。
| 代碼 | 判斷條件 |
|---|---|
| systematic_review | 有明確檢索與篩選方法的系統性回顧或統合分析 |
| review | 沒有系統性檢索的敘述性回顧、觀點或綜論 |
| rct | 人類受試者,而且有明確隨機分派的隨機對照試驗 |
| clinical_study | 非隨機的人類受試者或病歷研究,包括世代、病例對照、橫斷與單組試驗 |
| case_report | 單一病人或小型病例系列 |
| in_vivo | 活體動物或完整生物體實驗,含離體的完整器官 |
| in_vitro | 只用細胞、培養組織或無細胞系統 |
| computational | 計算、生物資訊、統計建模或 AI,沒有新的濕實驗或臨床資料 |
| original_research | 不屬於以上任何一類的其他原創研究 |
寫題時把右欄放進選項,不要只傳代碼。只傳 rct 這幾個字母,模型沒有被告訴必須看得到明確隨機分派,它就和 clinical_study 沒有界線。computational 若少了「沒有新的濕實驗或臨床資料」,一篇附帶新實驗的建模論文也沒有落點。下面三則是依照這些定義做的對照,不是另一次實測。人類受試者而且寫明隨機分派,歸 rct,不歸 clinical_study。只有細胞或無細胞系統,歸 in_vitro,不歸 in_vivo;in_vivo 要求活體動物、完整生物體,或離體的完整器官。純計算、沒有新的濕實驗或臨床資料,歸 computational。
論文管線不是把已經分過類的論文全部重算。它只對還沒有研究類型的新論文呼叫這一題。choice 回傳的 confidence 達到 0.6 或以上,採用決策模型的答案;低於 0.6,改用 regex。兩種來源合併之後,在 2026-10-11 的 77 篇上,準確率是 90.9%。
同一批 77 篇 PubMed 摘要、同一個 9 類題目上,若看決策模型自己的標籤,準確率是 92.2%;只走 regex,是 71.4%。本機 35B 聊天模型是另一種做法:只有它自報的信心達到 0.75,它才作答。這樣做的整體準確率是 50.6%,作答覆蓋是 51.9%,在它願意作答的那一部分大約 97.5%。三組做法都是當天的實測,分母要分開看。92.2% 用的是全部 77 篇。97.5% 只用它有作答的那個子集,不能與全部 77 篇上的 92.2% 放在同一個分母上比較。50.6% 才是把沒有作答的篇數也算進去之後的整體。這 77 篇不能外推成一般準確率。
想用自己的預測和結果檢查機率是否貼近命中比例,可以開校準檢查器。它在瀏覽器裡計算 Brier、ECE 與 reliability diagram,不把資料送出。ECE 是期望校準誤差的簡稱。這個工具不取代上面那 77 篇,它只讓你拿自己手上的配對重算。
在 Mac 與 NVIDIA 上跑:速度與一致性
2026-10-11 的實測裡,Mac 上把一篇論文分到研究類型大約 1.8 秒,NVIDIA 工作站的 p50 是 266 毫秒,兩邊對 77 篇的標籤 77/77 相同,準確率都是 92.2%。
我們沒有把資料送到託管的 Jev。原因是 state 會離開本機,而且該服務仍是 early access。我們也沒有 Jev 的憑證,沒有做 Jev 與 Clef 的頭對頭比較。下文的 Jev 額度來自文件。Clef-flash 在別台機器上的毫秒數會標明廠商自報。本機跑的是開源權重的 Clef-flash。Clef 是 27B 的多模態決策模型,由 Qwen3.8-27B 後訓;Clef-flash 是 9B 版本,由 Qwen3.5-9B 後訓。兩者都在骨幹上加一個 joint schema head,授權是 Apache-2.0,權重公開在 Hugging Face。我們載入的是 Clef-flash,不是 27B 的 Clef。它不把答案逐字生成出來,而是對事先列好的每個選項直接給出機率。
token 是模型計算長度的單位,不等於一個漢字,也不等於一個英文單字。MLX 4-bit 與 GGUF Q4_K_M 都是降低權重精度的格式,用來把模型放進記憶體。下表用來對照三條路徑的輸入上限,以及延遲是誰量的。右欄的毫秒不能直接相減。Workers AI 那一列是文件與廠商自報,機器和題目都不是我們這 77 篇。
| 路徑 | 實際使用的設定 | 輸入上限 | 延遲 |
|---|---|---|---|
| 一台 Mac,oMLX | clef-flash-4bit,MLX 4-bit,需要 Bearer key | 這個實作的 state 上限是 16,384 tokens | 行程內載入約 7 秒;研究類型約 1.8 秒/篇,量到的範圍約 1.5 到 2.4 秒 |
| 一台 NVIDIA 工作站,llama.cpp | ggml-org/Clef-Flash-GGUF 的 Q4_K_M | 整個 prompt 要放進一個 batch,context 設為 4096 | p50 266 毫秒/篇 |
| Cloudflare Workers AI(文件,截至 2026-10) | 可呼叫 Clef 與 Clef-flash | context 65,536 tokens | 廠商自報:Decision Index 0.2.1 於 H200 內部執行,Clef-flash 中位 38.8 毫秒 |
Mac 這條能跑,是因為 oMLX 已經內建 /v1/systemone,並且原生支援 Clef。我們用的權重名稱是 clef-flash-4bit。這個實作要求 Bearer key,state 上限是 16,384 tokens,和 Workers AI 文件上的 65,536 tokens 不是同一個額度。NVIDIA 這條用官方 llama.cpp。Clef 的原生支援在 PR #29831,於 2026-10-03 合併。BF16 權重約 18 GB,放不進 16 GB 的顯示卡,所以工作站上用 Q4_K_M,不用全精度。Clef-flash 在 Hugging Face 的完整檔案約 17.773 GiB,其中 joint head 那個檔是 243,538,016 bytes。完整檔案的體積,和後面算顯示卡時用的量化權重,是兩個數字。卡上的 Clef 權重約 5.6 GB。
模型卡寫 Clef 與 Clef-flash 可以接受文字、JSON 和影像。文件另寫 Clef 含 vision encoder,可讀影像;Jev 目前只接受文字 state。我們的 llama.cpp 路徑目前只支援文字,影像輸入尚未進 llama.cpp。Mac 這條的部署紀錄沒有寫它接不接受影像,這裡不補一個答案。
p50 是中位數,用來代表這批篇數的典型延遲,不是最快那一篇。NVIDIA 工作站上,研究類型的 p50 是 266 毫秒/篇。Mac 的約 1.8 秒是同一類題目的大約值,當下量到的範圍約 1.5 到 2.4 秒,行程內載入還要另計約 7 秒。兩台都跑完這 77 篇之後,標籤 77/77 相同,準確率都是 92.2%。各類機率差的平均是 0.005,最大是 0.217。標籤相同,只表示兩邊給出的類別相同;某一類的機率仍可以差到 0.217。一邊是 MLX 4-bit,一邊是 GGUF Q4_K_M。在這 77 篇上,兩種量化沒有改寫標籤。這仍然不是一般準確率。
同一張 16 GB 卡不要兩個模型一起常駐
同一張 16 GB 顯示卡上,若已經常駐一個約 12.2 GB 的聊天模型,再加上 Clef 權重約 5.6 GB 與計算約 0.9 GB,會超過容量。驅動把其中一方換到系統記憶體之後,Clef 由約 140 毫秒變成約 1.1 秒。我們因此改成切換,而不是共存:要跑分類時,先卸下聊天模型,再載入 Clef。約 140 毫秒這組數字來自這張卡的部署紀錄,和研究類型的 p50 266 毫秒不是同一條量測。讀到 NVIDIA 的速度時,要先看當時卡上還有沒有另一個模型。
不要讓長輸入被靜默截斷
需要完整讀入內容的用途,要以 truncate=False 呼叫,要求伺服器在 state 過長時回 413,而不是靜默截斷之後照樣回答。
論文分類和個資稽核都屬於這種用途,判斷要建立在完整內容上。Mac 這條的 state 上限是 16,384 tokens。NVIDIA 這條把 context 設成 4096,而且整個 prompt 必須放進一個 batch。我們的推論是:上限較小的那條,長摘要更容易放不下。託管 Jev 的文件寫的是另一個額度:state 與問題共用約 32,000 tokens,官方換算約 15 萬個英文字元。那是 Jev 文件上的數字,不是這台 Mac,也不是這台工作站。
這像閱卷時只看了摘要的前半段,表格上卻仍然填了一個完整的類別。我們的推論是:靜默截斷時,模型仍會回傳看起來正常的機率,呼叫端無從得知它只讀了前半段。所以截斷要變成明確的錯誤。truncate=False 的做法,就是讓過長的 state 回 413,而不是截完繼續給答案。
用戶端只用 Python 標準庫。沒有設定後端或模型時,它不發出請求,回傳失敗結果。呼叫失敗時,使用 profile 的 on_fail 標籤;study_type 的 on_fail 是 original_research。我們的推論是:標籤以外還要留下錯誤狀態。若一個 413 或一次失敗最後只留下 original_research,讀紀錄的人會以為模型已經判斷過,而那篇論文只是不屬於前八類。
決定要不要用、以及怎麼用,可以逐條對照:
- 題目合不合:選項能事先列成互斥選項,而且你要的是機率而不是一段文字。寫作、摘要、萃取、開放式推理或多步規劃不在這個範圍。
- 資料去哪裡:state 會離開本機、服務又仍是 early access,所以我們用開源的 Clef-flash,不把資料送到託管 Jev。
- Mac:oMLX 的 clef-flash-4bit,state 上限 16,384 tokens,需要 Bearer key。
- 16 GB 顯示卡:BF16 約 18 GB 放不下,改用 Q4_K_M,context 設 4096;卡上若常駐約 12.2 GB 的聊天模型,分類前先卸下。
- 長輸入:需要整段讀完時加上 truncate=False,讓過長變成 413。
- 管線門檻:confidence 達到 0.6 才採用模型,否則用 regex,而且只處理還沒有類型的新論文。
這些數字來自 2026-10-11 的這 77 篇與當天的部署,換一批文章或換一台機器之後不能照抄。