OpenChronicle 时间线机制揭秘:1 分钟块如何 100% 保留你敲下的每一行字
【免费下载链接】OpenChronicle项目地址: https://gitcode.com/gh_mirrors/op/OpenChronicle
OpenChronicle 是一款开源、本地优先的 AI 记忆工具:它在 macOS 上持续捕获你的屏幕活动,再把它压缩成人类可读的 Markdown 记忆。而整条流水线里最关键的一站,就是时间线机制(Timeline)——它用对齐真实时钟的1 分钟块,把你正在编辑的文字、URL、窗口标题逐字保留下来,再交给下游模型加工。本文将完整揭秘这套「100% 保真」机制的设计原理与实现细节 🕐
时间线是什么:记忆的「保真层」
先厘清一个常见误解:时间线不是摘要器,而是归一化器。
原始 AX 树动辄 200–400 KB,直接塞给下游模型会撑爆提示词预算;但下游阶段又必须知道「你到底输入了什么」——一条 TODO、一段消息草稿、一个搜索词。时间线恰好卡在两者之间(见 docs/timeline.md):
- 保留:你亲手敲的文字、URL、窗口标题、文件名、专有名词,一字不改;
- 剥掉:UI 装饰(工具栏按钮、侧边栏骨架)、重复的被动阅读快照;
- 留给下游:真正的压缩发生在再下一站的会话归约器(S2 reducer)。
官方定义:Timeline 是强制开启、逐字保留(verbatim-preserving)的归一化层,没有任何关闭开关。
为什么是 1 分钟块?时钟对齐的巧妙设计
时间线窗口默认是window_minutes = 1,且对齐真实时钟:[10:00, 10:01)、[10:01, 10:02)……而不是从某个启动时刻滚动计时(配置见 docs/config.md 的[timeline]一节)。这带来三个实际好处:
| 好处 | 说明 |
|---|---|
| 不重叠 | 守护进程重启、多实例、时钟漂移都不会产生交叠块 |
| 可幂等 | 块以(start_time, end_time)作为唯一键,重复生产自动跳过 |
| 好推理 | 人可以直接谈论「10:15 那个块」,无需心算偏移 |
为什么选 1 分钟而不是 5 分钟?原因有二(详见 docs/timeline.md):
- 短窗口 = 少快照。归一化提示词必须让每段输入文字「原样往返」,窗口里事件越少,模型越不会顺手改写或丢弃内容;
- 压缩另有其人。下游 flush 本来就是 5 分钟节奏,一次 flush 恰好消费约 5 个时间线块,分工干净。
1 分钟块如何做到 100% 保留你敲下的字
这是整篇文章的核心。在 src/openchronicle/timeline/aggregator.py 中,聚合器不读原始 AX 树,只消费 S1 解析器提取的focused_element、visible_text、url三个结构化字段,然后把它们填入归一化提示词。
提示词 src/openchronicle/prompts/timeline_block.md 里有四条硬性规则,堪称「防丢字」保险丝:
- 逐字保留:可编辑输入框里的内容必须加引号原样带入条目,禁止改写、禁止用「用户输入了一条笔记」这类泛化动词替代;
- 反幻觉:同一个 App 里多个独立对话(多个聊天、多个标签页)互不串线,A 对话里的人绝不能被安到 B 对话头上;
- 作者身份护栏:在搜索框/地址栏打字不算「参与聊天」,会被描述为搜索或导航;
- 有限去重:连续相同的被动阅读快照合并为一条;正在编辑的草稿只保留最长、最新版本——这是对原创内容唯一允许的去重方式。
每条输出的标准形状是:
[应用] 上下文(标题/URL/文件): 发生了什么。"逐字原文(如有)"。Involving: 本对话中的人物/主题/文件。
举例:你在备忘录里把购物清单从 "milk, eggs, flour" 逐字补写成 "milk, eggs, flour, butter",块里保留的正是最终完整版本,而不是「用户写了一个清单」。
每分钟自动生产:幂等与容错
守护进程内,src/openchronicle/timeline/tick.py 的run_forever每 60 秒醒一次,流程非常克制:
- 从
timeline_blocks表读取已有块的最新结束时间作为游标(首次运行最多回溯cold_lookback_minutes,避免启动时补录几小时历史); - 从游标扫到「当前时刻减去一个窗口」,只处理已关闭窗口——正在进行的半截窗口留在缓冲区当「尾部快照」;
- 每个没有块的窗口调用
produce_block_for_window生产一个新块; - 扫描结束后顺手清理已被块吸收且超期的捕获文件。
可靠性设计同样值得一提:
- 零事件窗口跳过 LLM 调用,空分钟零成本;
- LLM 失败也不丢窗:JSON 解析失败、超时、空返回时,代码退化为基于应用名的启发式条目,绝不让一个窗口无声消失;
- 生产幂等:手动执行
openchronicle timeline tick永远安全。
块最终写入index.db的timeline_blocks表,含entries(条目数组)、apps_used、capture_count等字段,与 FTS 表同库共存。
时间线块如何变成持久记忆 🧠
时间线本身只是「保真层」,真正的落地靠下游 S2 会话归约器:每次 5 分钟 flush,它按时间范围查询重叠的时间线块(SQL 见 docs/timeline.md),连同墙钟区间一起交给 LLM,产出形如[13:25-13:30, Cursor] edited tick.py; "fixed _stem_to_dt for negative offsets"的子任务条目,追加到当天的event-YYYY-MM-DD.md。完整链路可参考 docs/architecture.md,原始捕获侧的细节见 docs/capture.md。
一句话概括整条漏斗:
捕获 →时间线(1 分钟块,逐字保真)→ 会话归约(5 分钟,压缩) → 分类器(持久记忆)
快速上手:查看你的时间线块
装好 OpenChronicle 后(macOS 13+,克隆仓库后运行bash install.sh),两条命令即可亲眼验证 1 分钟块机制:
openchronicle timeline tick # 同步构建所有已关闭窗口 openchronicle timeline list -n 24 # 查看最近 24 个块由于生产是幂等的,这两条命令随时执行都安全。想彻底重跑?openchronicle clean timeline会清空时间线数据,下次 tick 会自动从缓冲区重建。
写在最后
OpenChronicle 的时间线机制证明了一件事:保真与压缩不矛盾——用 1 分钟块对齐时钟、用提示词把「逐字保留」变成硬规则、用启发式兜底防丢窗,AI 记忆系统就能在控制成本的同时,100% 记住你敲下的每一行字。更多调优细节(窗口大小取舍、模型速度瓶颈)都在 docs/timeline.md 的 Tuning 一节,欢迎深入源码 src/openchronicle/timeline/ 亲自验证 ✨
【免费下载链接】OpenChronicle项目地址: https://gitcode.com/gh_mirrors/op/OpenChronicle
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考