跳到主要內容

25 行 Python 拆穿 Jev:用下一個字的機率讓 LLM 做選擇題

閱讀時間約 7 分鐘

先說結論

最近社群吵得很熱的 Jev,被一篇諷刺文用 25 行 Python「重現」了:把選項編成 A、B、C,讓模型只算下一個字,再讀出這三個字的機率。這篇帶你一行一行走過那段程式,看懂「用 logits 做分類」到底在做什麼,也順便看清楚:這個簡化版漏掉了哪些真正困難的部分。

它想解決的問題:讓 LLM 給出「一個答案加一個信心」

很多實務工作只需要模型做選擇:這封信是正常、垃圾還是釣魚?用聊天方式問,模型會回一段話,你還得解析,也拿不到「它有多確定」。原文作者的主張是:Jev 說穿了就是拿到一個有選項的 prompt,輸出每個選項的機率,而這件事用本地的小模型就能做到——快、在本機跑、資料不用送去別的地方。

動手走一遍:一封可疑的薪資信

第一步:載入一顆小模型

原文用 llama-cpp-python 載入 Qwen3-0.6B 的 GGUF 量化版,作者註明任何 GGUF 模型都可以。

關鍵參數是 logits_all=True:要求程式保留每個位置的 logits。logits 是模型在「選下一個字」之前,對詞彙表裡每個 token 打的原始分數,還沒轉成機率。

第二步:把問題寫成選擇題

labels = ["A", "B", "C"]
choices = ["Legitimate", "Spam", "Phishing"]
email = "Payroll asks for your password on a non-company sign-in page."

範例信件是「薪資部門要你在非公司的登入頁面輸入密碼」。prompt 用 Qwen 的對話格式組成,system 只說 Choose one option.。

細節是:assistant 開頭預先塞了一組空的 <think></think>。Qwen3 會先「思考」再回答,這等於告訴它思考已結束,下一個字直接就是答案。

第三步:只跑一次前向計算

model.eval(...) 把 prompt 丟進模型,不生成文字,只取最後位置的 logits,也就是「接下來最想說什麼」的分數表。

第四步:從幾萬個分數裡,只挑三個出來

token_ids = [model.tokenize(text=label.encode(), add_bos=False)[0] for label in labels]
choice_logits = numpy.asarray([logits[token_id] for token_id in token_ids])
logprobs = choice_logits - numpy.logaddexp.reduce(choice_logits)
probabilities = numpy.exp(logprobs)

查出 A、B、C 的 token 編號,只取這三格分數,再做 softmax(轉成加總為 1 的機率)。

原文的輸出:

選項logit機率
Legitimate26.2540.031
Spam27.2620.084
Phishing29.6140.885

模型以 88.5% 判定這是釣魚信。我自己驗算了一下:三個 logit 之間只差 1 到 3 分,但指數放大後,差距就變成約 3% 對 88%。這也提醒我們,logit 的小差距會被 softmax 大幅放大。

簡化版漏掉的東西

原文自己也承認這是諷刺文。它刻意列出「我們沒做的事」:沒叫它 System One decision model、沒呼叫 API、沒造合成資料、也沒用 RLCD(Reinforcement Learning for Calibrated Decisions,針對校準決策的強化學習)去訓練。文末還附上了更完整的開源實作 OpenJev 等連結。

HN 討論剛好補上了這些差距:

  • 第一個 token 不等於答案:sigmoid10 指出,聊天模型被訓練成寫句子,它可能其實想說「A phishing attempt seems likely…」,這時第一個字 A 反而拿到最高分。他建議改用結構化輸出,直接限制模型只能生成 Legitimate、Spam、Phishing 這幾個完整的詞。
  • 選項該放前面:antirez 提到,LLM 的注意力是單向遮罩的,前面的字看不到後面。把選項放在信件之前,模型讀信時就已經知道要找什麼;另一個技巧是把題目和標籤重複一次。
  • 沒有比較數據:有留言指出文中沒有延遲、運算量和錯誤率的比較。

換句話說,這 25 行抓到的是骨架;真正難的是讓 88.5% 名副其實——說 88% 時真的約有 88% 會對。這就是「校準」,也是原文點名卻沒做的部分。

適合與不適合的場景

適合:標籤固定、數量少的分類;資料不能送到外部 API 的場景;需要分數當門檻,低於某個機率就轉人工。

不適合:需要先推理才答得出來的題目,因為這裡把思考關掉了;也不適合把機率直接當可靠信心——沒校準的小模型,數字好看不代表準。

延伸思考

  • 諷刺文反而是好教材:它把被包裝成「新典範」的東西拆回零件,讓人看清哪些是通用技巧、哪些才是附加價值。
  • 價值在校準,不在管線:讀 logits 誰都會,評估這類產品時該先問校準怎麼驗證。
  • 提示設計仍左右結果:選項順序、重複題目、第一個 token 是否被污染,都會改變那個看似精確的機率。
  • 留意「我也做了一個」的熱潮:HN 上已有人抱怨許多號稱重現 Jev 的示範經不起細看。

參考來源

回應

0 / 1000

還沒有回應,成為第一個留言的人吧。