# J-WorkBench 仕様（正典）

日本語実務でローカルLLMがクラウドLLMの代替になるかを、品質・速度・費用・ローカル価値・運用難度まで含めて測るベンチ。本書はハーネス実装者・課題作成者・記事執筆者の**唯一の契約**。迷ったらここに従う。判断の背景は [ADR 0025](../docs/adr/0025-jworkbench-local-vs-cloud-benchmark.md)。

---

## 0. ゴールと非ゴール

**ゴール**
- 「自分の手元PC（特に消費者GPU）で、日本語の実務がどこまでクラウドの代わりになるか」を数値で示す。
- 同じharnessに新モデルを通して速報し続けられる、再現可能なキットにする。

**非ゴール**
- MMLU/JGLUE/Nejumi の再発明（総合知能ランキング）。
- クラウドを従量APIで叩くこと（**サブスク限定**。下記参照）。
- 実測前に数値を捏造すること（サンプルは必ず「実測前サンプル」と明示）。

---

## 1. 全体フロー

```
ollama list で実在ローカルモデルを検出
  └→ 各モデル × 各タスク を実行（QAは直接chat / agentは自前ループ）
クラウドCLI（claude/codex/gemini）を検出
  └→ 各CLI × 各タスク をヘッドレス起動で実行
        ↓ 各実行 = 出力 + メトリクス + 生トランスクリプト
3層採点（客観 → ルーブリック → 人間監査フック）→ task.score01
  ↓
score.mjs: task.score01 → 5軸(100点) → 代替率(クラウド最良=100) → 称号
  ↓
report.mjs: results/<date>/*.json → ① markdownレポート ② サイト用データ src/data/jworkbench.ts
```

`npm run bench`（= `node bench/run.mjs`）で上記を回す。主なフラグ:

- `--models a,b` 対象モデルを限定（既定: 検出した全ローカル + 利用可能な全クラウドCLI）
- `--tasks cat/...` 対象課題を限定（既定: 全課題）
- `--repeat N` 同一課題をN回（信頼性=分散の計測に使う。既定1、本走は3）
- `--judge <model>` ルーブリック採点に使う judge（既定: 後述の固定judge）
- `--dry` 実行せず計画だけ表示
- `--out results/<date>` 出力先

---

## 2. モデルと実行アダプタ

### 2.1 ローカル（Ollama HTTP, `http://127.0.0.1:11434`）

- `run.mjs` は **ollama list で実在するモデルだけ**を対象にする（存在しないタグを決め打ちしない）。
- 候補リストと pull コマンドは [`config.mjs`](config.mjs) の `LOCAL_CANDIDATES` に置く（[LocalLLMRecommender](../src/components/LocalLLMRecommender.astro) のカタログと整合）。ユーザーが pull したものを自動採用。
- QAタスク: `/api/chat` を stream で叩き、TTFT・tokens・tok/s を計測。
- agentタスク: `agent-loop.mjs`（後述）に Ollama を function-calling バックエンドとして渡す。
- 量子化・コンテキスト・温度・シードは `config.mjs` の `RUN_PARAMS` で固定し、結果に必ず記録する（温度0・固定シードを既定）。

### 2.2 クラウド（サブスク限定・各社CLIをヘッドレス起動）

従量APIは**使わない**。`subscription-cli.mjs` が各CLIを非対話で1ショット起動する。コマンドテンプレートは `config.mjs` の `CLOUD_CLIS` に置く。**フラグはバージョン依存なので、実装者は各CLIで実際に起動確認し、必要なら下記を補正すること（要検証）:**

| CLI | 既定テンプレート（要検証） | 備考 |
| --- | --- | --- |
| `claude` (Claude Code) | `claude -p "<PROMPT>" --output-format json` | ヘッドレス print モード。作業ディレクトリにfixtureを置く |
| `codex` (ChatGPT) | `codex exec "<PROMPT>"` | 非対話実行サブコマンド |
| `gemini` (Gemini CLI) | `gemini -p "<PROMPT>"` | 非対話プロンプト |

- クラウドCLIは**それ自体がエージェント**（ツール・ファイルアクセスを持つ）。QAタスクでは回答テキストのみ抽出、agentタスクでは sandbox ディレクトリ上で実作業させる。この非対称性は method に明記する。
- **cap（利用上限）はデータ**。CLIがレート制限/上限で失敗したら `capHit:true` を記録し、その時点までの完走タスク数を rollup する。失敗を握りつぶさない。
- クラウドCLIは**ネットワーク/外部アクセスを持つ**ため、RAG系課題で「fixtureだけを根拠にせよ」という制約を破りうる。プロンプトで明示し、破った場合は信頼性で減点する。

### 2.3 judge モデル（ルーブリック採点）

- 既定 judge は `config.mjs` の `JUDGE`（クラウドCLIの中で最も能力が高いものを1つ固定。例: `claude`）。
- judge は被験者と同一でも可だが、**自己採点バイアス**を避けるため、判定対象モデルと judge が同一の場合はフラグを立て、人間監査対象に回す。
- judge は必ず「rubric.md の観点別に0/部分/満点」で採点し、根拠と減点理由をJSONで返す。プロンプトと judge モデル名は結果に記録。

---

## 3. タスク契約（`bench/tasks/`）

各タスクは1ディレクトリ。詳細スキーマは [`tasks/SCHEMA.md`](tasks/SCHEMA.md)。要点:

```
bench/tasks/<category>/<task-id>/
  task.json      # メタ + プロンプト + fixture参照 + 採点仕様 + 環境関連度
  fixtures/      # 入力（就業規則.md, 契約書.md, messy.csv, mini-repo/ 等）
  gold.json      # 客観採点の期待値（任意）
  rubric.md      # ルーブリック採点の観点と配点（任意）
```

### カテゴリと問数（第1弾＝30問）

| category(dir) | ラベル | 問数 | 主軸 | 採点の柱 |
| --- | --- | -: | --- | --- |
| `shisya-rules` | 社内規程RAG | 6 | 実務正確性 | 引用根拠/条件分岐/誤読/根拠なし断言 |
| `keiyaku` | 契約・見積照合 | 5 | 実務正確性 | 矛盾検出/数値/抽出漏れ |
| `gijiroku` | 議事録ToDo抽出 | 5 | 実務正確性 | タスク/期限/責任者/未決の分離 |
| `mail` | メール返信・敬語 | 4 | 信頼性 | 敬語/トーン/過剰推測なし |
| `hyou-csv` | 表/CSV処理 | 4 | 実務正確性 | 集計/整形/フォーマット遵守 |
| `code-hozen` | 日本語コード保守(dogfood) | 4 | 実務正確性 | テスト通過/`npm run check`/最小diff |
| `longctx` | 長文コンテキスト耐性 | 2 | 信頼性 | 遠距離参照/中盤無視しない |

`code-hozen` は抽象課題ではなく **codeagent.jp 風の実作業**（型エラー修正→`astro check`通過、frontmatter整備、`BarChart` 挿入→build通過 等）。fixture に最小リポジトリを同梱し、判定はコマンド実行（客観）で固める。

### タスク作成の必須要件

- **答えが1箇所にない / 例外条件がある / 日付・部署で条件分岐する**ものを優先（事故るところを集める）。
- fixture は**自己完結**（外部URL参照に依存しない）。架空企業・架空数値で、実在固有名詞は避ける。
- 各タスクに「客観で取れる部分」を必ず1つは作る（3層採点の最下層を客観で固めるため）。
- 出力フォーマットを指定する場合は task.json の `expect` に機械検証可能な形で書く。

---

## 4. 採点（3層）

`grade.mjs` が task.json の `grade.layers` を順に適用し、`score01 ∈ [0,1]` を出す。

1. **客観 (`graders/objective.mjs`)** — `method`:
   - `exact` / `includes` / `regex` / `numeric`(許容誤差) / `json-field`(構造化出力の特定フィールド) / `script`(コマンド実行し exit0 で合格。コード課題用)
2. **ルーブリック (`graders/rubric.mjs`)** — `rubric.md` の観点×配点を judge が採点。0..maxPoints を [0,1] 正規化。
3. **人間監査** — `score.mjs` が「judge=被験者同一」「客観とルーブリックの乖離が大」等を `needsAudit:true` でマークし、レポートに監査キューを出す。人手で上書きできる。

`score01 = Σ layer.weight * layer.score`（layer.weight は task.json、既定は客観0.5/ルーブリック0.5。客観のみ/ルーブリックのみも可）。`passed = score01 >= grade.passThreshold`。

---

## 5. メトリクス（`metrics.mjs`）

各実行で必ず取る:

- `ttftMs` 最初のトークンまで（ローカルのみ精密。クラウドCLIは取得不能なら null）
- `tokens` 出力トークン数、`tokPerSec`
- `wallMs` 起動〜完了の実時間（クラウドはこれが主指標。method に「UI/CLIオーバーヘッド込み」と明記）
- `toolCalls` / `toolCallInvalid`（agentループでの不正ツールコール数＝ローカルが壊れる場所）
- `capHit` / `errored` / `crashed`（運用難度の素材）
- `repeat` 実行時は各回を保存し**分散**を信頼性に使う

速度は **TTFT・tok/s・wallclock・P95 を分けて**保持する（単一ユーザー前提。並列スループットは測らない）。

---

## 6. スコア合成（`score.mjs`）

### 6.1 5軸（各0–100、重み付け合計100）

| 軸 | 重み | 算出 |
| --- | -: | --- |
| 実務正確性 quality | 35 | 全タスク score01 の加重平均 ×100 |
| 信頼性 reliability | 20 | フォーマット遵守率・根拠なし断言の少なさ・repeat分散の小ささ |
| 速度UX speed | 15 | tok/s と wallclock を閾値カーブで0–100（ローカル実測、クラウドwallclock+開示） |
| 経済性 economy | 15 | §7 のサブスク3パターン・シナリオ計算 |
| ローカル価値 localValue | 10 | 構造値: ローカル=高（オフライン/機密/再現/データ保持）、クラウド=0 |
| 導入容易性 setup | 5 | VRAM適合・クラッシュ率・pull容易性のテレメトリ |

### 6.2 代替率（主指標）

タスク t: `cloudBest(t) = max_{m∈cloud} score01(m,t)`（>0のときのみ）。
`代替率(m) = mean_t( clamp(score01(m,t)/cloudBest(t), 0, 1.2) )`。
カテゴリ別・環境クラス別にも出す。クラウド最良=100 が基準。

### 6.3 称号（記事の見せ場）

`config.mjs` の `SHOGO` 定義から導出:

- **クラウド代替率** = §6.2
- **月額破壊力** = §7 の3パターンで「ローカルが得」になる条件数
- **秘密文書適性** = RAG/規程系の score01 × ローカル価値
- **社畜耐性** = 長文・表・曖昧指示・議事録カテゴリの安定度（信頼性寄り）
- **普通のPC適性** = 必要VRAM適合 × ノート/ゲーミング級での完走率
- **待てる速度か指数** = wallclock/tok-s を体感閾値で

---

## 7. 経済性（サブスク版・正典）

token従量ではない。**サブスクは定額**。結論の骨格:

> 軽量ユーザーは定額サブ1本で足りる＝ローカルは元が取れない。
> ローカルが効くのは3パターンだけ:
> ①機密で外に出せない ②サブスクの利用上限(cap)を超える重量ユーザー ③複数人で1GPUを共有。

`score.mjs` は次を計算（金額は `config.mjs` の `COST` に置き、記事で更新）:

- サブスク月額（例: ChatGPT/Claude/Gemini の各プラン）
- ローカル初期費（GPU中古相場）+ 電気代（消費電力×時間×¥/kWh）+ セットアップ時間
- 3パターンそれぞれで「何ヶ月で/どの条件でローカルが得か」を出力。token損益分岐の数字は出さない。

---

## 8. 出力（`report.mjs`）

- `results/<date>/run-<model>.json` — 生結果（[results/SCHEMA.md](results/SCHEMA.md)）。透明性のためコミット可。
- `results/<date>/report.md` — 人間用サマリ + 監査キュー。
- `src/data/jworkbench.ts` — サイトの `JWorkBenchLeaderboard` 用データ。**スナップショット型**で、`snapshotDate` と「実測 / サンプル」フラグを持つ。形は [results/SCHEMA.md](results/SCHEMA.md) の `LeaderboardData` に従う。

実測がまだ無い場合、`src/data/jworkbench.ts` は `status:"sample"` の明示サンプルを出す（捏造禁止・UI上も「実測前サンプル」と表示）。

---

## 9. 透明性チェックリスト（公開前）

- [ ] 量子化・コンテキスト長・温度・シード・GPU・ドライバ・電力制限を結果に記録
- [ ] judge モデルとそのプロンプトを公開、自己採点ケースを監査
- [ ] クラウドは「サブスクCLI・各社の現実的構成」であり厳密同一ハーネスでない旨を明記
- [ ] 速度は TTFT/tok-s/wallclock/P95 を分離、クラウドwallclockのオーバーヘッドを開示
- [ ] 生トランスクリプトを添付
- [ ] 実測前は数値をサンプルと明示
