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

38 KiB
Raw Blame History

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.datapg-boss
    • 实例重启后自动从上次位置继续
  4. Platform层统一管理 🏗️

    • 任务管理信息不存储在 asl_schema.screening_tasks
    • 统一存储在 platform_schema.job.dataJSONB
    • 使用 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-21Week 4完成结果展示与导出功能
    • 统计概览与PRISMA排除分析
    • 初筛结果页面(混合方案)
    • Excel批量导出云原生

全文复筛(后端已完成,待前端开发):

  • 2025-11-22Day 2-3完成LLM服务与验证系统
    • 提示词工程体系System/User Prompt + JSON Schema
    • PromptBuilder服务动态Prompt组装
    • LLM12FieldsServiceNougat优先 + 双模型 + 3层JSON解析
    • 医学逻辑验证器5条规则
    • 证据链验证器(引用完整性)
    • 冲突检测服务(双模型对比)
    • 集成测试与容错优化
  • 2025-11-23Day 4上午完成数据库设计与迁移
    • 数据库Schema设计云原生架构
    • 修改 literatures 表(+13个全文字段
    • 创建 fulltext_screening_tasks 表
    • 创建 fulltext_screening_results 表
    • 手动SQL迁移脚本安全执行不影响其他模块
    • 数据库迁移状态文档详细记录Schema隔离情况
  • 2025-11-23Day 4下午完成批处理服务
    • FulltextScreeningService批量处理逻辑716行
    • 异步任务管理后台处理LLM调用
    • 并发控制p-queue
    • 进度跟踪和错误处理
  • 2025-11-23Day 5完成后端API开发
    • FulltextScreeningController5个核心API652行
    • ExcelExporter服务4-Sheet报告生成352行
    • Zod参数验证
    • 路由注册(/api/v1/asl/fulltext-screening
    • 31个REST Client测试用例
    • API文档更新到v3.0
    • PDF提取fallback机制
  • 🚧 2025-11-24Day 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

项目管理

POST   /projects                     # 创建项目
GET    /projects                     # 获取项目列表
GET    /projects/:projectId          # 获取项目详情

文献管理

POST   /literatures/import           # 导入文献JSON格式
POST   /literatures/import/excel     # 导入Excel文献
GET    /projects/:projectId/literatures  # 获取文献列表
DELETE /literatures/:literatureId    # 删除文献

筛选相关(标题摘要初筛)

GET    /projects/:projectId/screening-task      # 获取任务进度
GET    /projects/:projectId/screening-results   # 获取筛选结果
GET    /screening-results/:resultId             # 获取结果详情
POST   /screening-results/:resultId/review      # 提交人工复核

全文复筛NEW - Day 5

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报告

关键参数说明

创建项目

{
  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筛选项目

主键: 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文献 已扩展

主键: id (UUID)
外键: project_id  screening_projects(id) CASCADE
标题摘要字段:
  - title: TEXT(必需)
  - abstract: TEXT(必需)
  - authors, journal, publication_year, pmid, doi
全文复筛字段(2025-11-23新增):
  - stage: TEXT(生命周期:imported/title_screened/fulltext_pending/fulltext_screened
  - has_pdf: BOOLEAN(是否有PDF
  - 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标题摘要筛选任务

主键: 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标题摘要筛选结果

主键: 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全文复筛任务 新建

主键: 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全文复筛结果 新建

主键: 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隔离策略执行严格
  • 详见:数据库迁移状态说明

📊 数据流程(真实)

标题摘要初筛流程

用户上传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字段

// 前端/数据库格式
picoCriteria: { P, I, C, O, S }

// LLM服务兼容格式
picoCriteria: { 
  P || population, 
  I || intervention, 
  C || comparison, 
  O || outcome, 
  S || studyDesign 
}

// 映射位置: screeningService.ts (Line 82-92)

模型名称

// 前端展示名 → 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配置

模型参数

{
  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初筛按钮
  • 自动跳转到审核工作台

关键代码

// 文件: 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条/页)

关键代码

// 文件: 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, 模型名)
  • 文献验证(标题+摘要必需)
  • 详细日志输出

关键代码

// 文件: 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
  • 双模型并行调用
  • 批量筛选(并发控制)

关键代码

// 文件: 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无需横向滚动

关键代码

// 文件: 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判断中提取
  • 计算各类百分比
  • 云原生:后端聚合,减少网络传输

关键代码

// 文件: 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调用
  • ⚠️ 无监控和告警

详细技术债务清单技术债务清单


🚀 快速上手指南

环境要求

Node.js: v22.18.0+
PostgreSQL: 16+
npm: 10+

1. 初始化数据库

cd backend
npm install
npx prisma generate
npx prisma migrate dev

2. 配置环境变量

创建 backend/.env:

# 数据库
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. 启动后端

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. 启动前端

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质量测试

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测试

# 创建项目
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. 数据库验证

-- 查看最新项目
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

// 使用接口而非类型别名对外API
export interface ScreeningResult { ... }

// 严格类型检查
const picoCriteria: PicoCriteria = { ... };

// 使用可选链和空值合并
const models = config?.models ?? ['deepseek-chat', 'qwen-max'];

React

// 使用函数组件
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. 注释规范

/**
 * 筛选任务轮询Hook
 * 
 * @param projectId - 项目ID
 * @param pollingInterval - 轮询间隔毫秒默认1000
 * @returns 任务状态和进度信息
 */
export function useScreeningTask() { ... }

// 🔧 修复:字段名映射(前端格式 → LLM格式
const picoCriteria = { ... };

// ⚠️ 注意:双模型是并行处理
await Promise.all([...]);

4. 错误处理

// 后端
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提交规范

feat: 添加审核工作台进度显示优化
fix: 修复列表显示顺序反向问题
refactor: 重构字段映射逻辑
docs: 更新模块状态文档
test: 添加LLM筛选质量测试
chore: 更新依赖版本

🔗 相关文档

核心文档

  1. 本文档00-模块当前状态):模块真实状态快照
  2. 数据库设计:数据表结构
  3. API设计规范:接口定义
  4. 开发计划:功能清单与计划

开发记录

全文复筛:

标题摘要初筛:

测试文档


💡 开发建议

对新开发人员

  1. 先了解业务:阅读 开发计划
  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 6API集成与联调待开始

短期优化(标题摘要初筛)

  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