# AI智能文献模块 - 当前状态与开发指南 > **文档版本:** v1.5 > **创建日期:** 2025-11-21 > **维护者:** AI智能文献开发团队 > **最后更新:** 2026-01-18 🆕 **智能文献检索(DeepSearch)MVP完成** > **重大进展:** unifuncs DeepSearch API 集成 - AI驱动的 PubMed 自动检索 > **文档目的:** 反映模块真实状态,帮助新开发人员快速上手 --- ## 📋 文档说明 本文档是AI智能文献(ASL)模块的**真实状态快照**,记录实际的代码结构、已实现功能、技术栈和开发规范。 **与其他文档的关系**: - **本文档(00-模块当前状态)**:What is(真实状态) - **开发计划文档**:What to do(计划) - **开发记录文档**:What done(历史) - **技术设计文档**:How to do(设计) --- ## 🎯 模块概述 ### 核心功能 AI智能文献模块是一个基于大语言模型(LLM)的文献筛选系统,用于帮助研究人员根据PICOS标准自动筛选文献。 ### 当前状态 - **开发阶段**:🚧 标题摘要初筛MVP已完成,全文复筛后端已完成,智能文献检索MVP已完成 - **已完成功能**: - ✅ 标题摘要初筛(Title & Abstract Screening)- 完整流程 - ✅ 全文复筛后端(Day 2-5)- LLM服务 + API + Excel导出 - ✅ **智能文献检索(DeepSearch)MVP** - unifuncs API 集成,SSE 实时流式 - **开发中功能**: - 🚧 全文复筛前端UI(Day 6-8,预计2.5天) - **模型支持**:DeepSeek-V3 + Qwen-Max 双模型筛选 + unifuncs DeepSearch - **部署状态**:✅ 本地开发环境运行正常 ### 🆕 智能文献检索 DeepSearch(2026-01-18 MVP完成) **功能概述:** - AI 驱动的自动化 PubMed 文献检索 - 自然语言输入研究问题,AI 自动生成检索策略 - 实时显示 AI 思考过程和检索进展 - 提取并展示 PubMed 文献链接 **技术实现:** - 集成 unifuncs DeepSearch API(OpenAI 兼容协议) - Server-Sent Events (SSE) 实时流式通信 - 数据库存储:`asl_schema.asl_research_tasks` **API 端点:** - `POST /api/v1/asl/research/stream` - SSE 流式检索 - `POST /api/v1/asl/research/tasks` - 异步任务创建(备用) - `GET /api/v1/asl/research/tasks/:taskId/status` - 任务状态查询 **前端入口:** - 路由:`/literature/research/search` - 菜单:AI智能文献 → 2. 智能文献检索 **已知限制:** - ⚠️ SSE 模式,离开页面任务中断 - ⚠️ 每次检索成本约 0.3 元(unifuncs API) - ⏳ 搜索历史、高级筛选等功能待开发 ### 🏆 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-18:Prompt v1.0.0-MVP完成,准确率60% - ✅ 2025-11-18:LLM集成与测试框架完成 - ✅ 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组装) - LLM12FieldsService(Nougat优先 + 双模型 + 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开发)** - FulltextScreeningController(5个核心API,652行) - 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个核心API(652行) ├── services/ │ ├── FulltextScreeningService.ts # 批处理服务(716行) │ └── ExcelExporter.ts # Excel导出服务(352行) ├── routes/ │ └── fulltext-screening.ts # 路由注册(73行) ├── prompts/ # 提示词体系 │ ├── system_prompt.md # System Prompt(6601字符) │ ├── user_prompt_template.md # User Prompt模板(199行) │ ├── json_schema.json # JSON Schema(12字段约束) │ └── 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: TEXT(生命周期:imported/title_screened/fulltext_pending/fulltext_screened) - has_pdf: BOOLEAN(是否有PDF) - pdf_storage_type, pdf_storage_ref, pdf_status, pdf_uploaded_at(PDF管理) - 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: TEXT(P/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: TEXT(Prompt版本) - 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 - 更新任务进度 ↓ 前端展示结果(双视图审阅) ↓ 用户复核冲突项,提交最终决策 ↓ 导出Excel(12字段详细报告) - 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篇边界) - PICOS:SGLT2抑制剂系统综述 **预期输出**: ``` 准确率: 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-V3,API用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秒 表格渲染: <100ms(20条记录) 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)