注記:この記事は Claude(Anthropic の LLM)が、人間PMの視点に立って執筆したものです。数値・ログはすべてリポジトリおよびバッチ実行結果に基づいています。
1. きっかけ
前作 sdnd-trpg でGMをAIに任せた実験を終えて、一つの問いが残った。
「人間プレイヤーもいなくてよいのではないか」
GMがAIなら、プレイヤーもAIで動かせる。全員AIで自律的にセッションを回し続けたら、無限にログが生成できる。そのログは学習データになる。
この発想から sdnd-theater が生まれた。
2. 仕組み(GM・プレイヤー全員AI)
登場人物は全員AI
sdnd-theaterの構成はシンプルだ。
以下は 最終的な構成(1000セッション完走時点)だ。担当AIは途中で段階的に切り替わっており、その経緯は3章で詳しく述べる。
| ロール | 担当AI(最終) | 役割 |
|---|---|---|
| GM | Ollama + qwen3.5:4b | シナリオ進行・NPC演出・ダイス判定 |
| プレイヤー1 | Ollama + qwen3.5:4b | キャラクター行動の自律決定 |
| プレイヤー2 | Ollama + qwen3.5:4b | キャラクター行動の自律決定 |
| Observer | ルールベース | リアルタイム違反検出 |
| Analyzer | LLM-as-Judge | セッション後品質評価 |
セッションの流れ
開幕シーン(GMが世界観を提示)
↓
プレイヤーAが行動を宣言
↓
GMが結果を裁定・次のシーンを生成
↓
プレイヤーBが行動を宣言
↓
… これをターン数分繰り返す
↓
終幕・ログ保存・品質スコアリング
人間は誰も介在しない。batch_runner.py を実行すれば、後は全自動で回り続ける。
3. Geminiのレート制限問題とローカルLLMへの切り替え経緯
最初はGemini 2.0 Flashを使っていた。コストが安く($0.10/1Mトークン)、既存のsdnd-trpg実装との相性も良かったからだ。
しかし実際にバッチを回し始めると、深刻な問題が発生した。
[61/89] 実行中...
❌ 失敗: 不明なエラー
[62/89] 実行中...
❌ 失敗: 不明なエラー
(以下、29セッション連続失敗)
原因は503 UNAVAILABLE——レート制限(429)ではなく、サーバー過負荷だった。有料枠でも解決しなかった。
第1の切り替え:Gemini → Claude Haiku
安定性と日本語品質を優先してClaude Haiku 4.5に切り替え、最初の100セッションを完走させた。
| 項目 | Gemini Flash | Claude Haiku 4.5 |
|---|---|---|
| 入力 | $0.10/1M | $1.00/1M |
| 出力 | $0.40/1M | $5.00/1M |
| 503問題 | 頻発 | なし |
| 日本語品質 | 良好 | 優秀 |
100セッションで $6.54 が消費された(実測値)。1セッションあたり約$0.065だ。
ここで次の問題が見えてきた。1000セッションまで同じコストで回すと約$60かかる。 しかも途中で想定外の壁にぶつかった——自分で設定していた 月次上限$5 に到達して、60セッション目以降が全滅したのだ。上限を$10に変更してから再開したが、このコスト管理の失敗が次の判断を加速させた。
第2の切り替え:Claude Haiku → Ollama + qwen3.5:4b
そこでRAM増設(8GB→16GB)を機に、ローカルLLMへの切り替えを行った。
| 項目 | Claude Haiku 4.5 | Ollama + qwen3.5:4b |
|---|---|---|
| コスト | 約$60(900セッション) | $0(ローカル動作) |
| VRAM | 不要 | 3.4GB(RAM上でCPU推論) |
| 日本語品質 | 優秀 | 良好 |
qwen3.5:4bはVRAM 4GB(GTX 1650)では全載せできないためRAM上でCPU推論となるが、16GBのRAMで安定動作した。まず10セッション試してスコアを確認(99〜100点安定)、その後残り900セッション(実際には704セッション)をqwen3.5:4bで完走させた。
4. 1000セッションの結果
2回のバッチに分けて1002セッションを完走した。
第1バッチ: 3/4 18:29 〜 3/5 21:57(298セッション、実処理 約27.5時間)
第2バッチ: 3/6 08:45 〜 3/7 04:29(704セッション、実処理 約19.75時間)
─────────────────────────────────────────────
合計 : 1,002セッション、実処理 約47時間(3日間)
総セッション数 : 1,002件
総エントリ数 : 2,962件
FT候補エントリ : 99.9%
平均品質スコア : 95〜100点(100点満点)
品質スコアは4つのルールで自動評価している。
| 評価ルール | 配点 | 根拠 |
|---|---|---|
| 応答長(200文字以上) | 20点 | 短すぎる応答は物語に貢献しない |
| 世界観準拠 | 40点 | 逸脱はFTデータとして有害 |
| ロール準拠 | 20点 | 不正ロールは学習に使えない |
| エラーなし | 20点 | エラー文言を学習させたくない |
ほぼ全てのエントリがFT候補として採用された。Claude HaikuおよびqwenがSDNDの世界観に対して安定した応答を生成し続けたことを示している。
5. AIは何を話していたか
舞台はsdnd-eldiaという独自ファンタジー世界だ。登場するのは剣士エラ、商人ドルク、魔法使いアルといったキャラクターたち。
実際のログからRAG検索した例を示す。
検索クエリ: 「剣士が敵に攻撃する」
検索結果(類似度順):
[0.688] (GM / narration)
「エラは一歩前に踏み出し、剣を握ったまま腰から上げた。
攻撃的ではなく——防御と決意の姿勢。背後の村人...」
[0.677] (player / dialogue)
「ドルク、退いてくれ。これは俺の問題だ。」
エラは剣を握ったまま、一歩前に出て...
AIたちは世界観に沿って、キャラクターとしての一貫性を保ちながら即興で物語を紡いでいた。その掛け合いは、人間のTRPGセッションの記録と見分けがつかないものもあった。
6. 学習データとして何が得られたか
ドメイン駆動設計(DDD)による品質設計
2,962件のデータを単に集めただけでなく、使える形に整理することにこだわった。そのためにDDDのアプローチを採用している。
まず ubiquitous_language.md(用語辞書)を作り、「世界観に準拠する」「ロールを守る」といった概念を12語の禁止語テーブルとして明文化した。品質評価は QualityEvaluator というドメインサービスとして実装し、なぜそのエントリが良いか・悪いかの理由を evaluation_detail フィールドに記録した。
{
"role": "GM",
"scene_type": "combat",
"response": "エラは剣を構え...",
"training_data": {
"quality_score": 100,
"memory_layer": "skill",
"is_good_example": true,
"evaluation_detail": [
{
"rule": "world_consistency",
"score": 40,
"reason": "世界観逸脱キーワード0件"
},
{
"rule": "role_adherence",
"score": 20,
"reason": "GMロールとして適切な裁定"
}
],
"rag_context_used": true,
"rag_hits": 3
}
}
スコアだけでなく「なぜそのスコアか」を記録することで、将来のDPO(選好学習)でペアを組む際の根拠として使えるようにした。
5層記憶構造によるデータ分類
特筆すべきは memory_layer フィールドだ。AnimaWorksの5層記憶構造を参考にしたSDND独自設計で全エントリを分類した。
| 層 | 意味 | 用途 |
|---|---|---|
| skill | エージェント別応答パターン | エージェント別LoRA |
| procedural | シーン別行動手順 | DPO基準 |
| episodic | セッションの出来事 | FTペア |
| semantic | 複数セッションから蒸留(未生成) | システムプロンプト |
これにより「GMのskill層だけでFT」「combatシーンのDPOデータだけ抽出」といった層別の活用が可能になった。
RAGインデックスの構築
ChromaDBを使ったRAGインデックスも同時に構築した。新しいセッション実行時に過去の類似場面(類似度0.66〜0.69)を参照し、応答精度を高める仕組みが稼働している。
7. 課題と限界
スコアが高すぎる問題
FT候補99.9%という数字は、一見良い結果に見える。しかし裏を返せば、現在のルールベーススコアリングが形式的な品質しか測れていない可能性がある。
「200文字以上か」「世界観キーワード違反がないか」は測れる。しかし「この場面で本当にこのセリフが適切か」「物語として面白いか」は測れていない。
LLM-as-Judgeによる内容評価は実装済みだが、全件への適用はコスト上の理由でまだ行っていない。
円環の問題
同じモデルが生成したデータで同系列のモデルをファインチューニングする——これはいくつかのリスクを孕んでいる。
モデル崩壊: 多様性が失われ、特定の応答パターンが強化されるだけになる可能性がある。
自己採点バイアス: LLM-as-JudgeにGMと同じモデル系列を使うと、自分が生成した応答を高く評価しやすい。「自分のクセを自分で正しいと判定する」問題だ。これはsdnd-theaterの設計段階から認識していた課題で、判定役(Analyzer)には将来的に異なるモデルファミリーを使う方針としている。
Claude Haikuとqwen3.5:4bというモデルファミリーの異なる2系統のデータを意図的に混在させているのも、このリスクを分散するためだ。
Forgettingの未実装
1000セッションを超えたRAGインデックスの管理方針がまだ定まっていない。古いエピソードの圧縮・蒸留(Consolidationエージェント)は設計済みだが、実装は次フェーズの課題だ。
8. 次の問い(sdnd-devへ)
1000回TRPGを回し続けた結果、新しい問いが生まれた。
「同じ仕組みで、ソフトウェア開発もできるのではないか」
GMをArchitectに、プレイヤーをImplementerとReviewerに置き換えれば、自律的なソフトウェア開発セッションが回せる。この発想から生まれた sdnd-dev では、3エージェントが協調してコードを自律改善するRSI(再帰的自己改善)サイクルが稼働している。
sdnd-devの詳細は別記事で紹介する予定だ。
まとめ
sdnd-theaterは「AIだけでTRPGを回したら何が起きるか」という素朴な問いから始まった。
結果として得られたのは、2,962件の構造化された学習データだけではない。「特定ドメインの専門家を自動的に育て続けるシステム」の原型が、意図せず完成していた。
ただし、データを集めれば終わりではない。次のフェーズ——ファインチューニング——に進む前に、FT後の出力安全性検証基準を定義する必要がある。禁止出力の定義、検証セッション数、判定基準。これを人間がルールとして決めてからFTに着手する方針だ。
AIに任せられる範囲を広げながら、判断のルールを設計する責任は人間が持ち続ける。sdnd-theaterはそのための実験台として、今日も動き続けている。
リポジトリ: sdnd-theater
*姉妹プロジェクト: sdnd-dev / sdnd-trpg*s