# ADR-001:统一 AI 架构迁移决策 ## 状态 已接受(2026-06-19) ## 背景 当前知习项目存在两套独立的 AI 分析系统,以及一套规则出题系统: - **系统 A(BullMQ + TypeScript,运行中)**:处理 active-recall 和 feynman-evaluation 分析,通过 `AiAnalysisWorker` 在 NestJS 进程内执行,写入 `AiAnalysisJob`/`AiAnalysisResult` 表,创建 `FocusItem`,发布 `ai.analysis.completed` 事件驱动 `ReviewCardSubscriber` 生成复习卡片。 - **系统 B(Rust + HTTP 轮询,闲置)**:`zhixi-heavy-runtime` 独立进程,支持 5 种分析类型(learning_state_analysis、weak_point_analysis、next_action_planning、quiz_generation、flashcard_generation),通过轮询 `AiRuntimeJob` 表获取任务,调用 DeepSeek API,结果写入多个相互独立的领域表。 - **系统 C(规则出题,运行中)**:`QuizService.create()` 通过纯文本拼接生成测验题目,不调用任何 AI 模型。 系统 B 存在以下关键问题: 1. **无任务生产者** — 唯一创建 `AiRuntimeJob` 的入口 `POST /ai/jobs` 无人调用 2. **Snapshot 结构不兼容** — Rust 端 `LearningAnalysisSnapshot` 结构体与 API 端 `SnapshotBuilderService` 产出的 JSON 结构完全不匹配 3. **Rust 无重计算** — 所有 Pipeline 的独有业务逻辑总和不足 50 行,实际是一个 HTTP 代理层 4. **数据断层** — Rust 结果写入的表(`AiLearningAnalysis`、`WeakPointCandidate`、`NextActionRecommendation`)无 iOS/Admin 消费端 同时,当前 API 进程内注册 BullMQ Processor 的部署拓扑存在以下问题: - API 进程与 Worker 进程边界模糊,Docker 与生产环境配置不一致 - `AppModule` 中同时注册 `AiAnalysisWorker`、`DocumentImportWorker`、`NotificationWorker` - `WorkerModule` 和 `worker.main.ts` 已存在但未独立使用 ## 决策 采用 **8 批次渐进式迁移**,将 AI 分析能力从 BullMQ + Rust 双系统统一到单一 BullMQ + TypeScript 架构。 ### 目标架构拓扑 ``` ┌─────────────┐ │ iOS App │ └──────┬──────┘ │ HTTP ┌──────▼──────┐ │ zhixi-api │ NestJS (仅 Controller + Queue Producer) │ :3000 │ 不注册任何 @Processor() └──────┬──────┘ │ Redis (BullMQ) ┌──────▼──────┐ │ zhixi-worker│ NestJS (仅 @Processor()) │ (无端口) │ AiAnalysisWorker + DocumentImportWorker └──────┬──────┘ + NotificationWorker + AuditLogProcessor │ HTTP + FileCleanupProcessor ┌──────▼──────┐ │ DeepSeek │ │ API │ └──────────────┘ ``` ### API Process 职责 - 暴露所有 HTTP Controller - 注入 Queue Producer(`QueueService.add()`) - 不注册任何 `@Processor()` 或 `WorkerHost` - 不启动 BullMQ Worker 实例 ### Worker Process 职责 - 注册所有 `@Processor()` 和 `WorkerHost` - 消费 BullMQ 队列 - 调用 AI Workflow → DeepSeek API - 写入分析结果表 - 发布领域事件 - 不暴露 HTTP 端口 ### Heavy Runtime 当前处置 - 第一阶段保持部署但不修改 - 不停止 Rust 进程 - 不删除 `AiRuntimeJob` 及相关表 - M-AI-08 正式退场 ## 迁移批次 | 批次 | 名称 | 范围 | |------|------|------| | M-AI-01 | Worker 进程边界与部署收口 | 拆分 API/Worker 进程,不改变业务 | | M-AI-02 | 统一 AiJob 数据库 Expand | 扩展 `AiAnalysisJob`,新增 Artifact/Snapshot/Outbox | | M-AI-03 | 统一 Job Engine、Registry 与 Outbox | AiJobService + Registry + 双队列 | | M-AI-04 | Active Recall 端到端迁移 | 切换生产者,iOS 展示真实结果 | | M-AI-05 | Feynman 与 ReviewCard 可靠链路 | Outbox 替代进程内 EventEmitter | | M-AI-06 | AI Quiz 端到端迁移 | 迁移 Rust Prompt/Schema,异步生成 | | M-AI-07 | 后台学习分析与推荐闭环 | learning_state/weak_point/next_action | | M-AI-08 | Heavy Runtime 退场与 Legacy Contract | 停止 Rust,归档表 | ## 第一阶段非目标(M-AI-01) 1. 不修改 `AiAnalysisJob` / `AiRuntimeJob` 表结构 2. 不新建统一 AiJob 模型 3. 不迁移 Active Recall、Feynman 或 Quiz 业务链路 4. 不停止 `zhixi-heavy-runtime` 服务 5. 不修改 iOS 代码 6. 不删除任何数据库表 7. 不修改 AI Prompt、模型或业务结果结构 8. 不新增 Prisma Migration ## 架构约束 以下约束在所有批次中持续生效: 1. `AppModule` 不允许注册 `@Processor()` 或 `WorkerHost` 2. `WorkerModule` 不允许暴露公开 HTTP Controller 3. 不允许新建第三套 AI Job 模型(除 M-AI-02 统一扩展外) 4. 不允许顺带修改 Prompt、模型选择或业务结果 Schema(各自独立 Issue) 5. 没有 iOS/Admin 消费者的任务类型不得启用自动生成 6. 自动触发必须有频率限制、幂等保护、成本上限 ## 回滚原则 每个 Issue 必须提供独立回滚方案: 1. 代码层面:回滚提交或 revert PR 2. 数据库:本批次不涉及 Schema 变更,无需数据回滚 3. 部署:恢复旧 AppModule Processor 注册,停止独立 Worker service 4. 队列:验证无双重消费 ## 现有 Processor 清单 | Processor | 队列 | 文件 | |-----------|------|------| | `AiAnalysisWorker` | `ai-analysis` | `workers/ai-analysis.worker.ts` | | `DocumentImportWorker` | `document-import` | `workers/document-import.worker.ts` | | `NotificationWorker` | `notification` | `workers/notification.worker.ts` | | `AuditLogProcessor` | `audit-logs` | `modules/admin-audit-log/audit-log.processor.ts` | | `FileCleanupProcessor` | `file-cleanup` | `modules/files/file-cleanup.processor.ts` | ## 模块依赖图(当前) ``` AppModule ├── WorkerModule (已存在但未独立使用) │ ├── AiAnalysisWorker │ ├── DocumentImportWorker │ └── NotificationWorker ├── QueueModule │ ├── BullModule.forRootAsync (Redis 连接) │ └── BullModule.registerQueue (6 个队列) ├── AiAnalysisModule │ ├── AiAnalysisController (HTTP 端点) │ └── AiAnalysisService (BullMQ Producer) ├── ActiveRecallModule │ └── ActiveRecallService (BullMQ Producer 调用者) ├── ReviewModule │ ├── ReviewController (HTTP 端点) │ ├── ReviewCardSubscriber (监听 ai.analysis.completed) │ └── ReviewService ├── AiRuntimeModule │ ├── UserAiController (HTTP 端点) │ └── RuntimeInternalController (Rust 内部端点) ├── AdminAuditLogModule │ └── AuditLogProcessor (@Processor) └── FilesModule └── FileCleanupProcessor (@Processor) ``` ## 后续 Issue 引用 后续 M-AI-01 Issue 必须引用本文档(ADR-001)作为架构约束依据。 ## 证据 - 当前部署:`docker-compose.yml:1-70` — API 和 Worker 共享同一 NestJS 实例 - Worker 模块:`worker.module.ts:1-20` — 已定义但未独立使用 - Worker 入口:`worker.main.ts:1-10` — 已存在但未被 Docker/生产独立调用 - 现有架构文档:`docs/ai-runtime-architecture.md` — 描述 Rust Heavy Runtime 架构 - BullMQ 版本:`bullmq@5.77.1`、`@nestjs/bullmq@11.0.4`