AIに家を設計させたら、自分の実装の欠陥が4つ見つかった
直したのは、AIの設計力ではなく、こちらの仕組みでした。 住宅設計のループに「設計する役」「審査する役」「裁定する役」「直す役」を置き、点数は言語モデルではなく法規・構造の決定論エンジンに計算させました。同じ敷地・同じ主題で、断熱レバーを足す前と後を比べると 25.3点 → 82.2点。別の主題では 91.0点(その敷地の到達可能上限は96.2点)。数字が動く一方で、自分のコードの欠陥が4つ出てきました。その記録です。
動画の文字起こし(全文)
AIに家を設計させて、実際に何件も回してみました。その途中で、自分の実装の欠陥が4つ見つかりました。設計する役と、審査する役を分けました。審査役には、設計者の意図を見せません。仕様と実測値だけを渡します。採点は言語モデルではなく、法規と構造の決定論エンジンが行います。最初の実走では、どの案も20点台でした。原因は、寒冷地で断熱性能が足りないこと。ところが仕様に断熱の項目が無く、直しようがありませんでした。断熱の段階を追加したら、同じ敷地で82点まで上がりました。2つ目は、敷地の一覧と実行でIDが食い違っていたこと。3つ目は、90点が原理的に届くのか分からなかったこと。全探索を足して96点と分かりました。4つ目は、自動修正が点を最大化してしまい、審査の仕事を奪っていたこと。最終的に、札幌の117平米の敷地で、法規適合のまま91点まで届きました。クラウドのモデルは鍵が無効で、まだ試せていません。
25.3 → 82.2 → 91.0 (札幌117㎡/上限96.2)
なぜ「敵対的」にしたのか
同じモデルに設計させ、同じモデルに褒めさせると、点数は上がるが家は良くならない。
最初にぶつかったのは、ごく普通の失敗でした。言語モデルに設計案を出させ、その案を言語モデル自身に評価させると、もっともらしい点数が返ってくる。ところがその点数は、法規に適合しているかとも、構造が成り立つかとも関係がありません。モデルは文章として筋の通った評価を書くのが得意で、それは「家として成立している」ことの証明にはならないからです。
そこで役割を4つに割りました。
| 役割 | やること | 見せないもの |
|---|---|---|
| Proposer(設計) | 敷地と主題から案を作る | — |
| Adversary(審査) | 仕様と実測値だけを見て欠陥を指摘する | 設計意図・作品の物語 |
| Judge(裁定) | 指摘のうち採用するものを選ぶ | 指摘の「勢い」 |
| Reviser(修正) | 採用された指摘だけを反映する | — |
審査役に設計意図を見せないのが要点です。「自然と共に呼吸する家にしたい」という物語を渡すと、審査役はその物語に引きずられて、都合の良い評価を返します。仕様と実測値だけを渡すと、指摘は具体的な欠陥に寄ります。
裁定(Judge)はLLMですが、自由度はここだけに閉じています。審査役の指摘は「対象軸・深刻度・根拠となる実測値」の形で受け取り、①決定論エンジンの判定と矛盾する指摘は、Judge に渡す前に機械的に捨てる(法規適合なのに「法規NG」と言う指摘など)。②残った指摘から、実測と矛盾するもの・単なる好み・重複を落とし、最大4件まで採用する。点数には一切触れさせません。
そして点数は、言語モデルには一切書かせません。採点は決定論エンジンだけで行います。
- 合否(二値):
houki-engineが建ぺい率・容積率・高さ・斜線・採光などを判定(法規)。structural-engineが木造なら壁量・偏心・剛性率、高層なら軸力・細長比を検定(構造)。 - 4つの観点(0〜1の連続値):
func(機能=間仕切り壁・窓の数・延床)、beauty(美=採光・窓壁比・構成の質)、env(環境=材料・太陽光・雨水・建ぺいの低さ)、fun(楽しさ=吹抜・縁側・ロフト・ピアノ・外形の複雑さ)。 - 合成:4観点を重み付きで足し(機能0.18/美0.25/環境0.15/楽しさ0.20)、法規不適合なら ×0.3、構造不適合なら ×0.7。価格は総合に算入しません(高級な案を不当に沈めないため)。
同じ仕様を入れれば同じ点が出ます。モデルが「92点です」と言う経路は存在しません。
欠陥1:断熱にレバーが無かった
寒冷地で全案が20点台。原因はAIではなく、仕様の項目不足でした。
最初の実走は散々でした。札幌の117㎡の敷地で「雪国の家」を作ると25.3点、法規は不適合。「継ぐ家」も24.9点。複数まわしても20点台から抜けません。
レポートを読むと、原因ははっきりしていました。寒冷地では断熱性能(UA値)が法規の適合条件に入ります。ところが当時の仕様には断熱の項目そのものが無く、どんな案を出してもUA値を満たせない。つまりAIは「直せない問題」を延々と解こうとしていたわけです。
そこで仕様に断熱の段階(標準/高断熱/超高断熱)を足しました。同じ敷地・同じモデルで、82.2点まで上がりました。点数が上がったのは、AIが賢くなったからではなく、正しいレバーを渡したからです。
欠陥2:敷地IDが、母集団サイズ n に依存していた
同じIDでも、n が違うと別の土地になる。ここは「踏みかけた罠」です。
敷地は jp-01-0000 のようなIDで指定します。このIDは、日本の敷地を何件生成するか(母集団サイズ n)によって割り当てが変わります。--list-places で一覧を出すときと --place で実行するときで n が違うと、同じIDが別の土地を指します。
これは実走の数字を比べるときに致命的です。「同じ敷地で25.3点から82.2点に上がった」と言いたいのに、実際には違う土地を見ていた可能性があるからです。duel の実装では、一覧と解決の両方を n=3000 に固定してあります(src/main.rs の --list-places と --place 解決)。実装当初から同じ n を使うように書いていたので、今回の実走で数字が壊れたわけではありません。
n で書くと静かに壊れます。エラーも警告も出ず、数字だけがずれる。だから「なぜ n を固定しているか」をコードのコメントと記事の両方に残しました。
欠陥3:90点が原理的に届くのか知らなかった
目標を掲げる前に、天井を測る。
ループの目標は90点にしていました。しかし、その敷地でそもそも90点に届くのかを知りませんでした。届かないなら、何ラウンド回しても無駄です。
そこで --ceiling を足しました。その敷地で取りうる構成を全探索して、到達可能な最高点をLLMなしで計算します。札幌の117㎡では96.2点。所要は約9秒です(time 実測: real 9.106s / user 8.84s)。
これで「目標90、天井96.2、だから届く」と根拠を持って言えるようになりました。逆に、天井が目標を下回る敷地なら、生成器の拡張が必要だと分かります。
欠陥4:自動修正が、審査の仕事を奪っていた
不適合を直す処理が「最大化」だと、敵対ループが空回りする。
言語モデルの案が法規不適合だったとき、決定論的な修復処理で合法化します。このとき、形・階数・素材は保ち、しかけ(features)と断熱だけを変える設計にしました。理由は、スコアを最大化する修復にすると、常に天井の構成に張り付いてしまうからです。
もし修復が最大化を狙うと、どんな案を出しても最終的に同じ最良構成に落ちます。すると審査役が指摘する余地も、修正役が改善する余地も消え、ループはただの往復になります。「合法になる最小の変更」に留めることで、改善の余地を残しました。
最終的な実測
すべてローカルの qwen2.5:14b で実行。クラウドモデルは鍵が無効で未検証です。
| 段階 | 主題 | 総合 | 法規/構造 | 何を変えたか |
|---|---|---|---|---|
| 初回 | 雪国の家 | 25.3 | 不適合/適合 | — |
| 断熱の段階を追加 | 雪国の家 | 82.2 | 適合/適合 | 仕様に断熱を追加 |
| 全探索で天井を測定 | (構成の全列挙) | 96.2 | 適合/適合 | 到達可能上限の確認 |
| ループ実走 | 継ぐ家 | 91.0 | 適合/適合 | 1ラウンドで目標到達 |
※各条件1回のみの実測です(n=1・分散未測定)。25.3 と 82.2 は同一主題・同一敷地の別実行(断熱レバー追加の前後)で、同一実行内の推移ではありません。91.0 はさらに別主題の値なので、82.2 と 91.0 の差を「改善幅」として読まないでください。
91.0点は「継ぐ家」を1ラウンド回して到達した値です(初期案85.3 → 審査役の指摘1件を採用 → 91.0で目標到達、LLM呼出4回)。天井の96.2には届いていないので、まだ改善の余地があるということでもあります。
なお、91.0点の案は延床93.4㎡・概算5,604万円。天井構成は延床98.7㎡・概算7,107万円でした。点数の高い案が常に望ましいわけではなく、面積と費用のトレードオフは別途見る必要があります。
未確認のこと
できていないことを、できたことと同じ欄に書かない。
- モデル間の品質比較は未実施。設計・審査・裁定をすべて同一モデル(qwen2.5:14b)で回しています。役割と見せる情報は分けていますが、盲点は共有されている可能性があります。レポートにも警告として出るようにしました。
- クラウドモデルは未検証。
GEMINI_API_KEYはAPI_KEY_INVALID、ANTHROPIC_API_KEYは未設定でした。 - 同一条件の反復は未実施。すべて n=1 の実測で、シードを変えたときの分散を測っていません。91.0点が再現するかは未確認です。
- 狭小地は未対応。決定論エンジンの最小フットプリントは5.4m×7.0mです。これ未満の敷地では全案が建ぺい率超過になるため、実行時に警告を出します。
- 設計意図と最終仕様が食い違う場合がある。修復で仕様を変えたとき、物語文は元のまま残るためです。修復履歴をレポートに明示するに留めています。
使うなら
同じ構造は、点数を機械で出せる領域ならどこにでも移植できます。
# 敷地の一覧(母集団 n は統一済み) mu-house duel --list-places --limit 20 # その敷地の到達可能な最高点を先に測る(LLM不要・約9秒) mu-house duel --place jp-01-0000 --ceiling # ループを回す mu-house duel --place jp-01-0000 --theme 継ぐ家 --target 90 \ --rounds 4 --max-calls 12 --out /tmp/duels # max-calls = LLM呼び出しの総予算 # 複数主題をまとめて mu-house duel --place jp-01-0000 --themes "雪国の家,継ぐ家,一人と猫の家" --out /tmp/duels
大事なのは、点数をモデルに書かせないことと、点が伸びないときに仕様側のレバーを疑うことでした。今回見つかった4つの欠陥は、どれもコードを読んでいるだけでは気づけず、実際に回して数字を並べて初めて見えたものです。
この仕組みを自分の敷地で回す
Proposer / Adversary / Judge / Reviser の分離と、決定論スコアラ。手元の Ollama で動きます(クラウドの鍵は不要)。
bim.house で同じ流れを試すこのループの実体は mu-house(Rust製)。bim.house はその設計画面です。
関連: AIに電卓を渡したら、答えを聞き直すのをやめた / 公開ベンチマークと真逆の結論を出した:1回の測定で「最安モデル」と断定した失敗 / 検証器はすでに知っていた
実行環境: macOS / mu-house (Rust) / ローカル Ollama qwen2.5:14b-instruct-q4_K_M / 敷地 jp-01-0000(北海道 札幌周辺 #1・117㎡・第一種中高層住居専用地域)/
実走日時 2026-11-01 00:11〜02:08 UTC。数値は各レポートの 総合 行から転記。