Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/00-模块当前状态与开发指南.md
HaHafeng fa72beea6c feat(platform): Complete Postgres-Only architecture refactoring (Phase 1-7)
Major Changes:
- Implement Platform-Only architecture pattern (unified task management)
- Add PostgresCacheAdapter for unified caching (platform_schema.app_cache)
- Add PgBossQueue for job queue management (platform_schema.job)
- Implement CheckpointService using job.data (generic for all modules)
- Add intelligent threshold-based dual-mode processing (THRESHOLD=50)
- Add task splitting mechanism (auto chunk size recommendation)
- Refactor ASL screening service with smart mode selection
- Refactor DC extraction service with smart mode selection
- Register workers for ASL and DC modules

Technical Highlights:
- All task management data stored in platform_schema.job.data (JSONB)
- Business tables remain clean (no task management fields)
- CheckpointService is generic (shared by all modules)
- Zero code duplication (DRY principle)
- Follows 3-layer architecture principle
- Zero additional cost (no Redis needed, save 8400 CNY/year)

Code Statistics:
- New code: ~1750 lines
- Modified code: ~500 lines
- Test code: ~1800 lines
- Documentation: ~3000 lines

Testing:
- Unit tests: 8/8 passed
- Integration tests: 2/2 passed
- Architecture validation: passed
- Linter errors: 0

Files:
- Platform layer: PostgresCacheAdapter, PgBossQueue, CheckpointService, utils
- ASL module: screeningService, screeningWorker
- DC module: ExtractionController, extractionWorker
- Tests: 11 test files
- Docs: Updated 4 key documents

Status: Phase 1-7 completed, Phase 8-9 pending
2025-12-13 16:10:04 +08:00

1305 lines
38 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.
# AI智能文献模块 - 当前状态与开发指南
> **文档版本:** v1.4
> **创建日期:** 2025-11-21
> **维护者:** AI智能文献开发团队
> **最后更新:** 2025-12-13 🏆 **Postgres-Only 架构改造完成**
> **重大进展:** Platform-Only 架构改造 - 智能双模式处理、任务拆分、断点续传
> **文档目的:** 反映模块真实状态,帮助新开发人员快速上手
---
## 📋 文档说明
本文档是AI智能文献ASL模块的**真实状态快照**,记录实际的代码结构、已实现功能、技术栈和开发规范。
**与其他文档的关系**
- **本文档00-模块当前状态)**What is真实状态
- **开发计划文档**What to do计划
- **开发记录文档**What done历史
- **技术设计文档**How to do设计
---
## 🎯 模块概述
### 核心功能
AI智能文献模块是一个基于大语言模型LLM的文献筛选系统用于帮助研究人员根据PICOS标准自动筛选文献。
### 当前状态
- **开发阶段**:🚧 标题摘要初筛MVP已完成全文复筛后端已完成待前端开发
- **已完成功能**
- ✅ 标题摘要初筛Title & Abstract Screening- 完整流程
- ✅ 全文复筛后端Day 2-5- LLM服务 + API + Excel导出
- **开发中功能**
- 🚧 全文复筛前端UIDay 6-8预计2.5天)
- **模型支持**DeepSeek-V3 + Qwen-Max 双模型筛选
- **部署状态**:✅ 本地开发环境运行正常
### 🏆 Postgres-Only 架构改造2025-12-13完成
**改造目标:**
- 支持2-24小时的长时间任务1000篇文献筛选
- 实例重启后任务可恢复(断点续传)
- 零额外成本(使用 Postgres不需要 Redis
**核心实现:**
1. **智能双模式处理** 🎯
- 阈值50篇文献
- 小任务(<50篇直接处理快速响应<1分钟
- 大任务≥50篇队列处理可靠性高支持断点续传
2. **任务拆分机制** 📦
- 100篇 → 2个批次每批50篇
- 1000篇 → 20个批次每批50篇
- 自动推荐批次大小
3. **断点续传机制** 🔄
- 每10篇文献保存一次断点
- 断点数据存储在 `platform_schema.job.data`pg-boss
- 实例重启后自动从上次位置继续
4. **Platform层统一管理** 🏗️
- 任务管理信息不存储在 `asl_schema.screening_tasks`
- 统一存储在 `platform_schema.job.data`JSONB
- 使用 `CheckpointService` 操作 job.data所有模块通用
**改造文件:**
- `screeningService.ts`:添加智能阈值判断,推送批次任务到 pg-boss
- `screeningWorker.ts`:批次处理逻辑,断点续传实现
- `CheckpointService.ts`:操作 job.data不依赖业务表
**测试验证:**
- ✅ 小任务7篇- 直接模式测试通过
- ✅ 大任务100篇- 队列模式测试通过
- ✅ 任务拆分逻辑验证通过
- ✅ Platform-Only 架构验证通过
**技术债务:**
- ⚠️ Phase 8 全面测试断点续传压力测试、1000篇文献完整流程
- ⚠️ Phase 9 SAE 部署验证
### 关键里程碑
**标题摘要初筛(已完成)**:
- ✅ 2025-11-18Prompt v1.0.0-MVP完成准确率60%
- ✅ 2025-11-18LLM集成与测试框架完成
- ✅ 2025-11-19前端MVP设置与启动、审核工作台完成
- ✅ 2025-11-21真实LLM集成完成替换Mock数据
- ✅ 2025-11-21用户体验优化进度显示、列表排序
- ✅ 2025-11-21**Week 4完成结果展示与导出功能**
- 统计概览与PRISMA排除分析
- 初筛结果页面(混合方案)
- Excel批量导出云原生
**全文复筛(后端已完成,待前端开发)**:
- ✅ 2025-11-22**Day 2-3完成LLM服务与验证系统**
- 提示词工程体系System/User Prompt + JSON Schema
- PromptBuilder服务动态Prompt组装
- LLM12FieldsServiceNougat优先 + 双模型 + 3层JSON解析
- 医学逻辑验证器5条规则
- 证据链验证器(引用完整性)
- 冲突检测服务(双模型对比)
- 集成测试与容错优化
- ✅ 2025-11-23**Day 4上午完成数据库设计与迁移**
- 数据库Schema设计云原生架构
- 修改 literatures 表(+13个全文字段
- 创建 fulltext_screening_tasks 表
- 创建 fulltext_screening_results 表
- 手动SQL迁移脚本安全执行不影响其他模块
- 数据库迁移状态文档详细记录Schema隔离情况
- ✅ 2025-11-23**Day 4下午完成批处理服务**
- FulltextScreeningService批量处理逻辑716行
- 异步任务管理后台处理LLM调用
- 并发控制p-queue
- 进度跟踪和错误处理
- ✅ 2025-11-23**Day 5完成后端API开发**
- FulltextScreeningController5个核心API652行
- ExcelExporter服务4-Sheet报告生成352行
- Zod参数验证
- 路由注册(/api/v1/asl/fulltext-screening
- 31个REST Client测试用例
- API文档更新到v3.0
- PDF提取fallback机制
- 🚧 2025-11-24**Day 6-8待开发前端UI**
- 4个核心页面设置、进度、工作台、结果
- PDF上传和预览功能
- 双模型判断对比UI
- 实时进度监控(轮询机制)
- 详细前端开发计划已制定
---
## 🏗️ 技术架构
### 技术栈
#### 前端
```
框架: React 18 + TypeScript 5
路由: React Router DOM v6
状态管理: @tanstack/react-query (React Query v5)
UI组件: Ant Design v5
样式: TailwindCSS v3
构建工具: Vite v5
```
#### 后端
```
框架: Fastify v4 (Node.js 22)
数据库: PostgreSQL 16 + Prisma 5
LLM SDK: 自研 LLMFactory (统一适配层)
模型: DeepSeek-V3, Qwen-Max, GPT-4o, Claude-4.5
日志: Winston
```
#### 基础设施
```
数据库: PostgreSQL 16 with Schema isolation
Schema: asl_schema (独立隔离)
用户表: platform_schema.users (共享)
```
---
## 📂 真实代码结构
### 前端代码结构
```
frontend-v2/src/modules/asl/
├── api/
│ └── index.ts # API客户端所有后端调用
├── components/
│ ├── ASLLayout.tsx # 左侧导航布局
│ ├── JudgmentBadge.tsx # PICOS判断Badge
│ ├── ConclusionTag.tsx # 结论Tag纳入/排除)
│ └── DetailReviewDrawer.tsx # 详情+复核统一Drawer
├── hooks/
│ ├── useScreeningTask.ts # 任务进度轮询Hook
│ └── useScreeningResults.ts # 筛选结果查询Hook
├── pages/
│ ├── TitleScreeningSettings.tsx # 设置与启动页面
│ ├── ScreeningWorkbench.tsx # 审核工作台页面
│ └── ScreeningResults.tsx # 初筛结果页面(占位)
├── types/
│ └── index.ts # TypeScript类型定义
├── utils/
│ ├── excelUtils.ts # Excel导入/导出工具
│ └── tableTransform.ts # 表格数据转换(双行)
└── index.tsx # 模块入口(路由配置)
```
### 后端代码结构
```
backend/src/modules/asl/
├── controllers/
│ ├── projectController.ts # 项目管理API
│ ├── literatureController.ts # 文献管理API
│ └── screeningController.ts # 筛选相关API标题摘要初筛
├── services/
│ ├── screeningService.ts # 筛选任务服务(核心)
│ └── llmScreeningService.ts # LLM调用服务标题摘要初筛
├── schemas/
│ └── screening.schema.ts # Prompt生成与JSON Schema标题摘要初筛
├── types/
│ └── index.ts # TypeScript类型定义
├── routes/
│ └── index.ts # 路由注册
├── common/ # ✅ 全文复筛通用能力层NEW
│ ├── pdf/ # PDF存储与提取
│ │ ├── types.ts
│ │ ├── PDFStorageService.ts
│ │ ├── PDFStorageFactory.ts
│ │ ├── adapters/
│ │ │ ├── DifyPDFStorageAdapter.ts
│ │ │ └── OSSPDFStorageAdapter.ts
│ │ └── __tests__/
│ ├── llm/ # LLM 12字段服务核心
│ │ ├── types.ts
│ │ ├── PromptBuilder.ts # 动态Prompt组装
│ │ ├── LLM12FieldsService.ts # Nougat+双模型+3层JSON解析
│ │ ├── index.ts
│ │ └── __tests__/
│ │ ├── integration-test.ts # 完整集成测试
│ │ ├── quick-test.ts # 快速测试1篇PDF
│ │ └── cached-result-test.ts # 容错验证测试
│ ├── validation/ # 验证服务
│ │ ├── MedicalLogicValidator.ts # 医学逻辑验证5条规则
│ │ ├── EvidenceChainValidator.ts # 证据链验证
│ │ ├── ConflictDetectionService.ts # 冲突检测
│ │ ├── index.ts
│ │ └── __tests__/
│ │ └── validation-test.ts
│ ├── utils/
│ │ └── tokenCalculator.ts # Token计算与成本估算
│ └── index.ts
└── fulltext-screening/ # ✅ 全文复筛模块NEW
├── controllers/
│ └── FulltextScreeningController.ts # 5个核心API652行
├── services/
│ ├── FulltextScreeningService.ts # 批处理服务716行
│ └── ExcelExporter.ts # Excel导出服务352行
├── routes/
│ └── fulltext-screening.ts # 路由注册73行
├── prompts/ # 提示词体系
│ ├── system_prompt.md # System Prompt6601字符
│ ├── user_prompt_template.md # User Prompt模板199行
│ ├── json_schema.json # JSON Schema12字段约束
│ └── cochrane_standards/ # Cochrane标准MVP暂不加载
│ ├── 随机化方法.md
│ ├── 盲法.md
│ └── 结果完整性.md
└── __tests__/ # 测试文件
├── fulltext-screening-api.http # REST Client测试31个用例
├── api-integration-test.ts # 自动化集成测试
├── e2e-real-test.ts # 端到端测试真实PDF
└── e2e-real-test-v2.ts # 端到端测试(简化版)
backend/prisma/
└── schema.prisma # 数据库Schema定义
backend/prompts/asl/screening/
├── v1.0.0-mvp.txt # 标准Prompt标题摘要初筛
├── v1.1.0-lenient.txt # 宽松模式
└── v1.1.0-strict.txt # 严格模式
backend/scripts/
└── test-llm-screening.ts # LLM测试脚本标题摘要初筛
```
---
## 🔌 API端点真实
### 基础URL
```
开发环境: http://localhost:3001/api/v1/asl
```
### 项目管理
```http
POST /projects #
GET /projects #
GET /projects/:projectId #
```
### 文献管理
```http
POST /literatures/import # JSON
POST /literatures/import/excel # Excel
GET /projects/:projectId/literatures #
DELETE /literatures/:literatureId #
```
### 筛选相关(标题摘要初筛)
```http
GET /projects/:projectId/screening-task #
GET /projects/:projectId/screening-results #
GET /screening-results/:resultId #
POST /screening-results/:resultId/review #
```
### 全文复筛NEW - Day 5
```http
POST /fulltext-screening/tasks #
GET /fulltext-screening/tasks/:taskId/progress #
GET /fulltext-screening/tasks/:taskId/results #
PUT /fulltext-screening/results/:resultId/decision #
GET /fulltext-screening/tasks/:taskId/export # Excel
```
### 关键参数说明
#### 创建项目
```typescript
{
projectName: string;
picoCriteria: {
P: string; // 人群
I: string; // 干预
C: string; // 对照
O: string; // 结局
S: string; // 研究设计
};
inclusionCriteria: string;
exclusionCriteria: string;
screeningConfig?: {
models: ['DeepSeek-V3', 'Qwen-Max'];
style: 'standard' | 'lenient' | 'strict';
};
}
```
#### 获取筛选结果
```
Query参数:
- page: 页码默认1
- pageSize: 每页数量默认50
- filter: all | conflict | included | excluded | reviewed
```
---
## 🗄️ 数据库结构(真实)
### Schema: asl_schema
#### 1. screening_projects筛选项目
```sql
: id (UUID)
: user_id platform_schema.users(id)
:
- project_name:
- pico_criteria: JSONB{P, I, C, O, S}
- inclusion_criteria: TEXT
- exclusion_criteria: TEXT
- screening_config: JSONB{models, style}
- status: 'draft' | 'screening' | 'completed'
: user_id, status
```
#### 2. literatures文献✨ 已扩展
```sql
: id (UUID)
: project_id screening_projects(id) CASCADE
:
- title: TEXT
- abstract: TEXT
- authors, journal, publication_year, pmid, doi
2025-11-23:
- stage: TEXTimported/title_screened/fulltext_pending/fulltext_screened
- has_pdf: BOOLEANPDF
- pdf_storage_type, pdf_storage_ref, pdf_status, pdf_uploaded_atPDF管理
- full_text_storage_type, full_text_storage_ref, full_text_url
- full_text_format, full_text_source, full_text_token_count
: project_id, pmid, doi, stage, has_pdf, pdf_status
: (project_id, pmid), (project_id, doi)
```
#### 3. screening_tasks标题摘要筛选任务
```sql
: id (UUID)
: project_id screening_projects(id) CASCADE
:
- status: 'pending' | 'running' | 'completed' | 'failed'
- total_items, processed_items, success_items, conflict_items
- started_at, completed_at
: project_id, status
```
#### 4. screening_results标题摘要筛选结果
```sql
: id (UUID)
:
- project_id screening_projects(id) CASCADE
- literature_id literatures(id) CASCADE
:
DeepSeek结果:
- ds_*_judgment: 'match' | 'partial' | 'mismatch'
- ds_*_evidence: TEXTP/I/C/S的证据
- ds_conclusion: 'include' | 'exclude' | 'uncertain'
- ds_confidence: FLOAT(0-1)
- ds_reason: TEXT
Qwen结果: qwen_*
:
- conflict_status: 'none' | 'conflict' | 'resolved'
- conflict_fields: JSONB
:
- final_decision: 'include' | 'exclude' | NULL
- final_decision_by: ID
- final_decision_at: TIMESTAMP
- exclusion_reason: TEXT
: project_id, literature_id, conflict_status, final_decision
: (project_id, literature_id)
```
#### 5. fulltext_screening_tasks全文复筛任务✨ 新建
```sql
: id (UUID)
: project_id screening_projects(id) CASCADE
:
- model_a, model_b: TEXT
- prompt_version: TEXTPrompt版本
- status: 'pending' | 'running' | 'completed' | 'failed'
- total_count, processed_count, success_count, failed_count, degraded_count
- total_tokens, total_cost:
- started_at, completed_at, estimated_end_at
- error_message, error_stack
: project_id, status, created_at
```
#### 6. fulltext_screening_results全文复筛结果✨ 新建
```sql
: id (UUID)
:
- task_id fulltext_screening_tasks(id) CASCADE
- project_id screening_projects(id) CASCADE
- literature_id literatures(id) CASCADE
:
Model A (DeepSeek-V3) :
- model_a_name, model_a_status, model_a_fields (JSONB)
- model_a_overall, model_a_processing_log, model_a_verification (JSONB)
- model_a_tokens, model_a_cost, model_a_error
Model B (Qwen-Max) : model_b_*
:
- medical_logic_issues (JSONB):
- evidence_chain_issues (JSONB):
:
- is_conflict, conflict_severity, conflict_fields, conflict_details (JSONB)
- review_priority (0-100), review_deadline
:
- final_decision: 'include' | 'exclude' | NULL
- final_decision_by, final_decision_at
- exclusion_reason, review_notes
:
- processing_status, is_degraded, degraded_model
:
- raw_output_a (JSONB), raw_output_b (JSONB), prompt_version
: task_id, project_id, literature_id, is_conflict, final_decision, review_priority
: (project_id, literature_id)
```
### 数据库Schema隔离状态
**✅ 完全正确**
- 所有ASL表都在 `asl_schema`
- 无数据泄漏到 `public` schema
- Schema隔离策略执行严格
- 详见:[数据库迁移状态说明](./05-开发记录/2025-11-23_数据库迁移状态说明.md)
---
## 📊 数据流程(真实)
### 标题摘要初筛流程
```
用户上传Excel
解析并导入到 literatures 表
创建 screening_task
后台异步处理:
- 双模型并行调用DeepSeek + Qwen
- 保存到 screening_results
- 冲突检测
- 更新任务进度
前端轮询任务状态
用户审阅结果,提交人工复核
导出Excel前端生成或后端OSS
```
### 全文复筛流程(设计中)
```
用户上传PDF批量
PDF提取服务Nougat优先PyMuPDF降级
更新 literatures 表(全文引用字段)
创建 fulltext_screening_task
后台异步批处理:
- 双模型并行调用DeepSeek + Qwen
- 12字段结构化提取
- 医学逻辑验证 + 证据链验证
- 冲突检测(字段级对比)
- 保存到 fulltext_screening_results
- 更新任务进度
前端展示结果(双视图审阅)
用户复核冲突项,提交最终决策
导出Excel12字段详细报告
- total_items: INT
- processed_items: INT
- success_items: INT
- conflict_items: INT
- failed_items: INT
- started_at, completed_at: TIMESTAMP
索引: project_id, status
```
---
## 🤖 LLM集成真实实现
### LLM调用流程
```
前端: 点击"开始AI初筛"
后端: literatureController.importLiteratures()
后端: screeningService.startScreeningTask()
后端: screeningService.processLiteraturesInBackground()
↓ (for each literature)
后端: llmScreeningService.dualModelScreening()
后端: LLMFactory.getAdapter(model).chat()
真实API: DeepSeek API / Qwen API
后端: JSON解析 + Schema验证
后端: 保存到 screening_results 表
后端: 更新 screening_tasks 进度
前端: useScreeningTask 轮询1秒/次)
前端: 显示进度条和结果
```
### 字段映射关系
#### PICOS字段
```typescript
// 前端/数据库格式
picoCriteria: { P, I, C, O, S }
// LLM服务兼容格式
picoCriteria: {
P || population,
I || intervention,
C || comparison,
O || outcome,
S || studyDesign
}
// 映射位置: screeningService.ts (Line 82-92)
```
#### 模型名称
```typescript
// 前端展示名 → API名称
const MODEL_NAME_MAP = {
'DeepSeek-V3': 'deepseek-chat',
'Qwen-Max': 'qwen-max',
'GPT-4o': 'gpt-4o',
'Claude-4.5': 'claude-sonnet-4.5',
};
// 映射位置: screeningService.ts (Line 97-110)
```
### LLM配置
#### 模型参数
```typescript
{
temperature: 0, // 固定,确保结果一致性
top_p: 1.0,
max_tokens: 2048,
}
```
#### Prompt版本
```
当前使用: v1.0.0-mvp.txt
位置: backend/prompts/asl/screening/v1.0.0-mvp.txt
准确率: 60%(首次测试)
一致率: 70-100%
```
#### 处理性能
```
单篇文献耗时: 10-20秒DeepSeek + Qwen并行
5篇文献: 约50-100秒
199篇文献: 约33-66分钟串行处理
进度更新: 每1条更新数据库
前端轮询: 1秒/次
```
---
## ✅ 已完成功能
### 1. 标题摘要初筛 - 设置与启动 ⭐
#### 功能清单
- ✅ PICOS标准录入P/I/C/O/S两栏布局
- ✅ 纳入/排除标准录入(侧边对称布局)
- ✅ Excel模板下载包含字段说明
- ✅ Excel文件上传
- ✅ Excel解析内存中支持中英文表头
- ✅ 文献去重DOI优先标题辅助
- ✅ 文献预览表格固定列宽Tooltip显示全文
- ✅ 启动AI初筛按钮
- ✅ 自动跳转到审核工作台
#### 关键代码
```typescript
// 文件: frontend-v2/src/modules/asl/pages/TitleScreeningSettings.tsx
// 核心功能: PICOS表单 + Excel上传 + 文献预览 + 提交
// Excel处理
import { downloadExcelTemplate, processExcelFile } from '../utils/excelUtils';
// API调用
const projectResponse = await aslApi.createProject({ ... });
const importResponse = await aslApi.importLiteratures({ ... });
navigate('/literature/screening/title/workbench', { state: { projectId } });
```
### 2. 标题摘要初筛 - 审核工作台 ⭐
#### 功能清单
- ✅ 任务进度显示轮询1秒/次)
- ✅ 进度条实时更新(平滑增长)
- ✅ 模型处理数量显示DeepSeek + Qwen
- ✅ 双行表格DeepSeek上行Qwen下行
- ✅ PICOS判断Badge匹配/部分/不匹配)
- ✅ 结论Tag纳入/排除/不确定)
- ✅ 冲突文献高亮(红色背景)
- ✅ 点击标题展开证据(双模型对比)
- ✅ 统一复核Drawer左侧详情+右侧复核)
- ✅ 人工复核提交
- ✅ 筛选Tab全部/冲突/已纳入/已排除/已复核)
- ✅ 分页后端分页20条/页)
#### 关键代码
```typescript
// 文件: frontend-v2/src/modules/asl/pages/ScreeningWorkbench.tsx
// 核心功能: 双行表格 + 进度轮询 + 展开行 + 复核Drawer
// 轮询进度
const { task, progress, isRunning } = useScreeningTask({ projectId, pollingInterval: 1000 });
// 查询结果
const { results } = useScreeningResults({ projectId, page, pageSize, filter });
// 双行转换
const tableData = transformToDoubleRows(results);
// 展开行
expandable={{
expandedRowRender: (record) => { /* 双模型证据对比 */ },
expandedRowKeys,
onExpandedRowsChange: (keys) => setExpandedRowKeys([...keys]),
}}
```
### 3. 后端LLM集成 ⭐
#### 功能清单
- ✅ 双模型并行筛选DeepSeek + Qwen
- ✅ JSON结构化输出带Schema验证
- ✅ 冲突检测(结论不一致)
- ✅ 串行处理避免API限流
- ✅ 进度实时更新每1条
- ✅ 错误处理与重试
- ✅ 字段映射PICOS, 模型名)
- ✅ 文献验证(标题+摘要必需)
- ✅ 详细日志输出
#### 关键代码
```typescript
// 文件: backend/src/modules/asl/services/screeningService.ts
// 核心功能: 任务管理 + 字段映射 + LLM调用
// 字段映射
const picoCriteria = {
P: rawPicoCriteria?.P || rawPicoCriteria?.population || '',
I: rawPicoCriteria?.I || rawPicoCriteria?.intervention || '',
// ... C, O, S
};
const MODEL_NAME_MAP = {
'DeepSeek-V3': 'deepseek-chat',
'Qwen-Max': 'qwen-max',
// ...
};
// LLM调用
const screeningResult = await llmScreeningService.dualModelScreening(
literature.id,
literature.title,
literature.abstract,
picoCriteria,
inclusionCriteria,
exclusionCriteria,
[models[0], models[1]],
screeningConfig?.style || 'standard'
);
```
### 4. LLM服务层 ⭐
#### 功能清单
- ✅ 统一LLM适配器LLMFactory
- ✅ 支持4个模型DeepSeek, Qwen, GPT, Claude
- ✅ Prompt生成基于模板
- ✅ JSON解析容错支持中文引号
- ✅ Schema验证AJV
- ✅ 双模型并行调用
- ✅ 批量筛选(并发控制)
#### 关键代码
```typescript
// 文件: backend/src/modules/asl/services/llmScreeningService.ts
// 核心功能: LLM调用 + JSON解析 + Schema验证
async dualModelScreening(...) {
const [result1, result2] = await Promise.all([
this.screenWithModel(model1, ...),
this.screenWithModel(model2, ...),
]);
// 冲突检测只检测conclusion
const hasConflict = result1.conclusion !== result2.conclusion;
// 最终决策
let finalDecision = hasConflict ? 'pending' : result1.conclusion;
return { deepseek: result1, qwen: result2, hasConflict, finalDecision };
}
```
### 5. 标题摘要初筛 - 初筛结果 ⭐ **Week 4 新增**
#### 功能清单
- ✅ 统计概览卡片(总数、已纳入、已排除、待复核)
- ✅ 待复核提示(当有冲突时显示)
- ✅ PRISMA排除原因统计柱状图展示
- ✅ 结果列表Tab全部/已纳入/已排除/待复核)
- ✅ 混合方案表格AI共识 + 人工最终决策)
- ✅ 点击标题展开详细判断(双模型证据对比)
- ✅ 批量选择与导出3种导出方式
- ✅ Excel导出前端生成云原生
#### 混合方案设计
**核心特点**
- 明确区分AI决策和人工决策
- 排除原因逻辑清晰(纳入不显示原因)
- 状态标签准确4种状态
- 无逻辑矛盾
**表格列设计**
| 列名 | 宽度 | 说明 |
|------|------|------|
| # | 50px | 序号 |
| 文献标题 | 300px | 可点击展开 |
| AI共识 | 100px | DS+QW是否一致 |
| 排除原因 | 140px | 智能显示 |
| 人工最终决策 | 120px | 标注推翻AI/与AI一致 |
| 状态 | 90px | 4种状态 |
| 操作 | 70px | 展开/收起 |
**总宽度**870px无需横向滚动
#### 关键代码
```typescript
// 文件: frontend-v2/src/modules/asl/pages/ScreeningResults.tsx
// 核心功能: 统计展示 + 混合方案表格 + Excel导出
// 统计数据获取(云原生:后端聚合)
const { data: statsData } = useQuery({
queryKey: ['projectStatistics', projectId],
queryFn: () => aslApi.getProjectStatistics(projectId),
});
// Excel导出云原生前端生成零文件落盘
exportScreeningResults(data.items, {
filter,
projectName: `项目${projectId.slice(0, 8)}`,
});
```
### 6. 统计API ⭐ **Week 4 新增**
#### 功能清单
- ✅ 后端聚合统计Prisma并行查询
- ✅ 统计总数、已纳入、已排除、待复核、冲突、已复核
- ✅ 分析排除原因从AI判断中提取
- ✅ 计算各类百分比
- ✅ 云原生:后端聚合,减少网络传输
#### 关键代码
```typescript
// 文件: backend/src/modules/asl/controllers/screeningController.ts
// 核心功能: 统计聚合 + 排除原因分析
// ⭐ 云原生使用Prisma聚合查询并行执行
const [total, included, excluded, pending, conflict, reviewed] =
await Promise.all([
prisma.aslScreeningResult.count({ where: { projectId } }),
prisma.aslScreeningResult.count({ where: { projectId, finalDecision: 'include' } }),
// ... 更多并行查询
]);
// 返回统计数据从MB级降到KB级
return {
total, included, excluded, pending, conflict, reviewed,
exclusionReasons,
includedRate, excludedRate, pendingRate,
};
```
---
## ⚠️ 已知问题与限制
### 1. 功能限制
- ⚠️ 仅实现标题摘要初筛(全文复筛未开发)
- ⚠️ 串行处理处理时间较长199篇约30-60分钟
- ⚠️ 无任务暂停/取消功能
- ⚠️ 无断点续传(中断后需重新开始)
- ⚠️ 准确率60%需要Prompt优化
### 2. 技术债务
- ⚠️ 浏览器警告:`setTimeout handler took >50ms`(性能优化)
- ⚠️ 前端轮询建议改为WebSocket
- ⚠️ 缺少单元测试E2E测试
- ⚠️ Excel后端导出优化当数据量>5000条时
### 3. 用户体验
- ⚠️ 无估计剩余时间
- ⚠️ 无当前处理文献标题显示
- ⚠️ 批量修改决策功能未实现
### 4. 生产环境未就绪
- ⚠️ 使用默认测试用户(无真实认证)
- ⚠️ 无消息队列(异步任务)
- ⚠️ 无错误重试机制
- ⚠️ 无成本控制API调用
- ⚠️ 无监控和告警
**详细技术债务清单**[技术债务清单](./06-技术债务/技术债务清单.md)
---
## 🚀 快速上手指南
### 环境要求
```
Node.js: v22.18.0+
PostgreSQL: 16+
npm: 10+
```
### 1. 初始化数据库
```bash
cd backend
npm install
npx prisma generate
npx prisma migrate dev
```
### 2. 配置环境变量
创建 `backend/.env`:
```bash
# 数据库
DATABASE_URL="postgresql://user:password@localhost:5432/dbname?schema=asl_schema"
# LLM API密钥
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxx
QWEN_API_KEY=sk-xxxxxxxxxxxxxx
# 可选
GPT_API_KEY=sk-xxxxxxxxxxxxxx
CLAUDE_API_KEY=sk-xxxxxxxxxxxxxx
```
### 3. 启动后端
```bash
cd backend
npm run dev
```
应该看到:
```
✅ Fastify server listening on http://0.0.0.0:3001
✅ Database connected
✅ ASL module routes registered at /api/v1/asl
```
### 4. 启动前端
```bash
cd frontend-v2
npm install
npm run dev
```
应该看到:
```
VITE v5.x.x ready in xxx ms
➜ Local: http://localhost:3000
```
### 5. 测试流程
1. 访问 `http://localhost:3001`
2. 点击顶部 **"AI智能文献"**
3. 自动跳转到 **"设置与启动"**
4. 填写PICOS标准复制测试数据
5. 下载Excel模板或使用现有
6. 上传Excel建议先测试5篇
7. 点击 **"开始AI初筛"**
8. 等待10-100秒取决于文献数
9. 查看 **"审核工作台"**
10. 点击标题展开查看证据
11. 点击"复核"提交人工决策
### 6. 查看后端日志
```
🚀 开始真实LLM筛选:
任务ID: xxx
文献数: 5
模型(映射后): [ 'deepseek-chat', 'qwen-max' ]
PICOS-P: 2型糖尿病患者...
✅ 文献 1/5 处理成功
DS: include / Qwen: exclude
冲突: 是
```
---
## 🧪 测试指南
### 1. LLM质量测试
```bash
cd backend
# 方式1: 使用测试脚本
npm run test:llm
# 方式2: 直接运行
npx ts-node scripts/test-llm-screening.ts
```
**测试数据**
- 位置:`backend/scripts/test-samples/asl-test-literatures.json`
- 数量10篇6篇应排除3篇应纳入1篇边界
- PICOSSGLT2抑制剂系统综述
**预期输出**
```
准确率: 60%
一致率: 70-100%
JSON验证率: 100%
平均耗时: 10-15秒/篇
```
### 2. API测试
```bash
# 创建项目
curl -X POST http://localhost:3001/api/v1/asl/projects \
-H "Content-Type: application/json" \
-d '{
"projectName": "测试项目",
"picoCriteria": {"P":"成人","I":"药物A","C":"安慰剂","O":"结局","S":"RCT"},
"inclusionCriteria": "英文",
"exclusionCriteria": "综述"
}'
# 获取项目列表
curl http://localhost:3001/api/v1/asl/projects
```
### 3. 前端E2E测试
**手动测试清单**
- [ ] PICOS表单提交
- [ ] Excel模板下载
- [ ] Excel文件上传正常
- [ ] Excel文件上传错误格式
- [ ] 文献预览显示
- [ ] 去重逻辑相同DOI
- [ ] 启动AI初筛
- [ ] 进度条更新
- [ ] 自动跳转
- [ ] 表格显示
- [ ] 列排序
- [ ] 筛选Tab切换
- [ ] 展开行
- [ ] 复核Drawer
- [ ] 提交复核
### 4. 数据库验证
```sql
-- 查看最新项目
SELECT * FROM asl_schema.screening_projects
ORDER BY created_at DESC LIMIT 1;
-- 查看筛选任务
SELECT * FROM asl_schema.screening_tasks
WHERE project_id = 'xxx';
-- 查看筛选结果
SELECT
id,
ds_conclusion,
qwen_conclusion,
conflict_status,
SUBSTRING(ds_p_evidence, 1, 50) as ds_evidence
FROM asl_schema.screening_results
WHERE project_id = 'xxx'
LIMIT 5;
```
---
## 📚 开发规范
### 1. 代码风格
#### TypeScript
```typescript
// 使用接口而非类型别名对外API
export interface ScreeningResult { ... }
// 严格类型检查
const picoCriteria: PicoCriteria = { ... };
// 使用可选链和空值合并
const models = config?.models ?? ['deepseek-chat', 'qwen-max'];
```
#### React
```typescript
// 使用函数组件
export function ScreeningWorkbench() { ... }
// 自定义Hook命名以use开头
export function useScreeningTask() { ... }
// Props接口命名以Props结尾
interface ScreeningWorkbenchProps { ... }
```
### 2. 命名约定
```
文件名: PascalCase (组件) 或 camelCase (工具)
✅ ScreeningWorkbench.tsx
✅ excelUtils.ts
组件名: PascalCase
✅ function DetailReviewDrawer()
变量/函数: camelCase
✅ const screeningResult = ...
✅ function processLiteratures()
常量: UPPER_SNAKE_CASE
✅ const MODEL_NAME_MAP = ...
类型/接口: PascalCase
✅ interface ScreeningResult
```
### 3. 注释规范
```typescript
/**
* 筛选任务轮询Hook
*
* @param projectId - 项目ID
* @param pollingInterval - 轮询间隔毫秒默认1000
* @returns 任务状态和进度信息
*/
export function useScreeningTask() { ... }
// 🔧 修复:字段名映射(前端格式 → LLM格式
const picoCriteria = { ... };
// ⚠️ 注意:双模型是并行处理
await Promise.all([...]);
```
### 4. 错误处理
```typescript
// 后端
try {
const result = await llmScreeningService.dualModelScreening(...);
} catch (error) {
logger.error('Failed to process literature', {
literatureId: literature.id,
error: error instanceof Error ? error.message : 'Unknown error',
stack: error instanceof Error ? error.stack : undefined,
});
// 输出到控制台
console.error('\n❌ 文献处理失败:', error);
}
// 前端
try {
await aslApi.createProject(...);
} catch (error) {
message.error(`操作失败: ${(error as Error).message}`);
}
```
### 5. Git提交规范
遵循 [Git提交规范](../../04-开发规范/06-Git提交规范.md)
```bash
feat: 添加审核工作台进度显示优化
fix: 修复列表显示顺序反向问题
refactor: 重构字段映射逻辑
docs: 更新模块状态文档
test: 添加LLM筛选质量测试
chore: 更新依赖版本
```
---
## 🔗 相关文档
### 核心文档
1. **本文档00-模块当前状态)**:模块真实状态快照
2. [数据库设计](./02-技术设计/01-数据库设计.md):数据表结构
3. [API设计规范](./02-技术设计/02-API设计规范.md):接口定义
4. [开发计划](./04-开发计划/03-任务分解.md):功能清单与计划
### 开发记录
**全文复筛**:
- [2025-11-22 Day2-Day3 LLM服务与验证系统开发](./05-开发记录/2025-11-22_Day2-Day3_LLM服务与验证系统开发.md) ⭐ **最新**
**标题摘要初筛**:
- [2025-11-21 真实LLM集成](./05-开发记录/2025-11-21-真实LLM集成完成报告.md)
- [2025-11-21 字段映射修复](./05-开发记录/2025-11-21-字段映射问题修复.md)
- [2025-11-21 用户体验优化](./05-开发记录/2025-11-21-用户体验优化.md)
- [2025-11-19 Week2-Day2完成](./05-开发记录/2025-11-19-Week2-Day2完成报告.md)
- [2025-11-18 Prompt设计与测试](./05-开发记录/2025-11-18-Prompt设计与测试完成报告.md)
### 测试文档
- [测试数据](./05-测试文档/03-测试数据/)PICOS示例、Excel模板
---
## 💡 开发建议
### 对新开发人员
1. **先了解业务**:阅读 [开发计划](./04-开发计划/02-标题摘要初筛开发计划.md)
2. **再看代码**:按照本文档的代码结构阅读
3. **动手测试**:跑一遍完整流程
4. **查看日志**:理解后端处理逻辑
5. **阅读Prompt**理解LLM如何工作
### 对AI助手
1. **优先阅读本文档**:了解真实状态
2. **参考开发记录**:了解历史问题和解决方案
3. **查看测试数据**:了解实际使用场景
4. **检查字段映射**:注意前后端格式差异
5. **理解限制**:不要承诺未实现的功能
### 常见陷阱
1.**PICOS格式混淆**前端用P/I/C/O/S不是population/intervention
2.**模型名称错误**前端用DeepSeek-V3API用deepseek-chat
3.**结果查询时机**:任务未完成时查询结果为空
4.**轮询间隔过长**:用户体验差
5.**文献缺少摘要**LLM调用会失败
---
## 📊 性能指标(实测)
### 处理速度
```
单篇文献: 10-20秒DeepSeek + Qwen并行
5篇文献: 50-100秒
20篇文献: 200-400秒3-7分钟
199篇文献: 2000-4000秒33-66分钟
```
### 准确率v1.0.0-MVP
```
准确率: 60%
一致率: 70-100%
JSON验证率: 100%
需人工复核率: 20-30%(冲突)
```
### 前端性能
```
轮询间隔: 1秒
数据更新延迟: <1秒
表格渲染: <100ms20条记录
Drawer打开: <50ms
```
### 数据库性能
```
项目创建: <50ms
文献导入199篇: <500ms
筛选结果查询(分页): <100ms
进度更新: <50ms
```
---
## 🎯 下一步开发计划
### 当前Sprint全文复筛MVP
1. 🚧 **全文复筛 Day 4**:批处理任务服务(进行中)
2.**全文复筛 Day 5**前端UI开发待开始
3.**全文复筛 Day 6**API集成与联调待开始
### 短期优化(标题摘要初筛)
1. ⏳ Prompt优化提升准确率到85%+
2. ⏳ 添加任务暂停/取消功能
3. ⏳ 实现并发处理3-5个并发
4. ⏳ 添加估计剩余时间显示
### 中期Month 2
1. 🚧 全文复筛功能(开发中)
2. ⏳ 全文数据提取功能
3. ⏳ 用户自定义边界情况
4. ⏳ WebSocket实时推送
### 长期Month 3+
1. ⏳ 多用户支持(真实认证)
2. ⏳ 消息队列Bull/RabbitMQ
3. ⏳ 分布式处理
4. ⏳ 成本控制和监控
---
**文档维护者**AI智能文献开发团队
**更新周期**:每个重要功能完成后更新
**反馈方式**提交Issue或Pull Request
---
**最后更新**2025-11-22全文复筛 Day 2-3完成
**文档状态**:✅ 反映真实状态
**下次更新时机**全文复筛MVP完成 或 标题摘要Prompt优化完成
**本次更新内容**v1.1
- ✅ 更新当前状态(新增全文复筛开发进度)
- ✅ 更新关键里程碑Day 2-3完成
- ✅ 新增后端代码结构common层 + fulltext-screening层
- ✅ 新增开发记录链接Day 2-3工作总结
- ✅ 更新下一步开发计划当前Sprint