Jev-like Python 包裝器,使用 token logprobs 進行 LLM 和視覺模型操作

TL;DR – 包裝器的功能與重要性

作者建立了一個最小的 Python 包裝器,可將 Jev 風格的請求(狀態、問題、可選的影像附件)發送到任何 Chat Completion 端點,要求模型輸出 一個 token(代表所選選項的字母),並讀取所有候選 token 的 log-probabilities。此技術將生成式 LLM 轉化為低成本、低延遲的分類器,適用於純文字與視覺增強模型。


核心概念 – 使用 log-probs 將生成轉為分類

  • 提示格式 – 包裝器會建立一個提示,列出狀態、問題與以 [A]、[B] … 標記的選項,最後加上指令 「僅以最佳選項的字母作答。」 範例:
    狀態:
    檢查此網路攝影機畫面。僅根據可見內容判斷。
    
    問題:可見有人嗎?
    選項:
    [A] true
    [B] false
    
    僅以最佳選項的字母作答。
    
  • API 參數 – 請求包含:
    {
      "max_completion_tokens": 1,
      "logprobs": true,
      "top_logprobs": 20,
      "temperature": 0
    }
    
    將 max_completion_tokens 設為 1 可強制模型輸出單一 token,使回應極小且延遲低。
  • log-prob 提取 – API 回傳前 N 個 token 候選及其 log-probabilities。包裝器透過將每個選項字母對應至 token,將這些 log-prob 轉換為選項上的歸一化機率分佈。
  • 結果解讀 – 對於二元問題(noul 類型),包裝器回傳 true 的機率。對於多選題,回傳最可能的選項與完整機率表。對於序數評分,則計算期望值。

擴展 Jev 至視覺 – attachments 欄位

  • 原始 Jev 規格僅支援文字/JSON 的 state。作者新增了 attachments 陣列,可包含檔案路徑或 base64 編碼的資料 URL。
  • 當請求發送到 OpenAI 端點時,每張影像會以 type: "input_image" 元素加入;對於 llama.cpp 則以 type: "image_url" 加入。
  • 範例使用 OpenCV 捕捉即時網路攝影機畫面,將其編碼為 JPEG,包裝成資料 URL,並在每次請求前放入 attachments。

端到端 Python 範例(約 150 行)

該腳本在迴圈中執行三個步驟:

  1. 擷取 /dev/video0 的畫面幀。
  2. 編碼 畫面為 base64 JPEG,並設定 data["attachments"]。
  3. 提交 請求至所選後端(本地的 llama.cpp 伺服器或 OpenAI),使用背景執行緒。
  4. 列印 包含最新答案與測量 FPS 的表格。

關鍵函數:

  • score(data, url, model) – 為每個問題建立提示,發送請求,歸一化 log-probs,並回傳結構化答案字典。
  • main – 解析 CLI 參數(url 與 model),啟動網路攝影機,並協調非同步評分。

此腳本刻意自包含;唯一外部相依是 opencv-python 用於網路攝影機存取。其他所有函式庫皆為 Python 標準程式庫的一部分。


作者報告的效能數字

後端 模型 硬體 FPS(幀/秒)
llama.cpp(本地) Gemma‑4‑12B‑QAT(GGUF) RTX 3090 ≈ 1 fps(每幀三題)
OpenAI gpt‑6‑luna 雲端 ≈ 0.2 fps

作者指出,OpenAI 執行較慢的部分原因在於每幀會為每個問題建立 新的 HTTP 連線,此處可優化。


本地 llama.cpp 伺服器設定說明

# 1. 下載 7 GB 的 Gemma‑4‑12B 模型及其多模態投影器(約 175 MB)
mkdir -p ~/models/gemma-4-12b/
cd ~/models/gemma-4-12b/
curl -fL -C - -o gemma-4-12b-it-qat-q4_0.gguf \
  https://huggingface.co/google/gemma-4-12B-it-qat-q4_0-gguf/resolve/main/gemma-4-12b-it-qat-q4_0.gguf
curl -fL -C - -o mmproj-gemma-4-12b-it-qat-q4_0.gguf \
  https://huggingface.co/google/gemma-4-12B-it-qat-q4_0-gguf/resolve/main/mmproj-gemma-4-12b-it-qat-q4_0.gguf

# 2. 安裝 CUDA‑86 的 llama.cpp 二進位檔
curl -fL -o llama.zst \
  https://huggingface.co/buckets/ggml-org/install.sh/resolve/b11160/x86_64/linux/cuda/86/llama-app.zst
mkdir -p ~/bin/
zstd -d llama.zst -o ~/bin/llama
chmod +x ~/bin/llama

# 3. 在 8060 端口啟動伺服器
~/bin/llama serve --models-dir ~/models/ --port 8060

伺服器啟動後,執行包裝器:

uv run webcam.py http://localhost:8060/v1 gemma-4-12b
# 或使用 OpenAI(需先設定 OPENAI_API_KEY)
uv run webcam.py https://api.openai.com/v1 gpt-6-luna

社群反應(選取 HN 評論)

@TeMPOraL – 「這就是我們如何實現星際迷航風格的環境感知:從多模態情境中推斷意圖並自動行動。」 評論強調了此包裝器在即時意圖偵測上的廣闊願景,超越簡單分類。

@prathje – 「這只是基於語法的解碼,並以 JSON 回應?如果是這樣,Jev 本質上只是在那之上加了一層快取。」 作者的實作確實依賴於決定性提示與 token 級 logits,這類似於語法約束解碼,但增加了輕量級快取策略以處理重複的狀態前綴。

@frabcus – 「以 RLHF 訓練的普通 LLM 可能在網路早期就做出決定,因此 Jev 風格的 log-prob 包裝器可能比專為校準決策訓練的模型準確度較低。」 此點指出潛在限制:一般模型的機率校準可能不適合下游決策。

@arcticbull – 「這就像 Jev,但成本與速度差了好幾個數量級。」 評論反映了通用 LLM 的彈性與專用視覺分類器效率之間的權衡。

@CROON_tv – 「我希望看到尾部延遲的數字;在我們的即時語音端點中,Jev 比使用相同提示的普通 LLM 更快且更不猶豫。」 延遲是互動應用的關鍵指標,而包裝器的單 token 方法有助於維持低尾部延遲。

@czl_my – 「我建立了一個可與任何 OpenAI 兼容端點搭配使用的 Jev 包裝器:https://github.com/zhulinchng/jevper。」 外部實作顯示此概念正逐漸受到關注。


局限與開放問題

  • 機率校準 – 普通模型的原始 log-probs 可能未良好校準,特別是對稀有 token。使用者可能需要溫度縮放或事後校準。
  • 遺失 token 處理 – 包裝器將任何未出現在 top-N 列表中的選項視為機率為零,但若遺失機率超過 1e‑6 則會拋出錯誤。此安全檢查可防止靜默的錯誤排序。
  • 可擴展性 – 每個問題發送獨立請求(範例中每幀三題)會增加網路開銷。將多個問題合併至單一提示可提升吞吐量。
  • 視覺模型選擇 – 雖然 Gemma‑4‑12B 可用,但專用多模態模型(如 CLIP、Florence)可能達到更高的 FPS 與更好的視覺準確度。

結論

所發布的包裝器展示了一種實用、語言模型無關的方法,可利用 token 級 log-probabilities,將任何 Chat Completion API(包括視覺增強後端)轉化為快速、決定性的分類器。其簡單性(僅一個 Python 函數)與支援影像附件的能力,使其成為即時多模態決策系統的有用元件,儘管仍需注意機率校準與每問題請求開銷的常見限制。

Sources