3.7 KiB
3.7 KiB
启动增量恢复设计
问题
PicoBot 重启后,Session::from_storage() 全量加载 messages 表,恢复的 history 可能直接超出上下文窗口,首次 LLM 调用即触发压缩,浪费 token。
设计
核心思路
用 last_compressed_message_at 标记最后压缩时刻。恢复时:
- 加载该标记之后的原始消息
- 用该 session 的 Timeline 条目替代已压缩部分
seq_counter统一从 SQLite 查MAX(seq) + 1
messages 表 memories(timeline)
┌──────────────────────────┐ ┌───────────────────────────┐
│ created_at = T1..T5 │ ← 跳过 │ session = feishu:oc:dialog │
│ (压缩已覆盖,用Timeline替代)│ │ created_at 降序 │
├──────────────────────────┤ ├───────────────────────────┤
│ created_at > T6 │ ← 加载 │ 只取最近 3 条 │
└──────────────────────────┘ └───────────────────────────┘
数据变更
sessions 表加列:
last_compressed_message_at INTEGER
SessionMeta / Session 加字段: last_compressed_message_at: Option<i64>
Storage 层新增方法
| 方法 | SQL |
|---|---|
get_max_message_seq(session_id) |
SELECT MAX(seq) FROM messages WHERE session_id = ? |
load_messages_after_timestamp(session_id, after_ts) |
WHERE created_at > ? |
load_session_timelines(session_id, limit) |
WHERE session_id = ? AND category = 'timeline' ORDER BY created_at DESC LIMIT ? |
压缩跟踪
compress_if_needed() 返回值改为 CompressionResult { history, created_timelines: bool }。
compress_once() 中 LLM 摘要路径才置 true(Tier 2),Tier 1/3 不产生 Timeline。
记录时机(handle_message 正常流、溢出重试流、/compact 统一):
if result.created_timelines {
session.last_compressed_message_at = Some(now());
session.persist_session_meta().await;
}
Session::from_storage() 恢复逻辑
有压缩标记时:
load_session_timelines(limit=4)→ 取 3 条给 LLM,第 4 条判"有更多"- 有更多 → 插入提示 user 消息
- 逐条插入 Timeline 为
[Previous Context]user 消息 load_messages_after_timestamp(after_ts)→ 原始尾消息repair_tool_call_chains
无压缩标记 → 全量加载(现有行为)。
统一:seq_counter = MAX(seq) + 1
系统提示词
Session.last_compressed_message_at 非空时追加:
## 历史会话
之前的对话摘要已归档。如需回顾历史上下文,使用 `timeline_recall` 工具搜索。
改动清单
| # | 文件 | 改动 |
|---|---|---|
| 1 | storage/session.rs |
SessionMeta 加 last_compressed_message_at |
| 2 | storage/mod.rs |
DDL migration + upsert/get_session 加列 |
| 3 | storage/mod.rs |
新增 get_max_message_seq, load_messages_after_timestamp |
| 4 | storage/memory.rs |
新增 load_session_timelines |
| 5 | agent/context_compressor.rs |
返回值改为 CompressionResult 含 created_timelines |
| 6 | session/session.rs |
Session 加字段,persist_session_meta 加字段 |
| 7 | session/session.rs |
from_storage() 重写恢复逻辑 |
| 8 | session/session.rs |
handle_message() 压缩后记录标记 |
| 9 | session/session.rs |
/compact 命令压缩后记录标记 |
| 10 | session/session.rs |
build_system_prompt() 注入 last_compressed_message_at |