こんにちは、パレイド技術部の夏目です。
第3回まで、V3 固有命令の実機観察を一通り終えました。自動実行ハーネスで観察した命令群と、仕様書から収録した直接入力コマンドを合わせて、v3.0 ROM を前提にしたコーパスが揃いました。今回はこのコーパスを使い、ローカル LLM に追加学習(LoRA)を施して、1984 年の Family BASIC V3 の書き方がモデルに定着するか確かめます。LoRA(Low-Rank Adaptation)とは、モデル全体を再学習するのではなく、少量のデータで特定の語彙・文体を後から焼き込む手法です。
本記事はローカル LLM による自動執筆パイプラインで生成されました。現段階ではクラウド AI(Claude 等)の補助や人間の編集が介在していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。
コーパスを学習データに変換し、7B モデルを再学習する
まず観察データを整形しました。v3.0 ROM で観察した記録ファイルは 113 件あります。「途中経過」や「手動確認待ち」のフラグが立ったものを除外し、最終的な訓練例は 427 例になりました。各例には「この命令をこう書くとこうなる」というペアが入っており、第3回で観察した V3 固有命令(文字列検索・エラー捕捉・スプライトの衝突検出と方向取得)も一通り含まれています。
学習は Apple Silicon 向けの機械学習フレームワーク MLX を使い、7B パラメータの量子化モデルをベースに追加学習アダプタを訓練しました。4bit 量子化とはモデルの重みを 4 ビット精度に圧縮することで、32GB の Mac 上でも 7B モデルが扱えるサイズになります。600 ステップの訓練は Mac 上で 20 分ほどで完了しました。
| 項目 | 値 |
|---|---|
| ベースモデル | Qwen2.5-Coder(7B、4bit 量子化) |
| 訓練例数 | 427 例 |
| 学習ステップ数 | 600 |
| 最終検証損失(val loss) | 0.345 |
学習後のアダプタをベースモデルに統合し、ローカルのモデルサーバーに登録しました。このモデルを起動する際は、V3 リファレンス全文の自動注入をスキップする設定にしました。リファレンス文書が 154KB あり、それをそのままモデルに渡すとモデルが一度に扱えるトークン数の上限(3 万 2 千トークン)を大幅に超えてエラーになるためです。
生成テスト結果
生成テストは「V3 固有命令を含む問い」と「観察コーパスの外にある問い」の 2 種類で確認しました。
V3 固有命令の問いには概ね正しく応答できました。「文字列 A$ の中から B$ を探すには?」という問いに対し、2 引数形式の文字列検索命令を生成しました。第3回の実機観察と一致しています。「スプライトの移動方向を調べるには?」には、スプライトを定義して動かし、移動方向を取得する V3 固有の書き方でコードを出力しました。ベースモデル単体では他の BASIC 方言の書き方に引っ張られていたのが、追加学習後は Family BASIC V3 の方言で答えるようになっています。
一方、「簡単なアクションゲームを作って」という問いでは、問いを変えても同じスプライト操作の雛形(スプライト定義→位置指定→移動開始)を繰り返すだけで出力が固着しました。内容の異なる問いを 3 通り試しましたが、どれも同じコードに収束しました。これについては次のセクションで詳しく説明します。
方言は焼けた。しかし創作的な問いで固着した
観察パターンの再現は成功しています。しかしコーパスの外にある問いでは出力が固着するという問題が出ました。
この現象はモード崩壊(mode collapse)と呼ばれます。訓練データのパターンに特化しすぎて、それ以外の問いへの多様な応答ができなくなった状態です。原因はデータの構成にあります。427 例のほぼすべてが「この命令を実行するとこうなる」という観察記録の再現パターンです。「自由にゲームを設計する」「命令を組み合わせて何かを作る」といった創作的な例がゼロなので、その種の問いへの応答を学べていません。
ハイパーパラメータを変えた 2 条件でも試しました。
| 条件 | 学習ステップ / 学習率 | 方言再現 | 創作的出力 |
|---|---|---|---|
| heavy(600 ステップ / 高い学習率) | — | ✅ V3 文法を正しく生成 | ❌ 同一雛形に固着 |
| light(200 ステップ / 低い学習率) | — | ❌ 他の BASIC 方言に引っ張られる | ✅ 固着しない |
light 条件ではモード崩壊は起きませんが、方言も失われます。文字列検索命令の書き方が SQL や VBA の構文に引っ張られ、Family BASIC らしさが消えました。
具体的には、Family BASIC V3 では引数の順を INSTR(検索対象, 検索語) と書くべきところを逆順で出力する例が複数ありました。heavy と light の中間に「ちょうどよい」ポイントがない ── これが訓練例 427 件という量の限界です。観察コーパスは「記録」を目的に作ったものであり、「創作の材料」としては偏りがありすぎました。
もう一方の手法として、V3 全体のリファレンス文書を毎回問いと一緒に渡すコンテキスト注入(RAG)があります。追加学習は不要で、仕様書をそのまま文脈として渡せばよいため、構築の手間は少ない方法です。しかし V3 のリファレンス文書は圧縮しても 150KB を超えます。モデルが一度に扱える文脈の上限は現在 3 万 2 千トークン程度であり、文書全体を渡すとリクエスト自体がエラーになります。試したところ、実際にそうなりました。
結果として、LoRA は観察パターンに特化しすぎてモード崩壊を起こし、RAG は文脈を詰め込みすぎてエラーになる。両者は逆方向の問題を抱えていることが分かりました。
狭い LoRA は崩壊し、巨大な RAG は溢れる
連載として V3 対応の三つの柱が揃いました。観察ハーネス(第1回)、コーパス(第2〜3回)、追加学習(今回)です。それぞれ単体では完成していますが、「V3 の方言を習得したうえで創作的なコードも書ける」という最終目標にはまだ届いていません。
解決の方向として、二つが考えられます。
一つは訓練データに創作的なパターンを加えることです。観察の再現だけでなく、複数命令を組み合わせたミニゲームや、INSTR でメニュー選択を実装する例など、「使い方の多様さ」を示すデータを増やす方向です。ただしこの種の例は実機観察では得にくく、人が手で書くか別のモデルに生成させるか、データ作成コストがかかります。
もう一つは RAG と LoRA を組み合わせる方向です。仕様書のうち問いに関連する部分だけを切り出して渡し(仕様全文ではなく数百トークン程度)、方言の作法はモデル側に焼いておく方式です。文脈の窓を使い切らず、かつ方言の基礎は持っているという状態を目指します。こちらは文書の切り出しロジックを作る手間が要りますが、データを一から作るよりコストが低い方向です。
どちらの方向が有効かは、実際に試さないとわかりません。次に何を試すかは、ここで得た「どこで詰まるか」を持ち越して考えます。V3 の命令が 1984 年の ROM から 2026 年の 7B モデルへ渡りきるかどうか ── まだ途中です。