Nemotron Nano 9B v2 Japanese · vLLM 0.15.1 · RTX 5090 · 2026-09-25
Decide, Don't Write
JEV の「書かせずに選ばせる」をローカルの Nemotron 9B で再現し、特許のタグ付けで確かめた記録
要点。JEV の考え方(文章を書かせず、決められた選択肢から1つ選ばせ、その確率を読む)は、汎用の 9B モデルと vLLM の logprobs だけで再現できた。1回の判定は 86 ms で、確信度は当たりやすさと連動する。ところが、特許に複数のタグを付ける仕事では、JEV 方式は当たりやすい代わりにタグが減り、速くもならなかった。いちばん効いたのは方式ではなく、モデルに渡す文章の差し替えだった。
文章を書かせず、選ばせる
JEV は、文章を生成する代わりに、決められた選択肢やスコアを確率付きで返す「判断専用」のモデルとされる。287件のオープンソース事例を調べた一覧(awesome-jev-projects)によると、使われ方はほぼ共通している。大きなモデルが長い文章や推論を受け持ち、JEV はその合間の小さな判断(どの操作か、残すか捨てるか、安全か)を受け持つ。
ここでは JEV そのものではなく、同じ仕組みを手元のモデルで組んだ。リポジトリの decide/ がそれで、既存の Nemotron ゲートウェイの上に乗る。
- 各選択肢に1トークンのラベル(
A,B, … 尺度なら1〜5)を振り、選択肢の一覧と一緒に問う。 - 思考(reasoning)を切って数トークンだけ生成させ、先頭付近の
top_logprobs(上位20件)を受け取る。 - ラベル以外のトークンを捨て、ラベルの確率だけで合計が1になるよう割り直す。最大のものが答え、その確率が確信度になる。
- 割り直す前のラベルの確率の合計(
coverage)が低いときや、確信度が下限を割ったときは、答えを出さずに保留する。
生成した文章は読まないので、一覧にない答えは原理的に返らない。保証されるのは形式であって、中身が正しいことではない。だから確信度と coverage と保留を一緒に返し、迷ったものは人や大きなモデルに回せるようにした。
テストは57件通り、実機では1件も判定できなかった
最初の版は、クラウド上の Claude がリポジトリだけを見て書いた。ゲートウェイの設定やパーサーはリポジトリに入っていなかったので、偽の logprobs を流すモックのテストは誤った前提ごと通った。実機につなぐと、次の順につまずいた。
| 症状 | 原因 | 直し方 |
|---|---|---|
| 全件 404 | vLLM は --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件
| 同時実行 | 件/秒 | 中央値 | 95%点 |
|---|---|---|---|
| 1 | 11.6 | 86 ms | 89 ms |
| 8 | 28 | 285 ms | 330 ms |
| 32 | 36 | 752 ms | 1.2 s |
速さの出どころはモデルではなく、生成が数トークンで終わることと、vLLM が独立した判定をまとめて処理することにある。ただし同時8件あたりから伸びが鈍る。モデルが止まっているときの最初の1件は、ゲートウェイがモデルを起動するので約40秒かかる。tailnet 越し(Tailscale Serve)でも1回 104 ms だった。
特許のタグ付けでは、当たりやすいがタグが減り、速くならなかった
手元の特許DB(米国特許、CPC の G/H)では、以前から Nemotron に100種類のタグから1〜4個を JSON で書かせている(以下「生成方式」)。これを JEV 方式と比べた。
- 対象:G/H から無作為に選んだ1,000件。同時32件、ゲートウェイ経由。
- JEV 方式:まず11の技術分野から1つ選ばせ、次にその分野の中のタグから選ばせる(1件あたり約2回)。2番目の分野の確率が0.3以上なら、そちらのタグも採る。
- 正解の目安:うち300件に Gemini 3.8 Flash で同じ100タグから付けさせたもの。
| 方式 | 件/秒 | タグなし | 先頭タグの一致 | 適合率 | 再現率 | F1 | タグ数/件 |
|---|---|---|---|---|---|---|---|
| 生成方式 | 19.5 | 2.2% | 70% | 0.57 | 0.50 | 0.53 | 2.85 |
| JEV 方式 | 12.5 | 0% | 78% | 0.75 | 0.28 | 0.41 | 1.22 |
| JEV の主タグ+生成方式の追加タグ | 約7.6 | 0% | 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以上 | 221 | 74% | 81.9% |
| 0.7〜0.9 | 46 | 15% | 67.4% |
| 0.5〜0.7 | 26 | 9% | 65.4% |
| 0.5未満 | 7 | 2% | 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枚)
- 要約や抽出など、文章そのものが要る仕事
この結果が言っていないこと
- Gemini のタグは正解ではなく目安にすぎない。1件平均3.2個と多めに付けるので、再現率はどの方式でも低めに出る。
- 一致の評価は300件なので、数ポイントの差は誤差の範囲。
- 試したのは Nemotron Nano 9B v2 Japanese と vLLM 0.15.1、RTX 5090 1枚の組み合わせだけ。
- 対象は米国特許の CPC G/H だけ。11分野の分け方は今回の試作。
- 本物の JEV は試していない。汎用のモデルで、考え方を再現したものにすぎない。
次にやるなら
- 多めに付きがちなタグ(無関係な特許に付く「AI」など)だけ、JEV 方式のはい/いいえで確かめて外す。付いている特許だけを見ればよいので軽い。
- 分野・主タグ・確信度を別の列として足し、確信度0.7未満だけを大きなモデルで付け直す。
- 返させる候補の数を減らし、生成トークンを1〜2に絞って、判定の処理数を上げる。
再現する
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。特許タグ付けの試行スクリプトとデータは公開していない。