# AI智能文献模块 - 当前状态与开发指南 > **文档版本:** v2.3 > **创建日期:** 2025-11-21 > **维护者:** AI智能文献开发团队 > **最后更新:** 2026-02-26 🆕 **工具 4 SR 图表生成器 + 工具 5 Meta 分析引擎开发完成!** > **重大进展:** > - 🆕 2026-02-26:**工具 4 + 工具 5 开发完成!** PRISMA 流程图(中英切换)+ 基线特征表 + Meta 分析引擎(HR/二分类/连续型 + 森林图/漏斗图)+ R Docker meta 包集成 + E2E 36/36 通过 > - 2026-02-25:**工具 3 M1+M2 开发完成!** 散装派发+Aggregator 全链路、MinerU 集成、XML Prompt 隔离、fuzzyQuoteMatch 溯源、HITL 审核抽屉、Excel 导出、数据归一化修复 > - 2026-02-24:工具 3 V2.0 架构升级!Fan-out → 散装派发 + Aggregator 轮询收口,通用模式指南 v1.1 沉淀 > - 2026-02-23:V2.0 核心功能完成!SSE 流式架构 + 段落化思考日志 + 引用链接可见化 > - 2026-02-22:V2.0 前后端联调完成!瀑布流 UI + Markdown 渲染 + Word 导出 + 中文数据源测试 > - 2026-01-18:智能文献检索(DeepSearch)MVP完成 - unifuncs API 集成 > **文档目的:** 反映模块真实状态,帮助新开发人员快速上手 --- ## 📋 文档说明 本文档是AI智能文献(ASL)模块的**真实状态快照**,记录实际的代码结构、已实现功能、技术栈和开发规范。 **与其他文档的关系**: - **本文档(00-模块当前状态)**:What is(真实状态) - **开发计划文档**:What to do(计划) - **开发记录文档**:What done(历史) - **技术设计文档**:How to do(设计) --- ## 🎯 模块概述 ### 核心功能 AI智能文献模块是一个基于大语言模型(LLM)的文献筛选系统,用于帮助研究人员根据PICOS标准自动筛选文献。 ### 当前状态 - **开发阶段**:🎉 工具 3 M1+M2 + 工具 4 + 工具 5 开发完成 - **已完成功能**: - ✅ 标题摘要初筛(Title & Abstract Screening)- 完整流程 - ✅ 全文复筛后端(Day 2-5)- LLM服务 + API + Excel导出 - ✅ **智能文献检索(DeepSearch)V1.x MVP** - unifuncs API 集成 - ✅ **Unifuncs API 网站覆盖测试** - 18 站点实测,9 个一级可用 - ✅ **🎉 Deep Research V2.0 核心功能** — SSE 流式架构 + 瀑布流 UI + HITL + Word 导出 - ✅ **工具 3 M1 骨架管线** — 散装派发+Aggregator 全链路、PKB ACL 防腐层、DeepSeek-V3 纯文本盲提、3 步极简前端 - ✅ **工具 3 M2 HITL 工作台** — MinerU VLM 表格集成、XML Prompt 隔离、fuzzyQuoteMatch 溯源、SSE 实时日志、审核抽屉、Excel 宽表导出 - ✅ **🆕 工具 4 SR 图表生成器** — PRISMA 2020 流程图(中英切换)+ 基线特征表 + 双通道数据源(项目流水线/Excel 上传)+ SVG/PNG 导出 - ✅ **🆕 工具 5 Meta 分析引擎** — HR/二分类/连续型 3 种数据类型 + 随机/固定效应模型 + 森林图+漏斗图 + R Docker meta 包集成 + E2E 36/36 通过 - **待开发**: - 📋 **工具 3 M3 动态模板引擎** — 自定义字段 CRUD、Prompt 注入防护、E2E 测试 - **V2.0 已完成**: - ✅ **SSE 流式架构**:从 create_task/query_task 轮询改为 OpenAI Compatible SSE 流,实时推送 AI 思考过程 - ✅ **LLM 需求扩写**:DeepSeek-V3 将粗略输入扩写为结构化检索指令书(PICOS + MeSH) - ✅ **HITL 策略确认**:用户可编辑、保存、确认 AI 生成的检索指令 - ✅ **瀑布流 UI**:Landing → 配置 → HITL → Agent 终端 → 结果,已完成步骤折叠为摘要卡片 - ✅ **段落化思考日志**:reasoning_content 按段落聚合,连续思考合并为一段(非逐行碎片) - ✅ **Markdown 渲染**:react-markdown + remark-gfm 正确渲染报告中的标题、链接、列表 - ✅ **引用链接可见化**:报告中 `[6]` 引用后显示完整 URL,方便复制分享 - ✅ **Word 导出**:Pandoc 微服务,文献标题内嵌超链接,引用展开为可见 URL - ✅ **中文数据源支持**:CNKI/中华医学期刊网动态 prompt 增强 + 专项测试验证 - ✅ **5 个精选数据源**:PubMed(默认)、ClinicalTrials.gov、Cochrane Library、CNKI、中华医学期刊网 - **模型支持**:DeepSeek-V3(需求扩写) + unifuncs s2(深度搜索,SSE 流式) + Qwen-Max(筛选) - **部署状态**:✅ 本地开发环境运行正常 ### 🎉 Deep Research V2.0(2026-02-23 核心功能完成) **V2.0 架构与功能:** | 层级 | 组件 | 说明 | 状态 | |------|------|------|------| | 前端 | 瀑布流页面 | Landing→配置→HITL→终端→结果,折叠式摘要 | ✅ | | 前端 | react-markdown | 综合报告 Markdown 正确渲染 + 引用链接可见化 | ✅ | | 后端 | SSE 流式客户端 | OpenAI Compatible SSE,实时推送 reasoning_content | ✅ | | 后端 | 段落化解析器 | 连续思考行合并为段落,搜索/阅读/分析独立成条 | ✅ | | 后端 | 需求扩写服务 | DeepSeek-V3 PICOS+MeSH 结构化扩写 | ✅ | | 后端 | Word 导出 | Pandoc 微服务,内嵌超链接 + 引用展开 | ✅ | | 后端 | pg-boss 队列 | 异步任务,离开页面不中断 | ✅ | | 数据库 | 6 个新字段 | targetSources/confirmedRequirement/aiIntentSummary/executionLogs/synthesisReport/resultList | ✅ | **V2.0 核心技术决策:** 1. **SSE 流式替代轮询**:从 create_task/query_task 轮询改为 OpenAI Compatible SSE 流。解决了"等很久才一股脑显示思考过程"的体验问题,reasoning_content 实时推送、每 2 秒刷写 DB。 2. **段落化思考日志**:reasoning_content 按 `\n\n` 段落拆分,同段落内连续思考行用空格合并为一条,搜索/阅读/分析动作独立。Worker 每 200+ 字符批量解析,写入前再合并连续同类条目。 3. **引用链接可见化**:Web 端通过 react-markdown 自定义 `` 组件在链接后追加灰色 URL;Word 端通过 `expandReferenceLinks()` 将 `[[N]](url)` 展开为 `[N](url) (url)`。 4. **中文数据源策略**:纯中文源(CNKI/中华医学期刊网)单独搜索效果好;混合中英文源时 PubMed 主导,建议分批搜索。 **V2.0 选定数据源(5 个精选):** | 数据源 | 类型 | 默认选中 | 说明 | |--------|------|----------|------| | PubMed | 英文 | ✅ | 核心数据源,效果最佳 | | ClinicalTrials.gov | 英文 | - | 临床试验注册库 | | Cochrane Library | 英文 | - | 系统综述金标准 | | 中国知网 CNKI | 中文 | - | 中文核心期刊 | | 中华医学期刊网 | 中文 | - | 中华医学会官方期刊 | **V2.0 API 端点:** ```http POST /api/v1/asl/deep-research/generate-requirement # LLM 需求扩写 POST /api/v1/asl/deep-research/tasks # 创建任务(pg-boss) GET /api/v1/asl/deep-research/tasks/:taskId # 查询任务状态+日志+结果 GET /api/v1/asl/deep-research/tasks/:taskId/export-word # Word 导出 ``` **V2.0 关键文件:** ``` backend/src/modules/asl/ ├── services/unifuncsSseClient.ts # SSE 流式客户端(AsyncGenerator) ├── services/requirementExpansionService.ts # LLM 需求扩写 ├── services/wordExportService.ts # Word 导出(Pandoc + 引用展开) ├── workers/deepResearchV2Worker.ts # SSE Worker(段落解析 + 2s 刷写) ├── utils/reasoningParser.ts # 段落化解析器 + mergeConsecutiveThinking ├── utils/resultParser.ts # content 解析(报告 + JSON 文献列表) ├── controllers/deepResearchController.ts # 4 个 API 端点 ├── config/dataSources.ts # 5 个精选数据源配置 └── __tests__/ ├── deep-research-v2-e2e.ts # 端到端测试 ├── deep-research-v2-smoke.ts # 冒烟测试 └── deep-research-chinese-sources.ts # 中文数据源专项测试 frontend-v2/src/modules/asl/ ├── pages/DeepResearchPage.tsx # 瀑布流主页面(phase 0-4) ├── components/deep-research/ │ ├── LandingView.tsx # 搜索入口 │ ├── SetupPanel.tsx # 数据源+过滤器配置(可折叠) │ ├── StrategyConfirm.tsx # HITL 策略确认(可折叠) │ ├── AgentTerminal.tsx # 暗色终端日志展示 │ └── ResultsView.tsx # Markdown 报告 + 文献表格 + Word 导出 ├── hooks/useDeepResearchTask.ts # React Query 轮询 Hook ├── types/deepResearch.ts # TypeScript 类型 └── api/index.ts # 4 个 V2.0 API 函数 ``` **开发计划**:详见 `04-开发计划/07-Deep Research V2.0 开发计划.md` **通用能力指南**:`docs/02-通用能力层/04-DeepResearch引擎/01-Unifuncs DeepSearch API 使用指南.md` ### 🆕 工具 3 全文智能提取工作台 V2.0(2026-02-25 M1+M2 开发完成) **功能定位:** 批量读取 PDF 全文 → 动态模板驱动 AI 结构化提取 → 人工 HITL 审核 → Excel 导出。是 ASL 证据整合 V2.0 三大工具中最复杂的一个。 **开发状态:** ✅ M1 骨架管线完成 ✅ M2 HITL 工作台完成 📋 M3 动态模板引擎待启动 **v2.0 架构转型(2026-02-24):** | 维度 | v1.5 Fan-out(已废弃) | v2.0 散装派发(当前) | |------|---------|---------| | 派发 | Manager Job → N × Child Job | API 层直接 `insert` N 个独立 Job | | Worker | Child Worker 修改父 Task 表(行锁争用) | Worker 只写自己的 Result(零行锁) | | 收口 | Last Child Wins(最后一个翻转 Task) | Aggregator 定时 `groupBy` 轮询收口 | | 僵尸清理 | 独立 Sweeper Cron | Aggregator 兼职(一人两职) | | 复杂度 | 13 条红线、18 项反模式 | **9 条红线,极简 Worker** | **核心架构决策:** | 决策 | 方案 | |------|------| | 异步任务 | **散装派发 + Aggregator 轮询收口**(API 直接派发 N 个 `asl_extract_single` Job) | | 并发控制 | `teamConcurrency: 10` 扁平单队列(Worker 内串行调 MinerU + LLM) | | API 幂等 | `idempotencyKey @unique` + Prisma P2002 冲突捕获 | | Worker 幂等 | `updateMany({ where: { status: 'pending' } })` 幽灵重试守卫 | | 任务收口 | **Aggregator** 定时轮询 `groupBy`(`pending === 0 && extracting === 0` → completed) | | 僵尸清理 | Aggregator 兼职(`extracting > 30min` → error) | | PDF 文件来源 | 对接 PKB 个人知识库(ACL 防腐层,非自建上传) | | 表格提取 | MinerU Cloud API(VLM 模型) + OSS Clean Data 缓存 | | 全文提取 | 直接复用 PKB `extractedText`(pymupdf4llm 产物) | | 进度查询 | 前端 React Query 轮询 + 后端 `groupBy` 实时聚合 Result 状态 | | SSE 日志 | 本 Pod 内存事件(可选增强:NOTIFY/LISTEN 跨 Pod) | | Prompt 安全 | BEGIN/END 隔离 + XML 标签上下文污染防护 | | 数据一致性 | API 层快照 PKB 元数据到 `AslExtractionResult` | **文档体系(5 + 2 份):** | 文档 | 说明 | |------|------| | `08-工具3-全文智能提取工作台V2.0开发计划.md` | 架构总纲(v2.0) | | `08a-工具3-M1-骨架管线冲刺清单.md` | M1 Sprint(Week 1,5-6 天) | | `08b-工具3-M2-HITL工作台冲刺清单.md` | M2 Sprint(Week 2-3,8-9 天) | | `08c-工具3-M3-动态模板引擎冲刺清单.md` | M3 Sprint(Week 4,5-6 天) | | `08d-工具3-代码模式与技术规范.md` | 代码 Cookbook(9 章) | | `散装派发与轮询收口任务模式指南.md` | 🚀 **v2.0 核心参考**(通用能力层 Level 2) | | `分布式Fan-out任务模式开发指南.md` | 历史参考(Level 3,已不用于本模块) | **里程碑规划:** | 里程碑 | 核心交付 | 时间 | 状态 | |--------|---------|------|------| | M1 骨架管线 | 散装派发 + Aggregator 全链路 + PKB ACL + 纯文本盲提 + 极简前端 | Week 1 | ✅ 完成 | | M2 HITL 工作台 | MinerU + XML Prompt 隔离 + fuzzyQuoteMatch + SSE 日志 + 审核抽屉 + Excel 导出 | Week 2-3 | ✅ 完成 | | M3 动态模板引擎 | 自定义字段 + Prompt 注入防护 + E2E 测试 | Week 4 | 📋 待启动 | **M1+M2 已完成的核心代码组件:** | 组件 | 文件 | 说明 | |------|------|------| | 散装派发 API | `ExtractionService.ts` | API 层直接 insert N 个独立 Job | | 单文档 Worker | `ExtractionSingleWorker.ts` | PdfPipeline → DynamicPrompt → LLM → Validator | | Aggregator 轮询 | `ExtractionAggregator.ts` | 定时 groupBy 收口 + 僵尸清理 | | PKB 防腐层 | `PkbBridgeService.ts` → `PkbExportService.ts` | ACL 解耦,DTO 传输 | | PDF 管线 | `PdfProcessingPipeline.ts` | MinerU VLM 表格 + PKB extractedText fallback | | XML Prompt | `DynamicPromptBuilder.ts` | 扁平 JSON 输出模板 + HIGH_FIDELITY_TABLES 优先 | | Quote 溯源 | `ExtractionValidator.ts` | fuzzyQuoteMatch 三档置信度 | | SSE 事件 | `ExtractionEventBus.ts` | 内存事件总线 + 历史回放 | | Excel 导出 | `ExtractionExcelExporter.ts` | flattenModuleData 归一化 + 双行表头宽表 | | 模板服务 | `TemplateService.ts` | 3 套系统模板(RCT/Cohort/QC) | | 审核抽屉 | `ExtractionDrawer.tsx` | Schema-driven 动态字段渲染 | | 审核工作台 | `ExtractionWorkbench.tsx` | 全宽表格 + 700px Drawer | **M2 关键修复记录(2026-02-25):** - 🔧 DynamicPromptBuilder:LLM 返回数组格式 → 重写 Prompt 明确要求扁平 key-value 格式 - 🔧 ExcelExporter:新增 `flattenModuleData` 归一化,兼容 `[{key,value,quote}]` 数组格式 - 🔧 ExtractionDrawer:从硬编码字段改为 schema-driven 动态渲染 - 🔧 ExtractionValidator:兼容数组格式 quote 验证 - 🔧 SSE 路由:Fastify 插件封装隔离,SSE 端点绕过 authenticate - 🔧 LLM JSON 清洗:sanitize 非法控制字符防止 JSON.parse 崩溃 **9 条研发红线**:详见架构总纲文档 M1 红线表。 **通用能力沉淀**: - 🚀 `docs/02-通用能力层/散装派发与轮询收口任务模式指南.md`(v1.1,Level 2 Cookbook) - 📖 `docs/02-通用能力层/分布式Fan-out任务模式开发指南.md`(v1.2,Level 3 参考) **工具 3 新增 API 端点:** ```http GET /api/v1/asl/extraction/templates # 系统模板列表 POST /api/v1/asl/extraction/templates/clone # 克隆模板到项目 POST /api/v1/asl/extraction/tasks # 创建提取任务(散装派发) GET /api/v1/asl/extraction/tasks/:taskId/status # 任务状态(groupBy 聚合) GET /api/v1/asl/extraction/tasks/:taskId/results # 提取结果列表 GET /api/v1/asl/extraction/results/:resultId # 单条结果详情(含 schema) PUT /api/v1/asl/extraction/results/:resultId/review # 审核(approved/rejected) GET /api/v1/asl/extraction/tasks/:taskId/stream # SSE 实时日志(无需认证) GET /api/v1/asl/extraction/tasks/:taskId/export # Excel 导出 GET /api/v1/asl/extraction/pkb/knowledge-bases # PKB 知识库代理 GET /api/v1/asl/extraction/pkb/knowledge-bases/:kbId/documents # PKB 文档代理 ``` **工具 3 新增前端路由:** ``` /literature/extraction/setup # Step 1: 配置与启动 /literature/extraction/progress/:taskId # Step 2: 进度监控 /literature/extraction/workbench/:taskId # Step 3: 审核工作台 ``` **工具 3 新增数据库表(asl_schema):** | 表名 | 说明 | |------|------| | `extraction_templates` | 系统内置模板(RCT/Cohort/QC) | | `extraction_project_templates` | 项目模板(克隆自系统模板,含 outcomeType/customFields) | | `extraction_tasks` | 提取任务(idempotencyKey 幂等) | | `extraction_results` | 单文档提取结果(extractedData JSON + quoteVerification + reviewStatus) | ### 🆕 工具 4 SR 图表生成器(2026-02-26 开发完成) **功能定位:** 基于工具 3 提取结果,一键生成 PRISMA 2020 流程图 + 基线特征表(Table 1),支持从项目流水线或 Excel 导入数据。 **开发状态:** ✅ 开发完成 **核心功能:** | 功能 | 技术实现 | 状态 | |------|---------|------| | PRISMA 2020 流程图 | SVG 渲染,支持中英文切换 | ✅ | | 基线特征表(Table 1) | Ant Design Table 动态渲染 | ✅ | | 双通道数据源 | 项目流水线(API 聚合)+ Excel 上传 | ✅ | | 图表导出 | SVG / PNG 导出 | ✅ | | Excel 模板 | 下载标准模板 + 解析上传文件 | ✅ | | 中英文切换 | PRISMA 图中英文 I18N(默认中文) | ✅ | **核心架构决策:** | 决策 | 方案 | |------|------| | PRISMA 数据聚合 | 后端 Prisma `count` 聚合 aslLiterature / screeningResult / fulltextResult / extractionResult | | 基线数据来源 | 后端查询 approved 的 extractionResult,flattenModuleData 归一化 | | 图表渲染 | 前端 SVG 组件,无第三方图表库依赖 | | 中英切换 | I18N 对象 + lang prop + 切换按钮组 | **新增 API 端点:** ```http GET /api/v1/asl/charting/prisma-data/:projectId # PRISMA 聚合数据 GET /api/v1/asl/charting/baseline-data/:projectId # 基线特征数据 ``` **新增前端路由:** ``` /literature/charting # SR 图表生成器页面 ``` **核心代码组件:** | 组件 | 文件 | 说明 | |------|------|------| | 图表服务 | `charting/services/ChartingService.ts` | Prisma 聚合 + 基线数据提取 | | 图表控制器 | `charting/controllers/ChartingController.ts` | 2 个 API 端点 | | PRISMA 图 | `components/charting/PrismaFlowDiagram.tsx` | SVG 渲染 + I18N 中英切换 | | 基线表 | `components/charting/BaselineTable.tsx` | Ant Design 动态列表格 | | 数据源选择 | `components/charting/DataSourceSelector.tsx` | 项目流水线 / Excel 双通道 | | Excel 工具 | `utils/chartingExcelUtils.ts` | 模板下载 + 解析 + 图表导出 | | 主页面 | `pages/SRChartGenerator.tsx` | Tab 切换 PRISMA / 基线表 | ### 🆕 工具 5 Meta 分析引擎(2026-02-26 开发完成) **功能定位:** 定量 Meta 分析引擎,支持 HR / 二分类(OR/RR)/ 连续型数据,生成森林图 + 漏斗图 + 异质性统计量,基于 R Docker 服务(meta 包)。 **开发状态:** ✅ 开发完成,E2E 36/36 通过 **核心功能:** | 功能 | 技术实现 | 状态 | |------|---------|------| | 3 种数据类型 | HR(metagen)、二分类(metabin)、连续型(metacont) | ✅ | | 2 种效应模型 | 随机效应(DerSimonian-Laird)+ 固定效应(Inverse Variance) | ✅ | | 多效应量度 | HR / OR / RR(二分类)| ✅ | | 森林图 | R meta::forest() → base64 PNG | ✅ | | 漏斗图 | R meta::funnel() → base64 PNG | ✅ | | 异质性统计 | I²、Q 统计量、p 值、Tau² | ✅ | | 数据输入 | Excel 上传 + 项目流水线(工具 3 提取结果) | ✅ | | 只读数据预览 | Ant Design Table 预览 + 数据验证 | ✅ | | Excel 模板 | 3 种数据类型模板 + 示例数据 + 使用说明 | ✅ | | R 代码可复现 | 返回可复现的 R 代码片段 | ✅ | **核心架构决策:** | 决策 | 方案 | |------|------| | 统计引擎 | R Docker 服务(meta 包),Brain-Hand 架构(Node.js 编排,R 执行) | | 数据传输 | inline JSON(小数据直传) | | 效应量回转 | meta 包返回 log 尺度,R 脚本内 exp() 回转为临床可解释值 | | 前端数据输入 | Excel 上传(编辑后回传)或关联项目流水线自动提取 | | 数据预览 | 只读 Ant Design Table,不做浏览器内编辑 | **新增 API 端点:** ```http POST /api/v1/asl/meta-analysis/run # 运行 Meta 分析 GET /api/v1/asl/meta-analysis/project-data/:projectId # 从项目流水线提取数据 GET /api/v1/asl/meta-analysis/health # R 服务健康检查 ``` **新增前端路由:** ``` /literature/meta-analysis # Meta 分析引擎页面 ``` **核心代码组件:** | 组件 | 文件 | 说明 | |------|------|------| | R 分析脚本 | `r-statistics-service/tools/meta_analysis.R` | metagen/metabin/metacont + exp() 回转 + 森林图/漏斗图 | | 后端服务 | `meta-analysis/services/MetaAnalysisService.ts` | R Docker 代理 + 项目数据提取 | | 后端控制器 | `meta-analysis/controllers/MetaAnalysisController.ts` | 3 个 API 端点 | | 结果面板 | `components/meta/ResultsPanel.tsx` | 汇总统计 + 图表展示 + R 代码 + 下载 | | Excel 工具 | `utils/metaExcelUtils.ts` | 3 种模板生成 + 解析 + 验证 | | 主页面 | `pages/MetaAnalysisEngine.tsx` | 3 步向导(数据输入→参数配置→分析结果) | | E2E 测试 | `meta-analysis/__tests__/meta-e2e-test.ts` | 36 项测试全部通过 | **R Docker 更新:** - Dockerfile 新增 `meta` 包安装 - 镜像版本维持 `ssa-r-statistics:1.0.1` - 工具总数从 12 增至 13(新增 `ST_META_ANALYSIS`) - 详见 `docs/02-通用能力层/06-R统计引擎/01-R统计引擎架构与部署指南.md` **关键技术点:** 1. **Log 尺度回转**:meta 包对 HR/OR/RR 返回 log 尺度值,R 脚本中使用 `exp()` 回转为临床可解释值 2. **R JSON 序列化**:Plumber 默认会将单元素向量包装为数组,前端需要 `Array.isArray` 防御 3. **数据类型自动检测**:从 Excel 或项目数据自动推断 HR/二分类/连续型 ### 智能文献检索 DeepSearch V1.x(2026-01-18 MVP完成) **功能概述:** - AI 驱动的自动化 PubMed 文献检索 - 自然语言输入研究问题,AI 自动生成检索策略 - 实时显示 AI 思考过程和检索进展 - 提取并展示 PubMed 文献链接 **技术实现:** - 集成 unifuncs DeepSearch API(OpenAI 兼容协议) - Server-Sent Events (SSE) 实时流式通信 - 数据库存储:`asl_schema.asl_research_tasks` **API 端点(V1.x,保留兼容):** - `POST /api/v1/asl/research/stream` - SSE 流式检索 - `POST /api/v1/asl/research/tasks` - 异步任务创建 - `GET /api/v1/asl/research/tasks/:taskId/status` - 任务状态查询 **已知限制(V2.0 将解决):** - ⚠️ SSE 模式,离开页面任务中断 → V2.0 用异步模式解决 - ⚠️ 仅搜索 PubMed → V2.0 支持 9 个数据源 - ⏳ 无需求扩写、无 HITL → V2.0 新增 ### 🏆 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 ``` --- ## 🎯 下一步开发计划 ### 当前(工具 3 M3 动态模板引擎) 1. ⏳ **M3-1:自定义字段 CRUD**:用户可在项目模板上增删改自定义提取字段 2. ⏳ **M3-2:Prompt 注入防护**:用户输入的字段 description 经过清洗再注入 Prompt 3. ⏳ **M3-3:E2E 完整测试**:从模板配置 → 提取 → 审核 → 导出的端到端自动化测试 4. ⏳ **M3-4:模板版本管理**:支持锁定/解锁、版本快照 ### 工具 3 后续优化 1. ⏳ **RoB 自动评价增强**:Prompt 引导 LLM 基于方法学描述主动评价偏倚风险 2. ⏳ **study_id 格式标准化**:强制 "FirstAuthor Year" 格式,后处理校验 3. ⏳ **outcomes 模板匹配**:根据文献内容自动推荐 survival/continuous/dichotomous 4. ⏳ **缺失字段补充**:country、inclusion_criteria、primary_outcome 等(M3 自定义字段支持) ### 工具 4/5 后续优化 1. ⏳ **PRISMA 图数据自动关联**:自动读取项目各阶段实际计数,减少手动输入 2. ⏳ **基线表统计检验**:自动计算 p 值、标准差等描述统计 3. ⏳ **Meta 分析亚组分析**:支持 subgroup 分层分析 4. ⏳ **Meta 分析敏感性分析**:逐一剔除法(Leave-one-out) 5. ⏳ **Meta 分析发表偏倚检验**:Egger's test / Begg's test 6. ⏳ **网状 Meta 分析(NMA)**:netmeta 包集成 ### 短期优化 1. ⏳ Deep Research V2.0 端到端回归测试 2. ⏳ 搜索历史管理(历史任务列表) 3. ⏳ 标题摘要初筛 Prompt 优化(准确率 60% → 85%+) ### 中期(Month 2-3) 1. ⏳ 工具 6(证据质量评价 GRADE)开发 2. ⏳ 生产环境部署 3. ⏳ 证据图谱可视化 --- **文档维护者**:AI智能文献开发团队 **更新周期**:每个重要功能完成后更新 **反馈方式**:提交Issue或Pull Request --- **最后更新**:2026-02-26(工具 4 SR 图表生成器 + 工具 5 Meta 分析引擎开发完成) **文档状态**:✅ 反映真实状态 **下次更新时机**:工具 3 M3 动态模板引擎开发完成 或 工具 6 GRADE 开发完成 **本次更新内容**(v2.3): - ✅ 工具 4 SR 图表生成器完成:PRISMA 2020 流程图(中英切换)+ 基线特征表 + 双通道数据源 + SVG/PNG 导出 - ✅ 工具 5 Meta 分析引擎完成:HR/二分类/连续型 + 随机/固定效应模型 + 森林图/漏斗图 + R Docker meta 包 + E2E 36/36 通过 - ✅ 新增工具 4 API 端点(2 个)、工具 5 API 端点(3 个)、前端路由(2 个) - ✅ R Docker 镜像更新:新增 meta 包,工具总数 13 - ✅ 更新下一步计划:工具 4/5 后续优化 + 工具 6 GRADE