Add User Model Service and Temporal Recall for MeMind V0.1.

Introduce UMS ingest/snapshot pipeline, Context Planner with multi-source recall, runtime context injection, canonical user mapping, and session snapshot loading on auth/me.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-03 23:25:18 +08:00
parent bf66fdf493
commit 212ff3ff80
47 changed files with 4534 additions and 6 deletions
+187
View File
@@ -0,0 +1,187 @@
-- memind_user_model v0 — User Model Service (UMS)
-- 库:memind_user_model(与 meinput、goose 并列,独立 RDS 库或 schema
-- UMS 只 ingest Evidence Envelope v1,不读 meinput.mi_* 表。
-- ── L0: 原始 Evidenceimmutable append)────────────────────────────────────
CREATE TABLE IF NOT EXISTS um_evidence (
evidence_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
source_type VARCHAR(32) NOT NULL,
source_ref VARCHAR(512) NOT NULL,
evidence_type VARCHAR(64) NOT NULL,
occurred_at DATETIME(3) NOT NULL,
received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
content_hash CHAR(64) NOT NULL,
schema_version INT NOT NULL DEFAULT 1,
privacy_level VARCHAR(32) NOT NULL DEFAULT 'normal',
payload_json JSON NOT NULL,
UNIQUE KEY uq_um_evidence_content (user_id, content_hash),
KEY idx_um_evidence_user_time (user_id, occurred_at DESC),
KEY idx_um_evidence_source (user_id, source_type, occurred_at DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── L1: Signal(观察到了什么 — 确定性,可复算)────────────────────────────
CREATE TABLE IF NOT EXISTS um_signals (
signal_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
signal_type VARCHAR(64) NOT NULL,
-- 例:term_frequency | app_usage | entity_mention | rhythm_hour | segment_count
dimension_key VARCHAR(128) NOT NULL,
-- 例:term:MeInput | app:com.tencent.xin | hour:15
window_start DATETIME(3) NOT NULL,
window_end DATETIME(3) NOT NULL,
value_json JSON NOT NULL,
-- 例:{"count":126,"chars":8400,"distinct_days":7}
evidence_ids JSON NOT NULL,
-- 指向 um_evidence.evidence_id 数组
computed_at BIGINT NOT NULL,
content_hash CHAR(64) NOT NULL,
UNIQUE KEY uq_um_signal (user_id, signal_type, dimension_key, window_start, window_end, content_hash),
KEY idx_um_signals_user_window (user_id, window_end DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── L2: Candidate(系统推断了什么 — hypothesis)────────────────────────────
CREATE TABLE IF NOT EXISTS um_candidates (
candidate_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
candidate_type VARCHAR(64) NOT NULL,
-- project | interest | preference | relation | routine | focus
hypothesis_json JSON NOT NULL,
-- 例:{"type":"project","name":"MeInput","role":"active"}
status ENUM(
'observed',
'open',
'accepted',
'rejected',
'conflicted',
'revoked',
'memory_eligible',
'memory_promoted'
) NOT NULL DEFAULT 'observed',
promotion_score DECIMAL(6,4) NOT NULL DEFAULT 0,
confidence DECIMAL(6,4) NOT NULL DEFAULT 0,
signal_ids JSON NOT NULL,
evidence_ids JSON NOT NULL,
first_seen_at DATETIME(3) NOT NULL,
last_seen_at DATETIME(3) NOT NULL,
version INT NOT NULL DEFAULT 1,
parent_candidate_id CHAR(36) NULL,
conflict_with_id CHAR(36) NULL,
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
KEY idx_um_candidates_user_status (user_id, status, last_seen_at DESC),
KEY idx_um_candidates_user_type (user_id, candidate_type, promotion_score DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── L3: User Model Graph ───────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS um_entities (
entity_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
entity_type VARCHAR(32) NOT NULL,
-- person | project | topic | tool | preference_dim | role
canonical_name VARCHAR(256) NOT NULL,
aliases_json JSON NULL,
status ENUM('active', 'archived', 'revoked') NOT NULL DEFAULT 'active',
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL,
UNIQUE KEY uq_um_entity (user_id, entity_type, canonical_name(128))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS um_attributes (
attribute_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
entity_id CHAR(36) NULL,
attr_key VARCHAR(128) NOT NULL,
value_json JSON NOT NULL,
confidence DECIMAL(6,4) NOT NULL,
decay_halflife_days INT NOT NULL DEFAULT 90,
effective_weight DECIMAL(6,4) NOT NULL DEFAULT 1,
evidence_ids JSON NOT NULL,
candidate_id CHAR(36) NULL,
first_seen_at DATETIME(3) NOT NULL,
last_seen_at DATETIME(3) NOT NULL,
status ENUM('active', 'superseded', 'revoked') NOT NULL DEFAULT 'active',
version INT NOT NULL DEFAULT 1,
content_hash CHAR(64) NOT NULL,
KEY idx_um_attr_user_key (user_id, attr_key, status, effective_weight DESC),
CONSTRAINT fk_um_attr_entity FOREIGN KEY (entity_id) REFERENCES um_entities(entity_id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS um_relations (
relation_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
from_entity_id CHAR(36) NOT NULL,
rel_type VARCHAR(64) NOT NULL,
to_entity_id CHAR(36) NOT NULL,
confidence DECIMAL(6,4) NOT NULL,
evidence_ids JSON NOT NULL,
candidate_id CHAR(36) NULL,
first_seen_at DATETIME(3) NOT NULL,
last_seen_at DATETIME(3) NOT NULL,
status ENUM('active', 'superseded', 'revoked') NOT NULL DEFAULT 'active',
KEY idx_um_rel_user (user_id, from_entity_id, rel_type),
CONSTRAINT fk_um_rel_from FOREIGN KEY (from_entity_id) REFERENCES um_entities(entity_id) ON DELETE CASCADE,
CONSTRAINT fk_um_rel_to FOREIGN KEY (to_entity_id) REFERENCES um_entities(entity_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── L4: Profile ProjectionGraph 的结构化投影,非 narrative)──────────────
CREATE TABLE IF NOT EXISTS um_profile_versions (
profile_version INT NOT NULL,
user_id CHAR(36) NOT NULL,
structured_json JSON NOT NULL,
content_hash CHAR(64) NOT NULL,
parent_version INT NULL,
materialize_reason VARCHAR(64) NOT NULL,
-- daily_consolidation | candidate_accepted | threshold | manual
created_at BIGINT NOT NULL,
status ENUM('active', 'superseded', 'revoked') NOT NULL DEFAULT 'active',
PRIMARY KEY (user_id, profile_version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── L5: Agent SnapshotProfile Projection 的渲染视图,Session 加载)────────
CREATE TABLE IF NOT EXISTS um_profile_snapshots (
snapshot_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
projection VARCHAR(32) NOT NULL DEFAULT 'default',
-- default | coding | schedule
profile_version INT NOT NULL,
fast_revision INT NOT NULL DEFAULT 0,
snapshot_json JSON NOT NULL,
byte_size INT NOT NULL,
content_hash CHAR(64) NOT NULL,
created_at BIGINT NOT NULL,
expires_at BIGINT NULL,
status ENUM('active', 'superseded', 'revoked') NOT NULL DEFAULT 'active',
KEY idx_um_snapshot_user_proj (user_id, projection, status, created_at DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── 辅助:ingest 游标(按 user + source_type)────────────────────────────────
CREATE TABLE IF NOT EXISTS um_ingest_cursors (
user_id CHAR(36) NOT NULL,
source_type VARCHAR(32) NOT NULL,
cursor_value VARCHAR(256) NOT NULL,
updated_at BIGINT NOT NULL,
PRIMARY KEY (user_id, source_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── v0.1 预留:Memory lineage(暂不写入,schema 先冻结)────────────────────
CREATE TABLE IF NOT EXISTS um_memory_promotions (
promotion_id CHAR(36) PRIMARY KEY,
user_id CHAR(36) NOT NULL,
candidate_id CHAR(36) NOT NULL,
attribute_id CHAR(36) NULL,
memind_candidate_id VARCHAR(64) NULL,
content_hash CHAR(64) NOT NULL,
promoted_at BIGINT NOT NULL,
revoked_at BIGINT NULL,
status ENUM('promoted', 'revoked') NOT NULL DEFAULT 'promoted',
KEY idx_um_promo_user (user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;