“hindsight”这个词,英文里有个很妙的用法:hindsight is 20/20,意思是事后回头看,一切都看得清清楚楚。但问题恰恰在于——大多数时候,我们根本不会“事后回头看”,日子一天天过去,留下的只有模糊的记忆和一串没来得及消化的经历。我做这个小项目的初衷,就是想给自己造一个“后视镜”:把每天散落在备忘录、日记、相册里的零散信息自动收集起来,定期生成一份属于自己的复盘报告,让“事后视角”不再是偶尔灵光一现,而是一条固定运转的工作流。
这篇博文适合谁看?如果你也跟我一样,每天记录了一些东西但从不回看,或者想尝试用AI辅助做个人复盘却不知道从哪下手,又或者你对“用本地工具管自己的数据”这件事有天然的好感——这篇文章里的思路、代码和踩坑记录,应该能给你不少参考。
1. 项目思路:把“事后视角”变成一套可执行的工作流
1.1 为什么叫hindsight,而不是“复盘助手”
项目名字我纠结过很久,候选包括“recall”“review”“mirror”之类的,最后定了hindsight。原因很朴素:市面上叫“复盘助手”“个人总结”的工具太多了,但真正稀缺的不是“总结”这个动作,而是**“视角切换”**——同一个自己,站在今天看昨天,看到的重点完全不一样。hindsight这个名字提醒我:工具的核心价值不在生成文字,而在生成一个观察自己的新角度。
这个定位直接决定了我没有把项目做成“一个AI写作工具”。我不需要它把我一周的碎碎念扩写成优美的美文,我需要的是三个能力:
- 把散落各处的个人数据集中起来,变成结构化、可查询的记录;
- 定期用固定维度去审视这些记录,比如“这周时间花在哪了”“什么让我情绪低落”“什么决定是冲动的”;
- 输出一份简短、诚实、可追溯的回顾文本,让我愿意打开看。
换句话说,hindsight不是一个“智能助手”,而是一个**“数据管道 + 定时触发器 + 回顾生成器”**的组合体。它的核心流程长得像一条流水线:收集 → 清洗 → 存储 → 回顾 → 输出。这个架构我后来越用越顺,因为每一段都是独立的,数据源换了、模型换了、输出形式换了,都不影响其他环节。
1.2 整体架构:一条流水线到底怎么搭
整个项目我用了四层结构,每一层只干一件事:
- 采集层:监听/导入各类原始数据。我用的数据源有三个:手机备忘录导出的文本(我习惯随手记)、手工填写的每日模板(见后文)、以及截图/扫描件的OCR文本。采集层不负责理解内容,只负责把数据变成统一的纯文本格式。
- 处理层:做清洗和结构化。这里处理的内容包括:按日期切分、去重、提取关键词、识别“事件”“情绪”“决策”三类标记。清洗规则大部分是正则和关键词表,不涉及机器学习。
- 存储层:所有处理后的记录落进一个本地SQLite数据库,表结构很简单:date、content、source、tags、mood字段。
- 回顾层:脚本按设定的周期(我默认每天跑一次日回顾、每周跑一次周回顾)把数据库里的记录取出来,拼成一段提示词,送进本地大模型,生成复盘文本,然后写进一个新的markdown文件。
从实现难度看,采集和处理占了我整个项目大概60%的精力,反倒回顾层只是最后的一脚油门。这也给我的一个核心心得:AI 只是流水线的最后一段,前面数据的整洁程度决定了下游的一切。
1.3 为什么不用现成的时间追踪或日记应用
要说明的是,我一开始也试过几款成熟产品,比如带回顾功能的日记应用和自动统计屏幕时间的工具。它们有个共性缺陷:记录归记录,回顾归回顾,两件事被人为拆开了。有的App记录功能做得很好,但回顾只有“你本周写了1200字”这种统计数字,完全不分析你写了什么;有的时间追踪工具能精确到分钟,但拿到的是冷冰冰的类别标签,看不出背后的情绪和动机。
另一个痛点是数据归属。日记记在A应用、备忘录在B应用、相册截图在C应用,等我真正想做复盘的时候,需要手动去好几个地方复制粘贴。hindsight从根本上规避了这个问题:数据源可以继续用我习惯的工具,但统一回收到本地数据库,由我自己掌控全流程。才是能长期跑下去的关键——一旦工具变成了负担,再漂亮的功能也不会被坚持使用。
2. 数据收集与清洗:决定复盘质量的最短木板
2.1 先用“填空式日记”把记录成本降到最低
复盘的质量上限,其实由数据源决定。但我发现让普通人(包括我自己)每天老老实实写满一篇日记根本不现实,尤其忙碌时很容易断片。于是我设计了一个填空式的每日模板,记录成本压缩到两分钟以内:
【日期】 【最重要的三件事】 1. 2. 3. 【心情/情绪】(今天整体感受,一两句话) 【一个值得记录的瞬间】(可选) 【明天的一个计划】(可选)这套模板看起来简单,但它解决了一个关键问题:数据是“为回顾而生的”。“最重要的三件事”对应我关心的“时间去哪了”,“心情情绪”对应“我这一天的状态曲线”,“一个值得记录的瞬间”则是给未来的自己留了一颗时间胶囊。相比自由书写,它更容易坚持,也更容易被脚本解析。
我每天用的不是任何新奇App,就是手机自带的备忘录,加上一个快速填充的文本片段。晚上花两分钟填空,自动同步到电脑后,处理层就开工了。
2.2 OCR环节:把散落的“非文本”也收进口袋
文字记录还好办,真正让我头疼的是图片和截图。很多时候我懒得打字,直接截个图或者拍个照,里面可能是一段聊天记录、一篇文章标题、一个灵感想法。如果这些内容不收进数据库,复盘就会漏掉大量信息。
我调研了市面上几款OCR方案,最后选了系统自带OCR的捷径配合一个简单脚本,理由是识别精度够用、完全本地运行、不需要额外网络请求。脚本调用的逻辑其实很简单:接受一张图片路径,返回识别出的文本。我封装了一个命令行工具,统一处理截图目录下的新图片,每天早上自动跑一轮,把识别出的纯文本追加到当天的记录文件里。
一个深有体会的坑:截图OCR经常会带出一堆页面导航文字和广告文案,这些噪声会直接污染复盘的输入。我在处理层专门做了一遍清理——过滤掉长度小于5的文本块、去除高频页面词(比如“菜单”“首页”“返回”)、把连续重复字符压缩掉。不要小看这一步,它能把OCR噪声对最终生成质量的影响降低至少三成。
2.3 清洗规则与结构化:让数据从“可读的”变成“可算的”
清洗完的文本还是普通文本,想让它被脚本和模型高效使用,就得做结构化。我给每条记录打了三类标签:
- 事件标签,关键词匹配,比如“开会”“项目”“考试”“健身”,匹配到就归类;
- 情绪标签,用了一组简单的正负词表,比如“焦虑”“烦”“开心”“爽”,统计出现频率,给当天打一个偏正/偏负的标记;
- 决策标签,凡是句子带“决定”“还是算了”“最终选了”之类的话语,都会被特别标注,这对我来说是复盘的重中之重——我希望定期看见自己做过哪些决定,以及当时的情境。
打完标签的数据写进SQLite数据库,表名叫daily_log,字段为date、content、source、tags、mood。这里有个容易被忽视的细节:不要把清洗规则和逻辑写死在数据管道里。我后期把规则做成了外部配置文件,改关键词不必动主程序。我前期迭代时反复改代码才体会到这种设计的好处——数据和逻辑分离,是整个项目能长期维护的生命线。
3. 复盘生成:让脚本代替你把昨天“讲一遍”
3.1 提示词设计:告诉模型“你不是在写日记,你是在复盘”
收集好数据、定好结构之后,最后一步是让大模型生成复读文本。这一步我试了不同风格的提示词,踩过一些坑,最终沉淀下来一套持续有效的写法。核心原则就一条:必须强制模型站在“未来视角”看“过去的记录”。
我最终的日回顾提示词差不多长这样:
你是一个善于自我观察的复盘助手。下面是一天的原始记录,请从一个冷静、客观的第三视角出发,完成一次简洁的日回顾。 原始记录: {content} 回顾要求: 1. 先列出今天最重要的三件事,按实际影响排序; 2. 识别今天的主要情绪,并推测可能的原因; 3. 如果记录里有明确的决策,请单独指出,并简评这个决策的质量; 4. 用一句话总结:如果今天重来一遍,什么值得保持,什么值得调整。 语气:平实、直接,不吹捧,不空洞鼓励。 长度:控制在300字以内。这个提示词之所以有效,是因为它显式把“复述记录”变成了“分析记录”。如果只是让模型“总结一下今天”,它大概率会复读一遍原文;而当我强制它输出“影响排序、情绪归因、决策点评”,内容质量立刻不一样了。这背后的道理是:大模型的输出结构在某种程度上由你给出的问题结构决定,想让输出有深度,提问本身就得“逼”它思考。
3.2 生成流程:一条shell命令跑完“日回顾”
核心脚本我用Python写,大约150行,外部依赖只有两样:sqlite3标准库和调用本地模型的命令行工具。整个流程写成了一个函数:
def generate_daily_review(date_str: str): records = read_logs_by_date(date_str) if not records: return context = format_records_for_prompt(records) prompt = build_prompt(context) review_text = call_local_model(prompt) save_review(date_str, review_text)调用本地模型的函数我封装得比较薄,用的都是命令行接口,方便替换不同后端:
import subprocess def call_local_model(prompt: str) -> str: result = subprocess.run( ["llama-cli", "-m", "path/to/model.gguf", "-p", prompt, "-n", "600"], capture_output=True, text=True, encoding="utf-8" ) return clean_output(result.stdout)这里有一个我在项目早期反复碰壁的细节:提示词本身也会消耗模型的上下文长度。如果记录写得太长,加上提示词之后模型会出现截断,复盘的最后一句“建议”经常被吃掉。我的解决方法是:日回顾只取当天原始记录里每行的前80个字,周回顾则使用压缩脚本抽取出密度最高的片段。宁可少给一些素材,也要保证模型能完整输出结果。
3.3 周回顾:让hindsight真的拥有“后见之明”
日回顾解决的是“今天过得怎么样”,但真正的hindsight来自更长时间的跨度。每周日晚上我会额外跑一条周回顾脚本,它的输入不再是单日数据,而是七天里所有标签的汇总统计,外加每天回顾的简版。
周回顾的提示词,我会额外加这么几条:
- 和上周比,情绪曲线整体更平稳还是更波折?
- 哪一天的决定,放到整周来看带来了连锁影响?
- 有哪些反复出现的主题?这说明你真正在意什么?
- 未来七天,最值得关注的三个信号是什么?
这套“日回顾+周回顾”的组合拳下来,我的感受很直接:日回顾是给当天的自己交差,周回顾是给一周的自己开了一扇窗。很多当时觉得稀松平常的小事,拉到七天维度一看,才发现它其实一直在暗流涌动。这就是hindsight这个名字真正的神韵——事后回望,20/20。
4. 隐私优先:一台电脑完成全部闭环
4.1 数据不出门:选型时的取舍逻辑
我的日记、截图、聊天记录都是极度私密的数据,一开始就没打算上传任何云端API。这意味着我需要在本地跑一个大模型。这几年本地模型的生态成熟了不少,主流的推理框架有好几个,我在hindsight项目里试过两条路线:
- 纯CPU跑小参数量模型,比如7B甚至3B级别,优点是几乎没有显存门槛,缺点是输出质量有限,尤其在分析情绪时容易“胡说”;
- 用GPU推理中等参数量模型,比如14B级别,质量明显提升,代价是依赖设备配置。
我最终在一台内置GPU的轻薄本上跑通了14B量化模型,生成一篇300字的日回顾大约需要20到40秒(取决于文本长度)。这个速度完全能接受,因为我只需要每天晚上跑一次,跑完存成文件,第二天起床打开看就好。
整个流程没有一次网络请求,没有把任何一条数据发送到外部服务器,甚至生成的复读文件都只存在本地目录。对于我这种对隐私高度敏感的人,这种“一台电脑全闭环”的安心感,是任何云端工具都给不了的。
4.2 自动化与生命周期:别让脚本们养在深闺
脚本写得再好,如果每天都要手动点一遍,坚持不了三天。我的做法是用系统的计划任务工具在固定时间触发:
# 每天早上9点,OCR刚才积累的截图,并清洗入库 9 0 * * * cd /path/to/hindsight && python run_ocr_ingest.py # 每天晚上10点,生成今天的日回顾 0 22 * * * cd /path/to/hindsight && python generate_daily_review.py $(date +\%Y-\%m-\%d) # 每周日晚上10点30分,生成周回顾 30 22 * * 0 cd /path/to/hindsight && python generate_weekly_review.py这一套下去之后,hindsight彻底变成了“隐形工具”:平时它不打扰我,我只负责每天两分钟填一次模板;到了时间,脚本自己跑完,第二天醒来直接看结果。我强烈建议把“自动运行”纳入设计目标,任何一个需要手动喂数据的复盘工具,最终都难逃吃灰的命运。
4.3 保留策略:重要但不是越多越好
还有一个极容易被忽略的问题:历史数据该保留多久。我的做法是数据库全量保留,但生成的回顾文件只保留三个月滚动窗口。因为复盘的目的是帮助你调整近期行为,而不是做一份永久的日记档案;另外大模型的迭代太快,三个月前生成的文本再看也没什么价值,还会造成目录混乱。
清理策略我用一个小脚本,按文件修改时间删除掉90天前的回顧文件,每周随周回顾一起跑一次。这是我从实际使用中总结出来的经验——刚开始我什么都不舍得删,结果半年后回顾目录里堆了几百个文件,反而找不到想看的内容。克制,也是个人工具设计的一部分。
5. 踩坑实录与调试技巧:我从hindsight里学到的东西
5.1 跨日记录的时间归属问题
我的模板是“晚上填当天”,但有的时候加班太晚,填完已经过了午夜零点。最初脚本严格按日期匹配,结果这些记录全部掉进了第二天,白天的复读里总是缺少一些晚上才发生的信息。后来我改成了字段记录“实际填写时间”和“内容针对日期”两套时间,取内容日期作为归类依据,问题就地解决。
这个坑提醒我:个人数据的“时间”不是一个简单的物理时间,而是“内容所指向的时间”。凡是做个人复盘的,都应该用“事件发生时间”而非“录入时间”归档。
5.2 OCR误识别与噪声数据如何处置
我一度被OCR的识别噪声折磨得不轻。一句“今天晚上吃了火锅”经常被识别成“今天晚上——吃了火钢”,错别字会让情绪词表完全失效。我的解决方案不是追求更完美的OCR,而是做了一层“容错清洗”:建立一份与主题相关的同音/形近词表,比如“火钢→火锅”;情绪标签的匹配则使用模糊包含,而不是精确相等的关键词。这样一来,即便识别错了,核心语义还能被保留下来。
另外一个更稳妥的补充是:我在采集层增加了一个“不可靠来源”标记,OCR过来的文本不会被当作硬事实参与决策复盘,但仍参与情绪统计。这个怎么强调都不为过——宁可让模型少看一点内容,也别让它基于错误内容做推导。
5.3 模型幻觉:复盘里的“编造记忆”比不生成更危险
大模型生成优质复读的同时,也会带来一个致命问题:幻觉。所有模型都可能为了流畅性而“脑补”出不存在的细节,如果复盘文本里混入一句记录里根本没有的事,很容易被我误认为真实回忆,那就彻底违背了hindsight“忠实回看”的初衷。
我尝试了一系列对策:
- 在提示词里显式加上一行:
只使用给定记录中的事实,不得添加任何未提及的内容;如果信息不足,就明确说“记录里未涉及”; - 生成后用一段校验脚本,从输出文本中抽取所有名词短语,倒查它是否出现在原文里,没有命中的就标记为存疑;
- 所有复盘文件顶部都印着一行免责说明:
本报告仅供参考,包含生成内容,请以原始记录为准。
这个校验脚本没法100%堵住幻觉,但能把90%的明显编造抓出来。对个人复盘工具而言,我宁可它老老实实说“记录不足”,也不希望它演出一次天衣无缝的虚构。
5.4 模型选型的最终心得:效果和成本之间,我选了“够用”
本地模型这个环节我折腾过好几轮。追求最强效果时,我试过用大参数模型,结果生成一篇需要好几分钟,风扇狂转,体验非常劝退;追求极致轻量时,我用过3B模型,结果复读内容空洞到像套模板。最终站住脚的,是我笔记本能流畅运行的一个中等量化模型,它生成仓促时偶尔也会出现干巴巴的句子,但配合我前面设计的强提示词和结构化成输出要求,整体效果已经超过了我最初对“AI复盘”的预期。
如果你的设备更弱,没有独立显卡,我也试过一套纯CPU方案:用4-bit量化的极小模型跑日回顾,虽然深度欠一点,但胜在稳定;周回顾依然用强提示词来弥补模型能力的差距,实际能用的程度超出预期。这段经历让我彻底明白:工具的意义不是拼参数,而是稳定值守在你生活里。
最后再分享一个小技巧。输出目录我在每个文件名前面都加上了ISO格式日期,比如2025-01-15.md,这样文件列表天然按时间排序,配合全文搜索脚本,想找哪天的回顾一眼就能揪出来。这个不起眼的命名习惯,帮我在半年后回看历史时省了大量时间。hindsight项目做到现在,它带给我的不只是每周的几篇复盘报告,还养成了一种“记录-回看-修正”的生活节奏。愿你的后视镜也能照出清晰的路况。