乐于分享
好东西不私藏

一个工程合同 AI 审查助手,是怎么从 0 搭到能演示、能导出的?

一个工程合同 AI 审查助手,是怎么从 0 搭到能演示、能导出的?

做 AI 项目,最容易出现的一种情况是:

想法很完整,规划很宏大,但系统始终停留在“差一点就能跑”的状态。

一开始想做审批流,想做多租户,想接大模型,想做知识库,想把页面做漂亮,想把权限体系一次性设计完整。结果到了最后,真正能给用户演示的,往往只有几张页面,或者几个还没真正串起来的接口。

这次做“工程合同 AI 审查助手”时,我们刻意反着来。

我们没有先追求最复杂的能力,而是先盯着一条最朴素、也最关键的链路:

登录 -> 上传 PDF 合同 -> 提取文本 -> 提取关键信息 -> 识别风险 -> 生成摘要 -> 导出报告

这篇文章,不讲空泛概念,只讲一件事:

我们是怎样把一个“工程合同 AI 审查助手”从 0 搭成一个真正能启动、能登录、能上传、能分析、能导出的 MVP。


一、为什么要做这个项目?

工程合同审查,本身就是一个高频、繁琐、又非常依赖经验的工作。

一份合同拿到手之后,商务经理、合约人员、法务、项目经理往往都要重点关注这些内容:

  • 合同基本信息是否完整
  • 合同编号、签订日期、金额、工期是否清晰
  • 付款条款是否合理
  • 结算条款是否存在风险
  • 违约责任是否对等
  • 质保金条款是否过重
  • 发票和税务要求是否合理
  • 争议解决条款是否存在明显倾向
  • 变更签证、解除条款是否缺失

问题在于,这类工作并不是每次都必须完全从零开始人工通读。

很多时候,业务真正需要的是一个“第一轮预审助手”:

  • 先把 PDF 文本提出来
  • 先把基础信息整理出来
  • 先把明显风险点标出来
  • 先生成一版审查摘要
  • 再由人工做进一步判断和复核

所以,这个项目从一开始就没有把自己定义成“替代法务”的系统,而是明确定位为:

一个面向工程行业的合同 AI 预审助手。


二、为什么我们没有一开始就做“大而全”?

做业务 AI 项目时,一个很常见的问题就是:

什么都想做,结果什么都还没真正跑通。

比如一开始就把这些都放进范围:

  • 审批流
  • 多租户
  • 权限矩阵
  • 电子签
  • OCR
  • 大模型问答
  • 法规知识库
  • 模板中心
  • 完整财务结算联动

这些方向当然都很有价值,但如果一开始全部纳入,项目很容易进入一种状态:

需求看起来很完整,系统却始终没有形成一个真正的闭环。

所以这次我们从第一天就给自己定了一个非常明确的原则:

先做 MVP,只做最小可用版。

具体来说,就是坚持下面这些规则:

  • 先把链路跑通,不做复杂审批流
  • 所有实现优先保证“能跑通、可维护、易理解”
  • 不过度设计
  • 后端逻辑必须分层
  • 前端页面必须拆组件
  • 每个阶段都必须有验证方法
  • 如果验证失败,先修复,再进入下一阶段

这套原则看起来很普通,但它决定了整个项目不会跑偏。

因为它逼着我们不断回答一个问题:

这一阶段做完之后,用户到底能不能真实地往前走一步?


三、我们是怎么拆里程碑的?

为了避免一边做一边散,我们没有“想到哪做哪”,而是按里程碑推进。

整个项目被拆成了 6 个阶段:

Milestone 1:项目骨架

Milestone 2:数据库与认证

Milestone 3:合同上传与文本提取

Milestone 4:合同信息提取与风险识别

Milestone 5:前端联调

Milestone 6:报告导出与交付收尾

这个拆法的核心意义在于:

每个阶段都只解决当前最关键的问题。

而且每完成一个阶段,都必须回答清楚四件事:

  • 启动命令是什么
  • 测试命令是什么
  • 怎么验证
  • 失败时怎么排查

这样做的结果就是,项目不会在某个阶段堆一大堆“看起来快做完”的功能,而是始终保持每一步都有真实结果。


四、Milestone 1:先把项目“站起来”

第一阶段我们没有急着做业务功能,而是先搭项目骨架。

这一阶段完成的事情包括:

  • 创建前后端目录结构
  • 创建 Docker 基础文件
  • 创建 README 初稿
  • 后端增加 /health 健康检查接口
  • 前端增加一个最基础的首页占位页

很多人会觉得这一步“没业务价值”。

但实际上,任何项目如果骨架没搭好,后面都会越来越乱。

因为没有骨架,就会出现这些问题:

  • 前后端目录边界混乱
  • 启动方式不统一
  • 新人接手困难
  • 验证路径不明确
  • 甚至连系统“是不是活着”都不好判断

所以第一阶段真正的目标不是“做功能”,而是:

让整个项目先站起来。

当后端能启动、GET /health 返回 200、前端能打开时,这个项目才算真正有了继续开发的基础。


五、Milestone 2:让它成为一个“真系统”

第二阶段,我们开始把这个项目从“有页面、有接口的骨架”推进成一个“有真实用户体系的系统”。

这一阶段完成了:

  • PostgreSQL 连接配置
  • SQLAlchemy 模型基础
  • Alembic 数据库迁移
  • users 表
  • JWT 登录
  • 默认管理员初始化

这一步为什么必须尽早做?

因为后面所有能力都依赖数据库:

  • 合同记录
  • 文件元数据
  • 文本提取结果
  • 风险项
  • 审查报告
  • 用户和鉴权

同时,登录又是整个系统的基本入口。

我们不想做一个“前端看起来有登录,实际上后端并没有真正用户体系”的演示壳子,所以这一阶段我们坚持把登录做成真的:

  • 数据库里有真实用户
  • 后端真做账号密码校验
  • 后端真签发 JWT
  • /auth/me
     可以获取当前用户信息

同时,为了让整个系统更容易启动和演示,我们固定了默认管理员账号:

  • 用户名:admin
  • 密码:Admin123456

这一步完成后,系统第一次真正具备了“业务系统”的基础形态。


六、Milestone 3:让合同文件真正进入系统

第三阶段开始进入合同业务本身。

这一阶段我们解决的是:

一份 PDF 合同,怎么才能真正进入系统,并成为后续分析可用的数据。

这里看起来只是“上传”,但实际上做了四件关键事。

1. 只允许上传 PDF

系统明确限制:非 PDF 一律拒绝。

这件事看似简单,但其实非常重要。

因为如果输入不受控,后面所有解析、提取、识别都会变得脆弱。

所以我们要求:

  • 非 PDF 必须拒绝
  • 上传失败必须返回明确报错

2. 文件真实落盘

上传成功之后,文件会保存到 uploads 目录,而不是只是经过一次接口处理。

这样,合同就真正进入了系统的文件存储。

3. 文件元数据入库

我们把文件名、路径、大小、类型等信息写进数据库,确保后面:

  • 可以追踪
  • 可以查询
  • 可以导出
  • 可以审计

4. 提取 PDF 原始文本

这是这一阶段最关键的地方。

因为后面无论是字段提取、风险识别还是摘要生成,本质上都依赖一件事:

先拿到可分析的合同文本。

所以我们把 PDF 中提取出的原始文本保存到 contract_parse_results 表中。

到这里,合同就从“一个上传成功的文件”正式变成了“一个可分析对象”。


七、Milestone 4:让系统具备“合同审查能力”

如果说前面 3 个阶段主要解决的是:

  • 项目能不能启动
  • 用户能不能登录
  • 合同能不能进入系统

那么第四阶段解决的就是:

系统到底能分析出什么。

这一阶段,我们重点完成了三块能力:

1. 合同基础信息提取

至少提取这些字段:

  • 合同名称
  • 合同编号
  • 项目名称
  • 甲方
  • 乙方
  • 合同类型
  • 签订日期
  • 合同金额
  • 工期
  • 付款条款
  • 质保期
  • 争议解决
  • 违约责任

2. 风险识别

至少覆盖这 10 类风险:

  • 付款条款风险
  • 结算条款风险
  • 工期责任风险
  • 违约责任不对等
  • 质保金风险
  • 发票税务风险
  • 争议解决风险
  • 工作范围不清
  • 变更签证条款缺失
  • 合同解除条款风险

3. 审查摘要

系统根据提取结果和风险结果,输出一版总体审查结论和风险等级。

这里我们特别强调了一条架构原则:

service 层必须独立,不要把规则写死在路由里。

因为如果把规则直接塞进路由,后面一定会遇到这些问题:

  • 路由越来越胖
  • 测试越来越难写
  • 逻辑难复用
  • 将来接真实大模型时不好替换

所以我们把提取、风险识别、摘要生成都拆成独立 service。

另外,考虑到当前版本还没有接入真实 LLM,我们采用的是:

规则版 + mock fallback

也就是说:

  • 先用规则跑通字段提取和风险识别
  • 如果部分字段不完整,用 fallback 做兜底
  • 保证整条分析流程始终能跑完

这一步很务实,也很关键。

因为对于 MVP 来说,最重要的不是“一开始就最聪明”,而是:

先保证整个流程可跑通。


八、Milestone 5:把前后端真正打通

后端能力基本完整之后,第五阶段开始做真正的前后端联调。

这一阶段完成了:

  • 登录页
  • 合同列表页
  • 合同上传页
  • 合同详情页
  • 风险展示区
  • 审查摘要展示
  • 前后端打通

这一步最重要的一条原则是:

如果接口字段不一致,优先统一接口,不要前端硬拼。

这一点非常关键。

因为很多项目联调时,为了让页面先显示出来,前端会开始:

  • 自己猜字段
  • 到处兼容结构
  • 每个页面都写一套映射逻辑

短期看起来快,长期一定会非常痛苦。

所以我们的做法是:

  • 先统一后端返回结构
  • 再让前端按统一模型接数据
  • 页面尽量保持清晰简单

在视觉上,这一阶段也坚持“实用优先”,没有刻意追求复杂风格,而是使用:

  • Vue 3
  • Vite
  • Element Plus
  • Pinia
  • Axios

这套组合非常适合快速搭建后台型业务系统。

到这一阶段完成时,用户第一次可以真正走完一条完整页面链路:

登录 -> 列表 -> 上传 -> 详情 -> 分析 -> 查看结果

这也是一个 MVP 是否成立的关键标志。


九、Milestone 6:把“能开发”变成“能交付”

很多项目做到前后端打通就结束了,但真正交付时最难的往往是最后一步。

因为真正的使用者关心的是:

  • 系统怎么启动
  • 登录账号是什么
  • 上传后怎么演示
  • 结果怎么导出
  • 我不懂代码,能不能按文档跑起来

所以第六阶段我们重点完成了三件事。

1. 审查报告导出

分析结果不能只停留在页面里,还要能输出成文件。

所以我们补了:

  • 导出接口
  • 导出按钮
  • 报告记录表
  • 导出文件保存

当前版本先导出 Markdown 报告。

为什么是 Markdown?

因为在 MVP 阶段,它有几个非常明显的好处:

  • 简单
  • 稳定
  • 易验证
  • 易扩展

也就是说,我们先解决“导得出来”,再去追求“导得更漂亮”。

2. Docker Compose 完整化

我们不满足于“理论上能启动”,而是希望用户可以尽量做到:

一条命令拉起前端、后端和数据库。

所以我们完整补齐了 Docker Compose,并让后端容器启动时自动执行:

  • 数据库迁移
  • 管理员初始化

这样项目的最短启动方式就变成了:

docker compose up --build

3. README 和部署文档收尾

这一阶段,我们重写了 README 和部署文档。

并且要求非常明确:

README 必须让不懂代码的人也能看懂。

这意味着文档里不能只是堆技术术语,而是要真正告诉使用者:

  • 第一步做什么
  • 第二步做什么
  • 登录账号是什么
  • 怎么验证系统正常
  • 怎么完成一次完整演示
  • 失败时怎么排查

到这里,项目才真正具备了“交付属性”。


十、交付前,我们还专门做了一轮检查

在所有里程碑都完成之后,我们没有直接宣布结束,而是又做了一轮“交付前检查”。

这一步非常必要。

因为很多问题在开发阶段不明显,但在交付阶段会变成明显风险。

最后我们补掉了两个非常关键的问题:

1. 合同相关接口统一加 JWT 鉴权

避免出现“前端看起来需要登录,后端合同接口却实际不校验身份”的问题。

2. 重写 API 文档

把 docs/api-spec.md 同步成当前真实接口、真实测试账号和真实请求方式,避免文档和代码脱节。

这轮检查让项目从“功能完成”真正走向“可以放心交付”。


十一、这版系统现在是什么状态?

如果用一句话概括当前这个项目,我会说:

它已经不是一个概念验证,而是一个完整流程已跑通的工程合同 AI 审查 MVP。

它已经具备:

  • 真正登录
  • 真正上传
  • 真正存文件
  • 真正提取文本
  • 真正做字段提取
  • 真正做风险识别
  • 真正生成摘要
  • 真正导出报告
  • 真正支持 Docker 一键启动
  • 真正有可用的 README 和部署文档

当然,它也很清楚自己的边界:

  • 当前还是规则版,不是真实 LLM 版
  • 扫描件 PDF 支持还不够强
  • 导出目前是 Markdown,不是正式模板报告
  • 更适合演示、试运行和 MVP 验收

但这恰恰说明它是一个健康的 MVP:

能跑通,也知道下一步该往哪走。


十二、如果继续往下做,最值得优先增强什么?

如果这个项目继续迭代,我认为最值得优先投入的是这几件事:

1. 接入真实大模型

把当前规则版字段提取和风险识别逐步升级为“LLM 优先 + 规则兜底”。

2. 增强 OCR

支持扫描件 PDF,让系统适用面更广。

3. 升级导出能力

从 Markdown 升级到正式 Word / PDF 模板版报告。

4. 增强合同台账能力

补筛选、搜索、状态管理、分页等后台常见能力。

换句话说:

当前版本已经把主体搭起来了,下一阶段要做的是智能增强和交付增强。


十三、这次项目最值得复用的方法论

如果让我把整个过程浓缩成一句话,我会说:

做 AI 项目,最重要的不是先把能力想得多复杂,而是先把真实流程跑通。

这次“工程合同 AI 审查助手”的搭建过程,本质上验证了一件很重要的事:

  • 不需要一开始就最复杂
  • 不需要一开始就最智能
  • 不需要一开始就最漂亮

你只需要先做到一件事:

让用户真的能从头到尾走完一遍完整流程。

只有这样,后面的大模型、OCR、模板导出、知识库、审批流,才真正有落脚点。


结尾

如果你也在做 AI 业务系统,我真心建议你把目标先从“做一个完美平台”改成:

先做一个别人能启动、能登录、能上传、能看到结果、能导出的系统。

这看起来不宏大,但非常有力量。

因为只有当一个系统真的能跑通,后面的所有增强才有意义。

而这次“工程合同 AI 审查助手”的搭建过程,最想证明的也正是这一点:

先做能跑通的最小闭环,再做更聪明的增强版。