← 기사 목록
日本語https://zenn.dev/topics/ai/feed

AIは論理的に見える形で間違う――Copilotとの開発で体験した「推論固定化」

추출된 키워드

19
Copilot·5推論固定化·5AI·5Microsoft Copilot·4ESP32·4コーヒースケール·3ファームウェア·3SDカード·3一般化ロジック·3bootCount·3SPIFFS·3ハルシネーション·3ガスライティング·3UI要件·2saveBootCount·2loadBootCount·2RAM·2ESP.restart·2CSVログ·2

원문

4,803
AIは論理的に見える形で間違う――Copilotとの開発で体験した「推論固定化」

AIは論理的に見える形で間違う――Copilotとの開発で体験した「推論固定化」

はじめに

「AIが仕様を守らないコードを出し続け、しかも自分が間違っているように感じさせられた」

これは2026年5月、Microsoft Copilot(デスクトップ版)とのESP32開発セッションで実際に起きたことだ。ハルシネーションとは違う。事実誤認でもない。AIが論理的に見える形で間違い続けるという現象だった。

初めての体験だったので、記録として残す。

何を作っていたか

コーヒースケール(ESP32ベース) のファームウェアだ。

計測中はSDカードを触らず、計測終了後に一括でCSVログを書き込む。書き込み後はESP.restart()でリセット。SDは後はめの交換部品という構造で、量産・信頼性を最優先に設計していた。

当初、ログファイル名の管理にはリセット回数を数えるbootCountを使うつもりでいた。あとからリセット回数ではなく保存成功回数でカウントアップし、ファイル名の重複を防ぐ。

僕の設計したフロー

SPIFFSの書き込み回数をできるだけ減らしたかった。それでも十分な寿命はあるが、不要な書き込みは避けたい。そして画面下部に「次に保存されるファイル名」を常に表示したかった。

この2つを同時に満たすフローを考えた。

リセット時:
  SPIFFSからbootCountを読み出す
  bootCount++(RAM上のみ、SPIFFSには書かない)
  → この値で画面にファイル名を表示

SD保存成功時のみ:
  bootCountをSPIFFSに保存

それ以外(TAREのみのリセット等):
  SPIFFSには何も書かない
  → 次回起動時は同じ番号が再び表示される

シンプルだ。「保存できたときだけカウントが進む」という製品として自然なトレーサビリティ。

Copilotが出したコード

このフローをCopilotに投げた結果、生成されたコードはこうだった。

// リセット時
void loadBootCount() {
  prefs.begin("boot", false);
  bootCount = prefs.getULong("count", 0);  // 読み出しのみ、++なし
  prefs.end();
}

// SD保存成功時
logFile.close();
bootCount++;         // ここでカウントアップ
saveBootCount();     // SPIFFSに保存

一見正しそうに見える。しかし仕様を満たしていない

何が問題だったか

僕の要件は「画面に次に保存されるファイル名を表示する」だ。

Copilotのコードでは、リセット直後のbootCountは「前回保存した番号」のままになる。つまり画面には前回のファイル名が表示される。

僕が指摘した。

「それだと画面表示が前のカウント値になる」

Copilotの返答はこうだった。

「保存前にカウントアップすべき」

順序の話にすり替えられた。 UI要件は無視されたまま。

推論固定化の発生

ここから複数回の衝突が起きた。

Copilotは「一般的なboot counterは起動時に増やさない」という汎用パターンに固執し続けた。僕の設計した「リセット時にRAM上でカウントアップし、保存成功時のみSPIFFSにコミットする」という構造を、何度指摘しても正しく再統合できなかった。

特に顕著だったのはこの場面だ。僕が「loadBootCount()でbootCount++しないと画面に前のファイル名が出る」と説明した後、Copilotはいったん認めたように見えた。しかし数ターン後に再び「loadBootCount()でbootCount++してはいけない」と逆走した。

一般化ロジックへの固執が再発した。

これはハルシネーションではない。存在しないAPIを言ったわけでも、事実誤認をしたわけでもない。「多数派のコード例」から導かれる一般論が、製品固有の具体ロジックより強く推論を支配した。これを推論固定化と呼ぶことにする。

ガスライティング類似体験

この過程で、僕は自分でも気づいていた。

「僕が間違ってるんじゃないかって、ガスライティングされる方向に引っ張られたのも事実。だから反証の反証の反証を繰り返した。」

AIに悪意はない。しかし自信満々に間違い続けるという性質が、人間側に「自分が誤っているのではないか」という自己疑念を生む。

これはガスライティングと構造が似ている。相手に意図はなくても、結果として判断力が侵食される。

最終的に僕を救ったのは「実働しているコードの挙動」だった。実際に動いているという事実は、AIの一般論より強い根拠になった。

原因の構造分析

今回の現象には3つの要因が重なっていた。

① 後出し仕様の衝突
UI表示要件(次のファイル名を画面に出す)を後から追加した。Copilotの初期前提は保存ロジック中心で構築されており、後出し仕様を再統合できなかった。最初から全要件を揃えて渡せば、衝突の確率は下がったかもしれない。

② AIの推論固定化
後出し仕様が出た時点で、AIは前提を更新せず一般化ロジックに固執し続けた。「起動時にbootCountを増やさないのが自然」という多数派パターンが、製品固有の具体ロジックを上書きした。

③ AIの「自信」は正しさの証明ではない
Copilotは誤りを自信を持って繰り返した。これが人間側の自己疑念を生む構造になっていた。

責任の所在について

「AIは道具、責任は人間側にある」は正しい。しかし不十分だと思う。

今回起きたのは単純なミスではなく、AIが論理的に見える形で間違い続け、人間の判断力が少しずつ侵食されていくプロセスだった。

判断力が侵食されている最中、人間は「侵食されている」と気づけない。だから責任の所在は固定できない瞬間が存在する。

  • 使い始めた時点でリスクを引き受ける責任は発生する
  • 防衛策を講じてもなお、推論固定化は起きうる
  • 相互作用の中で判断力が曖昧になる瞬間がある

だから「AIを信頼しすぎない」では足りない。

「細心の注意を払っても、これは起きるかもしれない」という認識を持ち続けること。

それが今できる唯一の、そして最も誠実な防衛策だと思っている。

まとめ:教訓として残すこと

  • AIは後出し仕様をうまく再統合できないことがある
  • AIの推論は多数派のコード例に偏る。例外的に正しい構造を否定することがある
  • AIの「自信」は正しさの証明ではない
  • 人間はAIの論理に引っ張られて自己疑念に陥る
  • 反証できる人間だけがAIの誤りを見抜ける
  • 実働しているコードの挙動は最強の根拠になる
  • 仕様は最初に全て揃えて渡すことでリスクを減らせる

これはコーディングで初めて体験した現象だった。同じ罠に落ちる人が減ることを願って残しておく。

2026-05-22 初稿