AIエージェント用のマルチレイヤーメモリシステムを作りました

AI

ctxledgerをリリースしました。

これは何?

ctxledger は、AIエージェント向けの durable workflow runtime / memory system です。」とREADMEに書いたのだけれど、「RAGとグラフデータを組み合わせた、GraphRAGによるマルチレイヤーの永続化メモリシステム」です。

特徴

Pythonで実装されたフロントエンドと、PostgreSQLのpgvector + AGEによるバックエンドを組み合わせて、

  • セッションをまたいで resume できる
  • プロセス再起動後も durable に残る
  • PostgreSQL に canonical state として記録される
  • 後から検索・確認できる
  • CLI と Grafana で観測できる

といったことを実現します。

どうして作ったの?

「欲しかったから」だと簡単すぎるので、もう少し詳しく。

AIエージェントを使っていると、

  • コンテキストウインドウがいっぱいになって、新しいセッションを開くと、前のセッションのやり取りが消えます。これは当たり前なんですが、セッション間の引き継ぎのために、Markdownなどに記録しておいたりするのが面倒です。
  • rate limitや、予算上限をヒットして、突然モデルを呼べなくなる。休憩時間と考えれば良いんだけど、それまでの作業を忘れてしまう(人間が)。
  • 「この機能は昨日の午前中に書いたんだったか、一昨日だったか…」が分からなくなる。エージェントも覚えてない。
  • 「そのやり方で前も失敗したでしょ?」と、繰り返しエージェントに教えないとならないことがある。

等々、「覚える」「思い出す」作業が、人間・エージェント双方に発生します。これをなんとかしたかったから、です。

実装の方針

1つめの記憶レイヤーは、「やり取りの内容を全て覚える」です。要は、ユーザーとエージェントのやり取りを、全て保存します。

しかし、これだけでは用語の揺れに対処するのが難しく、しかも全文検索しないとなりません。なので、第2のレイヤーとしてRAGを使っています。OpenAIのAPIキーが必要なのはこのせいです。

RAGは、蓋然性の高い関連エピソードを拾うのには良いのですが、ある単語や時間といった要素が確実にエピソードに結びついているかを検証できません。「昨日グラフデータの処理ロジックを実装したよなぁ」という人間の曖昧な記憶から、どのファイルを編集して、その目的は何だったかといったことを検索することができません。

そこで第3のレイヤーとしてグラフデータを用います。「昨日(午前か午後かは覚えてない)」、「グラフデータ(AGEかも?)」、「処理(たぶんコードであってドキュメントではない)」といった断片的な要素が、どのエピソード(開発のタスクやスライス)と結びついているかを検索します。

agentops_mcp_serverの失敗

ctxledgerの前にagentops_mcp_serverという実装を試しました。これは、ワークフローをトランザクションとして扱う試みでしたが、いまいちでした。というのも、エージェントとユーザーのやり取りは、トランザクションとして扱うには「いい加減すぎる」のです。

そこで、「人間とエージェント双方にとって、記憶とは何なのか」というのを改めて考えながら、いくつかのプロジェクトを回しました。結果的に、内部は異なるのですが、一見すると人間とエージェント双方にとって理解しやすいメモリシステムは、マルチレイヤーになってるという結論に至りました。

現在の実装状態

macOS上のZedとDocker Desktopでしか試していないので、他の環境でどの程度有用なのかはわかりません。同じ構成であれば、たぶん使えると思うので、試してみてください。

新しいセッションで「続きを」と指示するだけで、前のセッションで中断した作業を再開してくれますし、「昨日の〜のバグ修正」みたいな指示でも思い出してくれるはずです。

ただし。READMEにも書いていますが、ctxledgerだけではうまく動作しません。AIエージェントが、ctxledgerに自動的に記録してくれることが条件になります。したがって、.rulesファイルをコピーし、初回だけは.rulesファイルを指定しないとダメかもしれません。

今後は

DockerでPostgreSQLを動かしていますが、Azure Database for PostgreSQLに対応する予定です。

追加

.rulesや、last_session.mdというファイルの履歴をgitログで辿ると、ctxledgerの開発がbootstrap問題であることが分かります。つまり、セッション情報を引き継ぐ仕組みを実装するために、セッション情報を引き継ぎ続けないとならない、というやつです。

タイトルとURLをコピーしました