0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントの記憶をTTLで昇格/降格運用

0
Last updated at Posted at 2026-06-04

AIエージェントが賢く振る舞うためには「記憶」が不可欠です。しかし、記憶をただ蓄積するだけでは、冗長性、陳腐化、そして何よりコストの問題に直面します。agentmemoriesでは、この課題に対し「記憶のティアリング」というアプローチで解決を図っています。本記事では、AIエージェントの記憶を「仮→確定→実働」の3つのティアに分け、参照頻度と検証に基づいて昇格させ、未使用期間に応じて降格(TTL)させるための最小実装をQiita読者向けに解説します。

AIエージェントの記憶を仮→確定→実働で昇格/降格(TTL)運用する

記憶のティアリング戦略:なぜ「仮・確定・実働」なのか

AIエージェントの記憶は、生成された直後はその信頼性が低いことがあります。例えば、LLMが生成したタスク実行計画や、ユーザーとの会話から抽出した情報などは、そのまま永続化するにはリスクが伴います。そこで、私たちは以下の3つのティアを設けています。

  1. 仮 (Provisional): エージェントが生成したばかりの、まだ検証されていない情報。短期間で破棄されるか、検証を経て次のティアへ昇格します。
  2. 確定 (Confirmed): エージェント自身または外部システムによって検証され、信頼性が高いと判断された情報。ある程度の期間保持され、エージェントの行動に影響を与え始めます。
  3. 実働 (Active): 頻繁に参照され、エージェントの主要な知識ベースとして機能している情報。最も長期にわたり保持され、エージェントの推論や計画立案に直接的に利用されます。

このティアリングにより、エージェントは常に最新かつ最も関連性の高い情報にアクセスしつつ、不確実な情報の永続化コストを最小限に抑えることができます。

記憶オブジェクトのデータ構造設計

記憶オブジェクトは、その内容だけでなく、ティア、最終参照日時、参照回数といったメタデータを持つ必要があります。ここでは、簡潔なJSON形式を想定します。

{
  "id": "mem_001",
  "content": "ユーザーは先週、新しいプロジェクトを開始した。",
  "tier": "provisional",
  "last_used": "2023-10-26T10:00:00Z",
  "hit_count": 0,
  "created_at": "2023-10-26T09:30:00Z",
  "ttl_days": {
    "provisional": 7,
    "confirmed": 30,
    "active": 365
  }
}
  • id: 記憶の一意な識別子。
  • content: 実際の記憶内容。
  • tier: 現在のティア(provisional, confirmed, active)。
  • last_used: 記憶が最後に参照された日時。昇格・降格の判断基準となります。
  • hit_count: 記憶が参照された回数。昇格の判断基準となります。
  • created_at: 記憶が作成された日時。
  • ttl_days: 各ティアでのデフォルトTTL(日数)。

記憶の昇格ロジックの実装

記憶の昇格は、主にhit_countlast_usedに基づいて行われます。例えば、「仮」の記憶が一定回数以上参照され、かつ直近で利用されている場合、「確定」へ昇格させます。さらに、「確定」の記憶が頻繁に利用されるようであれば、「実働」へ昇格させます。

import datetime

def promote_memory(memory: dict) -> dict:
    current_tier = memory["tier"]
    hit_count = memory["hit_count"]
    last_used = datetime.datetime.fromisoformat(memory["last_used"].replace("Z", "+00:00"))
    now = datetime.datetime.now(datetime.timezone.utc)
    
    # 仮 -> 確定
    if current_tier == "provisional":
        # 例: 3回以上参照され、かつ過去24時間以内に利用されたら昇格
        if hit_count >= 3 and (now - last_used).total_seconds() < 24 * 3600:
            memory["tier"] = "confirmed"
            print(f"Memory {memory['id']} promoted from provisional to confirmed.")
    
    # 確定 -> 実働
    elif current_tier == "confirmed":
        # 例: 10回以上参照され、かつ過去72時間以内に利用されたら昇格
        if hit_count >= 10 and (now - last_used).total_seconds() < 72 * 3600:
            memory["tier"] = "active"
            print(f"Memory {memory['id']} promoted from confirmed to active.")
            
    return memory

# サンプルデータ
sample_memory = {
  "id": "mem_001",
  "content": "ユーザーは先週、新しいプロジェクトを開始した。",
  "tier": "provisional",
  "last_used": "2023-10-26T10:00:00Z",
  "hit_count": 5,
  "created_at": "2023-10-26T09:30:00Z",
  "ttl_days": {
    "provisional": 7,
    "confirmed": 30,
    "active": 365
  }
}

# 参照回数を更新(例として)
sample_memory["hit_count"] += 1
sample_memory["last_used"] = datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='seconds').replace("+00:00", "Z")

promoted_memory = promote_memory(sample_memory)
print(f"Updated memory tier: {promoted_memory['tier']}")

この昇格ロジックは、エージェントが記憶を利用するたびに実行されるか、定期的なバッチ処理で実行されることを想定しています。

記憶の降格(TTL)ロジックの実装

記憶の降格(または削除)は、各ティアに設定されたTTL(Time To Live)に基づきます。last_usedからTTL期間を超過した記憶は、ティアが降格されるか、最終的には削除されます。

import datetime

def demote_or_delete_memory(memory: dict) -> tuple[dict | None, bool]:
    current_tier = memory["tier"]
    last_used = datetime.datetime.fromisoformat(memory["last_used"].replace("Z", "+00:00"))
    now = datetime.datetime.now(datetime.timezone.utc)
    
    # 各ティアのTTL
    ttl_map = memory["ttl_days"] # {"provisional": 7, "confirmed": 30, "active": 365}
    
    # 最終使用からの経過日数
    days_since_last_used = (now - last_used).days
    
    if current_tier == "active":
        if days_since_last_used > ttl_map.get("active", 365):
            memory["tier"] = "confirmed"
            print(f"Memory {memory['id']} demoted from active to confirmed due to TTL.")
    elif current_tier == "confirmed":
        if days_since_last_used > ttl_map.get("confirmed", 30):
            memory["tier"] = "provisional"
            print(f"Memory {memory['id']} demoted from confirmed to provisional due to TTL.")
    elif current_tier == "provisional":
        if days_since_last_used > ttl_map.get("provisional", 7):
            print(f"Memory {memory['id']} deleted from provisional due to TTL.")
            return None, True # 削除されたことを示す
            
    return memory, False

# サンプルデータ(Activeから降格するケースを想定)
sample_memory_active = {
  "id": "mem_002",
  "content": "重要な顧客Aの担当者は山田さん。",
  "tier": "active",
  "last_used": (datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=400)).isoformat(timespec='seconds').replace("+00:00", "Z"), # 400日前に最終利用
  "hit_count": 100,
  "created_at": "2022-01-01T00:00:00Z",
  "ttl_days": {
    "provisional": 7,
    "confirmed": 30,
    "active": 365
  }
}

demoted_memory, is_deleted = demote_or_delete_memory(sample_memory_active)
if not is_deleted:
    print(f"Updated memory tier: {demoted_memory['tier']}")
else:
    print("Memory was deleted.")

# サンプルデータ(Provisionalから削除されるケースを想定)
sample_memory_provisional = {
  "id": "mem_003",
  "content": "今日のランチはカレー。",
  "tier": "provisional",
  "last_used": (datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=10)).isoformat(timespec='seconds').replace("+00:00", "Z"), # 10日前に最終利用
  "hit_count": 1,
  "created_at": "2023-10-16T09:00:00Z",
  "ttl_days": {
    "provisional": 7,
    "confirmed": 30,
    "active": 365
  }
}

demoted_memory_p, is_deleted_p = demote_or_delete_memory(sample_memory_provisional)
if not is_deleted_p:
    print(f"Updated memory tier: {demoted_memory_p['tier']}")
else:
    print("Memory was deleted.")

この降格ロジックは、定期的なバッチ処理(例えば、日次や週次)で全ての記憶オブジェクトに対して実行されるべきです。

運用上の落とし穴とチェックリスト

agentmemoriesの運用の中で、私たちはいくつかの「落とし穴」を経験してきました。

実録: 昇格閾値の調整不足による過学習
当初、昇格の閾値を低く設定しすぎていました。「仮」の記憶が少し参照されただけで「確定」に昇格してしまうため、エージェントが一時的な情報や誤った情報を過度に記憶し、その後の推論に悪影響を与える事態が発生しました。例えば、ユーザーが冗談で言った一言が「確定」記憶として残り、エージェントがその情報を真実として扱ってしまうケースです。この経験から、昇格閾値は慎重に、かつ継続的にチューニングする必要があると痛感しました。特に、「確定」や「実働」への昇格には、より厳密な検証プロセス(例: 人間による確認、複数エージェントによる検証、外部APIとの突合など)を組み込むことが重要です。

運用チェックリスト:

  • 昇格閾値の定期的な見直し: hit_countlast_usedの期間設定は、エージェントの利用状況や記憶の性質に合わせて調整が必要です。
  • TTL設定の最適化: 各ティアのTTLは、記憶の陳腐化速度やストレージコストを考慮して決定します。短すぎると重要な記憶が失われ、長すぎるとゴミが増えます。
  • 手動によるティア変更機能: 緊急時や特定の重要な記憶については、人間が手動でティアを昇格・降格できる管理機能があると便利です。
  • 監査ログの記録: 記憶の昇格・降格が行われた際、誰が、いつ、どのような理由で行ったかを記録することで、問題発生時の追跡が容易になります。
  • バックアップ戦略: 誤って重要な記憶が削除されないよう、定期的なバックアップは必須です。特に「実働」ティアの記憶は重要度が高いです。
  • 記憶の重複排除: 同じ内容の記憶が複数のティアに存在しないよう、定期的な重複排除処理を検討します。
  • パフォーマンス監視: 記憶の量が増えるにつれて、検索やティアリング処理のパフォーマンスが低下する可能性があります。適切なインデックス設計やデータベース選定も重要です。

まとめ

AIエージェントの記憶を「仮→確定→実働」のティアで運用し、参照頻度と未使用期間に基づいて昇格・降格させることで、エージェントはより効率的かつ賢く振る舞うことができます。本記事で紹介した最小実装と運用上の落とし穴チェックリストが、皆さんのAIエージェント開発の一助となれば幸いです。記憶の管理はAIエージェントの性能を左右する重要な要素であり、継続的な改善が求められます。


関連リンク

設計思想の詳細はこちら(Zenn)

agentmemories 公式サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?