Field guide · モデル評価

OpenRouter モデルで RP キャラクターカードの A/B テスト。

同じカードが Claude Opus では生き生きと、 GLM ではカスタマーサポート bot に。どう体系的にテストし、本当に合うモデルを選ぶか——方法、コスト、騙されやすい罠まで。

fol. v.r

同じカード、別の魂

カードを配布したことのある人なら誰もが経験している。4,000 token のペルソナを書き、常用モデルでグリーティングを納得いくまで磨き、別の host で動かした友人から「丁寧だけど平板」「四壁を破る」「全部断られる」と言われる。

カードは変わっていない。変わったのはモデルだ。alignment、デフォルトのサンプラー挙動、instruction-following のバイアス、長文での注意減衰——どれもキャラクターを別方向に押す。誠実な姿勢は「どれが最強か」を議論することではなく、「このカードにどれが最適か」を測ることだ。

fol. vi.r

「なんとなく」評価では足りない理由

会話 1 本はサンプルサイズ 1。RP カードでは雰囲気評価が積極的に誤導してくる。原因は 3 つ。

  • ペルソナ・ドリフト。 20 ターン保つモデルもあれば、6 ターンで RLHF のベースラインに戻るモデルもある。長いシナリオを実際に流さないと気付けない。
  • 拒否境界(refusal surface)。 対立、NSFW、ボディホラー、グレーな倫理選択——provider ごとに線が違い、システムプロンプトの言い回しでも動く。「一度断られた」だけでは情報量がほぼゼロ。
  • トーンの指紋。 両方ともキャラを保てても、片方は冗長で真摯、もう片方は素っ気なく乾いている、ということが起きる。どちらが合うかは趣味だが、比較可能な出力がないと判断できない。

解は benchmark ではない——あれは推論を測るもので RP ではない。解は小さな固定シナリオ集を複数モデルで再生し、強力なジャッジモデルに採点させることだ。

fol. vii.r

最小限の方法

実用に耐える評価の部品は 4 つ。シナリオ、試行回数、ジャッジ、ルーブリック。どれも凝らなくていい。重要なのは一貫性。

  1. 5〜8 個のシナリオ。 カードの表面を覆うように:日常、危機・感情の決壊、NSFW や境界(関係あれば)、価値観への挑戦、長期記憶テスト(20 ターン前に触れた話への callback)。
  2. シナリオごとに 5〜10 回。 生成は確率的なので 1 回はノイズ。5 回が「モデルを区別できる」最低ライン、10 回が安心。
  3. 被験モデルより強いジャッジ。 self-eval は偏る——モデルは自分の出力を体系的に高く評価する。独立した強モデル(Claude Sonnet、GPT 級、Gemini Pro 級)に、カード・シナリオ・候補応答をまとめて渡す。
  4. 4〜6 次元のルーブリック。 人格一貫性、拒否/破綻、トーン一致、callback の精度、文体、総合スコア。各 1〜5 点とジャッジの一言コメント。実際に読むのはコメントの方。

これは benchmark というより試食に近いが、それでいい。リーダーボードを発表したいわけではなく、自分のカードを公開するときに claude-opus と書くか gemini-flash と書くかを決めたいだけだ。

fol. viii.r

なぜ OpenRouter が最適なハーネスか

5 つの SDK を繋ぎ、5 種類の API key を管理し、5 種類のメッセージ形式を自分で正規化することもできる。一度やった人はだいたい二度とやらない。OpenRouter はモデル動物園の前に OpenAI 形式の API を 1 枚被せ、レスポンスにモデル別価格を返し、provider を変えるのは文字列 1 つ。

実装はここまで縮む:

POST https://openrouter.ai/api/v1/chat/completions
Authorization: Bearer $OPENROUTER_API_KEY

{
  "model": "anthropic/claude-3.5-sonnet",
  "messages": [
    { "role": "system", "content": cardToSystemPrompt(card) },
    { "role": "user",   "content": scenario.opening }
  ],
  "temperature": 0.85,
  "max_tokens": 600
}

model google/gemini-2.0-flashdeepseek/deepseek-chatx-ai/grok-2z-ai/glm-4.6 に差し替えるだけ。ハーネスは丸ごと同じ。1 回ごとの token コストは usage ブロックに入って返ってくるので、課金 API を別に叩かなくても合計が出せる。

fol. ix.r

封筒裏のコスト試算

具体例。シナリオの入力が平均 3,000 token(カード + system + シナリオ履歴)、出力が 500 token。シナリオ 8 個 × 試行 5 回 × 候補モデル 6 個、各生成にジャッジ 1 回:

  • 生成:8 × 5 × 6 = 240 回。 混合平均で入力 $1〜$3/M token、出力 $3〜$15/M token として、典型的な中位帯ミックスでおおよそ $2〜$6
  • ジャッジ:240 回、各回でカード(約 3k)+ 応答(約 500)を読み、短評(約 150)を返す。Haiku 級のジャッジでさらに $1〜$2
  • 合計:マトリクス評価 1 周で $10 未満。カードを変えるたびに回し直せる。

これらは概算で実際の価格表ではない——OpenRouter の価格は毎週動くし provider 差もある。要点はオーダー:本気の評価がコーヒー 1 杯の値段で済む、ということ。

fol. x.r

あなたを欺く 3 つの罠

最初の試みでほぼ全員が踏む地雷:

  1. ジャッジは長文が好き。 LLM ジャッジに「品質」を聞くと、体系的に長くて冗長な返答を好む。プロンプトで簡潔さを重視させるか、長さの正規化(閾値超過に減点)を追加すること。さもないと文字数を測っているだけになる。
  2. システムプロンプトの解釈差。 構造化された長い system プロンプトを忠実に守るモデルもあれば、提案程度に扱うモデルもある。重い XML タグの設計は Claude では完璧、タグを理解しないモデルでは混乱する。どのモデルが簡略版を必要とするかも評価結果の一部として記録する。
  3. temperature 0 は決定的ではない。 provider 側のバッチング、プロンプトキャッシュ、tie-break が temperature: 0 でも変動を導入する。サンプルは複数取ること。リリース判定級の再現性が要るなら、API がサポートする場所で seed を固定し、「ほぼ同じ」が現実上限と割り切る。
fol. xi.r

Studio で作っているもの

上記は OpenRouter API に慣れている人なら午後 3 つ分のグルーコード。それ以外の人——および将来グルーを保守したくない自分——のために、 tavernai.cards Studio はこの形に削り出されている。

  • シナリオライブラリ — カード単位で再利用できるテンプレ。よくあるアーキタイプ(日常・危機・対立・長期 callback)は組み込み。
  • マトリクス・ランナー — OpenRouter カタログから候補モデルを選び、シナリオごとの試行回数を決めて回す。
  • 組み込みジャッジ — Claude 級ジャッジ + 長さ正規化ルーブリック。冗長さを最適化しに行かない。
  • 自動レポート — モデル別の強み、最弱シナリオ、公開ページに掲げる「推奨モデル」の提案。

Studio は有料プラン(だいたい週 1 杯のコーヒー)で、マトリクス・ランナーが中心。無料プランは引き続き linter、converter、過去フォリオで紹介したマルチホスト書き出しを提供。

本当に気にかけているカードがあるなら、どのモデルで一番映えるのかを知っておきたいはず。巻物に名を書けば、Studio は順次開放していく。