지식 그래프

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 타임스탬프를 가진 엔티티에 연결된 하나의 사실.
  • Relation — 두 엔티티(source ──relation_type──▶ target) 사이의 유형화된 엣지, 예: Alice ──works_at──▶ Acme.

또한 큐레이션된 그래프와 별도로 원시 턴을 기록하는 에피소드 저장소(kg_episodic)가 있으므로 대본과 정제된 모델을 모두 유지할 수 있습니다.

이중 시간적인 이유

모든 관찰과 관계는 시간 축을 따라 추적됩니다.

  • 유효 시간 — 세상에서 사실이 참이었던 시점(valid_fromvalid_to).
  • 수집 시간 — 시스템이 그것을 학습한 시점.

사실이 변경될 때, 이전 사실은 삭제되지 않습니다. 무효화(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?;

엔티티 생성은 upsert입니다. 알려진 엔티티를 다시 생성하면 중복하는 대신 해당 유형과 타임스탬프가 업데이트됩니다.

다시 읽기

트레이트의 search 외에 세 가지 리콜 형태:

// 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에 대해서는 도구 및 에이전트를 참조하십시오.

다음: 도구 및 에이전트 →