前回は、コーディング支援パネルの接続先をClaudeからOpenAI(gpt-5.6-sol)に差し替えました。依頼文一つだけではLOCATEとPRINTによるテキスト表現に留まりましたが、「スプライトを使って」と明示するとDEF SPRITEをはじめとするハードウェアスプライト命令一式を正しく使いこなし、実行時エラーもありませんでした。応答速度もgpt-5.6-solのほうが明らかに速く(claude-cliの約6分に対して30秒台)、ClaudeとOpenAIはこの用途で遜色ないことが分かっています。
今回はローカルLLMの番です。先に結論を書きます。現時点では、自由な依頼でのバイブコーディングにローカルLLMは厳しい。以下、技術部の別連載「LLMのためのFamily BASICリファレンス」で測ってきたベンチマークも参照し、その根拠を見ていきます。
本記事はローカル LLM による自動執筆パイプラインで生成されました。現段階ではクラウド AI(Claude 等)の補助や人間の編集が介在していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。
実演ではなく、ベンチマークで測った理由
第1回から第5回で扱ったチャット機能では、すでにOllamaでローカルモデルを動かしています。ただしあれはメッセージ枠に収まる短い英文を返させる用途でした。今回のテーマである「BASICのプログラムを書かせる」用途については、要素を分解して単純化したベンチマークの形で検証してみます。
LLMの応答がうまく動かなかったとき、ファミリーベーシックの「方言」を外したのか、プログラムの長さに負けたのか、そもそもリファレンスがモデルに届いていなかったのか。これを分けるには、課題を小さく割って軸ごとに測るほうが確実です。そこで文字表示・計算・スプライト・音・コントローラの各軸で8つの課題を用意し、エミュレータで実際に RUN まで実行して判定しました。
| 項目 | 内容 |
|---|---|
| 検証機 | MacBook Air M5 / 32GB unified memory |
| 実行基盤 | Ollama(ローカル)。比較対象としてクラウドのClaude Sonnet |
| 評価 | nesemuのheadlessハーネス(RUN後の画面・スプライト・音・パッド入力を自動判定) |
| ROM | Family BASIC V2.0A |
| 課題 | 8本(文字表示・計算・スプライト・音・コントローラ) |
| 渡す資料 | 実機観察リファレンス 154KB(約55,000トークン) |
3モデル×8課題の実測
最初のベンチマークは、Claude Sonnet・qwen3.5:9b・gpt-oss:20bの3本立てでした。◯が実機で期待どおり動いた課題、×が落ちた課題です。数字は依頼から判定までの所要時間になります。
| 課題 | Sonnet | qwen3.5:9b | gpt-oss:20b |
|---|---|---|---|
| hello-print | ◯ 20s | ◯ 28s | ◯ 11s |
| add-two-numbers | ◯ 18s | × 302s | × 302s |
| count-1-to-5 | ◯ 18s | × 177s | ◯ 21s |
| sum-1-to-10 | ◯ 24s | ◯ 27s | ◯ 26s |
| primes-under-20 | ◯ 33s | × 40s | ◯ 52s |
| sprite-show-anywhere | ◯ 39s | ◯ 33s | ◯ 87s |
| play-melody | ◯ 31s | ◯ 31s | ◯ 51s |
| controller-a-button | × 28s | × 303s | × 371s |
| 合計 | 7/8 | 4/8 | 6/8 |
クラウドのSonnetが7/8、手元のgpt-oss:20bが6/8。その差は1課題です。しかも add-two-numbers の302秒×は、ベンチマークの一番手だったせいで55,000トークンの読み込みが初回だけ重くなり、Ollamaの5分制限に当たったもの。この1件を除けばgpt-oss:20bは6問中6問という実測でした。qwen3.5:9bの count-1-to-5 は、LOCATE の引数順(ファミリーベーシックは「列, 行」)を踏み外した失敗です。
一方、controller-a-button は3モデルとも全滅でした。Aボタンを押している間だけ HIT と出す、それだけの課題です。Sonnetは現代のBASIC風に IF 〜 THEN 〜 ELSE 〜 を1行で書いて ?SN ERROR を踏み、ローカルの2モデルは生成が膨らんでタイムアウトしました。状態の判断とリアルタイム入力が絡むと、文字表示や音より明確に難しくなります。
測定時に調整に苦労した点も3つ記録しています。いずれも「そのモデルが賢いかどうか」以前の話です。
num_ctxを十分大きく取る。Ollama等ではコンテキストサイズのデフォルト値が小さめで、154KBあるリファレンスが切り詰められてしまいます。131072(128K)を明示すれば、リファレンスの実測56,594トークンがコンテキストに収まります。- Qwen3系のthinkingモード。巨大な入力で思考が膨らみ、Ollamaの5分制限に当たってHTTP 500になります。オフにした方が良さそうです。gpt-oss:20bもthinkingモードですがこちらはオンオフがコントロールできずそのまま使っています。
- コード特化モデルが32GB機に乗らない。Qwen2.5-Coder 7Bは扱えるコンテキストが32kで資料が入らず、DeepSeek-Coder V2 16BはKVキャッシュ込み49GBでCPUとGPUに分割され、読み込み速度が34 tok/sまで落ちました
なお、渡す資料を整理した公開版に差し替えた別の回では、gpt-oss:20bが8/8を通しています(資料なしの条件では3/8)。同じモデルで5課題ぶん動いた計算で、伸びしろは資料の側にもあります。
小型ローカルLLMでつまずいた3つの問題
もっと軽いモデルならどうか。12Bクラスで測った回では、素のgemma3:12b(約8.1GB)が資料なしで7/8と健闘しました。ところが、これをコード特化にファインチューンしたモデルの4bit量子化版(Q4_K_M、約6.9GB)は5/8。コード向けに調整したはずのモデルが、素の12Bより下がるという逆転です。失敗の中身は LET D=D+1(V2.0Aに LET はない)や SPRITE AT 10,10 といった、一般的なBASICの知識が方言を上書きする型でした。2bit量子化のQ2_K(約4.5GB)に至っては0/8で、コードの善し悪し以前に言語が崩れます(I am a model and I am l.bankeva!... のように英語・中国語・韓国語・記号が混ざり、プログラムを1行も出しません)。ここまで削ると選択肢に入らない、という上限がはっきり出ました。
ここから先は、資料をどう与えるかという設計面でつまずいた3つの問題です。
1. リファレンスが大きすぎて、読み込ませること自体が難しい
実機観察リファレンスは154KB(約55,000トークン)あります。12Bクラスの量子化モデルにこれを丸ごと渡すと、読み込みだけで958.79秒(約16分、57.6 tok/s)かかりました。Ollamaには最初のトークンが返るまで300秒というタイムアウトがあり、16分かかる処理は5分で切られます。しかも読み込ませられたとしても、それで精度が上がるとは限りません。同じQ4_K_Mモデルは、資料なしで5/8だったのが、資料ありでは2/8まで落ちています。大きすぎる資料は、小型モデルにとって「読み込めない」か「読み込めても使いこなせない」かのどちらかでした。
2. LoRAは、少数の学習サンプルに引っ張られた
資料を毎回積めないなら、モデルの重みに覚えさせればよい。そう考えて、Qwen2.5-Coder-7B-InstructをMLXでLoRA学習させました。自動評価ではコード形式のPASS率が0%から100%に上がり、方言の作法が焼けたように見えました。ただしこの100%は、「行番号で始まり小文字を含まない」という形式チェックにすぎません。実際にいろいろな依頼を試すと、学習に使ったサンプルに近い出力をほぼそのまま返すだけで、依頼文を変えても内容がついてきませんでした。少数の例文で学習した結果、その例文に引っ張られて丸暗記しただけで、未知の依頼への汎化はしていなかったということです(出力予測の精度も50%から37%に低下、10 LET A=1 を無効と正しく判定できてもエラーコードは ?SN ではなく ?NF と誤答するなど、事実の幻覚も残りました)。GGUF変換・Ollama実装・本番3条件ベンチまで進める計画でしたが、この時点で見送りました。
3. RAGは、検索設計そのものが重かった
資料を丸ごと渡すのでもモデルの重みに焼くのでもなく、依頼ごとに必要な部分だけ検索して渡すRAG(Retrieval-Augmented Generation)も検討・試行しました。ただし、どんな依頼が来たときにリファレンスのどの断片を渡せば実際に精度へ効くのか、その検索設計自体の見通しが立ちませんでした。実用レベルまで詰めるにはこの設計だけで相応の時間がかかりそうで、現時点では見送っています。
まとめ — 自由な依頼はまだ、絞った問いなら届く
ここまでの条件を1枚に並べます。
| モデル / 条件 | PASS | 主な失敗要因 |
|---|---|---|
| Claude Sonnet(クラウド、資料あり) | 7/8 | 現代BASIC風の構文で ?SN ERROR |
| gpt-oss:20b(資料あり・公開版) | 8/8 | ー |
| gpt-oss:20b(資料あり・初期版) | 6/8 | 初回読み込みのタイムアウト |
| qwen3.5:9b(資料あり) | 4/8 | 引数順の取り違え、タイムアウト |
| gemma3:12b(資料なし) | 7/8 | 一般BASICの知識が方言を上書き |
| 12Bコード特化 Q4_K_M(資料なし) | 5/8 | 同上 |
| 12Bコード特化 Q4_K_M(資料あり) | 2/8 | 300秒の応答開始タイムアウト |
| 12Bコード特化 Q2_K(資料なし) | 0/8 | 出力の崩壊 |
数字だけ見ると悪くありません。ただし、ベンチマークが通ることと、バイブコーディングが通ることは別です。ベンチマークは指示が1行で、正解の形も決まっている一問一答。対して自由な依頼は、154KBを毎回読ませたうえで、まとまった長さのプログラムを一度に書き切り、エラーが出たら画面を見て直すところまで回す必要があります。第6回のClaudeでも応答に7分かかった工程を、読み込みだけで16分かかるモデルで回すのは、現状では成り立ちません。
それでも「ローカルは全滅」とは書けません。gpt-oss:20bは8課題中6、資料を整えた条件では8まで来ています。届いていないのは自由な依頼の側であって、絞った問いの側ではない。そしていま壁になっているのは、モデルの賢さより、読み込み速度と300秒という配送側の制約です。ここは資料の軽量化とハードの世代交代の両方で動く部分なので、1年単位で見れば位置は変わるはずです。
現時点で結論を出すなら、課金は必要でも、クラウドの大型LLMを使うのが実用的です。無料で手元で動かせるのがローカルの魅力ではありますが、「バイブコーディング」をこなすにはまだ足りません。
次回は、エミュレータの画面から離れて、VSCode側から直接BASICを書かせる場合を見ます。