jev × LLM 判定対決ビューア
September 17, 2026 · View on GitHub
同じ user の発言を TypeSafe の jev と LLM の両方に判定させ、判定結果のズレと速度差を1画面で見せるデモ。判定は affectus の感情状態として別々に蓄積され、2つの状態が会話を重ねるにつれて分岐していく様子をプルチックの輪で見られる。さらに、分岐したそれぞれの感情状態で同じ発言への返答を生成するので、判定の差が2つの返答の違いとして読める。
両者が受け取るのは、判定の直前に読んだ自分の現在の8軸と user の発言。affectus の agent は毎ターン自分の状態を読んでから感情の動きを申告するので、判定の入力にも現在値が要る。各側は自分の状態を読むため、状態が分かれた2ターン目以降は入力も分かれる。比較の公平性は、同じ状態から出発する最初の判定で見る。
必要なもの
- macOS(Apple Silicon / Intel のどちらでも)
- Node 24 以上
- Vercel AI Gateway の API キー
配布 zip には affectus のバイナリと node_modules が入っているので、Go もネットワーク越しの依存解決も要らない。
使い方
bash scripts/setup.sh
# 案内に従って .env.local に API キーを書く
node --env-file=.env.local src/server.ts
ブラウザで http://localhost:8787 を開く。8787 が埋まっている場合は
PORT=9000 node --env-file=.env.local src/server.ts のように変えられる。起動時に実際の URL が出る。
中央のテキスト欄に user の発言を書いて送る。「メッセージを送信」だけが実行点で、 押すと判定・感情の更新・返答生成が走る。自動で送信する経路は無いので、API を叩くのは押したときだけ。
会話を重ねるには、同じ欄に次の発言を書いて送り直す。感情状態は送信のたびに両側へ積まれていくので、
比較をやり直すときは reset で両方を初期値に戻す。
上部の人格は、返答を生成する話し手の性格。friendly(明るく協力的)と contrarian(天邪鬼)の2つがあり、両側とも同じ人格を使う。 送信前ならいつでも変えられる。判定には人格を与えない。
画面の読み方
- 中央に出るのは user の発言(自分で書く)と判定のずれだけ
- 左が LLM、右が jev。 同じ発言を同時に判定させ、先に返ったほうから埋まる
- プルチックの輪は花弁の長さが各軸の強さ。円の外に軸名を同じ色で添えてあるので、どの花弁がどの感情かが図の中で読める。左右で形が違えば、判定が食い違っている
- 判定の対比は中央に8軸ぶん並ぶ。中央が 0、左右の末端が 1.0。左が LLM、右が jev で、棒の長さがその軸をどれだけ動かしたか
- 符号は色で表す。正はその側の色、負はくすんだ灰。長さが同じで色が違えば、両者は正反対の判断をしている
- 中央には軸名とその軸の差を上下に重ねて置く。差は
|LLM − jev|で、符号付きの値どうしの差なので、−0.5 と +0.5 なら 1.00 になる - 判定のずれ(8軸の差の合計) は両者のデルタがどれだけ離れているかの1数値。0 なら完全一致で、上限は 16
- 判定 / 生成の ms は別の数字。上が判定、下がそのあとに走る返答生成。生成は両側とも同じ Haiku 4.5 なので、速度差として読むのは判定のほう
- 生成された返答は両側で同じモデル・同じ人格・同じ指示文を使い、違うのは渡す感情状態だけ。読み比べると、判定の差がそのまま口調の差になっている。人格を固定して判定器だけを変えているので、見えているのは「同じ人格でも、判定器が違えば別人のように振る舞う」という差
- 判定の入出力(JSON) はパネルの一番下に常に出ている。そのターンでモデルに渡した内容と返ってきた内容がそのまま読める。枠は高さ固定で、長い JSON は枠の中でスクロールする。対象は判定だけで、返答生成の入出力は出さない
受け取った側向けの引き継ぎ資料は HANDOFF.html。zip に同梱されるので、
ダブルクリックでブラウザが開く。外部のフォントもスクリプトも読まないため、
ネットワークが無い環境でも読める。
構成
| ディレクトリ | 内容 |
|---|---|
src/ | サーバーと判定ロジック |
public/ | 画面 |
bin/ | affectus バイナリ |
HANDOFF.html | 受け取った側向けの引き継ぎ資料(zip に同梱) |
EXPLAINER.html | affectus と処理フローの図解(zip に同梱) |
state/ | 2つの感情状態(setup.sh が生成) |
テスト
npm test
配布 zip を作る
./scripts/package.sh
dist/jev-duel-<日付>.zip ができる。API キーと感情状態は含まれない。
受け取った側は setup.sh の案内に従って自分のキーを .env.local に書く。
--with-key を付けると .env.local をそのまま同梱し、ファイル名が
jev-duel-<日付>-withkey.zip になる。この zip を渡した相手は、そのキーで課金できる。
受け取り手を限れる場合にだけ使う。