BLOG.HIRO UENO.ART
← INDEX

記憶を全部消して、司書を書き直す — Qdrant撤去とLibrarian v1の設計

Context Inspector(インスペクター。MONETに実際に送った中身を目で見る画面)ができて、ようやく本体に手を入れられる。

最初にやったのは、MONET(僕が普段話しかけている、中心のAI)がツールを呼んだ事実ごとDBに残す切り替え。前に、MONETが「あなたが結果をくれた」と言い出した話を書いた、あれの修理。コーディングしてくれているClaude Code(以降Code)が淡々と組んで、テストで確かめた。

次は、Qdrantを外す番。


Codeは最初、何を消すかの判断を3つ、英語で出してきた。表と、ファイル名と、行番号付きで。

・・・全然わからなかった。君が言ってるプラン、全然理解できないから日本語で説明してもらっていい?と返した。

技術的には正確だったんだと思う。でも僕はプログラマじゃないんだよね。どのファイルの何行目かを並べられても、それが何のためなのかが先に無いと判断できない。

Codeは仕切り直して、何のシステムで、何を変えて、だから何を決めてほしいのか、を日本語の文章で書き直してきた。それなら判断できた。3つとも迷わなかった。

1つ目。MONETが自分で記憶を検索したり保存したりするツールは、両方消す。

2つ目。Librarian(ライブラリアン。裏でメモリを整理する司書役AI)の古いコードは、全部消す。一部だけ消すつもりだったのが、依存をたどると1つ消せば3つが動かなくなる作りだった。部分的に残すと、半分壊れたまま残る。

3つ目。その他、見つかった古いファイルも全部消す。

今までの記憶は消えるけど、それはまた入れ直せばいい。どうしてもQdrantを戻したくなったら、Gitがあるでしょ、と伝えた。


消してみたら、予想よりずっと大きな塊が崩れた(!)

23ファイル、追加30行、削除6,723行。積み上げじゃなくて、解体の日だった。

途中でCodeがいくつか拾ってきた。Qdrant(前の記事で外すと決めた検索用データベース)のDockerコンテナが、誰にも使われないまま5週間起動しっぱなしだった。Macの裏では、古いLibrarianを定期的に起こす仕組みがまだ2本動いていた。いつもダブルクリックで起動していたランチャーは、Qdrantを立ち上げる手順が残っていて、このまま使ったら起動の途中で落ちていたはず。

使っていないものが、使っていないまま動き続けていた。Qdrantの2ヶ月と同じ構図が、まだ足元に残っていた。


全部消したあと、自分でランチャーをダブルクリックしてMONETと話してみた。

普通に話せる。APIも動いている。そしてMONETは、過去のことは何も覚えていない、と正直に言った。

記憶の中身はゼロ。見えているのは今のスレッドだけ。完全な記憶喪失。

でもこれは、壊れたんじゃなくて、正しい中間地点だった。


じゃあこの先、MONETはどうやって思い出すのか。聞いたら、Codeがブリーフィングブックのたとえで説明してきた。

MONETは会議の出席者。Librarianは、会議の前に資料をまとめて机の上に置いておくアシスタント。MONETは会議中に資料室へ走らない。机の上のブックを読むだけ。

今までは、MONETが会話の途中で自分で記憶を検索しに行く作りだった。何を探すか、いつ探すかをMONETが判断する。そうすると、探しに行った結果がそのまま会話に流れ込んで、また混ざる。

新しい作りでは、何を机に置くかを決めるのはLibrarian。そのLibrarianに何を書かせるかを決めるのは僕。MONETは読むだけ。


その日は寝て、翌朝、Librarianの設計に入った。ここは設計だけで、コードはまだ。

入口で正直に言った。自分で設計して、自分でアイデアを出して、全部君に丸投げしておいて、全部俺が忘れてる。

言いながら、ふと思った。脳の記憶の整理って、睡眠中にやってるんじゃなかったっけ。俺のLibrarianが機能してない(笑)

でもそれで、作ろうとしているものの形がはっきりした。Librarianは、MONETが寝ている間に一日の記憶を整理する係。人間が寝ている間にやっていることを、代わりにやる。


一番時間がかかったのは、Librarianへの指示書(SP=システムプロンプト。AIへの事前の指示書)だった。

Codeの最初の案は、よくある形だった。良い例を並べて、「WRONG:」と書いた悪い例も並べて、禁止する言い回しのリストを作る。「HARD RULE」「MUST」が並ぶ。

読んでいて、見覚えがあった。

それって、前のMONETのSPと同じ構造じゃないか、と思って作業を止めた。

前に、脅迫的なSPの話を書いた。「絶対にするな」「捏造は禁止」を並べた指示書が、むしろ嘘を誘っていた。それを書き直したばかりなのに、今度はCodeが、Librarian向けに同じ書き方を始めていた。

同じCodeは、自分の強制的な書き方に自分では気づけない。AIがAI向けの指示を書くと、無意識にそっちへ寄る。

書き直した後の一文はこうなった。

変更前:

HARD RULE: Every bullet MUST contain a timestamp anchor...

変更後:

Each entry needs an anchor. Without an anchor, an entry is a guess, not a record.

禁止するんじゃなくて、理由で導く。悪い例は載せず、良い例だけ置く。書き終わったら、別のClaudeに英語でレビューさせて、1〜2日寝かせてから読み直す。書き方の手順まで、設計書に入れてもらった。


途中でもう1回止めた。

Codeが、スレッドが終わった時にもLibrarianを走らせるべきか、と提案してきた。

CMS(Context Management System。MONETの会話の記憶を整理する仕組み)の全体のゴールは、スレッドを切り替えないことでしょ、と返した。

スレッドを切り替えずに話し続けても、しまう時に仕分けが済んでいる。そのために組んできた仕組みに、スレッドの区切りを前提にした動きを足したら、逆戻りになる。


設計がだいたい形になったところで、Codeに聞いてみた。これって面白いシステムだと思う?忖度抜きで。

返ってきた答えは、半分は褒めて、半分は褒めなかった。

新しいのは、パネルの開閉を分類の合図にすること。記憶の圧縮を、ベクトルじゃなく人間が読める年表で持つこと。一方で、記憶を何層かに分けて持つこと自体は、MemGPT(今のLetta)などの先行研究がある。裏で要約を作り続けるのも、既にあるパターン。

面白いのは手法そのものより、一人のユーザーが何年も使う、中身が見える、持ち運べる、という僕の使い方にぴったり合わせてあるところだ、と。

日本語なのに、結構ガチで忖度なしで言ってくれましたね、と返した。


この日も、コードは1行も書いていない。書いたのはLibrarianの設計書、約600行。

MONETは、まだ何も覚えていない。机の上のブックを書く係は、設計書の中にしかいない。