知识图谱
GraphMemoryService 是一种不同形式的记忆:它不是一堆文本条目,而是存储用户的知识图谱——实体、附加到实体的事实(“观察”)以及它们之间带类型的关系——并且它双时间性地跟踪所有这些。这是 Mindfulness-with-Mia example 和 realtime memory page 背后的后端。
它实现了与其他后端相同的 MemoryService trait,因此它以相同的方式集成到 agent 中——但它在顶部暴露了一个更丰富的图 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— 附加到实体的一个事实,带有一个稳定的id和一个valid_from时间戳。Relation— 两个实体(source ──relation_type──▶ target)之间的一个带类型边,例如Alice ──works_at──▶ Acme。
还有一个情景存储(kg_episodic),它记录原始轮次,与精心策划的图谱分开——因此您可以同时保留转录本和提炼出的模型。
为什么是双时间性
每个观察和关系都沿着两个时间轴进行跟踪:
- 有效时间 — 事实在世界中真实发生的时间(
valid_from→valid_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——重新创建已知实体会更新其类型和时间戳,而不是重复它。
读回它
除了 trait 的 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?;
个人资料卡
agent 的杀手级功能: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);
让 agent 管理它
在生产环境中,您很少手动调用 create_entities——您会赋予 agent 工具,让它在学习时写入图谱。请参阅 Tools & agents 以了解 remember 和 relate,它们直接映射到上述调用并随 adk-tool 一起提供。
下一步:Tools & agents →