Nemotron Nano 9B v2 Japanese · vLLM 0.15.1 · RTX 5090 · 2026-09-25

Decide, Don't Write

JEV の「書かせずに選ばせる」をローカルの Nemotron 9B で再現し、特許のタグ付けで確かめた記録

soy-tuber · github.com/soy-tuber/nemotron

1回の判定(モデル読み込み済み)
86 ms
同時32件で毎秒36件
確信度0.9以上のときの当たり
82%
それ未満は67%前後
タグが付かない率(入力を差し替え)
14.4% → 2.2%
生成方式のまま、入力だけ変更
本番の「該当なし」
35.3万 → 2.5万
5.3時間で付け直し、失敗0件

要点。JEV の考え方(文章を書かせず、決められた選択肢から1つ選ばせ、その確率を読む)は、汎用の 9B モデルと vLLM の logprobs だけで再現できた。1回の判定は 86 ms で、確信度は当たりやすさと連動する。ところが、特許に複数のタグを付ける仕事では、JEV 方式は当たりやすい代わりにタグが減り、速くもならなかった。いちばん効いたのは方式ではなく、モデルに渡す文章の差し替えだった。

文章を書かせず、選ばせる

JEV は、文章を生成する代わりに、決められた選択肢やスコアを確率付きで返す「判断専用」のモデルとされる。287件のオープンソース事例を調べた一覧(awesome-jev-projects)によると、使われ方はほぼ共通している。大きなモデルが長い文章や推論を受け持ち、JEV はその合間の小さな判断(どの操作か、残すか捨てるか、安全か)を受け持つ。

ここでは JEV そのものではなく、同じ仕組みを手元のモデルで組んだ。リポジトリの decide/ がそれで、既存の Nemotron ゲートウェイの上に乗る。

  1. 各選択肢に1トークンのラベル(A, B, … 尺度なら 1〜5)を振り、選択肢の一覧と一緒に問う。
  2. 思考(reasoning)を切って数トークンだけ生成させ、先頭付近の top_logprobs(上位20件)を受け取る。
  3. ラベル以外のトークンを捨て、ラベルの確率だけで合計が1になるよう割り直す。最大のものが答え、その確率が確信度になる。
  4. 割り直す前のラベルの確率の合計(coverage)が低いときや、確信度が下限を割ったときは、答えを出さずに保留する。

生成した文章は読まないので、一覧にない答えは原理的に返らない。保証されるのは形式であって、中身が正しいことではない。だから確信度と coverage と保留を一緒に返し、迷ったものは人や大きなモデルに回せるようにした。

テストは57件通り、実機では1件も判定できなかった

最初の版は、クラウド上の Claude がリポジトリだけを見て書いた。ゲートウェイの設定やパーサーはリポジトリに入っていなかったので、偽の logprobs を流すモックのテストは誤った前提ごと通った。実機につなぐと、次の順につまずいた。

実機で見つかった食い違い(すべて vLLM とモデルは変えずに直した)
症状原因直し方
全件 404vLLM は --served-model-name なしで起動しており、短い別名が通らない(ゲートウェイはモデルを起動したうえで 404 になる)正式名 nvidia/NVIDIA-Nemotron-Nano-9B-v2-Japanese を使う
全件保留(coverage 0.001)思考オフを /no_think で指示していたが、このモデルのチャットテンプレートには分岐がない。先頭の数トークンが英語の推論になり、ラベルの確率が残らないchat_template_kwargs: {"enable_thinking": false}
制約付きの予備経路が黙って効かなくなるエラーが1回出ると旧名 guided_choice に切り替える作りだったが、vLLM 0.15.1 は未知のフィールドをエラーにせず無視するstructured_outputs に固定し、自動切り替えを削除
まとめて判定すると全件 500接続エラーやタイムアウトを拾っていなかったエラーを1件ごとに閉じ込める
確信度が「較正済み」に見える結果の項目名が calibrated だったmasked に改名(制約なし ≠ 較正済み)

直した後の版で、想定答えを付けた11件のうち9件が一致した。テストは61件(接続エラーなどを追加)。モックのテストは実機との食い違いを検出できないので、変更したら実機で一度流す、を手順に入れた。

1回 86 ms、同時32件で毎秒36件

問い合わせの振り分け(5択)をゲートウェイ経由で繰り返した結果。64件×2回の2回目
同時実行件/秒中央値95%点
111.686 ms89 ms
828285 ms330 ms
3236752 ms1.2 s

速さの出どころはモデルではなく、生成が数トークンで終わることと、vLLM が独立した判定をまとめて処理することにある。ただし同時8件あたりから伸びが鈍る。モデルが止まっているときの最初の1件は、ゲートウェイがモデルを起動するので約40秒かかる。tailnet 越し(Tailscale Serve)でも1回 104 ms だった。

特許のタグ付けでは、当たりやすいがタグが減り、速くならなかった

手元の特許DB(米国特許、CPC の G/H)では、以前から Nemotron に100種類のタグから1〜4個を JSON で書かせている(以下「生成方式」)。これを JEV 方式と比べた。

入力はアブストラクト。一致は Gemini のタグとの比較(300件)、速度とタグなしは1,000件
方式件/秒タグなし先頭タグの一致適合率再現率F1タグ数/件
生成方式19.52.2%70%0.570.500.532.85
JEV 方式12.50%78%0.750.280.411.22
JEV の主タグ+生成方式の追加タグ約7.60%78%——0.58—

JEV 方式は付けたタグが当たりやすい(適合率 0.75 対 0.57)が、1件あたり1.2個しか付けないので取りこぼしが多い。しきい値を変えても、確率の分布が尖っているのでタグはほとんど増えなかった。速度も、2回呼ぶぶん生成方式より遅い。このモデル(Mamba2 とのハイブリッド)では共通部分のキャッシュ(prefix caching)が使えず、呼ぶたびに全文を読み直すことも効いている。両方を組み合わせると F1 は最も高いが、速度は両方の合計になる。

確信度は当たりやすさを示す

JEV 方式の取り柄は、どれだけ自信があるかを数字で返すことだ。1段目(分野)の確信度で区切ると、先頭タグが Gemini と一致する割合ははっきり分かれた。

確信度ごとの、先頭タグが Gemini と一致した割合

JEV 方式、入力はアブストラクト、300件。棒の下は件数

同じ値の表
1段目の確信度件数全体に占める割合先頭タグの一致
0.9以上22174%81.9%
0.7〜0.94615%67.4%
0.5〜0.7269%65.4%
0.5未満72%71.4%

全体の74%を占める「0.9以上」は82%が一致し、それ未満はおおむね3分の2にとどまる(0.5未満は7件しかなく、値は当てにならない)。確信度の低い1割強だけを大きなモデルに回す、という使い方ができる。

いちばん効いたのは、方式ではなく入力だった

比較の途中で、生成方式が使っていた入力に問題が見つかった。本番のタグ付けは、特許の要約欄の先頭400字を読ませていた。ところがその25%は出願の定型文(CROSS REFERENCE TO RELATED APPLICATION …)で、発明の中身が書かれていない。モデルは正直に空の配列を返し、それが「該当なし」として残っていた。

例:「Gate drive circuit」の要約欄の先頭は、中国出願の優先権主張の定型文だけ。アブストラクトなら “A gate drive circuit is disclosed. The gate drive circuit comprises multi-stage of GOA drive unit …” と、発明そのものが書いてある。

入力をアブストラクト(別表にあり、サンプルの1,000件すべてに存在、中央値770字)に替えるだけで、生成方式のままタグが付かない率は 14.4% から 2.2% に下がった。以前「該当なし」になった207件のうち199件にタグが付いた。

本番への反映

「該当なし」の付け直し(生成方式、入力はアブストラクト)
項目値
対象(付け直し前の「該当なし」)353,242件
タグが付いた328,410件(93%)
「該当なし」のまま24,832件
通信失敗0件
所要時間5.3時間(毎秒18.6件)

あわせて二つ直した。一つは、通信の失敗まで「該当なし」と同じ値で保存していたことで、これでは二度と処理し直されない。失敗は未処理のまま残すようにした。もう一つは全文検索の索引で、全体を作り直すスクリプトは索引を消してから全件を入れ直すため、その間は検索が空になる。索引は行単位で消せる設定(FTS5 の contentless_delete=1)だったので、タグが変わった328,410行だけを差し替えた。87秒で終わり、検索は止まらなかった。

JEV が向くところ、向かないところ

向く:1つ選んで、自信の程度も知りたい

  • 問い合わせや作業の振り分け
  • はい/いいえの審査(付いたタグが本当に当てはまるかの確認など)
  • 絞り込んだ候補の中から1つ選ぶ
  • 迷ったものだけ大きなモデルや人に回す

向かない

  • 複数のタグを漏れなく付ける仕事(1件1.2個しか付かない)
  • 速度を上げたいだけの場面(段数が増えると遅くなる)
  • 実時間の制御ループ(1回86 ms、GPU 1枚)
  • 要約や抽出など、文章そのものが要る仕事

この結果が言っていないこと

次にやるなら

再現する

decide/ は OpenAI 互換のエンドポイントに話すだけで、vLLM とは別の環境で動く。

git clone https://github.com/soy-tuber/nemotron && cd nemotron
uv venv decide/.venv --python 3.12
uv pip install --python decide/.venv/bin/python -r requirements-decide.txt pytest

# ゲートウェイ(既定 http://localhost:8000/v1)に向けて判定する
decide/.venv/bin/python -m decide.cli route_inquiry --var input="先月の請求が二重に引き落とされています"

# 速度を測る / テスト(モック、GPU 不要)
decide/.venv/bin/python -m decide.bench --decision route_inquiry --repeat 64 --concurrency 1 8 32
decide/.venv/bin/python -m pytest

接続先は NEMOTRON_GATEWAY_URL、モデルは NEMOTRON_DECIDE_MODEL で変えられる。詳しくは decide/README.md。特許タグ付けの試行スクリプトとデータは公開していない。