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
+190
View File
@@ -0,0 +1,190 @@
# Temporal Recall API v1
| 字段 | 值 |
|------|-----|
| 状态 | **FrozenV0.1** |
| 建议 Base URL | MeMind Portal 同域 `/api/v1/temporal-recall/*` |
| 输入 | `ContextPlan` 或简化 query |
| 输出 | `TimelineItem[]` + 分组元数据 |
---
## 1. 职责
按 Context Plan **并行检索**多源,归一化、Dedupe、Rank,返回 Personal Timeline Recall Bundle。
**回答:** 「某个时间范围内发生了什么?」
---
## 2. `POST /v1/temporal-recall/query`
### 方式 A — 传入完整 Plan(推荐)
```json
{
"plan": { "...ContextPlan..." },
"limit": 50
}
```
### 方式 B — 快捷 query(内部先调 Planner
```json
{
"query": "我这周有什么重要的事?",
"user_id": "a70ff537-8908-486e-9b6c-042e07cc25db",
"now": "2026-09-03T22:00:00+08:00",
"limit": 50
}
```
### 响应
```json
{
"query_type": "personal_temporal_recall",
"temporal_mode": "AMBIGUOUS",
"time_range": {
"start": "2026-09-01T00:00:00+08:00",
"end": "2026-09-08T00:00:00+08:00"
},
"groups": [
{
"label": "occurred_in_range",
"items": [
{
"timeline_item_id": "...",
"source": "meinput",
"type": "mention",
"event_time": null,
"observed_time": "2026-09-02T14:30:00+08:00",
"title": "MeInput 验证上屏",
"content": "MeInput验证上屏",
"importance": 0.71,
"confidence": 0.95,
"recall_score": 0.78,
"source_ref": "meinput:segment:...",
"status": "mentioned"
}
]
},
{
"label": "mentioned_or_planned",
"items": []
}
],
"items": [],
"stats": {
"sources_queried": ["meinput", "chat"],
"raw_count": 42,
"deduped_count": 38,
"returned_count": 25,
"elapsed_ms": 320
},
"plan": { "...echo ContextPlan..." }
}
```
`groups``temporal_mode=AMBIGUOUS` 时区分「实际发生」与「提到/安排」;否则 `items` 为 flat ranked list。
---
## 3. `GET /v1/temporal-recall/info`
```json
{
"schema_version": 1,
"supported_sources": ["meinput", "chat"],
"planned_sources": ["calendar", "memory_v2", "email", "browser", "tasks"],
"temporal_modes": ["OCCURRED_IN", "MENTIONED_IN", "PLANNED_IN", "CREATED_IN", "DUE_IN", "AMBIGUOUS"],
"default_limit": 50,
"max_limit": 200
}
```
---
## 4. Source Adapter 契约
每个 adapter 实现:
```typescript
interface TemporalSourceAdapter {
source: 'meinput' | 'chat' | 'calendar' | 'memory_v2';
search(ctx: {
userId: string;
retrieval: ContextPlan['retrievals'][0];
time: ContextPlan['time'];
temporalMode: ContextPlan['temporal_mode'];
}): Promise<TimelineItem[]>;
}
```
### MeInput AdapterV0.1
- 调用 `GET /v1/evidence/export`MeInput Cloud
- 过滤 `expression_segment`,按 `occurred_at` 映射 `observed_time`
- 规则抽取 `event_time`(「明天下午三点」→ 解析为绝对时间)
- `source_ref = meinput:segment:{evidence_id}`
### Chat AdapterV0.1
-`h5_agent_runs` + session messages(用户可见范围)
- `observed_time = message.created_at`
- commitment/todo 规则抽取
---
## 5. Rank 公式
```
recall_score =
source_quality(source)
× temporal_match(item, plan.time, plan.temporal_mode)
× semantic_match(item, expanded_queries)
× importance(item)
× confidence(item)
```
| 阈值 | 展示 |
|------|------|
| ≥ 0.75 | 主答案 |
| 0.50 ~ 0.75 | 次要 |
| < 0.50 | 丢弃 |
---
## 6. Dedupe
- 时间:`|event_time_a - event_time_b| < 15min` 或同日 + 同类
- 语义:title/content keyword overlap > 0.7 或 embedding cosine > 0.85v0.2
- Merge → 保留最高 `source_quality`,填充 `merged_from`
---
## 7. 认证
| 调用方 | 认证 |
|--------|------|
| Agent Runtime | 用户 sessionToken |
| 内部 Worker | `TEMPORAL_RECALL_TOKEN`(可选) |
---
## 8. V0.1 不做
- Calendar / Email / Browser adapter
- 持久化 timeline 索引表
- LLM 答案生成(只返回 structured timelineAnswer 层在 Agent
---
## 9. 错误码
| HTTP | code | 说明 |
|------|------|------|
| 400 | `invalid_plan` | Plan schema 校验失败 |
| 401 | `unauthenticated` | 未登录 |
| 503 | `source_unavailable` | MeInput export 不可用 |
| 504 | `recall_timeout` | 并行检索超时(默认 5s |