从「能用」到「可治理」: AI 随手记做了一次「不动皮只动骨」的升级
最近我们给「 AI 随手记」做了一次大改造。
用户看到的还是老样子——写随手记、点生成、拿到一篇日记。但里面已经从一个「大杂烩流程」,变成了一条可组合、可追踪、可回放、还能做质量把关的「技能流水线」。
这篇文章用大白话讲讲:我们为什么要改、改了什么、踩了哪些坑,以及这件事对我们(和对想做类似产品的人)意味着什么。
一、为什么要动刀?——「能跑」和「能管」是两回事
以前的实现也能跑,但有几件事让我们越来越头疼:
逻辑缠在一起
生成一篇日记时,清洗、检索、写作、存库、向量化全挤在一坨,改一处怕动全身。出了问题不好查
用户说「这次写得怪」,我们只能翻日志猜,很难精确还原「到底是哪一步、输入输出长什么样」。想小步试新东西很难
比如只想换一段提示词或某一步策略,几乎要动整条链路,没法单独试。质量会飘
不同模型(尤其像 Qwen 这类)有时会「脑补」事实,规则不好统一管。
所以我们这次的目标很明确:
把「写日记」从一个大函数,拆成一条「有标准接口的技能流水线」。
这样每一步都可以单独升级、单独排查、单独做灰度。
二、我们具体做了什么?(一句话版)
我们把系统重构成了四块:
- SkillRegistry:技能注册表,知道有哪些技能、怎么找。
- SkillExecutor:执行器,按标准接口跑每一个技能。
- SkillOrchestrator:编排器,决定先跑谁、后跑谁、怎么串起来。
- Trace:每次运行都留痕,谁在什么时候、吃了什么、吐出了什么、花了多久、有没有报错。
然后把「生成日记」这条主流程,拆成了 5 个技能:
note-normalize (清洗)
把随手记整理成统一的结构化块,去噪音,准备好给后面用。memory-retrieve (记忆检索)
用本地记忆做召回,给生成阶段补一点上下文;可以降级为空,不阻塞主流程。diary-compose (生成)
按规则生成正文。diary-critic (审校门控)
检查有没有「硬伤」:比如图片标记幻觉、背景信息泄露、拼接感太重等。
不只是打分,还能拦:不合格就不落库,避免脏数据。persist (落库)
通过审校的才存进去;不通过就阻断,并返回可解释的原因。
用户依然只点「生成日记」,但内部已经是一条清晰的流水线:清洗 → 检索 → 生成 → 审校 → 落库。
三、最关键的四种能力:可追踪、可回放、可灰度、可门控
这次重构,我们最在意的是四件事。它们不炫,但决定了能不能长期迭代、少背锅。
1 ) Trace:可追踪
每次运行都有一个 run_id,会记录:
每个技能吃了什么(输入摘要)、吐出了什么(输出摘要)、耗时多少、有没有报错。
以前:用户说「这次写得怪」→ 我们猜。
现在:按 run_id 一查,就能看到是哪一个技能、在什么输入下、产出了什么,相当于可回放的一盘录像。
2 ) Replay:可回放
我们加了一套「固定样本」的复测数据。
改一个技能或一段提示词,可以用同一批样本反复跑,看有没有「修一个坏三个」。
这对稳定迭代特别重要:先能复现,再谈优化。
3 ) Rollout:可灰度
支持「按技能切版本」。
比如只把「 diary-compose 」换成新版本,其他技能不动,整条链路不用大动。
这样我们可以小步试新策略、新 prompt ,出问题也能快速回滚。
4 ) Gate:可门控
diary-critic 不只是打分数,而是有「拦」的能力。
高风险内容(幻觉、泄露、拼接味太重)可以不落库,并给用户一个可解释的原因,而不是悄悄存错。
四、踩过的坑
坑 1:Xcode 资源重名冲突
多个技能里都有 SKILL.md、input.json、output.json,Xcode 拷贝资源时会扁平化,结果出现「重复输出」之类的问题。
解决:改成全局唯一文件名(例如 SKILL-note-normalize.md、note-normalize-input.json),并在 registry 里用 SKILL*.md 这种方式扫描,避免重名。
坑 2:第二次生成时崩溃( SwiftData detached backing data )
第一次生成后,我们在异步任务里还在读旧的 DiaryElement;第二次生成时先把旧元素删了,就触发了 fault 崩溃。
解决:去掉在后台乱跑的并发 Task ,把向量生成和保存放回同一条 async 执行流里,保证对象生命周期一致,不再「用已删掉的东西」。
坑 3:日记「像在拼接 notes 」
提示词太保守时,模型会变成「安全复述器」:一条条复述随手记,不像日记,像清单。
解决:
- 在 prompt 里允许「合并同主题、时间线重排、口语转书面、压缩重复」;
- 在 Critic 里加「拼接味检测」(例如重合度阈值);
- 命中后自动重写一轮,但不放宽事实约束,避免编造。
五、最难的一关:既不虚构,又要像日记
「禁止虚构」和「读起来像日记」经常打架:
管太严 → 像清单;放太松 → 容易编造。
我们的做法是三层:
硬约束守底线
不新增输入里没有的关键事实。这是红线。结构规则保可读
强制段落规划、主题合并,让文本有节奏、有重点,而不是流水账。审校规则兜质量
用 Critic 检测「拼接味」,必要时自动重写一次,仍然不放宽事实约束。
结果就是:既不把 notes 原样粘贴,也不靠「脑补」润色。
六、用户能感受到的变化
表面上看,还是「写随手记 → 一键生成日记」。但你会慢慢感觉到:
首行格式更稳定
例如:2026-2-6 上海,多云,2.8°C,不会乱变。文本更像日记
不再是「一行行原始随手记的复制」,而是有合并、有节奏、口语转书面。出错更可解释
我们内部能通过 trace 看到是哪个技能、在什么环节出了问题,修起来更有针对性;未来也可以把「可解释」适度开放给用户(比如「因内容未通过审校,未保存」)。
七、一点结论:AI 应用拼到后面,拼的是「能不能治理」
单次回答好不好,很重要;但产品要长期活下来,更关键的是:
- 能不能治理:流程清晰、每一步可观测、可调参。
- 能不能复盘:出问题能回放、能定位,而不是靠猜。
- 能不能小步快跑:改一点、测一点、灰度一点,而不是一改就炸。
这次把「生成日记」做成 Skills 流水线,本质上就是把「提示词工程」升级成「系统工程」。
如果你也在做类似的产品(日记、总结、写作助手等),我们会建议优先补三件事:
可追踪、可回放、可门控。
它们看起来不炫,但会直接决定你能不能长期迭代、少背锅、少踩坑。