ナレッジグラフ

GraphMemoryServiceは、異なる形状のメモリです。テキストエントリの山ではなく、ユーザーのナレッジグラフ(エンティティ、それらに付随する事実(「観測」)、およびそれらの間の型付き関係)を保存し、そのすべてをバイテンポラルに追跡します。これは、Mindfulness-with-Miaの例リアルタイムメモリページの背後にあるバックエンドです。

他のバックエンドと同じMemoryServiceトレイトを実装しているため、同じ方法でエージェントに組み込むことができます。しかし、その上にさらにリッチなグラフAPIを公開します。

データモデル

   Entity "Alice"  (type: person)
     ├─ observation: "prefers email over phone"   valid_from 2026-06-01
     ├─ observation: "timezone is CET"            valid_from 2026-06-10
     └─ relation:    Alice ──works_at──▶ "Acme"
  • Entity — 自由形式のentity_typeを持つ、名前付きの物事(人物、場所、好み、トピック)。
  • Observation — 安定したidvalid_fromタイムスタンプを持つ、エンティティに付随する1つの事実。
  • Relation — 2つのエンティティ(source ──relation_type──▶ target)間の型付きエッジ。例:Alice ──works_at──▶ Acme

キュレーションされたグラフとは別に、生のターンをログに記録するエピソードストア(kg_episodic)もあります。これにより、トランスクリプトと抽出されたモデルの両方を保持できます。

なぜバイテンポラルなのか

すべての観測と関係は、2つの時間軸に沿って追跡されます。

  • valid time — 事実が世界で真であったとき(valid_fromvalid_to)。
  • ingestion time — システムがそれを学習したとき。

事実が変更されても、古いものは削除されません。それは無効化され(そのvalid_toが設定され)、新しいものが追加されます。これは、グラフが「ユーザーの現在の好みは何ですか?」という質問に、「以前はどうだったか」を失うことなく答えることができることを意味します。置き換えられた事実は、現在を上書きするのではなく履歴に残ります。これは、数か月にわたって信頼できるメモリにとってまさに望ましいことです。

kg.invalidate_observation(old_id).await?;   // mark a fact no longer valid
kg.invalidate_relation(old_id).await?;      // mark an edge no longer valid

作成

graph-memoryはSQLiteをバックエンドとしているため、ファイル(またはテスト用のインメモリ)です。

use adk_memory::GraphMemoryService;
use std::sync::Arc;

let kg = GraphMemoryService::new("sqlite://mia-memory.db").await?;
kg.migrate().await?;                         // idempotent schema setup
let kg = Arc::new(kg);

グラフへの書き込み

use adk_memory::{CreateEntityInput, CreateRelationInput};

kg.create_entities("coach", "alice", vec![CreateEntityInput {
    name: "Alice".into(),
    entity_type: "person".into(),
    observations: vec!["prefers morning sessions".into(), "goal: run a 10k".into()],
}]).await?;

kg.create_relations("coach", "alice", vec![CreateRelationInput {
    source: "Alice".into(), relation_type: "training_for".into(), target: "10k race".into(),
}]).await?;

// add facts to an existing entity later
kg.add_observations("coach", "alice", /* entity */ "Alice", vec!["timezone is CET".into()]).await?;

エンティティの作成はアップサートです。既知のエンティティを再作成すると、重複させるのではなく、そのタイプとタイムスタンプが更新されます。

読み戻し

トレイトのsearchに加えて、3つのリコール形状があります。

// 1. Token-scored relevance search → entities + their relations + a score
let hits = kg.search_nodes("coach", "alice", "what is she training for?", 5).await?;

// 2. Fetch specific entities by name
let nodes = kg.open_nodes("coach", "alice", &["Alice".into()]).await?;

// 3. The whole graph (small graphs / debugging)
let graph = kg.read_graph("coach", "alice").await?;

プロフィールカード

エージェントにとってのキラー機能:profile_cardは、ユーザーが誰であるか(最新のエンティティとその有効な観測)のコンパクトで現在の要約をレンダリングし、セッション開始時にシステムプロンプトに注入する準備ができています。

let card = kg.profile_card("coach", "alice").await?;
// → a short text block: "Alice (person): prefers morning sessions; goal: run a 10k…"

グラフが成長してもプロンプトが小さく保たれるように、予算でそのサイズを制限します。

let kg = GraphMemoryService::new(url).await?
    .with_profile_budget(/* entities */ 12, /* observations per entity */ 5);

エージェントによるキュレーション

本番環境でcreate_entitiesを手動で呼び出すことはめったにありません。学習するにつれてグラフに書き込むためのツールをエージェントに与えます。上記の呼び出しに直接マッピングされ、adk-toolで提供されるrememberrelateについては、ツールとエージェントを参照してください。

次へ:ツールとエージェント →