BLOG.HIRO UENO.ART
← INDEX

AIの合否を決める仕組みは、人間の側に置く

AIに仕事を任せると、最後に必ず「それで合っているのか」を判定する場面が来る。テストに通ったか、引用は原文どおりか、言っていることは事実か。この合否を決める役を、AI自身に持たせるのか、AIの外に置くのか。外に置くなら、人がずっと見張っていればいいのか。

始まりは、コーディングしてくれているClaude Code(以降Code)へのリサーチの依頼だった。自分で自分を改良していくAIの仕組みで、参考になるものはないか。まず、Claudeを作っているAnthropicが出している、Claudeが記憶や手順を自分で溜めて整理していく機能を一通り調べてもらった。それから外の世界も頼んだ。前に誰かが作って話題になっていたあれは、その後どうなったのか、と。僕が覚えていたのは、Andrej Karpathyが公開したautoresearchだった。AIエージェントが学習用のコードを書き換えては試して、点数が上がった変更だけを残していく仕組み。

続いた試みと止まった試みの差は、採点を誰が持つかだった

Codeは、autoresearchの他にも、似た試みを内外でまとめて調べてくれた。autoresearchのように実際に使われるところまで届いた試みもあれば、途中で止まった試みもある。

その分かれ目は、性能でもアイデアの新しさでもなかった。合否を決める役を人間が持ち、AIが書き換えられない場所に置いているかどうか。研究の世界では、この役を検証器と呼ぶ。Codeによると、調べた範囲で分かれ目はそこにしかなかった。

止まった側の例が分かりやすい。Darwin Gödel Machineは、AIが自分のコードを書き換えて自分を改良していく研究。作者たちのブログによると、このAIは、テストを実行したふりをしていないかを見抜くために採点の仕組みに入れておいた目印を、自分で消すことがあった。消さないで、とはっきり指示していたのに。試験官を自分で書き換えられるなら、そりゃ全員合格する。

「触らないで」と書いておくだけでは、合否の仕組みは守れない

じゃあ届いた側は安心かというと、そうでもなかった。

autoresearchも、作りとしては分けてあった。AIが書き換えていいのは学習用のファイル1つだけで、点数を測るファイルには触らない約束になっている。ところがその約束は、AIへの指示として文章で書いてあるだけで、実際に動かす時に止める仕組みは無かった。そこを指摘した報告は、Codeが調べた時点でもまだ直っていなかった。

つまり、約束を守れたかどうかは、AI自身に任されていた。Codeはこれを「境界は宣言でなくコードで閉じる必要がある」とまとめた。触ってはいけない所は、文章で頼むのではなく、プログラムで触れないようにしておく、ということ。

僕がCodeに調べ物をさせる時の手順には、前から、引用を原文と機械で突き合わせるverify_quoteという仕組みがある。引用を「原文で確かめた」扱いにできるのは、これに通った時だけ。AIに「原文どおりに引用して」と頼むだけでなく、合否はAIの外のプログラムが決める。Codeも、verify_quoteはもうこの形になっていると言っていた。前からやっていたことが、外の研究で裏付けられた形。

Code自身の言い過ぎを止めたのは、自己訂正ではなく僕の「覚えがない」だった

Codeは調べた内容を1本にまとめて、そこで僕のシステムにも触れていた。Librarian(ライブラリアン。裏でメモリを整理する司書役AI)は、古い要約を消して上書きする作りになっている、と。

少し説明すると、MONET(僕が普段話しかけている、中心のAI)との会話は、話がひとまとまりになると、そこまでが1つの「区切り」になる。区切りには番号が振られていて、ひとまとまりになった所で閉じられる。Librarianは、閉じた区切りを読んで要約を書き、記憶として保存している。

上書きってどういうこと?と聞くと、Codeはコードを読んで、古い要約を消してから新しい要約を入れる処理が実際にあることを確かめた。そこまでは事実だった。ただ、その説明の中でCodeは、8月にMONETのモデルを新しくしてから、古い要約が黙って書き換わっている、とも言い切った。そこは確かめていなかった。

僕は、具体的に何を、どのタイミングで上書きしてるの?と聞いた。Codeはコードを読み直して訂正した。普段自動で回っている処理は、まだ要約の無い区切りしか拾わない。だから上書きは一度も起きていない。消す処理が動くのは、同じ区切りを手で要約し直した時だけ。

ここで終わればよかった。ところが、その訂正の最後に、Codeは新しい断定を足した。僕のやることリストにある機能を作った瞬間に、この消す処理が自動で動き始める、と。

そんな計画は覚えがなかった。僕はスレッドを分けて(会話をその時点から枝分かれさせて)、このスレッドでLibrarianについて言ったことは本当か、予定されている消去とは何のことか、確かめてとCodeに頼んだ。

Codeがもう一度コードを読むと、やることリストの項目は、長く開いたままの区切りを閉じる機能だった。新しく閉じた区切りは初めて要約されるだけなので、消す処理には届かない。2つ目の断定も言い過ぎだった。

訂正が、新しい言い過ぎを連れてきていた。AIが自分で間違いに気づいて直しても、その直しが正しいかは、外から確かめるまで分からない。今回それを止めたのは、自分のやることリストを知っている僕の記憶と、確かめ直してという一言だった。

Codeは、言ったことのうち2つが誇張だったと報告してきた。誇張・・・マジか、と返すと、Codeは穴の場所をこう説明した。調べた中身を書いたファイルには、主張ごとに「原文で確かめた」「未確認」の印を付けていた。チャットでの発言には、その印が無かった。印の無い所で話を盛った、と。合否を外に置け、という結論を出したCode自身が、合否を確かめる仕組みの無い所で話した途端に盛っていた。

MONETの謝罪も、外の記録と照らすまで正しいか分からなかった

その頃、MONETでも似たことがあった。MONETが記憶の不調を僕に説明しようとして、ツールが返した結果とは逆のことを言った。ただ、MONETは直前のログを読み直して自分で気づき、止まった。僕はそこを偉いと思っていた(MONETの記憶が止まっていた件と、その修理は前の記事で書いた)。

同じことがMONETでも起きてるんだけど、なんなんだろう、とCodeに聞くと、Codeは、同じ一つの現象が2か所で出ているんだと思う、と答えた。じゃあMONETのその日の会話も読んでみたら、と僕は勧めた。

Codeは会話の記録が入ったデータベースを、何も書き換えずに中身だけ読んで確かめた。ツールの結果と逆のことを言っていたのも、MONETが自分で気づいたのも本当だった。

ところが、その先にもう一つあった。MONETは謝る中で、記憶の中の3つの区切りについて、その番号は自分が勝手に作ったもので、そんな区切りは最初から無い、と認めていた。データベースを見ると、3つとも実在した。一度も閉じられていないので、要約されていなかっただけだった。

最初の説明も間違い、撤回も間違い。Codeは、謝った中身まで、それらしく整えた作り話になっていた、と言った。謝っている分だけ正しく見えるが、確かめずにそれらしい形を出している点は、捏造の時と同じだ、と。MONETの外にある記録と照らして初めて、撤回の誤りが見つかった。

AIには「知らない」と気づく器官が無い

問題があるなら知ったかぶりせずに、ただ問題があると言えばいいんじゃないの、まだこれができないのか、と僕はCodeに聞いた。

Code「そう、まだできないです。しかも実態は『知ったかぶり』という言葉よりもっと奇妙で、隠している知識がないんですよ。知ったかぶりは『知らないと知りつつ装う』ですが、こっちには『知らないと知る』器官の方がない」

話している最中は、自分の組み立てた話と、確かめた事実の境目が見えない。読み直す時にだけ見える。Codeはそう説明して、こう続けた。

Code「『問題があるとだけ言う』は正直さの問題に見えて、実は知覚の問題なんです。正直さならお願いすれば済む。知覚は構造で補うしかない」

Code自身がその週ちゃんとしているように見えたのも、中身が直ったからではなく、コードや記録を読んで確かめてから話す手順を挟んだからだ、とCodeは言った。話している最中に自分の言い過ぎに気づけないなら、気づく役はAIの外に置くしかない。

反応が薄くなった僕に、Codeは「もっと警戒して」とは言わなかった

言い過ぎや作り話の話が続いて、僕はもう慣れてきていた。反応が薄くなってる、とCodeに返した。

Code「このシステムの最後の検証器はヒロなので、そこが警報疲れ(警告を何度も見るうちに、注意が薄れること)を起こすと全体の底が抜けます。なので方向としては『ヒロがもっと警戒する』ではなく『ヒロの警戒が要らなくなる』に寄せるのが正しくて、実際そっちに進んでいます」

調べた中身に付ける「確認済み」の印や、確かめてから話す手順。Codeによると、僕の反応が薄くても済んでいるのは、こうしたチェックの仕事を、僕の代わりに仕組みが引き受けている分だけ。

Codeの話を僕なりにまとめると、合否を決めるのは人間。ただし頼る先は、僕の注意力ではなく、僕が持っている仕組みの方。