摘要:Notion Agent 开始支持逐条建议修改。本文讨论如何把 AI 改稿建模为带锚点、理由、风险和冲突检测的 Patch 流程,并保留作者声音、版本历史与人工确认边界。
调用模型做改稿,最偷懒的接口大概长这样:
ts
const revised = await llm.rewrite(document, '润色一下');
await db.save(revised);
Demo 很顺,生产很难审。revised 里可能混着标点修复、段落重排、语气变化和新事实;一旦直接覆盖,用户甚至不知道模型替他做了哪些决定。
Notion 8 月 28 日更新了一个值得 Agent 产品借鉴的交互:让 Agent suggest edits,用户从上到下逐条批准,而不是让 Agent 直接改掉页面。官方主要把它用于语法等行级修改,但其设计价值不只在文字工具------它提供了一种"提议权"和"决定权"分离的协议。

从 rewrite() 改成 proposePatches()
系统不再返回完整文档,而是返回一组变更:
ts
type Patch = {
id: string;
baseRevision: string;
anchor: {
blockId: string;
beforeHash: string;
quote: string;
};
oldText: string;
newText: string;
rationale: string;
kind: 'typo' | 'clarity' | 'structure' | 'fact' | 'brand' | 'compliance';
risk: 1 | 2 | 3;
sources?: string[];
};
这套结构至少带来三个好处:
- UI 能准确展示 Diff;
- 审批策略可以按风险路由;
- 每一次接受、拒绝和回滚都能追溯。
Anchor 比 Offset 更重要
纯 offset 很脆弱。上游改一个字,后续 Patch 的字符位置全部失效。
更实用的锚点由块 ID、原文引用和上下文哈希共同组成。应用前先做乐观锁检查:
ts
function applyPatch(doc: Doc, p: Patch): Result<Doc, 'STALE'> {
if (doc.revision !== p.baseRevision) return err('STALE');
const block = doc.block(p.anchor.blockId);
if (!block || hash(block.text) !== p.anchor.beforeHash) {
return err('STALE');
}
return ok(doc.replace(p.anchor.blockId, p.oldText, p.newText));
}
发生冲突时,不要让模型猜一个最像的位置继续改。把 Patch 标为 stale,再基于当前版本重算,通常比静默错贴便宜。
风险路由不是一个"确认"按钮

建议修改的核心不是多一步点击,而是不同修改走不同审批路径:
ts
const policy = {
typo: { maxRisk: 1, mode: 'batch-accept-with-undo' },
clarity: { maxRisk: 2, mode: 'review-group' },
structure: { maxRisk: 2, mode: 'preview-document' },
fact: { maxRisk: 3, mode: 'source-required' },
brand: { maxRisk: 3, mode: 'owner-approval' },
compliance: { maxRisk: 3, mode: 'specialist-approval' }
};
错别字允许批量接受,但仍可撤销;改标题力度要预览全文语境;数字、引语、产品承诺必须回到来源;医疗、法律和金融表述不能因为模型"很有把握"就自动通过。
作者声音也应该进入 invariant set
工程团队容易只保护事实,却忽略另一类回归:稿子没错,但作者没了。
可以把声音约束放进任务输入:
yaml
invariants:
claims:
- 不增加原稿没有的效果承诺
- 观点强度不得提高
voice:
- 保留第一人称和具体案例
- 允许短句,不强行合并段落
- 不新增感叹号
- 禁用"赋能、重塑、颠覆、时代浪潮"
facts:
- 数字与日期只能来自 source_set
这些约束无法把文风完全量化,但能把"不要改成 AI 腔"变成可复查的失败条件。
别让一个 Prompt 同时做四种编辑
建议把 pipeline 拆成独立阶段:
text
source grounding
→ claim review
→ structural review
→ line edit
→ platform rewrite
→ publish verification
每一阶段只生成对应种类的 Patch。结构还没确认时,不要花成本逐句润色;事实还没落地时,不要先把错误写得更流畅。
平台改写尤其应该最后做。CSDN、掘金和头条可以共享事实清单、禁用表述与产品资料,但不应共享同一篇正文。共享的是约束,不是最终字符串。
Patch 需要幂等键与审计日志
同一建议被用户连点两次,不应重复插入。可以用:
text
idempotencyKey = hash(baseRevision + anchor + oldText + newText)
审计日志则记录:
json
{
"patchId": "p-108",
"action": "accepted",
"actor": "human-editor",
"fromRevision": "r12",
"toRevision": "r13",
"timestamp": "2026-08-31T10:41:00+08:00"
}
日志不是为了把内容团队变成合规部门,而是为了能回答:"这句话是谁在什么依据下改的?"
从编辑器机制回到岗位交付
只实现 Patch 仍然只是一个改稿组件。真实任务还包括调研、事实清单、写作、配图、摘要、标签、平台适配、预填和发布回读。
这也是我们在 Tipkay 里把公众号编辑、知乎博主、博客发布助手拆成岗位的原因:它们共享业务资料和品牌口径,但按照各平台的方法分别交付,发布等关键操作由人确认。不是把一次聊天回复原样扔到所有平台。
边界也要讲明:Tipkay 官网没有宣称已经为所有文本编辑实现本文这套 Patch 协议。这里讨论的是产品和工程方法;Tipkay 当前可验证的选择,是把业务上下文、岗位流程、平台工具和关键确认放进一条交付链。
最小实现顺序
- 先保存不可变原稿和 revision;
- 让模型输出 JSON Patch,而不是全文;
- 校验 schema、锚点和基础版本;
- 按风险展示批量或逐条审批;
- 接受后生成新 revision,保留撤销;
- 平台改写完成后再次做最终回读。
AI 编辑的上限,不只是生成质量。它是否愿意把修改拆开、把理由说清、把最后决定还给人,决定了它能不能进入真正的内容生产系统。
参考资料:
标签:人工智能、AI Agent、自然语言处理