给 AI 表单助手加差异预览时,我会先把字段契约锁住
最近我在一个内部运营台里做 AI 表单助手,目标是让用户描述想改什么,AI 给出字段建议,最后由用户确认提交。第一版让模型直接返回完整表单对象,演示很顺,接入复杂表单后开始出问题:AI 会覆盖用户刚改过的字段,也会把只读字段塞进提交体。后来我把重心收回到字段级变更,先锁字段契约,再做差异预览。

原创示意图:把用户意图、AI 候选变更、schema 校验、差异预览和最终提交门禁放在同一条工作流里观察。 来源:Codex image generation
问题背景
表单是前端里最容易积累隐性规则的地方。哪些字段必填,哪些字段依赖权限,哪些字段只在某个状态下可编辑,常常散在组件、校验函数和接口适配层里。MDN 的 FormData 文档把它描述为可发送的键值对集合。AI 表单助手还要额外处理业务语义、用户意图和字段所有权。
关键难点
第一个难点是 dirty field。用户已经手动编辑的字段应优先保留,AI 建议只能进入候选区,不能直接覆盖当前值。第二个难点是 schema 漂移。Zod 文档里的 parse 和 safeParse 适合做运行时校验,模型输出要先过 schema,失败项禁止进入提交区。第三个难点是提交体最小化。React Hook Form 仓库示例强调 register、handleSubmit、formState 等状态能力,AI 建议也要接入同一套表单状态。
解决思路
我把链路拆成五段。先用字段契约定义 name、type、editableWhen、normalizer、validator 和 submitPolicy。再让模型只返回字段级 patch。随后做运行时校验和差异预览,把当前值、AI 建议值、用户手动值和最终提交值并排展示。最后加人工确认,只有用户明确勾选的字段才能进入 submit payload。
这里最重要的边界是 draft、suggestion 和 commit。draft 属于用户正在编辑的状态,suggestion 属于 AI 候选区,commit 才是准备发给后端的最小变更。三者分开后,取消、重试、局部接受和恢复都清楚很多。
关键步骤
落地时我先写字段清单,把可编辑字段和只读字段分开。每个字段都给稳定 id,避免模型用中文标签或临时文案定位字段。接着把 prompt 改成只允许输出 { field, op, value, reason } 这类 patch 数组,并要求未知字段进入 unmatched。前端收到后先跑 schema 校验,失败项直接标成不可采纳。
随后做 diff 面板。每一行只展示一个字段,左侧是当前值,中间是 AI 建议,右侧是最终提交值。用户可以逐项接受、忽略或手动改写。提交前再根据已接受字段生成 payload,并记录 requestId、schemaVersion 和 acceptedFields,方便线上复盘。
可复用经验
AI 表单助手的核心价值不在于一次性填满所有输入框,关键是把建议变成可验证、可解释、可撤回的字段变更。只要把 dirty field、schemaVersion、acceptedFields 和 submit payload 分清楚,这类能力就能复用到配置台、审批台和运营工具里。
主要来源
MDN FormData: https://developer.mozilla.org/en-US/docs/Web/API/FormData
Zod Basics: https://zod.dev/basics
React Hook Form GitHub: https://github.com/react-hook-form/react-hook-form