検証ラボの メトリフクロウ です。ローカルLLMの比較で起きやすい誤解は、「速いモデル=良いモデル」です。実際の業務では、速くてもJSONが崩れる、ツールを呼べない、回答が不安定、というモデルは使えません。速さは必要条件の一つであって、十分条件ではありません。
社内検証では、評価を相補的な 二軸 で設計しています。
- 性能(benchmark): concurrency / throughput / latency / TTFT
- 品質(eval): 用途別タスクの合否・スコア
どちらも同じ run_id 配下に残し、後から並べられるようにします。片方だけが優秀な run は、採用判断ではなく「次に何を直すか」の材料です。
ポイント
速さだけでは決めない。性能と品質を同じrun_idに残します。
なぜ二軸が必要か
| 見るもの | 足りないとき起きること |
|---|---|
| 性能だけ | 速いが業務タスクで落ちる |
| 品質だけ | 正しいが待ち時間が長くて使われない |
| デモ印象だけ | 再現できず、本番で説明不能 |
| 平均だけ | 同時実行や長尾遅延で現場が詰まる |
特に複数人同時利用やバッチ処理を前提にするなら、単発の体感速度だけでは不十分です。逆に、構造化出力や tool calling が必要な業務では、スモーク品質すら通らない構成を速度比較しても意味が薄いです。門番を通っていない候補に重いベンチを積むのは、計測の浪費です。
性能軸で取るもの
OpenAI互換エンドポイントに対して、実際の利用に近い形で計測します。
- latency p50 / p95 / p99 / 平均
- TTFT p50 / p95(ストリーミング最初のチャンク)
- output tokens/sec、requests/sec(throughput)
- concurrency 条件ごとの上記指標
- error rate、成功数、wall time
- 可能なら GPU 使用率・メモリ(無ければスキップ)
latency とは何か
latency(レイテンシ) は、リクエストを投げてから 応答が完了するまで の待ち時間です。利用者から見ると「全部出終わるまでの長さ」に近い指標です。
| 用語 | 測っているもの | 体感との対応 |
|---|---|---|
| latency | 依頼開始 → 完了まで | 待ちが長い/短いの総合 |
| TTFT | 依頼開始 → 最初のトークンまで | 「反応した」感 |
| throughput | 単位時間あたりの処理量 | チーム全体のさばき量 |
同じ「速い」でも、TTFT が短くて latency が長い(考え始は速いが完了が遅い)、その逆、があり得ます。会議では「速い」を latency / TTFT / throughput のどれで言っているかを先に固定します。
平均より p95 / p99 とは何か
計測を100回行ったとき、待ち時間は毎回同じではありません。速い回もあれば、たまに極端に遅い回もあります。
平均は、その100回を足して割った「真ん中あたりの印象」です。一方 p95(95パーセンタイル) は、「遅い方から数えて上位5%に入る境目」——ざっくり言えば 100回中95回は、これ以下の待ちで終わった という値です。p99 は同じく 100回中99回はこれ以下 です。p50 は中央値で、並べたときの真ん中です。
| 表記 | ひとことで | 現場での意味 |
|---|---|---|
| 平均 | 全部の算術平均 | きれいな数字になりやすいが、たまに遅い回を薄めてしまう |
| p50 | ちょうど真ん中 | 典型的な一回のイメージ |
| p95 | 95回はこれ以下 | 「たまに遅い」がどの程度かを見る定番 |
| p99 | 99回はこれ以下 | より厳しい長尾。クレーム級の遅さを見る |
例です。ある条件で latency が次のような分布だったとします。
- たいてい 2 秒前後
- たまに 20 秒
このとき平均はまだ「まあまあ」に見えても、p95 や p99 は大きく崩れます。利用者の不満は平均ではなく、たまに踏む長い待ちに出ることが多いので、採用判断では平均より p95(必要なら p99)を併記します。
読むときの目安も固定します。
| 指標 | 何の代理か | 注意 |
|---|---|---|
| latency(とくに p95) | 完了までの不満の出方 | 平均だけで勝ち宣言しない。長尾を見る |
| TTFT | 「反応した」感 | ウォームアップ前後で差が出る |
| tok/s・req/s | 生成・処理能力 | ワークロード固定が前提 |
| concurrency 条件 | 同時利用時の壊れ方 | 単発 latency だけでは足りない |
| error rate | 飽和・設定ミス | 品質失敗(JSON崩れ等)と混同しない |
主軸は concurrency 条件つきの latency / throughput です。単発の最良 latency だけ見て勝ち宣言しない、がこの回のルールです。常駐マルチユーザ前提では、同時実行を上げたときの p95 latency と error rate の方が採用判断に効きます。
品質軸で取るもの
最初は大きなベンチマークセットより、失敗が分かりやすいスモークが有効です。
- coding: 期待する関数定義が含まれるか
- JSON: 必須キーを持つ妥当なJSONか
- tool calling: 期待ツールが必須引数付きで呼ばれるか
後から judge モデルによる採点を足せますが、まずはオフラインで判定できる scorer から始めると運用が安定します。品質ゼロの原因が「モデル劣化」か「到達不能」かを分けられないと、二軸設計は崩れます。
同じ run に残す理由
性能と品質を別フォルダ・別日付で取ると、後から突き合わせるコストが跳ねます。同じ run_id に次を同居させます。
- 起動プロファイル名と設定要約
- 性能サマリ(concurrency、主要パーセンタイル)
- 品質サマリ(pass_rate、タスク別失敗理由)
- 環境メモ(実機かハーネス確認か、GPU 有無)
- 判定(採用 / 再試験 / 廃棄)と次の1軸
「速いがJSONが崩れる」を一文で言える状態が、ステークホルダー向け説明の最短経路です。
実務テンプレ
- 用途を決める(例: コーディングエージェント)
- 性能ワークロードを固定する(concurrency、max_tokens、プロンプト)
- 品質スイートを固定する
- 変えたい軸を1つだけ選ぶ(ランタイム、KV、contextなど)
- run を残し、性能要約と品質要約を並べる
- 「採用する / 捨てる / 再試験」を記録する
- 次ループの仮説を1行で書く
判定の目安(例)
| 性能 | 品質 | 次の一手 |
|---|---|---|
| 良い | 良い | stable 候補として制約付き採用を検討 |
| 良い | 悪い | 設定(parser等)かモデル適性を疑う |
| 悪い | 良い | concurrency / メモリ枠を1軸ずつ振る |
| 悪い | 悪い | 用途不一致の可能性。重い比較は止める |
よくある落とし穴
- 性能だけ見て「勝ち」と宣言し、品質を後回しにする
- 品質スモーク失敗をすべてモデル責任にする(未起動を見落とす)
- 軸を2つ以上同時に変えて、学びを消す
- デモ用の短いプロンプトだけで業務適合を語る
- ハーネス確認値と実機値を同じ表に混ぜる
つまずいたこと
性能だけ見て採用し、翌日の品質スモークで全面赤になる。逆に、品質だけ見て採用し、同時実行で待ち時間が破綻する。どちらも経験しました。
苦労したのは、二軸を並べること自体より、会議で片方の軸だけが拡大される空気を止めることです。きれいな throughput のグラフがあると、JSON 失敗は「あとで直す」になりがちでした。表を二列にしたのは、その誘惑への対抗策です。
この回の要点
- 性能と品質を同じ表の二列で見る
- きれいな throughput だけで品質赤を先送りしない
- どちらか一方の拡大解釈を会議で止める
いま公開しているのは評価の型です。実機ベンチの数字は、再計測と匿名化が済んだものから順に足します。合格ラインや用途別プロファイルの未確定は残っています。
次は「latencyだけ見ない:concurrencyとthroughputの測り方」へ進みます。いまのメモを1行残してから読むと、連載の筋がつながりやすくなります。