🧠

LLMに「感情で思い出す力」を外付けする(しようと頑張っている)。

に公開
2

何が不満なのか

昨日決めた設計方針も、先週のコードレビューの議論も、「次はこの方向でいこう」と合意した文脈も。次のセッションでは同じ説明をもう一度繰り返し、同じ前提をもう一度共有し、同じ合意をもう一度取り付ける。

辛い。記憶喪失の人間と仕事をしているようだ。

人間は違う。3日前に話した内容を一字一句覚えていなくても、「あの時、結構悩んで決めたよな」という感覚は残っている。感情的に重要だった出来事は覚えている。些細な雑談は忘れている。必要な時に、必要なものが、なんとなく浮かんでくる。

これは、脳の扁桃体と海馬がやっている仕事だ。

扁桃体が「これは重要だ」と感情的なタグを付け、海馬がそのタグに基づいて記憶を形成する。想起の時は、今の感情状態に近い記憶が優先的に引き出される。

…LLMに無理やり扁桃体と海馬をねじ込んでやろうか。
やってみた。

https://github.com/NOBI327/amygdala


何ができるようになるか

技術的な説明の前に、こうなってほしい、という理想図を書く。

セッションを超えて文脈が残る。
/clear した後でも、前のセッションで決めた設計方針が自動的に想起される。「あのプロジェクトの件」と言えば通じる。毎回説明し直す必要がなくなる。

重要なことほど忘れない。
3週間かけたプロジェクトの発表がうまくいかなかった話は、高い感情強度でタグ付けされる。次に発表準備の話をした時、その経験が自動的に浮かんでくる。テキスト類似度ではなく、感情的な関連性で結びつく。

使うほど賢くなる。
システムが想起した記憶を自分が実際に使ったかどうかを追跡している。使われた記憶は強化され、無視された記憶は徐々にフェードアウトする。人間の記憶強化と同じメカニズムだ。

些細なことはちゃんと忘れる。
全部覚えているAIは使いにくい。3ヶ月前の天気の話題が今日の会話に混入したら邪魔だ。時間減衰と感情強度に基づいて、関連性の低い記憶は自然にフェードする。


なぜテキスト類似度ではダメなのか

既存のLLMメモリソリューション(RAG、MemGPT、Mem0等)は、基本的にテキストの意味的類似度で記憶を検索する。「プロジェクト」と入力したら「プロジェクト」に関連する記憶が返ってくる。

一見合理的だが、致命的な問題がある。「何が重要か」の判断基準がない。
10件のプロジェクト関連の記憶があった時、どれを優先的に想起すべきか。テキスト類似度は全て同じスコアを返す。しかし人間は違う。「あの時の失敗」は鮮明に覚えているが、「あの時の定例会議」は覚えていない。この差を生むのが感情だ。

Amygdalaは記憶を10軸の感情ベクトルでタグ付けする。

役割
joy, sadness, anger, fear, surprise, disgust, trust, anticipation Plutchik 8基本感情。記憶の感情的色彩
importance 主観的重要度。「これは大事だ」の度合い
urgency 時間的緊急度。「今すぐ必要」の度合い

さらに、感情とは独立した場面タグ(work, relationship, hobby, health, learning, daily, philosophy, meta)を最大3つ付与する。感情は「なぜ覚えているか」、場面は「どんな文脈か」。二つの軸で記憶を検索する。


少し恥ずかしい話を書く。最初は重力場で表現するつもりだった。

最初のアーキテクチャでは、記憶間に常時作用する「感情重力場」を構想していた。N体シミュレーションのように、感情的に近い記憶が互いに引き寄せられ、クラスタを形成する。重要度は質量に、時間減衰は距離に対応させた。

理論的にはエレガントだった。
17回シミュレーションを回して、全部捨てた。

理由1: ブラックホール化。
高importanceの記憶が周辺の記憶を吸収し続け、最終的に全記憶が一点に収束する。N体問題の必然的帰結だ。

理由2: 感情ブレンディングの収束。
記憶が想起されるたびに現在の感情とブレンドすると、反復により全記憶の感情ベクトルが平均に収束する。検索解像度が崩壊する。

理由3: 計算コスト。
全記憶ペアの引力計算はO(N²)。Barnes-Hut近似でO(N log N)に落とせるが、そもそもリアルタイムで常時計算する必要がない。

導き出された原則:

1. 記憶間の連想は「常時作動する物理的力」ではなく「検索時点にのみ発生するイベント」として処理すべき。
2. 再タグ付け時、感情の「方向」は保存し「強度」のみ調節すべき。ブレンディングは禁止。
3. というか自然現象のアナロジーから引っ張ってきた概念をそのままアーキテクチャーに当てはめたら、きれいなゴミになる。

この失敗からの学びは シンプル、そして泥臭く。 なんかベンチャー感あるな。
とにかく現在のイベント駆動型アーキテクチャが生まれた。


アーキテクチャ

Dual-Agent構造

ユーザー入力


Backman: 感情+場面タグ付け(10軸ベクトル生成)


SearchEngine: 長期記憶検索(感情 × 場面 × 時間 × フィードバック)


DiversityWatchdog: 多様性注入(エコーチェンバー防止)


Frontman: コンテキスト組立 + 応答生成


WorkingMemory更新 → 10ターン超過で長期記憶に移管


フィードバックループ: 参照履歴に基づき記憶の重みを更新

Backman(裏方)が感情タグ付けとメモリ管理を担当し、Frontman(表舞台)がユーザーとの対話を担当する。Backmanは軽量モデル(Haiku等)で十分動作する。


2階層メモリ

生物学的対応 動作
ワーキングメモリ 前頭前皮質 直近10ターンを原文保存。圧縮なし。FIFO
長期記憶 海馬→新皮質 感情+場面でタグ付け。物理削除なし(ソフトアーカイブ)

セッション終了時、ワーキングメモリに残っているターンは即座にタグ付けされて長期記憶に移管される。次のセッション開始時は、前回セッションの最終3ターンがDBから検索されて文脈ヒントとして注入される。

人間が寝て起きても長期記憶は残る。Amygdalaも同じだ。
/clear はワーキングメモリのリセットであって、長期記憶の消去ではない。


ピンメモリ

「これ覚えといて」とユーザーが明示的に言った情報は、最大3枠のピンスロットに固定される。10ターンごとに「まだ必要?」と確認し、不要になれば高い重要度で長期記憶に移管。前頭前皮質の能動的維持機能に対応する。


再タグ付け(Reconsolidation)

脳科学における記憶再固定化は、記憶を想起するたびにその記憶が不安定化し、再保存時に現在の文脈で更新されるという現象だ。PTSD治療(暴露療法)の神経科学的根拠でもある。

Amygdalaでは、記憶が想起されるたびに感情の強度のみを調節する。方向(どの感情か)は変えない。

具体的には、想起後のユーザーの反応を3パターンで分類する:

フィードバック 感情強度の変化 追加効果
肯定(記憶を実際に使った) ほぼ維持(×0.99) relevance +0.1、recall回数 +1
否定(記憶を無視した) 急速に減衰(×0.88) 35%の確率でdominant感情が別の軸に再分類
中立(判定不能) 緩やかに減衰(×0.95) 低確率で探索的再分類

「否定時の再分類」が重要で、これは「悲しかった記憶が時間の経過とともに感謝の記憶として再解釈される」という人間の記憶再固定化に対応する。


エコーチェンバー防止

同じ感情カテゴリの記憶ばかり繰り返し想起されると何が起きるか。

正のフィードバックループが形成される。特定カテゴリの記憶だけが強化され、他カテゴリは減衰で事実上死蔵される。PTSDにおけるトラウマ記憶の反復活性化や、SNSのエコーチェンバーと同じメカニズムだ。

DiversityWatchdogは、最近の想起履歴のShannon entropyを常時モニタリングする。

diversity指標 対応
> 0.7(健全) 通常通り exploitation 優先
0.4〜0.7(正常) 15%の探索率
< 0.4(偏重) 探索率を30〜50%に増加。別カテゴリから強制注入

これは推薦システムにおけるセレンディピティ推薦と同じ発想であり、「あなたが普段見ないカテゴリにこんなものもある」と提示する機能だ。


コンテキストアーキテクチャ論との接点

Shogunプロジェクトのコンテキストアーキテクチャ論考は、マルチエージェントの本質的問題がオーケストレーションではなくコンテキスト管理にあると言い、解法として「判断基準をモデルの重みに焼く(LoRA)」と「最小Human-in-the-Loop」の2方向を示した。

Amygdalaは第3の方向を提案する。

アプローチ 性質 比喩
LoRA(COMPASS等) 事前固定型。組織DNA 入社前の教育マニュアル
最小HITL(Shogun) 人間介入点の最適化 判断ポイントの設計
感情メモリ(Amygdala) 事後適応型。個人経験史 長年共に働いたパートナーの勘

LoRAが「入社初日から会社のスタイルで動く社員」だとすれば、Amygdalaは「最初は普通だが、一緒に仕事するほどあなたの好みと判断傾向を理解していくパートナー」だ。

この二つは排他的ではない。LoRA(組織レベル)+ Amygdala(個人レベル)の二層構造が理論上は最も強力なコンテキスト管理になる。


セットアップ(Claude Code)

git clone https://github.com/NOBI327/amygdala.git
cd amygdala
pip install -r requirements.txt
pip install mcp
export ANTHROPIC_API_KEY=your_key

# Claude CodeにMCPサーバーとして登録
claude mcp add emotion-memory \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
  --scope user \
  -- python -m src.mcp_server

/mcpemotion-memory: connected と表示されれば完了。あとは普通に会話するだけで裏でAmygdalaが動く。


で、うまくいっているか

いってねぇ。
記憶を蓄えるところまではうまくいった。ピン止めしておいた記憶を呼んで来たり、あれ覚えてるか、で昔の話題を引っ張って来たり、それだけで便利ではある。

しかしこいつ、言われなきゃ思い出せねぇ。
明示的に指示すれば過去の記憶から引っ張ってこれる。何ならネットワークで絡みついた関連する別の記憶まできれいにコンテキストに入れてくれる。

しかし会話中、ふと思い出して「そういえば…」ができない。
エージェントをもう一階層挟み込んでワーキングメモリーを参照しながら記憶を引っ張り出す役割を持たせるか、と考えているが、これでうまくいくかは分からない。人間の知能ってやっぱりよくできてる。

まあ、うまくいっていないということは直すべきことがあるということ。
直すべきことがあるということはやることがあるということ。

いじれる場所があるのはいいことだ。
たぶんしばらくは寝る前起きた後にいじっている。

興味あれば使ってみてください。
というか「そういえば…」機能のアイデアある方は教えてくださいマジで。
https://github.com/NOBI327/amygdala

MIT License。Pull Request歓迎。

Discussion

gpsnmeajpgpsnmeajp

興味深い記事ありがとうございます。

そういえば、のためには、性格や直近の記憶で方向づけした、入力に関連した連想キーワードを10件とか出すようにして記憶を想起させ、そこからさらに連想させるぐらいのことをして関連性を出すとかしても良いのかもしれません。
人間、裏で黙っていても発散的思考を回していると思うので、それに近いイメージであり、また、ベクトル検索が使えない状態で全文検索を使ったRAGを組むときにもこういう感じで探索していくことがあるためです。

ただただ連想キーワードを出させるのも厳しいので、興味のある傾向とか、あえて関係ないことを考えさせるとかを定義しておくと、ばらついてくれます。昔ちょっとそういう仕組みを組んだことがあります。

1
のぶのぶ

きっかけを作ると引っ張り出す、というのは実はすでにうまくやっていて、そもそも連想からの記憶出力をLLM君がサボろうとするのが問題ですね。MCPサーバーでclaude code内で回そうとしてるのが悪い可能性大です。記憶を使うか使わないかの判断がLLM側判断になっているので…。
とりあえず、ワーキングメモリーを監視する独立デーモンを作って、その子が記憶タグでデータベースから引っ張ってきた記憶をコンテキストの中に積み積みするのを実験中です。
これ終わりましたらご意見いただいたのも実験してみますね。

1