# AI 合同平台 V2 数据库与代码重构决策 日期:2026-06-28 ## 结论 当前 V2 的总体方向是正确的:代码已经拆成合同平台、AI 中台、基础设施三块,文档和 compose 也已经把数据库目标收口为 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` 三库。 但当前落地状态还没有达到“最佳长期方案”的要求,主要问题不是功能是否能跑,而是环境权威性、数据库边界、代码模块边界和模型长期可维护性还不够清晰。继续新增业务功能前,应该先做一轮非破坏性的治理和重构准备。 本轮不建议删除任何数据库,也不建议继续临时新建数据库。下一步应该先确定唯一权威 V2 环境,再迁移、验证、归档临时库。 ## 已核验的当前状态 ### 文档目标状态 V2 数据库最终边界: | 数据库 | 归属 | 主要内容 | 连接变量 | | --- | --- | --- | --- | | `yuqei_contract` | `yuqei-contract-platform` | 合同、审批、附件元数据、审查任务业务结果、合同事件、模板/条款/规则管理 | `CONTRACT_API_DATABASE_URL` | | `yuqei_ai` | `yuqei-ai-platform` | 模型配置、Prompt、知识库、RAG、向量、AI Trace、质量评测、配置执行 | `AI_PLATFORM_DATABASE_URL`、`YUQEI_WORKER_DATABASE_URL` | | `yuqei_ops` | `yuqei-infra` | 发布记录、备份记录、运行审计、监控扩展预留 | 后续运维服务独立配置 | 这比 V1 的单库模型更合理。V1 中合同业务、AI、知识库、商业化、治理、发票、审批等全部堆在 `ai_contract_platform` 这类单体库里,不适合作为 V2 长期生产模型。 ### 远端 192.168.3.90 当前状态 只读检查结果显示: | 位置 | 数据库/环境 | 状态判断 | | --- | --- | --- | | 宿主机 PostgreSQL `5432` | `ai_contract_platform` | 旧版/历史单体库,47 张表,迁移头为 `20260619_0045`,有 `generated_contracts`,没有 V2 `contracts` | | 宿主机 PostgreSQL `5432` | `yuqei_contract` | 临时 V2 合同测试库,12 张表,迁移头为 `20260628_0017`,有 `contracts` 和 `legal_change_impact_scans` | | 宿主机 PostgreSQL `5432` | `yuqei_ai` | 不存在 | | 宿主机 PostgreSQL `5432` | `yuqei_ops` | 不存在 | | Docker smoke | `yuqei-contract-v2-smoke-*` | 容器和卷存在,但当前停止;Postgres 映射端口为 `15432`,卷为 `yuqei-contract-v2-smoke_postgres-data` | 因此不能把宿主机 `5432/yuqei_contract` 直接认定为完整 V2 数据库。它只是合同平台部分测试库,缺少 V2 目标中的 `yuqei_ai` 和 `yuqei_ops`。 ## 当前设计问题 ### 1. 数据库环境权威性不清 现在同时存在: - V1/旧单体库:`ai_contract_platform` - 临时 V2 合同测试库:`yuqei_contract` - 停止状态的 V2 Docker smoke 环境 风险是开发者不知道本地/测试/准生产应该连哪一个库,后续迁移可能打到错误环境。最危险的不是“多了一个库”,而是没有一个明确登记表说明每个库的身份、用途、负责人、迁移头和是否允许写入。 ### 2. 三库目标没有在宿主机 5432 上完整落地 宿主机只看到 `yuqei_contract`,没有 `yuqei_ai`、`yuqei_ops`。这说明如果当前本地后端连的是宿主机 5432,它只验证了合同 API 的一部分,没有验证 AI 中台和 worker 的真实 PostgreSQL 数据边界。 ### 3. 本地 Contract API 示例仍默认 SQLite `yuqei-contract-platform/services/contract-api/.env.example` 和 README 仍把 SQLite 放在默认示例里。SQLite 可以保留用于轻量单测,但对 V2 当前阶段来说,开发联调和验收应该默认指向 PostgreSQL,否则很容易出现“本地能跑,PostgreSQL 才暴露问题”的情况。 ### 4. 健康检查不足以证明数据库结构正确 当前健康接口更多检查配置和后端类型,不足以证明: - 连接的是不是预期数据库名。 - Alembic version 是否等于当前 head。 - 核心表是否存在。 - PostgreSQL 扩展 `pg_trgm`、`vector` 是否就绪。 这也是之前容易误判“后端已启动但模板/法律资产数据为空”的原因。 ### 5. 合同平台代码模块过大 当前核心文件规模: - `yuqei_contract_api/contracts.py`:约 7300 行。 - `yuqei_contract_api/main.py`:约 1500 行。 `contracts.py` 同时承载 Pydantic schema、SQLAlchemy model、内存仓储、SQLAlchemy 仓储、demo seed、模板生命周期、法律资产生命周期、文件、审批、审计、备份、权限、通知等多个领域。 这已经不适合继续叠功能。短期能跑,长期会让迁移、测试、审查和性能优化变慢。 ### 6. AI 平台仓储也过于集中 当前核心文件规模: - `yuqei_ai_platform_api/repository.py`:约 6100 行。 - `yuqei_ai_platform_api/main.py`:约 1200 行。 AI 平台已经有知识库、Prompt、Provider、AI Trace、质量闭环、worker runtime、pgvector 检索等能力,但仓储层仍集中在一个大文件里。继续扩展法规库、黄金样本、质量评测和运营后台时,应拆成独立领域模块。 ### 7. 部分数据库模型仍偏 MVP 合同库仍有一些不适合长期作为事实字段的列: - `status_label` - `status_tone` - `next_action` - `next_actions` 这些更适合由 API serializer/BFF/前端根据状态和角色推导。数据库应保存事实状态,例如 `lifecycle_status`、`review_status`、`approval_status`、`signing_status`、`archive_status`。 `review_tasks.risk_items`、`citations`、`primary_sources`、法律影响扫描 payload 等 JSON 字段可以作为快照,但高频筛选、统计、排序和权限判断字段应逐步结构化。 ### 8. 合同生命周期表还不完整 V2 已经补了模板、条款、规则、审查推荐、法律影响扫描等功能,但合同生命周期的长期模型还没有完全稳定: - 缺少正式 `contract_versions` 表承载正文版本。 - 审批仍主要依赖 timeline,缺少 `approval_instances`、`approval_steps`、`approval_actions`。 - 合同正文仍在 `contracts.body_content`,后续应迁到版本表或对象存储快照。 - 软删除、创建人、更新人、部门、组织等字段还没有在全部核心表统一。 ### 9. 安全与数据治理仍需硬化 需要继续补齐: - PostgreSQL RLS 或至少数据库层租户隔离策略。 - 合同库与 AI 库使用不同账号和最小权限。 - Provider/OCR/API key 入库加密或改由密钥服务托管。 - 审计事件 append-only 约束和篡改检测。 - AI Trace 脱敏、保留周期、归档策略。 ## 推荐的目标方案 ### 数据库权威方案 推荐将 V2 数据库环境分成三类,避免混用: | 环境 | 目的 | 推荐状态 | | --- | --- | --- | | 本地单测 | 快速单元测试 | 可继续 SQLite/fake repository,但只覆盖纯逻辑 | | 本地/远端联调 | Codex 浏览器和开发调试 | 必须 PostgreSQL,连接明确登记的 V2 dev/smoke 三库 | | 准生产 smoke | 发布前验收 | 使用 Docker smoke 环境或正式 staging PostgreSQL,必须同时存在 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` | 当前最稳妥的选择: 1. 先把 `yuqei-contract-v2-smoke` Docker 环境启动并只读核验其三库状态。 2. 如果 smoke 卷中三库和迁移历史完整,将它登记为当前 V2 准生产 smoke 权威环境。 3. 宿主机 `5432/yuqei_contract` 标记为“临时合同测试库”,不要继续作为权威环境扩展。 4. `ai_contract_platform` 标记为“V1/旧单体历史库”,只读保留,用于资产映射和行为对照。 5. 若后续决定不用 Docker smoke,而改用宿主机 5432 作为正式 V2 dev/staging,则必须一次性补齐 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` 三库和独立账号,再把 smoke 作为可重建环境。 ### 代码重构目标结构 Contract API 建议拆分为: ```text yuqei_contract_api/ api/ contracts.py files.py review_tasks.py templates.py legal_assets.py legal_fulltext.py approvals.py audit.py admin.py domain/ contracts.py review.py templates.py legal_assets.py approvals.py persistence/ models.py session.py repositories/ contracts.py files.py review_tasks.py templates.py legal_assets.py audit.py services/ contract_lifecycle.py template_lifecycle.py clause_recommendation.py legal_change_impact.py audit_integrity.py seed/ demo_data.py ``` AI Platform 建议拆分为: ```text yuqei_ai_platform_api/ api/ providers.py prompts.py knowledge.py ai_runs.py quality.py workers.py domain/ providers.py prompts.py knowledge.py ai_runs.py quality.py persistence/ models.py session.py repositories/ providers.py prompts.py knowledge.py ai_runs.py quality.py workers.py services/ retrieval.py trace.py quality_gate.py ingestion.py ``` 拆分原则: - API 层只负责路由、鉴权、参数和响应。 - service 层负责业务编排。 - repository 层只负责数据库读写。 - domain/schema 层不依赖 FastAPI。 - migration 只从 persistence models 或明确 migration 脚本演进,不从大杂烩文件隐式生成。 ## 重构执行顺序 ### Phase A:数据库环境治理 目标:先消除“连错库”的风险。 任务: 1. 新增 V2 数据库环境登记表,记录每个库的用途、连接入口、迁移头、是否权威、是否允许写入。 2. 新增只读检查脚本,能输出远端 DB 清单、表数量、Alembic head、核心表存在性。 3. 启动并核验 Docker smoke 环境,确认 `15432` 下是否存在 `yuqei_contract`、`yuqei_ai`、`yuqei_ops`。 4. 决定权威开发/准生产库。 5. 本地后端只连接权威 V2 PostgreSQL,不再用临时 SQLite 作为功能验收依据。 验收标准: - 文档中明确唯一 V2 dev/smoke 权威库。 - `ai_contract_platform` 标记为旧库,不再作为 V2 写入目标。 - 临时 `5432/yuqei_contract` 有归属说明,未确认前不继续扩展。 - 健康/检查脚本能显示当前连接数据库名和迁移头。 ### Phase B:运行时安全检查 目标:应用启动和健康检查能发现错误数据库。 任务: 1. Contract API 增加 `/api/v1/runtime/schema-check`。 2. AI Platform API 增加 `/api/v1/runtime/schema-check`。 3. 检查项包括数据库名、Alembic version、核心表、PostgreSQL 扩展。 4. staging/production 环境禁止 SQLite,禁止 auto create,禁止 demo seed。 验收标准: - 连接旧 `ai_contract_platform` 时 schema check 必须报错。 - 连接缺表或迁移头落后的库时 schema check 必须报错。 - Docker smoke 健康检查从“服务 alive”升级为“服务 alive + schema ready”。 ### Phase C:代码模块化拆分 目标:先拆结构,不改接口行为。 任务: 1. 将 `contracts.py` 中 SQLAlchemy model 移到 `persistence/models.py`。 2. 将 Contract API repository 按合同、文件、审查、模板、法律资产、审计拆分。 3. 将路由从 `main.py` 拆到 `api/*`,由 `create_app` 注册。 4. 将 AI Platform repository 按 Provider、Prompt、Knowledge、AI Run、Quality、Worker 拆分。 5. 保持现有 API path、响应结构和测试不变。 验收标准: - 拆分后功能测试全通过。 - 单文件不再继续承载多个领域。 - 新增功能只能落到对应领域模块,不再向大文件继续堆。 ### Phase D:数据库模型硬化 目标:把 MVP 表逐步收敛到生产模型。 任务: 1. 新增 `contract_versions`,合同正文版本化。 2. 新增正式审批模型:`approval_instances`、`approval_steps`、`approval_actions`。 3. 将 UI 展示字段从长期事实表中逐步迁出或转为派生字段。 4. 为核心表补齐 `tenant_id`、`created_by`、`updated_by`、`deleted_at`。 5. 将高频 JSON 查询字段结构化,JSON 只保留快照和扩展。 6. AI 库补齐 `tenant_id`、保留周期、归档策略和敏感字段加密策略。 验收标准: - 合同列表、审批待办、统一搜索、AI Trace、知识库检索不依赖 JSON 全表扫描。 - 合同正文修改有版本历史。 - 审批动作可追溯到步骤、人员、时间、结果。 - 数据库字段表达事实,不表达 UI 文案。 ### Phase E:V1 资产迁移策略 目标:吸收 V1 优秀资产,但不复制 V1 单体结构。 任务: 1. 模板、条款、规则、黄金样本、精选法律全文通过导入脚本迁入 V2 新模型。 2. 每类资产都保留 V1 source id、导入批次、版本、hash。 3. V1 表结构不直接搬入 V2。 4. V1 数据库只读保留,作为迁移源和行为对照。 验收标准: - V2 可独立从空库迁移到 head,再导入 V1 精选资产。 - 导入可重复执行,具备幂等性和差异报告。 - V1 与 V2 数据边界清楚,不出现一半沿用旧表、一半新表的混合状态。 ## 立即不做的事 - 不删除 `ai_contract_platform`。 - 不删除或覆盖 `5432/yuqei_contract`。 - 不继续新建第三个、第四个 V2 候选库。 - 不把 V1 的单体 schema 复制到 V2。 - 不在未确认权威库前继续向数据库写入新业务数据。 ## 下一步建议 优先执行 Phase A: 1. 写数据库环境登记表。 2. 写只读 DB 检查脚本。 3. 启动并检查 Docker smoke 数据库三库状态。 4. 决定权威 V2 dev/smoke 库。 这个阶段完成后,再开始代码模块化和 schema 硬化。这样重构不是边跑边猜,而是有清晰的数据库落点和验收门槛。