kikuta@dev:~$cat ./notes/direct-logits-vs-json-generation.md
·10 min·kikuta

LLMのJSON生成をやめてoption logitsを直接読む性能比較

Qwen3.5-4Bでdirect readoutとyes/no JSON生成を同一state・21 criteriaで比較し、速度・精度・校正上の差を測る。

binary decisionにautoregressive generationを使う必要があるか

入力stateに対してruntime-definedなcriterionを多数評価し、最終結果がyes/noの二択だけなら、JSON文字列を生成してparseする経路は必須ではありません。OpenJEVでは各criterionに対するoption tokenのlogitを直接取り出し、二つのscoreからdecisionを作る経路を実装しました。

固定classifier headではなく、criterion自体は自然言語でruntimeに与えます。違いは出力段だけで、文章生成を完了する代わりに候補tokenのreadoutで停止します。

21 criteriaでは1.023秒対5.332秒

同一model・同一stateで21 criteriaを処理した比較では、parallel direct readoutのmedianは1.023秒でした。baselineはordered JSON arrayとして21個のyes/noだけを生成させ、median 5.332秒、time-to-first-token 0.489秒、111 output tokensでした。

さらにwhitespaceを削った厳密なminified arrayも試しましたが、modelが21要素を超えて値を繰り返し、3回とも128-token capへ到達したためfailureとして扱いました。structured outputを短く指示しても、decode loop自体のtermination問題は残ります。

semantic qualityは別workloadで評価する

Qwen3.5-4B direct logitsはauthored 144 rowsでmean family balanced accuracy 0.813、WANLI 256 rowsで0.637、TypeSafe subset 102 rows / 20 casesでreference agreement 0.845でした。4B rerankerは同じauthored workloadで0.625、WANLIで0.522でした。

retrieval taskではrerankerのMRRが1.0でも、general decision accuracyは別でした。ranking品質とruntime-defined binary decisionを同じmetricへ畳まず、用途ごとに評価対象を分けています。

shared-state reuseでthroughputが変わる

one RTX 3090でのfrozen workloadでは、direct fresh batch-1が2.33 decisions/s、serial state-prefix reuseが10.75 decisions/s、parallel suffixesが20.03 decisions/sでした。同じstateに多数のcriterionを掛けるため、state側の計算を繰り返さないことが効いています。

一方、rerankerはbinary decisionごとにstate/question/optionの評価を二回行うため、pair batch 1〜8では1.76〜1.86 decisions/sに留まりました。batchを増やしてもshared-state computationを回収できない構造ではthroughputが伸びません。

logit scoreを校正済み確率として扱わない

direct logitsはoption reversalでaccuracy 0.813でしたが10件のflipがあり、missing-evidence 36 rowsでは0.8を超えるscoreでinsufficient以外を選ぶケースもありました。高速にscoreを取れることと、そのscoreが運用可能なconfidenceであることは別です。

次の課題はdecode最適化ではなくcalibrationです。held-out operational dataset、abstention条件、option-order robustnessを固定してからthresholdを決める必要があります。