Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-21-真实LLM集成完成报告.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

382 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 真实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