api-server/docs/architecture/adr-001-unified-ai-architecture.md
wangdl 54bc505f7a docs: add ADR-001 unified AI architecture decision record
Freeze the architecture decision for 8-batch unified AI migration.
Covers current/target topology, API/Worker process boundaries,
5 Processors, Heavy Runtime disposition, phase-1 non-goals,
rollback principles, and cross-batch constraints.

Includes Appendix A: worker dependency closure audit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 20:10:35 +08:00

170 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-001统一 AI 架构迁移决策
## 状态
已接受2026-06-19
## 背景
当前知习项目存在两套独立的 AI 分析系统,以及一套规则出题系统:
- **系统 ABullMQ + TypeScript运行中**:处理 active-recall 和 feynman-evaluation 分析,通过 `AiAnalysisWorker` 在 NestJS 进程内执行,写入 `AiAnalysisJob`/`AiAnalysisResult` 表,创建 `FocusItem`,发布 `ai.analysis.completed` 事件驱动 `ReviewCardSubscriber` 生成复习卡片。
- **系统 BRust + 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`