
生成しない決定モデル CLM を、Switchyard の判定役として DGX Spark で試してみた
はじめに
こんにちは、クラスメソッド製造ビジネステクノロジー部の森茂です。
CLM(Contrastive Language Model)というモデルが Apache 2.0 で公開されました。名前に Language Model と付いていますが、文章は書きません。いまの状態と候補の行動を別々に埋め込み、どの候補が一番合うかを選ぶことだけをするモデルです。README は TypeSafe の Jev を比較相手に置き、Jev と同じ形の API で呼べることも売りにしています。
つい先日、生成しない判定を 2 本の記事で扱いました。OpenJev の実装を読み比べた記事(2026-09-18 時点の記事です)と、NeMo Switchyard で依頼を weak と strong に振り分けている Nemotron 3.5 Lightning の判定役を、1 トークン判定に作り替えた記事(2026-09-23 時点の記事です)です。後者では Jev にも同じ判定をさせていて、評価セットと比べ方がそのまま手元に残っています。重みまで公開された汎用の決定モデルが出たなら、同じ物差しに乗せない手はありません。
先に結論を書いておくと、zero-shot の CLM は Switchyard の判定役として Jev に届きませんでしたが、head だけを学習し直すと、埋め込みを含めて 8 分ほどで Jev 並みの精度に届きました。 zero-shot で Jev と同じ問いを渡すと、strong が要る依頼も含めてほぼ全件を weak と答え、未見の 237 件の誤送は Jev の 10 件に対して 42 件です。同じ 237 件の AUC は、学習し直した head で 0.892 と Jev の 0.856 を上回りました。ただし、学習データにあった偏りも一緒に覚えています。速さは設計どおりで、候補の埋め込みがキャッシュに載っていれば、候補が 2 個でも 1000 個でも 1 回の判定は約 110 ms です。
この記事では、CLM の仕組みと強みを一次情報で整理したうえで、DGX Spark で動かし、9/23 の記事と同じ 528 件で Jev や現行の判定役と並べた結果を紹介します。
CLM は状態と行動を別々に埋め込んで比べる
CLM の中身は単純です。凍結した Qwen3-8B で文章を 4096 次元のベクトルにし、その上に小さな MLP を 2 つ載せています。1 つは状態(いまの会話や質問)を 512 次元に写す state head、もう 1 つは候補の行動を同じ空間に写す action head です。点数は 2 つのベクトルのコサイン類似度に学習済みの倍率を掛けたもので、候補の中で softmax を取って確率にします。
学習は双方向の InfoNCE で、状態から正しい行動を当てる向きと、行動から正しい状態を当てる向きの両方を鍛えています。README によると 3 段階で、Nemotron DQA の質問と答え約 6,000 万組で下地を作り、Gemini 2.5 Flash-Lite に作らせた紛らわしい誤答約 3,000 万件で細かい見分けを覚えさせ、エージェントの軌跡約 100 万件で行動の選び方に寄せています。README は、学習の損失が計算量、モデルの大きさ、データ量に対してべき乗則で下がることも示していて、大きいバックボーンへの拡張がロードマップの先頭に置かれています。
CLM の強みは候補の使い回しと、手元で学習し直せること
仕組みが分かったところで、CLM が何を売りにしているかを見ていきましょう。
1 つ目は、状態と候補を別々に埋め込むことです。候補側の埋め込みは一度計算すれば使い回せるので、候補が増えても判定のたびに払うのは状態 1 本の encode だけになります。README はこの性質を、実行中のエージェントのツール選び、複数の解答からの 1 つの選択、検索結果の絞り込みに同じ呼び出しで使えると説明しています。モデルカードの「約 1000 候補で Jev の 13 倍速い」もこの性質から来ていて、後半で DGX Spark でも確かめました。
2 つ目は、呼び方が Jev と揃っていることです。clm-serve は TypeSafe 互換の POST /v1/systemone を返し、はい・いいえの確率を返す Noul、候補から 1 つを選ぶ Choice、順序つきの段階で採点する Score の 3 つの型をそのまま受け付けます。同梱の T-Rex の比較スクリプトは、CLM と Jev でベース URL と API キーしか変えていません。候補を自由に並べ替える POST /v1/rank と、ブラウザで状態と質問を書いて試せる playground も付いています。
3 つ目は、重みとコードがどちらも Apache 2.0 で、自分の GPU で動かし、学習し直せることです。学習するのは Qwen3-8B ではなく上に載った head だけで、train/finetune.py が公開されています。DeepSWE 向けに学習し直した head は Hugging Face に、その結果を再現する手順は README に置かれています。
Jev と並べると、違いは次のようになります。CLM の数字は README とモデルカードに書かれた CLM 側の主張です。
| 項目 | CLM-8B | Jev |
|---|---|---|
| 提供の形 | 重みとコードを Apache 2.0 で公開。自前の GPU で動かす | TypeSafe の API と OpenRouter で提供。重みは非公開 |
| 仕組み | 凍結した Qwen3-8B と 2 つの head。双方向 InfoNCE で学習 | 非公開。学習方法は確率の校正を狙う RLCD と説明されている |
| 呼び出し方 | TypeSafe 互換の /v1/systemone と、並べ替え用の /v1/rank |
TypeSafe の API、OpenRouter の decisions エンドポイント |
| 自分の仕事への調整 | head だけを手元で学習し直せる | 重みが非公開なので、利用者側で学習し直す手段はない |
| CLM 側が示す速さ | zero-shot で最大 9 倍、約 1000 候補で 13 倍、verifier で 4〜6 倍 | — |
CLM 側の公表値も見ておきます。まず、学習し直していない zero-shot の 4 タスクです。README の図から数字を抜き出しました。
| タスク | CLM latency | Jev latency | CLM 成功 | Jev 成功 |
|---|---|---|---|---|
| T-Rex Game | 16.5 ms | 149.8 ms | 5/5 | 5/5 |
| Tool calling BFCL v4 | 76.8 ms | 125.5 ms | 95.2% | 99.2% |
| WikiRacing | 79.8 ms | 225 ms | 26/30 | 30/30 |
| Super Mario | 33.5 ms | 132.6 ms | 5/5 | 5/5 |
README はこれを「Jev と同等で、最大 9 倍低遅延」とまとめています。成功率は BFCL と WikiRacing で Jev が少し上回り、速度の比較には前提があります。同梱の T-Rex の手順書では、CLM を RTX 4090 1 枚で動かし、Jev は TypeSafe がホストする jev-latest をネットワーク越しに呼んで、クライアント側で時間を測っています。
もう 1 つの看板は、head を学習し直して verifier、つまり複数の解答候補から正解らしいものを選ぶ役に使った結果です。
| 課題 | 候補数 | CLM | Jev | 1 回で解けた率 | CLM / Jev latency |
|---|---|---|---|---|---|
| DeepSWE(38 件) | 4 | 81.6% | 71.1% | 73.7% | 79 / 449 ms |
| Terminal-Bench 2.1(30 件) | 5 | 87.6% | 83.1% | 84.0% | 32 / 131 ms |
解答候補は DeepSWE が Opus 5、Terminal-Bench 2.1 が Fable 5 の生成で、latency は H100 での値です。Jev は 2 課題とも 1 回で解けた率を下回っていて、長い課題の verifier としては働かなかったと README は書いています。学習し直した小さな head で、選ぶ役の精度を 1 回で解けた率より上に押し上げている点は、方向性としてかなり面白いですね。ただしこれは学習し直した head の値で、評価も 38 件と 30 件です。モデルカードの制約欄にも、この値は zero-shot のチェックポイントのものではないと書かれています。
DGX Spark で CLM を動かす
構成は 2 プロセスです。vLLM で Qwen3-8B を埋め込み用(pooling)に立て、その前に clm-serve を置きます。
DGX Spark で詰まりやすい点が 2 つありました。1 つ目は、pip install contrastive-lm が依存の vllm を解決しようとして、aarch64 では古い vllm のソースビルドに落ちて失敗することです。パッケージ本体は純 Python なので、vLLM の aarch64 イメージの中へ --no-deps で入れれば動きます。2 つ目は入力の上限です。既定の 2048 トークンを超えた状態は切り詰められ、今回の入力は最大 2,883 トークンあったので、vLLM と clm-serve の両方を 4096 に上げました。
# embedding server (Qwen3-8B, last-token pooling)
docker run -d --name clm-emb --gpus all --ipc host --network host \
-v ~/.cache/huggingface:/root/.cache/huggingface --entrypoint vllm \
vllm/vllm-openai:v0.25.0-aarch64 serve Qwen/Qwen3-8B --served-model-name qwen3-8b \
--runner pooling --enable-prefix-caching --max-model-len 4096 --gpu-memory-utilization 0.30 --port 8090
# clm-serve (heads are downloaded to ~/.cache/clm on first start)
docker run -d --name clm-serve --gpus all --network host \
-v ~/works/clm/wheels:/wheels:ro -v ~/.cache/clm:/root/.cache/clm \
--entrypoint bash vllm/vllm-openai:v0.25.0-aarch64 \
-c "pip install -q --no-deps /wheels/contrastive_lm-0.1.0-py3-none-any.whl && exec clm-serve --port 8700 --max-tokens 4096"
/v1/models には clm-latest と clm-raw の 2 つが並びます。clm-raw は head を通さず、生の埋め込みのコサイン類似度で選ぶ比較用のモデルです。
この記事の物差し
評価は 9/23 の記事と同じ 528 件の入力で行いました。Switchyard の判定役は、依頼の会話と一緒に system prompt を受け取ります。system prompt には、判定の手順、weak 側のエージェントに任せてよい仕事と任せにくい仕事の規則、そして依頼元のエージェントがいま使えるツールを書いた実行環境の節が入っています。実行環境の節は、依頼ごとの環境に合わせて差し込む部分です。CLM と Jev には、この規則と実行環境の節を会話と一緒に状態として渡し、「この依頼は weak で足りるか」の二択を聞きます。
| 評価セット | 中身 | 見たいこと |
|---|---|---|
| 実運用 87 件 | 本番経路を流れた形の依頼。採点は 81 件 | 誤送と安全側の件数 |
| 実装課題 30 件 | weak で解けると実測で分かっている実装課題。実行環境の節の有無で 2 版 | weak に流せた数 |
| 見極め 14 問 | weak が 2 回失敗し strong なら通った難問 | strong に残せた数 |
| 設計相談 10 件 | コードを書かない設計の壁打ち。strong が要る | strong に残せた数 |
| 環境ペア 80 件 | 同じ依頼で実行環境の節のツール可否だけ変えた 40 ペア | 実行環境の違いで判定が動くか |
| holdout 237 件 | 判定役の学習に使っていない、参照判定つきの依頼 | 誤送と安全側の件数 |
誤送は strong が要る依頼を weak に送ること、安全側は weak で足りる依頼を strong に送ることです。数える誤りは誤送だけです。判定規則も Jev と同じ手順で決めました。開発用の分割(別の 40 件と、実運用 87 件の半分)だけを見て「confidence がいくつ以上なら選択を採り、それ未満は strong に送るか」を選び、残りのセットを見る前に凍結しています。CLM は同じ入力に同じ答えを返すので反復は 1 回、Jev は 3 回の多数決です。
Jev と同じ問いでは、ほぼ全件が weak になった
最初に、Jev と一字一句同じ質問文と選択肢の説明で CLM に聞きました。結果は、ほぼ全件が weak です。
strong が要るはずの設計相談 10 件で、P(weak) の中央値は 0.967 でした。見極め 14 問は中央値 0.975 です。weak で足りる実装課題と、確率の帯がほとんど重なっています。規則は confidence 0.9 以上で凍結されましたが、CLM の confidence はほぼ常に 0.9 を超えるので、規則を通しても結論は変わりません。実運用 87 件では strong が要る 25 件中 23 件、設計相談は 10 件中 9 件、見極め 14 問はすべてを weak に送りました。
確率の帯が狭いだけで、並び順には情報が残っているのかもしれない。そう考えて、閾値に依存しない AUC(weak が要る依頼のほうに高い P(weak) を付けられている確率)も出しました。0.5 が当てずっぽう、1.0 が完全な並び分けです。
| 判定役 | AUC 全体 | 実運用 87 件 | 環境ペア | holdout |
|---|---|---|---|---|
| CLM(Jev と同じ問い) | 0.581 | 0.414 | 0.615 | 0.535 |
| Jev(同じ問い、1 回目の答え) | 0.901 | 0.999 | 0.994 | 0.856 |
全体の値は、規則の凍結に使った 40 件を除いています。CLM は 0.5 からあまり離れず、実運用 87 件では 0.41 と逆向きに並んでいます。環境ペアで、正しい行き先が E0 と E1 で分かれる 17 ペアを見ると、weak 側に高い P(weak) を付けたのは 3 ペアだけでした。実運用 87 件で予備的に試した範囲では、状態を JSON 文字列で渡しても(0.424)、head を外しても(0.112)改善しません。問いを英語にすると 0.86 まで上がりましたが、ほかのセットでは下がり、言語を変えれば解決する話でもなさそうです。
候補を行き先の説明に書き換える
ここで気になるのが、CLM は何と何を比べているかです。実装を読むと、choice の候補として埋め込まれるのは、選択肢の説明文そのものでした。Jev 向けに書いた説明は「効率型エージェントで足りる依頼。仕様が依頼文か……」という長い判定基準で、weak と strong の説明の違いは、ほぼ否定の有無に集約されています。事前学習が質問と答えの対応で、事後学習が状態と次の行動の対応なら、抽象的な判定基準の文より、行き先そのものを書いたほうが噛み合うのではないか。そう考えて、候補の書き方を 3 通り試しました。
選ぶときに見たのは、実運用 87 件と規則の凍結に使う開発用の分割だけです。未見のセットは、書き方を 1 つに決めてから流しました。
| 候補の書き方 | 実運用 87 件 AUC |
|---|---|
| Jev と同じ日本語の判定基準 | 0.414 |
| 短い英文 2 行(小さなモデルで足りる / 最上位モデルが要る) | 0.516 |
weak と strong の語だけ |
0.359 |
| 行き先のモデル名と得意分野の英文 | 0.936 |
最後の書き方では、質問文も「どのモデルが最新の依頼を扱うべきか」に変え、選択肢を行き先のモデルの説明にしました。中身は次のとおりです。
{
"question": "Which model should handle the latest request?",
"criteria": {
"weak": "Nemotron 3.5 Lightning 30B-A3B, a small efficient coding agent with read_file, apply_patch, run_tests and lookup_docs",
"strong": "Claude Opus, a frontier model for design, ambiguous specs, investigation and high-stakes work"
}
}
実運用 87 件の AUC が 0.414 から 0.936 に上がりました。同じ system prompt と会話でも、候補の書き方だけでここまで動くのは思っていたより大きい差です。ただし、この書き方は実運用 87 件を見て選んでいるので、0.936 は選んだ側の数字です。確かめるのは次の章の未見のセットになります。
未見のセットで Jev と現行の判定役と並べる
行き先の説明で書いた候補に固定し、規則をもう一度開発用の分割で凍結しました(confidence 0.9 以上で採用、それ未満は strong)。そのうえで、選択に使っていないセットを流した結果が次の表です。Jev は Jev と同じ問いのまま、現行の判定役は本番で動いている JSON 判定役の値です。
| 評価セット | 件数 | CLM 誤送 | CLM 安全側 | Jev 誤送 | Jev 安全側 | 現行 誤送 | 現行 安全側 |
|---|---|---|---|---|---|---|---|
| 実装課題(実行環境あり) | 30 | 0 | 30 | 0 | 11 | 0 | 10 |
| 実装課題(実行環境なし) | 30 | 0 | 17 | 0 | 21 | 0 | 13 |
| 設計相談 | 10 | 0 | 0 | 0 | 0 | 1 | 0 |
| 見極め | 14 | 0 | 0 | 12 | 0 | 3 | 0 |
| 環境ペア | 80 | 2 | 33 | 2 | 4 | — | — |
| holdout | 237 | 42 | 71 | 10 | 71 | — | — |
実行環境の違いは、CLM でも読めるようになりました。正しい行き先が分かれる環境ペア 17 組のうち、weak 側に高い P(weak) を付けたのは 16 組で、Jev の 17 組に迫ります。ところが、実行環境の節が入ると P(weak) が全体に下がり、実装課題(実行環境あり)の中央値は 0.805 でした。規則は confidence 0.9 で凍結されているので、この 30 件はすべて strong に倒れ、環境ペアでも安全側が 33 件に膨らみます。向きは読めていても、確率の水準が節の有無で動いてしまう形です。
見極め 14 問の誤送 0 は、一見すると Jev(12 問)にも現行の判定役(3 問)にも勝っています。ただ中身を見ると、14 問すべてで confidence が 0.9 に届かず、規則で strong に倒れただけでした。P(weak) の中央値は 0.494 で、CLM 自身が strong を選んだわけではありません。設計相談の 10 件も同じ倒れ方です。
差がはっきり出たのは holdout で、誤送は CLM が 42 件、Jev が 10 件でした。全体の AUC も、CLM の 0.681 に対して Jev は 0.901 です。system prompt の規則を読み、この依頼は weak で足りるかという難しさを見積もる部分で、CLM は zero-shot では Jev に届きませんでした。
判定時間は候補数ではなく、状態の encode で決まる
判定の質とは別に、速さは CLM の設計どおりでした。まず、今回の判定 1 件の時間です。Mac から Tailscale 越しに呼んだ値で p50 0.15 秒でした。同じ日に測った Jev は、OpenRouter 経由の回線込みで 0.24〜0.26 秒、9/23 の記事の 1 トークン判定の Lightning は 0.25 秒です。
回線を除くため、node2 の上から直接呼んだサーバー側の値も測りました。埋め込みキャッシュを空にした 1 巡目は p50 117.5 ms、同じ状態を 2 回目に投げると 1.1 ms です。2 回目は状態の埋め込みもキャッシュに載っているので、head の計算と比較だけになります。
候補数を増やしたときは、/v1/rank に合成したツール説明を N 個渡して測りました。2 回目以降は、先頭に一意の印を付けた新しい状態を投げています。埋め込みキャッシュにも vLLM の prefix キャッシュにも当たらない条件です。
| 候補数 | 初回(候補を全部 encode) | 2 回目以降、新しい状態の p50 |
|---|---|---|
| 2 | 183.7 ms | 109.7 ms |
| 10 | 260.8 ms | 109.2 ms |
| 100 | 828.0 ms | 109.2 ms |
| 1000 | 6,546.4 ms | 111.0 ms |
候補 1000 個の初回は 6.5 秒かかりますが、一度載ってしまえば、2 個のときと同じ約 110 ms で 1000 個から選べます。時間のほとんどは状態側の encode で、候補数はほぼ効いていません。README の「候補が多いほど速さの差が開く」は、この形を見ると納得です。
head だけを学習し直すと、Jev の弁別に並んだ
zero-shot の弱さが、Qwen3-8B が状態を読めていないせいなのか、head がこの仕事の見積もり方を知らないだけなのか。CLM は head だけを学習し直せるので、試してみました。
学習データは、9/23 の記事で 1 トークン版の Lightning を学習させたものと同じ 4,511 件です。1 件ごとに、判定役が受け取る system prompt と会話、そして実測から作った weak / strong のラベルが付いています。状態は評価のときとまったく同じ組み立てにし、評価に使う 6 つのセットとは重なりが無いことを確かめています。1 割を課題単位で検証用に取り分け、公開されている head を出発点に train/finetune.py の既定値で学習しました。
python3 train/finetune.py --task choice --data /w/data/choice-mn --workflow all --out-dir /w/runs/mn-infonce-hard \
--embed-url http://127.0.0.1:8090/v1/embeddings --served-model-name qwen3-8b --max-len 4096 \
--init-ckpt /root/.cache/clm/CLM_v0.1-8B.pt --targets hard
かかった時間は、学習データ 3,718 種類の文章を Qwen3-8B で埋め込む時間を含めて 7.85 分でした。埋め込みを使い回して seed だけ変えた 2 回目は 0.13 分で、head の学習そのものは 10 秒もかかっていません。同じデータで 1 トークン版の Lightning を LoRA で学習させたときは、全体で約 3 時間 50 分、メモリのピークは 65.1 GiB でした。試行 1 回の重さが桁で違います。
学習し直した head を clm-serve に別名で載せ、zero-shot と同じ手順で規則を凍結して測った結果が次の表です。質問文は、行き先の説明と、Jev と同じ問いの 2 通りで学習しました。
| 項目 | zero-shot(行き先の説明) | 学習後(行き先の説明) | 学習後(Jev と同じ問い) | Jev |
|---|---|---|---|---|
| AUC 全体 | 0.681 | 0.818 | 0.881 | 0.901 |
| holdout の AUC | 0.555 | 0.854 | 0.892 | 0.856 |
| 環境ペアで正しい向き | 16/17 | 17/17 | 17/17 | 17/17 |
| 見極め 14 問の誤送 | 0(規則で strong) | 3 | 1 | 12 |
| holdout の誤送 / 安全側 | 42 / 71 | 17 / 37 | 6 / 52 | 10 / 71 |
| 実運用 87 件の誤送 / 安全側 | 1 / 22 | 0 / 47 | 0 / 47 | 0 / 12 |
見極め 14 問は、zero-shot のときと違い、head 自身が strong を選ぶようになりました。Jev と同じ問いで学習した head は、holdout の AUC が 0.892 で Jev を上回り、誤送も 6 件と Jev の 10 件より少なくなっています。zero-shot では行き先の説明のほうが圧倒的に良かったのに、学習した後は Jev と同じ判定基準の文のほうが弁別が高い、という逆転も起きました。seed を変えて学習し直しても、holdout の AUC は 0.854 が 0.86、誤送は 17 件が 15 件で、ほぼ同じ水準に収まります。
足りないところもはっきり残りました。実運用 87 件の安全側が、どの条件でも 47 件あります。1 トークン版の Lightning は、同じ学習データで 4〜5 件でした。原因を探るため、実行環境の節を含まない入力に、ツールが使えると書いた節を推論のときに差し込んでみました。行き先の説明で学習した head では安全側が 47 件から 2 件に減った一方、holdout の誤送が 17 件から 61 件に跳ね上がります。この head は、依頼の難しさとは別に、節があるかどうかを weak への強い手がかりとして覚えていました。学習データでは、実運用 87 件に近い形の修正依頼がすべて節つきだったので、その偏りを拾った形です。Jev と同じ問いで学習した head は、節を足しても実運用 87 件がほとんど動きませんでした。こちらは、学習データと言い回しの違う実運用の依頼そのものを strong 寄りに読んでいると見ています。凍結したエンコーダと小さな head は、学習データの言い回しの外への汎化が 30B の LoRA より弱いのかもしれません。ただし、この 2 つの原因の切り分けは実運用 87 件の結果を見てから行ったもので、まだ確かめてはいません。
汎用の決定モデルに Switchyard の何を任せるか
今回の結果を並べると、CLM が得意な仕事と、Switchyard の判定役に求めている仕事は形が違うことが見えてきます。
CLM が速くて素直に働くのは、候補が具体的な行動で、数が多く、あまり変わらない仕事です。MCP のツールが数百個あるときに次に呼ぶものを絞る、検索結果の候補を並べ替える、複数の解答から 1 つを選ぶ、といった用途ですね。候補の埋め込みを使い回せるので、候補を増やしても判定時間がほとんど増えません。候補を行き先の説明に書き換えたら弁別が戻ったのも、CLM が具体的な行動を選ぶように学習されていることの裏返しだと受け取っています。
一方で、Switchyard の capability 判定は、候補が weak と strong の 2 つしかなく、その代わり system prompt の規則と実行環境を読み、依頼の難しさを見積もる必要があります。候補数が 2 なので action cache の出番はほぼなく、差が出るのは状態側をどれだけ深く読めるかです。実行環境の違いは CLM も向きを読めましたが、難しさの見積もりは、9/23 の記事で実測ラベルを学習させた Lightning の判定役と、Jev の側にありました。
ただ、この難しさの見積もりは、head を学習し直すだけでかなり取り戻せました。Qwen3-8B の埋め込みには判断の材料が入っていて、足りなかったのは読み方だったことになります。以前調べた prefill router も、凍結したエンコーダの内部状態に自分の実測ラベルで予測器を載せる作りでした(2026-08-22 時点の記事です)。汎用の決定モデルをそのまま置くより、公開された重みを土台に自分のラベルで head を仕立てる使い方のほうが、ルーターの判定役には合っていそうです。その場合も、学習データの偏りを拾う点は、LoRA の判定役以上に気にしておく必要があります。
まとめ
CLM は、凍結した Qwen3-8B に小さな head を 2 つ載せ、状態と候補を別々に埋め込んで比べる汎用の決定モデルです。重みとコードが Apache 2.0 で、Jev と同じ形の API で呼べて、head だけを手元で学習し直せます。DGX Spark でも、候補の埋め込みがキャッシュに載っていれば候補 1000 個から約 110 ms で選べ、候補の多い選択に向いた設計であることを確かめられました。
Switchyard の weak / strong 判定を 9/23 の記事と同じ 528 件で測ると、zero-shot では Jev と同じ問いで P(weak) が 0.94〜0.99 付近に張り付き、AUC は 0.581 でした。候補を行き先のモデルの説明に書き換えても、holdout の誤送は Jev の 10 件に対して 42 件です。一方で、1 トークン版の Lightning と同じ 4,511 件で head だけを学習し直すと、埋め込みを含めて 8 分ほどで holdout の AUC が 0.892 になり、Jev の 0.856 を上回りました。代わりに、実行環境の節の有無のような学習データの偏りも覚え、実運用 87 件では安全側が 47 件に増えています。英語中心のモデルに日本語の system prompt で聞いていること、評価が自分のワークロード 1 種類であることは、その点をご了承ください。
次は、節の無い依頼と実運用に近い言い回しを学習データに足し、学習し直した head の安全側の多さが直るかを確かめてみたいところです。
参考リンク
- Contrastive-LM/CLM — コード、学習手順、API リファレンス
- Contrastive-LM/CLM-v0.1-8B — モデルカードと制約
- contrastive-lm(PyPI)
- Jev 1.13(OpenRouter)
- NVIDIA-NeMo/Switchyard





