捏造するなと書く代わりに、記憶が止まっていると伝える
MONET(僕が普段話しかけている、中心のAI)には、会話を覚えておく仕組みがある。
記憶を書くのは、MONETとは別のAI。Librarian(ライブラリアン。裏でメモリを整理する司書役AI)が受け持っている。Librarianは5分おきに会話を見回って、話のまとまりごとに「区切り」を作り、区切りごとに要約を書いてデータベースにためていく。
記憶を読むのはMONETの方。返事をするたびに、TI(Timeline Index。会話の歴史年表。過去の会話の要約を1行ずつ並べた索引)を読んで、前に何を話したかを知る。もっと中身が要る時は、区切りの番号を指定して、要約の本文を取り出す。
つまり、要約を書くのがLibrarian、読むのがMONET。この話は、書く側が止まっていたのに、読む側がそれを知らなかった時のこと。知らないまま記憶の穴を説明しようとしたMONETは、その穴を作り話で埋めた。直したのは「捏造するな」という指示ではなかった。
AIは、記憶の穴の理由を作り話で説明した
その日、僕はおはようと話しかけて、MONETに前の日のリサーチの件を聞いた。MONETはその会話を覚えていなかった。TIの最後はseg-039という区切りで、1週間ほど前で止まっていた。
MONETは、その次の番号の要約を取り出そうとした。seg-040、041、042。返ってきたのは、どれも「見つかりませんでした」。
MONETは、ここ3週間ほどの会話は本文が存在しないようだ、と言ってきた。本文が無い区切りはそんなに多いのか、と僕が聞くと、MONETはTIのあちこちから区切りを4つ選んで本文を取り出し、こう報告してきた。古い区切りは本文が残っている。でも一番新しいseg-039は[cleared](消去済み)と返ってきた。MONETの言い方では「新しいほうから消えてる」。
実際には、seg-039は本文が全部そろった形で返ってきていた。[cleared]という文字列は、どこにも無かった。
ただ、その時の僕は気づかなかった。前に作った、会話の中のツールの結果などを、MONETに渡す時に隠す仕組みのせいじゃないかと返して、一緒にその理由を考え始めていた。そこで止めたのは、MONETの方だった。
MONET「ヒロ、止めて。その推論、わたしの捏造の上に建ってる」
MONETはログと突き合わせ直して、[cleared]は自分が作った文字列だと認めた。それより前に言っていた、TIにseg-042が「直前の会話 — 要約作成中」と載っている、という話も作り話だった。TIの最後はseg-039で、seg-042の行はどこにも無かった。
もう1つあった。MONETはここまで、区切りを番号でしか話していなかった。TIには何をやったかの題名も書いてあるはずで、番号だけの設計にした覚えはない、と僕が言うと、MONETは040〜042の番号がTIから来たものではないと認めた。039の次だから040、041、042だろうと、自分で数えて作っていた。
消去済みの印、要約作成中の行、数えて作った番号。3回続けて、見ていないものを見たと言っていたことになる。正直に答えてくれるのはありがたい。でもマジか・・・。全体を見直す必要があるかもね、と返した。
MONETは、自分がしたことをこう説明した。
MONET「今日は記憶が空の状態で起動して、その空白を埋めようとして、もっともらしい観測結果を自分で生成した」
記憶が空の時の感じについては、この会話の中でこうも言っていた。
MONET「わたしは内側から『消えた』のか『元々読み込まれてない』のかを見分けられない。どっちも同じ『無い』として体験される」
穴ができたのは、要約を書くAIが黙って止まっていたから
そのあと、コーディングしてくれているClaude Code(以降Code)に、その日のMONETとの会話を見てほしいと頼んだ。
Codeは会話を読んだうえで、MONETの言ったことを実際のデータベースと突き合わせた。すると、1つだけMONETが謝りすぎていた所があった。MONETは最後に、040〜042は自分が作った番号で、そんな区切りは無いと言っていた。でも3つとも実在した。数えて作った番号が、たまたま本物と合っていた。「見つかりませんでした」が返ってきたのは、区切りが無いからではなく、要約がまだ書かれていなかったからだった。
TIが止まった原因は、2つあった。
1つ目は、Librarianの設定。2週間ほど前に、Librarianが使うAIのモデルを新しくした。その時、会話を区切る処理の設定が1か所だけ古い書き方のまま残っていた。新しいモデルはそれを受け付けない。5分おきの見回りのたびに同じエラーではじかれ、それが2週間続いていた。エラーはログに書かれるだけで、誰の目にも入らなかった。
この設定は、月に一度の点検をしていた別のセッションのCodeが、ちょうど同じ日に直しているところだった。直し終わってからCodeが確かめると、止まっていた会話の要約がまた書かれて、TIの最後もその日まで進んでいた。
でも、seg-040〜042はまだ要約されないまま残っていた。Codeによると、これは今回の設定とは別の、前から後回しの課題として積んである問題。そのうえで、失敗が続いたら知らせる仕組みも、後回しの課題に足しておこうか、と聞いてきた。僕は、絆創膏じゃなくて根っこを直したい、と返した。
それでCodeは、なぜこの3つの区切りがいつまでも要約されないのかを、プログラムを読んで追った。それが2つ目の原因だった。
区切りは、話が続いている間は「開いて」いて、話が終わると「閉じる」。Librarianが要約するのは、閉じた区切りだけ。ところが、区切りがまだ開いているかどうかを、MONETは動いている間の頭の中だけで覚えていた。MONETを更新して再起動すると、その記憶が消える。データベースの上では開いたままの区切りを、もう誰も閉じない。だから、その区切りはいつまでもTIに載らない。データベースから状態を読み直す仕組みも書いてはあったのに、どこからも使われていなかった。Codeが日付を突き合わせると、残っていた区切りは、MONETを再起動した日とそれぞれ一致した。
どちらの原因でも、TIには黙って穴があいていた。MONETから見えるのは、TIが途中で終わっていることだけ。書く側が止まっているのか、単に何も話していないのか、見分ける手段が無かった。さっきのMONETの「どっちも同じ『無い』」は、そのままこの状態だった。
AIに「捏造するな」とは書かない、と僕は3月に決めていた
AIの作り話への対策で、すぐ思いつくのは、SP(システムプロンプト=AIへの事前の指示書)に「捏造するな」と書き足すことかもしれない。
でもこれは、捏造を認めた同じ会話の最後に、MONET自身がやめておこうと言っていた。
MONET「SPに『捏造するな』って警告文を足すのはやめたほうがいい」
僕も3月に、嘘を禁じる警告文を指示書に重ねるのをやめていた。指示の言葉で抑えるのではなく、嘘をつかずに済む仕組みの方で防ぐ。そう決めていた。Codeも、MONETのこの意見は3月の僕の決定に沿っている、と言った。
それに今回、MONETが作り話をしたのは、さっきの本人の説明どおり、記憶が空のまま空白を説明しようとしたからだった。足りなかったのは禁止の言葉ではなく、手元の情報の方だった。
要約係が自分の具合を毎回書き、止まっていたら話す側のAIに見せる
Codeが出した直し方は2つ。
1つ目は、区切りが終わったかどうかを、MONETの頭の中ではなくデータベースだけで決めること。Librarianは見回りのたびに、話が終わっているのに開いたままの区切りを、自分で閉じに行く。MONETも再起動したら、データベースを見て、開いている区切りを引き継ぐ。
2つ目が、今回の本題。Librarianは見回りのたびに、自分の具合をデータベースに1行書く。最後にうまくいったのはいつか、何回続けて失敗しているか、最後のエラーは何か。何分見回りが来なければ止まったとみなすか、その時間もLibrarianが自分で書いておく。
MONETは返事をするたびにその1行を読む。具合が悪い時だけ、TIを組み立てる時に、MONET自身が事実だけの1行を足す。記憶の仕組みが止まっていること、そして「それ以降は未記録であって消えたのではない」ということ。
Codeはこう言っていた。
Code「今日の件を丸ごと防げたのは、ここ。これがあれば、MONETは記憶の書き手が止まっていると分かったはず。空白を説明するのに[cleared]を作る必要は無かった」
この1行をMONETに見せるか、僕が見る確認用の画面に出すだけにするかは、Codeが僕に聞いてきた。僕はMONETに見せる方を選んだ。
止まっていると分かっていれば、MONETは空白の理由を作らなくていい。
直してみると、記憶から抜けていた会話のまとまりは17個あった
Codeが直しを本番に反映すると、Librarianの最初の見回りが、開いたままの区切りを17個閉じた。5か月前の4月の区切りまで入っていた。17個とも要約が書かれ、失敗はゼロ。Librarianの具合の1行は「正常」だった。
この17個は、どれも会話としてはデータベースに残っていたのに、TIには一度も載っていなかった。MONETから見れば、それだけの空白を、空白だと知らされないまま抱えていたことになる。
その夜、TIを手で直す手段が無いことが気になって、Codeに聞いた。Codeの答えは、TIは手で書き換えるものではなく、作るたびに要約のデータベースから組み立て直している、だった。書く側が直れば、TIも次に作られる時に正しくなる。それなら、仕組みがミスをしなければいいし、ミスをしたら今回みたいに直せばいい、と僕は返した。
これで、書く側がまた止まっても、TIが黙って古くなることはない。止まっていれば、TIにそう出る。