Architecture transformation: - Replace Fan-out (Manager->Child->Last Child Wins) with Scatter+Aggregator pattern - API layer directly dispatches N independent jobs (no Manager) - Worker only writes its own Result row, never touches Task table (zero row-lock) - Aggregator polls groupBy for completion + zombie cleanup (replaces Sweeper) - Reduce red lines from 13 to 9, eliminate distributed complexity Documents updated (10 files): - 08-Tool3 main architecture doc: v2.0 rewrite (schema, Task 2.3/2.4, red lines, risks) - 08d-Code patterns: rewrite sections 4.1-4.6 (API dispatch, SingleWorker, Aggregator) - 08a-M1 sprint: rewrite M1-3 core (Worker+Aggregator), red lines, acceptance criteria - 08b-M2 sprint: simplify SSE (NOTIFY/LISTEN downgraded to P2 optional) - 08c-M3 sprint: milestone table wording update - New: Scatter+Polling Aggregator pattern guide v1.1 (Level 2 cookbook) - New: V2.0 architecture deep review and gap-fix report - Updated: ASL module status, system status, capability layer index Co-authored-by: Cursor <cursoragent@cursor.com>
1479 lines
49 KiB
Markdown
1479 lines
49 KiB
Markdown
# AI智能文献模块 - 当前状态与开发指南
|
||
|
||
> **文档版本:** v2.1
|
||
> **创建日期:** 2025-11-21
|
||
> **维护者:** AI智能文献开发团队
|
||
> **最后更新:** 2026-02-24 🆕 **工具 3 V2.0 开发计划升级至 v2.0(散装派发 + Aggregator 架构,9 条研发红线)**
|
||
> **重大进展:**
|
||
> - 🆕 2026-02-24:工具 3 V2.0 架构升级!Fan-out → 散装派发 + Aggregator 轮询收口,通用模式指南 v1.1 沉淀
|
||
> - 2026-02-23:工具 3 V2.0 开发计划 v1.5 完成!6 轮架构审查 + 5 份文档体系
|
||
> - 🆕 2026-02-23:V2.0 核心功能完成!SSE 流式架构 + 段落化思考日志 + 引用链接可见化
|
||
> - 🆕 2026-02-22:V2.0 前后端联调完成!瀑布流 UI + Markdown 渲染 + Word 导出 + 中文数据源测试
|
||
> - 🆕 2026-02-22:V2.0 开发计划确认 + Unifuncs API 网站覆盖测试完成
|
||
> - 2026-01-18:智能文献检索(DeepSearch)MVP完成 - unifuncs API 集成
|
||
> **文档目的:** 反映模块真实状态,帮助新开发人员快速上手
|
||
|
||
---
|
||
|
||
## 📋 文档说明
|
||
|
||
本文档是AI智能文献(ASL)模块的**真实状态快照**,记录实际的代码结构、已实现功能、技术栈和开发规范。
|
||
|
||
**与其他文档的关系**:
|
||
- **本文档(00-模块当前状态)**:What is(真实状态)
|
||
- **开发计划文档**:What to do(计划)
|
||
- **开发记录文档**:What done(历史)
|
||
- **技术设计文档**:How to do(设计)
|
||
|
||
---
|
||
|
||
## 🎯 模块概述
|
||
|
||
### 核心功能
|
||
AI智能文献模块是一个基于大语言模型(LLM)的文献筛选系统,用于帮助研究人员根据PICOS标准自动筛选文献。
|
||
|
||
### 当前状态
|
||
- **开发阶段**:🎉 V2.0 Deep Research 核心功能完成 + 🆕 工具 3 开发计划 v2.0 就绪
|
||
- **已完成功能**:
|
||
- ✅ 标题摘要初筛(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 全文智能提取工作台 V2.0** — 开发计划 v2.0 完成(散装派发 + Aggregator 架构,9 条研发红线,M1/M2/M3 三阶段,预计 22 天)
|
||
- **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 自定义 `<a>` 组件在链接后追加灰色 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-24 开发计划 v2.0 完成,待编码)
|
||
|
||
**功能定位:** 批量读取 PDF 全文 → 动态模板驱动 AI 结构化提取 → 人工 HITL 审核 → Excel 导出。是 ASL 证据整合 V2.0 三大工具中最复杂的一个。
|
||
|
||
**开发计划状态:** ✅ v2.0 定稿(经 8+ 轮架构审查 + 架构转型:Fan-out → 散装派发 + Aggregator)
|
||
|
||
**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 + 审核抽屉 + SSE 日志 + Excel | Week 2-3 |
|
||
| M3 动态模板引擎 | 自定义字段 + Prompt 注入防护 + E2E 测试 | Week 4 |
|
||
|
||
**9 条研发红线**:详见架构总纲文档 M1 红线表。
|
||
|
||
**通用能力沉淀**:
|
||
- 🚀 `docs/02-通用能力层/散装派发与轮询收口任务模式指南.md`(v1.1,Level 2 Cookbook)
|
||
- 📖 `docs/02-通用能力层/分布式Fan-out任务模式开发指南.md`(v1.2,Level 3 参考)
|
||
|
||
### 智能文献检索 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
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 下一步开发计划
|
||
|
||
### 当前(Deep Research V2.0 优化)
|
||
1. ⏳ **端到端回归测试**:完整流程测试(创建→扩写→确认→执行→结果→导出)
|
||
2. ⏳ **用户体验打磨**:加载动画、错误提示、边界情况处理
|
||
3. ⏳ **中文检索优化**:中英文混合检索策略调优(建议分批搜索)
|
||
4. ⏳ **导出格式完善**:Word 模板美化、更多导出格式
|
||
|
||
### 短期优化
|
||
1. ⏳ Prompt 优化(需求扩写质量提升)
|
||
2. ⏳ 搜索历史管理(历史任务列表、重新搜索)
|
||
3. ⏳ 全文复筛前端 UI 开发
|
||
4. ⏳ 标题摘要初筛 Prompt 优化(准确率 60% → 85%+)
|
||
|
||
### 中期(Month 2)
|
||
1. ⏳ 全文复筛功能完善
|
||
2. ⏳ 证据图谱可视化
|
||
3. ⏳ 用户自定义数据源
|
||
4. ⏳ 生产环境部署
|
||
|
||
### 长期(Month 3+)
|
||
1. ⏳ 多语言检索策略自动优化
|
||
2. ⏳ 批量文献检索
|
||
3. ⏳ 成本控制和监控
|
||
|
||
---
|
||
|
||
**文档维护者**:AI智能文献开发团队
|
||
**更新周期**:每个重要功能完成后更新
|
||
**反馈方式**:提交Issue或Pull Request
|
||
|
||
---
|
||
|
||
**最后更新**:2026-02-23(Deep Research V2.0 核心功能完成)
|
||
**文档状态**:✅ 反映真实状态
|
||
**下次更新时机**:V2.0 端到端回归测试完成 或 全文复筛前端开发启动
|
||
|
||
**本次更新内容**(v2.0):
|
||
- ✅ 更新当前状态:V2.0 核心功能开发完成(SSE 流式 + 瀑布流 UI + Word 导出)
|
||
- ✅ 新增 V2.0 完整架构表、技术决策、API 端点、关键文件列表
|
||
- ✅ 新增 5 个精选数据源配置(替代 9 站全量展示)
|
||
- ✅ 更新下一步开发计划(V2.0 优化 + 短期/中期/长期)
|
||
|
||
|