综合小项目:用 Python 构建可校验的 AI 文档变更通知草稿器
文档更新后,真正容易出错的不是把句子写得通顺,而是遗漏变更范围、把草稿误当成最终通知,或者让模型输出无法被程序检查。本文把前面学过的输入预检、结构化输出、结果校验、模型适配和人工审批组合成一个小项目:输入旧版与新版文档,生成一份可复核的通知草稿。示例只使用 Python 标准库和离线演示适配器,不需要密钥,也不伪造线上模型返回值。
先划定工具的边界
这个工具只做三件事:比较两版文本、请求模型生成通知草稿、检查草稿是否满足最低要求。它不直接发送邮件,不修改原文,也不自动宣布变更已经生效。发送动作必须留给后续人工审批或已有的发布系统。
把“生成”和“发布”拆开很重要。模型擅长把差异整理成自然语言,但它不能替我们确认变更是否经过审批。程序则适合检查字段是否齐全、通知是否提到变更主题,以及输入是否为空。两者各自做擅长的事,系统才容易测试。
用数据结构表达输入和输出
先用数据类定义边界。ChangeInput 保存比较所需的内容;NoticeDraft 是模型适配层交给业务层的结构化结果。这里的 audience 和 summary 都是字符串,方便示例保持最小;生产项目可以进一步换成枚举或更严格的模式。
1 | from dataclasses import dataclass |
requires_review 默认是 True,而不是让调用方记得主动打开审批。安全的默认值应当让草稿停留在待审核状态;如果以后增加自动发布能力,也要单独设计权限和审计记录。
先做确定性的输入检查
模型调用之前,先拒绝无法处理的输入。比较两版文档时,标题不能为空,新旧文本也不能同时为空。示例用字符数控制预算,它不是 Token 数量,只是低成本的第一道门。
1 | def validate_input(data: ChangeInput, max_chars: int = 8_000) -> None: |
输入校验失败时不要调用模型。这样既节省成本,也避免把明显无效的请求写入第三方服务日志。真实应用还应根据目标模型的 tokenizer 估算 Token,为系统提示词、差异内容和输出预留上下文空间。
生成一份稳定的变更摘要
为了让模型只关注差异,可以先计算按行的变化。difflib 不是语义比较器,但对配置、说明文档和 Markdown 等行结构清晰的文本已经足够演示。差异越小,提示词中的无关内容越少。
1 | from difflib import unified_diff |
接下来定义模型适配器。适配器的接口只接受输入并返回 NoticeDraft,业务流程不需要知道具体 SDK 的消息格式。下面的实现是离线演示器:它根据差异是否为空生成固定草稿,用来验证程序控制流,不代表真实模型效果。接入实际服务时,应在适配器内部读取环境变量中的密钥,并设置超时、错误处理和调用预算。
1 | def demo_model(data: ChangeInput, diff: str) -> NoticeDraft: |
如果换成真实模型,不要让模型直接返回一段自由文本再用脆弱的字符串切割。应要求结构化输出,并在应用侧再次解析和校验。模型输出永远是不可信输入,即使 SDK 声称提供了结构化格式,也不能省略业务规则检查。
校验并保留待审状态
校验函数只关心业务必需条件:主题、受众、摘要和行动建议不能是空白;通知必须明确是待复核草稿。校验失败就停止流程,而不是自动猜测缺失字段。
1 | def validate_draft(draft: NoticeDraft) -> None: |
把整个流程串起来,并输出机器可读的字典,便于命令行、任务队列或测试使用:
1 | def build_notice(data: ChangeInput) -> dict[str, object]: |
把代码保存为 document_notice.py 后运行 python document_notice.py,可以验证输入、差异、生成和校验四个步骤都能离线执行。打印出的内容是演示器明确构造的结果,不应被理解为真实模型调用结果。接入服务时只替换 demo_model,并保留其余边界。
常见问题
为什么不让模型直接发送通知? 因为发送是有外部影响的动作,可能涉及错误受众、未审批内容和重复发送。模型可以生成草稿,程序可以校验字段,但最终发送应由明确的审批状态和权限控制。
difflib 能判断语义变化吗? 不能。它主要识别文本行的增删改,适合提供候选差异,不等于理解业务影响。对关键文档,应让负责人确认影响范围,并保留旧版、新版和生成草稿的关联编号。
校验失败能否让模型自动修复? 可以在低风险场景设置有限次数的修复,但每次修复都要重新解析、校验并记录。达到次数上限就转人工,不要无限重试,也不要把缺失字段静默填成猜测内容。
日志应该记录什么? 可以记录请求编号、输入版本、耗时、校验状态和模型版本;不要默认记录完整文档或密钥。需要审计时保存受控的版本引用和脱敏后的摘要,并限制访问权限。
小结
这个小项目的重点不是生成一封漂亮通知,而是把 AI 放进一个可控的流程:先用确定性规则检查输入,再通过独立适配器生成结构化草稿,最后用业务校验和人工复核阻止不完整结果流向外部。离线演示器让核心逻辑无需网络即可测试;真实模型只承担语言整理工作,不能绕过预算、权限和发布边界。沿着这条思路继续扩展时,可以加入版本存储、幂等键、有限重试和回归样例,但每增加一个自动化动作,都应同时增加对应的校验和审计记录。