Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/04-开发计划/08a-工具3-M1-骨架管线冲刺清单.md
HaHafeng dc6b292308 docs(asl): Complete Tool 3 extraction workbench V2.0 development plan (v1.5)
ASL Tool 3 Development Plan:
- Architecture blueprint v1.5 (6 rounds of architecture review, 13 red lines)
- M1/M2/M3 sprint checklists (Skeleton Pipeline / HITL Workbench / Dynamic Template Engine)
- Code patterns cookbook (9 chapters: Fan-out, Prompt engineering, ACL, SSE dual-track, etc.)
- Key patterns: Fan-out with Last Child Wins, Optimistic Locking, teamConcurrency throttling
- PKB ACL integration (anti-corruption layer), MinerU Cache-Aside, NOTIFY/LISTEN cross-pod SSE
- Data consistency snapshot for long-running extraction tasks

Platform capability:
- Add distributed Fan-out task pattern development guide (7 patterns + 10 anti-patterns)
- Add system-level async architecture risk analysis blueprint
- Add PDF table extraction engine design and usage guide (MinerU integration)
- Add table extraction source code (TableExtractionManager + MinerU engine)

Documentation updates:
- Update ASL module status with Tool 3 V2.0 plan readiness
- Update system status document (v6.2) with latest milestones
- Add V2.0 product requirements, prototypes, and data dictionary specs
- Add architecture review documents (4 rounds of review feedback)
- Add test PDF files for extraction validation

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-23 22:49:16 +08:00

172 lines
7.8 KiB
Markdown
Raw 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.
# M1骨架管线 — The Skeleton Pipeline
> **所属:** 工具 3 全文智能提取工作台 V2.0
> **架构总纲:** `08-工具3-全文智能提取工作台V2.0开发计划.md`
> **代码手册:** `08d-工具3-代码模式与技术规范.md`(所有代码模式均在此手册中,开发时按需查阅)
> **建议时间:** Week 15-6 天)
> **核心目标:** 证明 "PKB 拿数据 → Fan-out 分发 → LLM 盲提 → 数据落库 → 前端看到 completed" 这条管线是通的。
---
## Demo 形态
用户在前端点击按钮,系统后台静默跑完流程,前端 `useTaskStatus` 轮询到 `status = completed`,数据库能查到 JSON 提取结果。前端只需一个极简列表。
**关键妥协M1 不接 MinerU不做审核抽屉不做 SSE 日志流。**
---
## 任务清单
### M1-1Prisma 数据模型 + Migration + Seed1 天)
**做什么:**
- 新增 `AslExtractionTemplate``AslProjectTemplate``AslExtractionTask``AslExtractionResult` 四张表
- 运行 `npx prisma migrate dev --name add_extraction_template_engine`
- Seed 脚本注入 3 套系统内置模板RCT / Cohort / QC
**验收标准:**
- [ ] `npx prisma migrate deploy` 成功
- [ ] `npx prisma db seed` 后数据库有 3 套模板记录
- [ ] `AslExtractionTask``pkbKnowledgeBaseId` 字段
- [ ] `AslExtractionResult``snapshotStorageKey` + `snapshotFilename` 快照字段v1.5
- [ ] `AslExtractionResult``pkbDocumentId` 字段、`status``extracting` 状态值
> 📖 Schema 详情见架构总纲 Task 1.1
---
### M1-2模板 API + 提取任务 API — 仅基座模板1.5 天)
**做什么:**
- `TemplateController.ts`GET 模板列表、GET 模板详情、POST 克隆到项目
- `ExtractionController.ts`POST 创建任务、GET 任务状态(**React Query 轮询用**、GET 结果列表
- 创建任务时:锁定模板 → 批量创建 `AslExtractionResult`status=pending`pgBoss.send('asl_extraction_manager', { taskId })`
**不做什么:**
- 不做自定义字段 CRUD APIM3
- 不做 SSE 端点M2
- 不做 Excel 导出M2
**验收标准:**
- [ ] `POST /api/v1/asl/extraction/tasks` 能创建任务并入队
- [ ] `GET /api/v1/asl/extraction/tasks/:taskId` 返回 `status``successCount``totalCount`
- [ ] `GET /api/v1/asl/extraction/tasks/:taskId/results` 返回提取结果列表
> 📖 端点完整列表见架构总纲 Task 1.3 + Task 2.4
---
### M1-3PKB ACL 防腐层 + Fan-out 调度核心2 天)⚠️ 本里程碑最关键
**做什么(按顺序):**
**Step A — PKB 侧 ACL0.5 天):**
- `PkbExportService.ts`PKB 模块维护):`listKnowledgeBases()``listPdfDocuments()``getDocumentForExtraction()` 返回 DTO
- 通过依赖注入暴露给 ASL
**Step B — ASL 侧桥接0.5 天):**
- `PkbBridgeService.ts`:调用 `PkbExportService`,代理所有 PKB 数据访问
**Step C — Fan-out Manager + Child Worker1 天)⚠️ 核心战役:**
- `ExtractionManagerWorker.ts`:读取任务 → ⚠️ v1.5 批量快照 PKB 元数据(`snapshotStorageKey` + `snapshotFilename`)冻结到 `AslExtractionResult` → 为每篇文献 `pgBoss.send('asl_extraction_child', ...)` → 退出Fire-and-forget
- `ExtractionChildWorker.ts` 完整逻辑:
1. **乐观锁抢占**`updateMany({ where: { status: 'pending' }, data: { status: 'extracting' } })`
2. **纯文本降级提取**:从 PKB 读 `extractedText` + 写死 RCT Schema → 调用 DeepSeek
3. **原子递增**:事务内 `update Result + increment Task counts`
4. **Last Child Wins**`successCount + failedCount >= totalCount` → 翻转 `status = completed`
5. **错误分级路由**:致命错误 return / 临时错误 throw
**Worker 注册(遵守队列命名规范):**
```
jobQueue.work('asl_extraction_child', { teamConcurrency: 10 }, handler)
```
**M1 阶段简化:不注册 `asl_mineru_extract` 子队列M2 才接 MinerU**
**验收标准:**
- [ ] PkbExportService 能返回知识库列表和文档详情DTO
- [ ] Manager 派发后 `AslExtractionResult.snapshotStorageKey``snapshotFilename` 已填充v1.5 快照验证)
- [ ] 手动删除 PKB 文档记录后Child Worker 仍能通过 `snapshotStorageKey` 从 OSS 获取 PDFv1.5 一致性验证)
- [ ] Manager 能为 N 篇文献派发 N 个 Child Job
- [ ] Child Worker 乐观锁正确:并发重试不会双倍处理
- [ ] Child Worker 原子递增10 篇并发提取后 `successCount = 10`
- [ ] Last Child Wins最后一个 Child 翻转 Task status = completed
- [ ] 致命错误PKB 文档不存在)→ 该篇标 error + 不重试 + 不阻塞其他篇
- [ ] 临时错误429→ pg-boss 指数退避重试
> 📖 Fan-out 架构图、Worker 代码模式、研发红线见架构总纲 Task 2.3
> 📖 ACL 防腐层设计见架构总纲 Task 3.3b
---
### M1-4前端极简 Step 1 — 选模板 + 选 PKB 文献1 天)
**做什么:**
- `ExtractionSetup.tsx`:左栏模板下拉(只读,默认 RCT+ 右栏 PKB 知识库下拉 + 文献 Checkbox 列表
- `PkbKnowledgeBaseSelector.tsx`:调用 PKB API 加载知识库和文献
- 底部 "确认并开始提取" 按钮 → 调用 `POST /api/v1/asl/extraction/tasks`
**不做什么:**
- 不做自定义字段 UIM3
- 不做基座字段标签云展示M2 附带做)
**验收标准:**
- [ ] 能选择 PKB 知识库并展示 PDF 文档列表
- [ ] 能勾选文献并提交创建任务
- [ ] 空知识库时显示引导提示 + PKB 跳转链接
---
### M1-5前端极简 Step 2 + Step 3 — 轮询进度 + 极简列表1 天)
**做什么:**
- `ExtractionProgress.tsx``useTaskStatus` 轮询3s驱动进度条 + 检测 `completed` 跳转
- `ExtractionWorkbench.tsx`极简表格展示提取结果Study ID、状态
- `ExtractionPage.tsx`状态驱动路由pending→Step1 / processing→Step2 / completed→Step3
- 路由注册(前端 + 后端)
**不做什么:**
- 不做 SSE 日志终端M2
- 不做审核抽屉M2
- 不做 Excel 导出按钮M2
**验收标准:**
- [ ] 进度条从 0% 推进到 100%React Query 轮询驱动)
- [ ] `status = completed` 后自动跳转到 Step 3
- [ ] Step 3 能看到提取结果列表(状态列展示 completed/error
- [ ] 关闭浏览器重新打开 → 恢复到正确步骤(断点恢复)
---
## M1 研发红线(全员必须背诵)
| # | 红线 | 违反后果 |
|---|------|---------|
| 1 | 队列名用下划线(`asl_extraction_child`),禁止点号 | pg-boss 路由截断 |
| 2 | Child Worker 用 `updateMany` 乐观锁,禁止 `findUnique → if` | 并发穿透,算力翻倍 |
| 3 | Last Child Wins 终止器,成功和失败路径都要检查 | Task 永远卡在 processing |
| 4 | `teamConcurrency: 10`,禁止无限拉取 Child Job | Node.js OOM |
| 5 | Job Payload 仅传 ID< 200 bytes禁止塞 PDF 正文 | pg-boss 阻塞 |
| 6 | ACL 防腐层ASL 不 import PKB 内部类型 | 模块耦合蔓延 |
| 7 | Manager 必须快照 `snapshotStorageKey` + `snapshotFilename`Child 禁止运行时回查 PKB 获取 storageKeyv1.5 | 提取中 PKB 删文档 → 批量崩溃 |
---
## M1 结束时的状态
```
✅ Prisma 表 + 3 套 Seed 模板
✅ PKB ACL 防腐层 → PkbExportService + PkbBridgeService
✅ Fan-out 全链路Manager → N × Child → Last Child Wins → completed
✅ 乐观锁 + 原子递增 + 错误分级路由 — 所有并发 Bug 已验证
✅ 前端三步走:选模板/选文献 → 轮询进度 → 极简结果列表
❌ 无 MinerU纯文本降级
❌ 无 SSE 日志流
❌ 无审核抽屉
❌ 无自定义字段
❌ 无 Excel 导出
```
> **M1 的核心价值:** 所有分布式 Bug并发死锁、幂等穿透、终点丢失、背压 OOM在第一周就被逼出来。M2 加特性时地基是稳的。