Tiered Memory|階層化メモリ¶
一言で(TL;DR)¶
エージェントのメモリを作業記憶(Working)・短期記憶(Short-term)・長期記憶(Long-term)の3層に分離し、層ごとにTTL・容量上限・書込ポリシー・信頼度を定めます。層間の昇格(promotion)と降格(demotion)を明示的に制御することで、コンテキストウィンドウの枯渇と記憶汚染の両方を防ぎます。
解決する問題¶
エージェントが複数ターンにまたがるタスクを扱うとき、すべての情報をコンテキストウィンドウに詰め込む「フラット記憶」では2つの問題が同時に起きます。
第一に、コンテキスト/メモリで状態を跨ぐ(F6)という特性上、会話履歴・ユーザー属性・中間結果・外部知識が混在するとウィンドウが溢れ、古い情報から押し出されて文脈が断絶します。第二に、LLMが生成した推測や中間的な判断をそのまま永続化すると、ハルシネーション(F4)が長期記憶に定着し、以降のすべてのセッションを汚染してしまいます。
階層化メモリは「何をどの寿命で保持し、何を捨てるか」を構造的に決めることで、コンテキスト効率と記憶の信頼性を両立させます。
選定条件(When to use / When NOT)¶
- 使う条件
- エージェントが複数セッションにわたって情報を引き継ぐ必要があります(ユーザープロファイル、過去の意思決定、蓄積された知識)。
- 1セッション内でも中間結果の量がコンテキストウィンドウの概ね30%を超える見込みがあります。
- 記憶の「鮮度」と「確度」が混在しています(確定事実と推測の区別が必要です)。
[failure_cost]が中〜高で、誤った記憶が後続タスクに波及すると影響が大きいケースです。
- 使わない条件(=代替に倒す)
- 1ショットで完結し、セッション間の引継ぎが不要な場合 → 作業記憶のみで十分です(メモリ階層化は不要です)。
- コンテキストウィンドウに全情報が収まり、セッション状態もトークン数も問題にならない場合 → D2 コンテキスト予算配分 の範囲で対処します。
- メモリの書込制御だけが課題で、階層分離は不要な場合 → D3 メモリ書込ゲート を単独で適用します。
駆動変数とチューニング(程度)¶
| 目盛り | 効かなすぎ ⇔ 効きすぎ | 決め方 [駆動変数] |
目安(出発点) |
|---|---|---|---|
| 層数 | 少なすぎ:粒度不足で全部長期に入る ⇔ 多すぎ:昇格/降格ルールが爆発 | ユースケースの時間スケールの種類数 [failure_cost] |
3層(作業/短期/長期)が出発点。共有メモリが要れば4層目 |
| 短期→長期の昇格閾値 | 低すぎ:推測が長期に混入 ⇔ 高すぎ:有用な記憶が消失 | 誤記憶の影響度。[failure_cost] が高いほど閾値を上げる |
同一事実が2回以上確認された、またはユーザー承認済み |
| 短期のTTL | 短すぎ:セッション中に記憶喪失 ⇔ 長すぎ:古い文脈が邪魔 | セッションの典型的な継続時間 [failure_cost] |
対話セッション:数時間〜1日。バッチ:タスク完了まで |
| 長期の容量上限 | 小さ���ぎ:知識が蓄積されない ⇔ 大きすぎ:検索精度低下���コスト増 | ���索品質とストレージコストの均衡 [failure_cost] |
ユーザー単位で概ね数百〜数千エントリ。���期的に本パターンの減衰・版管理機能で整理 |
値は定数でなく [failure_cost] の関数です。失敗コストが高い領域ほど昇格閾値を厳しくし、短期TTLを長めにとって安全側に寄せます。
相反における立ち位置(相反)¶
F-16 自動メモリ vs 承認型メモリ → hybrid です。3層それぞれで書込ポリシーを変えます。
- 作業記憶:完全自動です。エージェントの推論中間物を自由に読み書きします。コンテキストリセットで消える前提なのでリスクが低いです。
- 短期記憶:自動書込ですが、信頼度タグを付与します。ユーザー発話由来は高信頼、LLM推測由来は低信頼とマークします。
- 長期記憶:
[failure_cost]が高い場合は承認型に倒します。低リスクな嗜好情報(表示言語の好みなど)は自動、重要な事実(住所・契約情報など)はユーザー承認を経て昇格させます。
判定基準は [failure_cost] です。失敗コストが低ければ長期も自動寄り、高ければ承認寄りにします。詳細な書込制御は D3 メモリ書込ゲート を参照してください。
構造¶
flowchart TD
Input[入力 / エージェント出力]
WM[作業記憶<br/>TTL: リクエスト/ターン<br/>容量: コンテキストウィンドウ]
STM[短期記憶<br/>TTL: 時間〜日<br/>容量: セッションストア]
LTM[長期記憶<br/>TTL: 無期限〜減衰<br/>容量: ベクトルDB / KVS]
Input --> WM
WM -->|昇格: 反復確認 or 承認| STM
STM -->|昇格: 信頼度閾値超過| LTM
LTM -->|検索・想起| WM
STM -->|TTL失効 → 降格/破棄| X1[破棄]
LTM -->|減衰スコア低下| X2[アーカイブ / 破棄]
作業記憶はコン���キストウィンドウそのもので��。短期記憶はRedisやセッションDBに格納し、TTL付きで自��失効します。長期記憶はベクトルDB���KVSに永続化し、本パターンの記憶の減衰とバージョン管理セクションで鮮度を���理します。
実装メモ¶
最小実装の骨格(疑似コード)を示します:
class TieredMemory:
def __init__(self, user_id: str):
self.working = {} # dict: ターン内の中間状態
self.short_term = SessionStore( # Redis等。TTL付き
user_id=user_id,
ttl=timedelta(hours=4), # failure_cost に応じて調整
)
self.long_term = VectorStore( # ベクトルDB
namespace=user_id,
max_entries=1000,
)
def recall(self, query: str, budget: int) -> list[Memory]:
"""コンテキスト予算内で3層から想起する"""
results = []
results += self.working.get_relevant(query)
results += self.short_term.search(query, limit=budget // 2)
results += self.long_term.search(query, limit=budget // 2)
return rank_by_relevance_and_trust(results, budget)
def promote(self, memory: Memory):
"""短期→長期への昇格。信頼度と承認状態を検査する"""
if memory.trust_score < PROMOTE_THRESHOLD:
return # 閾値未満は昇格しない
if memory.requires_approval and not memory.approved:
queue_for_approval(memory)
return
self.long_term.upsert(memory)
落とし穴:
- 作業記憶と短期記憶の境界が曖昧になりがちです。作業記憶は「コンテキストウィンドウがリセットされたら消える」、短期記憶は「明示的にストアに書いたもの」と機械的に区別します。LLMの内部状態に頼らず、外部ストアへの書込を境界線にしてください。
- 長期記憶の検索ノイズに注意が必要です。エントリ数が増えると無関係な記憶がコンテキストに混入し、ハルシネーションの原因になります。検索結果には信頼度スコアでフィルタをかけ、D2 コンテキスト予算配分 で注入量を制御します。
- マルチエージェント環境での記憶分離も重要です。B3 予算付き自律ループ の Supervisor-Worker 構成では、各Workerの作業記憶は分離し、短期・長期はSupervisorが一元管理する設計が安全です。Workerが直接長期記憶に書き込むと整合性が崩れてしまいます。
記憶の減衰とバージョン管理¶
階層化メモリの各層に格納された記憶は、時間経過とともに鮮度が低下します。ここでは記憶の TTL(Time-To-Live)設計、確信度の減衰、および事実の版管理について述べます。
記憶種別ごとの TTL¶
記憶する情報の種類によって適切な TTL は大きく異なります。
| 記憶の種類 | TTL の出発点 | 根拠 |
|---|---|---|
| リアルタイム価格・在庫状況 | 5〜30 分 | データソースの更新頻度に合わせます |
| ユーザ嗜好・設定 | 7〜30 日 | 行動変化の時間スケールに対応します |
| 不変属性(法人番号・ID等) | 無期限 | 変更頻度が極めて低いため版更新で対応します |
| 会話中の一時的事実 | セッション終了まで | 作業記憶に留め、セッション外に持ち出しません |
[failure_cost] が高い領域ほど TTL を短めに設定し、陳腐化した記憶による誤判断を防ぎます。
確信度の減衰(Freshness Scoring)¶
記憶エントリには書込時点での確信度(confidence)を付与し、時間経過に伴い減衰させます。たとえば、書込時に 0.95 だった確信度が 24 時間後に 0.80 へ低下する線形または指数減衰を適用します。想起時に確信度が閾値(概ね 0.7〜0.85、[failure_cost] が高いほど閾値を上げる)を下回った記憶は、再取得または破棄の対象とします。
版番号とテンポラル・トゥルース¶
同じ事実が更新された場合、旧版を即座に削除せず valid_from / valid_to のタイムスタンプ付きで保持します。これにより「いつ時点でどの事実が真だったか」を事後に再現でき、監査要件を満たせます。版保持数は概ね 3〜10 版を出発点とし、規制領域では法定保持期間に合わせます。
矛盾する情報の競合解決¶
新しい情報が既存の記憶と矛盾する場合の解決ポリシーを定めます。新版の確信度が旧版以上であれば自動採用し、旧版に superseded マークを付与します。新版の確信度が旧版より低い場合は、フラグを立ててレビュー待ちとし、誤った更新の混入を防ぎます。[failure_cost] が高い領域では、確信度に関わらず人間レビューを経由させる設計も検討してください。
効かせる力学(forces)¶
- F4(ハルシネーション):層ごとに信頼度を管理し、LLM推測を長期記憶に直接書き込ませません。昇格には反復確認や承認を要求することで、幻覚の永続化を防ぎます。
- F6(コンテキスト/メモリで状態を跨ぐ):3層に分けることで、短命な中間結果と長命な知識を分離します。作業記憶の揮発性を受け入れつつ、必要な情報は短期・長期に退避させてセッション間の連続性を確保します。
関連・代替¶
- 関連
- D2 コンテキスト予算配分:各層から想起した記憶をコンテキストウィンドウにどれだけ注入するかを制御します。階層化メモリの「出口」を管理する補完パターンです。
- D3 メモリ書込ゲート:短期→長期の昇格時にフィルタ・PII検査・承認を挟みます。本パターンの昇格ポリシーの実装手段です。
- 本パターンの記憶の減衰とバージョン管理セクション:長期記憶の鮮度管理を担います。古くなった記憶の減衰・上書き・バージョン管理を行います。
- D6 セマンティックキャッシュ:頻出クエリへの応答を短期層でキャッシュし、LLM呼び出しを削減します。
- B3 予算付き自律ループ:Supervisor-Worker 構成でのメモリ共有/分離の境界設計に関連します。
コーディングエージェント向け指示(machine-actionable)¶
このパターンを人間に提案するなら、同時に以下を提案/確認してください:
- [ ]
[failure_cost]を評価し、昇格閾値と長期記憶の書込ポリシー(自動/承認)を導出したか - [ ] 短期記憶のTTLをセッション特性から導き、理由を添えて提示したか
- [ ] 長期記憶への書込がある場合、D3 メモリ書込ゲート を併置したか
- [ ] 長期記憶の容量上限と減衰ポリシーを定め、本パターンの記憶の減衰とバージョン管理に基づいて設計したか
- [ ] コンテキストウィンドウへの注入量を D2 コンテキスト予算配分 で制御する設計になっているか
- [ ] マルチエージェント構成の場合、作業記憶の分離と長期記憶の共有範囲を B3 の Supervisor-Worker 構成と整合させたか