# 真实LLM集成完成报告

**日期**: 2025-11-21  
**任务**: 将Mock AI替换为真实LLM调用  
**状态**: ✅ 完成  

---

## 📋 背景

### 之前的状态
- ✅ 已完成 Prompt 设计（v1.0.0-MVP）
- ✅ 已实现 `llmScreeningService.ts`（真实LLM调用）
- ✅ 已完成测试框架和质量验证
- ❌ **问题**: `screeningService.ts` 中使用 `mockAIScreening` 生成假数据

### 用户需求
从"设置与启动"页面上传真实文献数据后，**使用真实的 DeepSeek 和 Qwen API 进行筛选**，而不是模拟数据。

---

## ✅ 完成内容

### 1. 修改 `screeningService.ts`

**文件**: `backend/src/modules/asl/services/screeningService.ts`

#### 核心改动

**引入真实LLM服务**:
```typescript
import { llmScreeningService } from './llmScreeningService.js';
```

**替换处理逻辑**:
```typescript
// ❌ 旧代码（Mock）
const result = await mockAIScreening(projectId, literature);

// ✅ 新代码（真实LLM）
const screeningResult = await llmScreeningService.dualModelScreening(
  literature.id,
  literature.title,
  literature.abstract,
  picoCriteria,
  inclusionCriteria,
  exclusionCriteria,
  [models[0], models[1]],
  screeningConfig?.style || 'standard',
  literature.authors,
  literature.journal,
  literature.publicationYear
);
```

#### 新增功能

1. **从项目读取PICOS标准**:
   ```typescript
   const project = await prisma.aslScreeningProject.findUnique({
     where: { id: projectId },
   });
   
   const picoCriteria = project.picoCriteria;
   const inclusionCriteria = project.inclusionCriteria;
   const exclusionCriteria = project.exclusionCriteria;
   ```

2. **支持自定义模型选择**:
   ```typescript
   const models = screeningConfig?.models || ['deepseek-chat', 'qwen-max'];
   ```

3. **详细日志记录**:
   ```typescript
   logger.info('Processing literature', {
     literatureId: literature.id,
     title: literature.title?.substring(0, 50) + '...',
   });
   ```

4. **结果映射到数据库格式**:
   ```typescript
   const dbResult = {
     projectId,
     literatureId: literature.id,
     // DeepSeek结果
     dsModelName: screeningResult.deepseekModel,
     dsPJudgment: screeningResult.deepseek.judgment.P,
     // ... 完整的字段映射
   };
   ```

---

## 🔄 完整流程

### 用户操作流程
```
1. 访问"设置与启动"页面
   ↓
2. 填写 PICOS 标准
   ↓
3. 上传 Excel 文献列表（例如：199篇）
   ↓
4. 点击"开始AI初筛"
   ↓
5. 后端自动处理：
   a. 创建项目
   b. 导入文献
   c. 启动筛选任务
   ↓
6. 真实LLM处理（每篇约10-15秒）
   a. 调用 DeepSeek API
   b. 调用 Qwen API
   c. 对比结果，检测冲突
   d. 保存到数据库
   ↓
7. 前端自动跳转到"审核工作台"
   ↓
8. 显示真实的AI筛选结果
```

### 技术流程

```
前端: TitleScreeningSettings.tsx
  ↓ POST /api/v1/asl/literatures/import
  
后端: literatureController.ts
  ↓ importLiteratures()
  ↓ startScreeningTask()
  
后端: screeningService.ts
  ↓ processLiteraturesInBackground()
  ↓ for each literature:
      ↓ llmScreeningService.dualModelScreening()
      
后端: llmScreeningService.ts
  ↓ Promise.all([
      screenWithModel('deepseek-chat', ...),
      screenWithModel('qwen-max', ...),
    ])
  
后端: LLMFactory
  ↓ getAdapter('deepseek-v3')
  ↓ getAdapter('qwen3-72b')
  
真实API调用
  ↓ DeepSeek API
  ↓ Qwen API
  
结果保存
  ↓ AslScreeningResult 表
  
前端: ScreeningWorkbench.tsx
  ↓ GET /api/v1/asl/projects/:projectId/screening-results
  ↓ 显示真实结果
```

---

## ⏱️ 性能预期

### 单篇文献处理时间
| 步骤 | 耗时（串行） |
|-----|------------|
| DeepSeek API 调用 | 5-10秒 |
| Qwen API 调用 | 5-10秒 |
| 结果保存 | 0.1秒 |
| **总计** | **10-20秒** |

### 批量处理时间（199篇）
| 模式 | 耗时 | 说明 |
|-----|------|-----|
| **串行处理** | 33-66分钟 | 当前实现（避免API限流）|
| 并发处理（3个） | 11-22分钟 | 可选优化（需测试） |
| 并发处理（10个） | 3-7分钟 | 风险：可能触发API限额 |

**当前策略**: 串行处理（稳定优先）

---

## 🎯 与Mock数据的对比

### Mock 数据（旧）
```javascript
// ❌ 假数据
dsPEvidence: "模拟证据: 研究人群与PICO中的P标准匹配"
dsReason: "基于标题和摘要分析，该文献符合纳入标准。"
dsConclusion: randomConclusion() // 随机！

// 特点：
- 1秒完成199篇
- 证据都是"模拟证据"
- 判断结果随机生成
```

### 真实LLM（新）
```javascript
// ✅ 真实数据
dsPEvidence: "This study included adult patients with type 2 diabetes mellitus aged 18 years or older, which matches the population criteria."
dsReason: "The study population consists of T2DM patients, the intervention is an SGLT2 inhibitor (empagliflozin), the comparator is placebo, and the study design is a randomized controlled trial. All PICO criteria are met. The study reports on cardiovascular outcomes including MACE, heart failure hospitalization, and cardiovascular death, which are the outcomes of interest."
dsConclusion: "include" // AI真实判断！

// 特点：
- 33-66分钟完成199篇
- 证据引用文献原文
- 判断基于Prompt v1.0.0-MVP
- 准确率：60%（首次测试）
```

---

## 🔍 数据验证

### 验证方法
```bash
cd AIclinicalresearch/backend
node check-data.mjs
```

### 预期输出（真实数据）
```
🔬 筛选结果样本:
  [1] 文献: Assessment of Thrombectomy versus Combined...
      DeepSeek: include (P:match, I:partial, C:mismatch, S:match)
      Qwen:     exclude (P:mismatch, I:mismatch, C:partial, S:match)
      冲突状态: conflict
      是否有证据: DeepSeek=true, Qwen=true  ✅

  证据示例:
  - dsPEvidence: "The study population consists of..."
  - qwenPEvidence: "Patients with acute ischemic stroke..."
```

---

## 📊 质量保障

### 已实现的质量措施

1. **JSON Schema 验证**:
   - 所有LLM输出必须通过Schema验证
   - 不合格的输出会被拒绝

2. **错误处理**:
   - 单篇文献失败不影响整体任务
   - 详细错误日志记录

3. **进度追踪**:
   - 每10篇更新一次进度
   - 实时统计成功/冲突/失败数

4. **可追溯性**:
   - 记录原始LLM输出（`rawOutput`）
   - 记录Prompt版本（`promptVersion`）
   - 记录处理时间（`aiProcessedAt`）

---

## 🚀 测试步骤

### Step 1: 准备测试数据
```
使用现有测试文件:
- PICOS: docs/.../测试案例的PICOS、纳入标准、排除标准.txt
- Excel: docs/.../Test Cases.xlsx (199篇文献)
```

### Step 2: 执行测试
1. 启动后端: `cd backend && npm run dev`
2. 启动前端: `cd frontend-v2 && npm run dev`
3. 访问: `http://localhost:3001`
4. 填写PICOS + 上传Excel
5. 点击"开始AI初筛"
6. **等待30-60分钟**（199篇×20秒）
7. 查看审核工作台

### Step 3: 验证结果
```bash
cd backend
node check-data.mjs
```

**检查项**:
- [ ] 所有文献都有筛选结果
- [ ] 证据不再是"模拟证据"
- [ ] 证据包含文献原文引用
- [ ] 判断理由详细且符合逻辑
- [ ] 冲突检测准确（conclusion不同）

---

## ⚠️ 注意事项

### API密钥配置
确保环境变量已配置:
```bash
# .env
DEEPSEEK_API_KEY=sk-xxxxx
QWEN_API_KEY=sk-xxxxx
```

### API限流
- DeepSeek: 60 RPM（每分钟请求数）
- Qwen: 60 RPM

**当前策略**: 串行处理，不会触发限流

### 成本估算
- DeepSeek: ~$0.001/次 × 199 = **$0.20**
- Qwen: ~$0.001/次 × 199 = **$0.20**
- **总计**: **$0.40** / 次完整测试

---

## 💡 优化建议

### 短期优化（Week 2 - Day 4-5）
1. **并发控制**: 改为3个并发（33分钟 → 11分钟）
2. **进度显示**: 前端轮询显示进度百分比
3. **错误重试**: 失败的文献自动重试1次

### 中期优化（Week 3）
1. **消息队列**: 使用Bull Queue异步处理
2. **批量优化**: 使用批量API接口（如果有）
3. **缓存机制**: 相同文献不重复筛选

---

## 📁 相关文件

### 修改的文件
- `backend/src/modules/asl/services/screeningService.ts` ⭐

### 依赖的文件（已存在）
- `backend/src/modules/asl/services/llmScreeningService.ts`
- `backend/src/modules/asl/schemas/screening.schema.ts`
- `backend/prompts/asl/screening/v1.0.0-mvp.txt`
- `backend/src/common/llm/adapters/LLMFactory.ts`

### 测试文件
- `backend/scripts/test-llm-screening.ts`
- `backend/scripts/test-samples/asl-test-literatures.json`

---

## 🎉 成果总结

### 已实现
✅ 真实LLM调用替换Mock数据  
✅ 从项目读取PICOS标准  
✅ 双模型并行筛选  
✅ 冲突检测与标记  
✅ 完整的日志追踪  
✅ 错误处理机制  

### 待优化
⚠️ 处理时间较长（30-60分钟）  
⚠️ 串行处理（可改为并发）  
⚠️ 前端进度显示（需优化轮询频率）  

---

## 🔗 参考文档

- [Prompt设计与测试完成报告](./2025-11-18-Prompt设计与测试完成报告.md)
- [卒中数据泛化测试报告](./2025-11-18-卒中数据泛化测试报告.md)
- [任务分解](../04-开发计划/03-任务分解.md)

---

**报告人**: AI Assistant  
**日期**: 2025-11-21  
**版本**: v1.0.0


