docs(iit): Add QC system UI and LLM format optimization plan

- Add development plan: 07-QC system UI and LLM format optimization

- Phase 1: PromptBuilder + XML clinical slice format (~5.5h)

- Phase 2: QC cockpit + stat cards + risk heatmap (~9.5h)

- Phase 3: Variable tagging system (~5h)

- Add CRA Agent design document and prototype

- Update module status: design 100%, code 45%

- Update system status: real-time QC complete + plan ready

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-08 09:59:44 +08:00
parent 5db4a7064c
commit 45c7b32dbb
6 changed files with 1234 additions and 15 deletions

View File

@@ -0,0 +1,384 @@
# 质控系统 UI 与 LLM 格式优化开发计划
> **版本:** v1.0
> **创建日期:** 2026-02-08
> **基于讨论:** 团队技术方案评审 + 产品原型对比分析
> **决策确认:** 方案 A渐进式改进
---
## 一、背景与目标
### 1.1 现状问题
1. **LLM 格式问题**:当前使用简单 JSON 格式返回数据LLM 理解力有限,容易产生幻觉
2. **UI 展示缺失**:管理端只有批量操作按钮,无法直观查看质控结果和录入进度
3. **入口层级深**IIT 管理嵌套在运营管理端中,质控监控功能不够突出
### 1.2 参考文档
| 文档 | 路径 | 核心内容 |
|------|------|----------|
| CRA Agent 深度设计方案 | `docs/03-业务模块/IIT Manager Agent/01-需求分析/CRA Agent (临床监查) 深度设计与展现方案.md` | 变量分组、双层质控、临床切片格式 |
| 质控管理原型图 | `docs/03-业务模块/IIT Manager Agent/01-需求分析/质控管理原型图.html` | 风险热力图、统计卡片、智能诊断抽屉 |
### 1.3 目标
1. **提升 AI 回答准确性**:采用 XML 临床切片格式,减少 LLM 幻觉
2. **提升运营效率**:提供可视化质控驾驶舱,一眼看穿数据问题
3. **渐进式改进**:不破坏现有架构,逐步增强功能
---
## 二、详细评估表
### 2.1 团队方案 vs 当前代码对比
| 功能点 | 团队方案描述 | 当前状态 | 建议 |
|--------|-------------|---------|------|
| **1. 变量语义标签 (Tagging)** | 为变量打 `#demographics`, `#lab`, `#safety` 等标签,按需加载 | ❌ 未实现 | 🔴 **采纳** - 在 `iit_field_metadata` 表增加 `tags` 字段 |
| **2. 双层质控引擎** | Layer 1: HardRuleEngine, Layer 2: AI Logic Engine | ✅ Layer 1 已完成 | 🟡 Layer 2 可延后 |
| **3. 临床切片格式** | XML + Markdown 结构化提示词,对 LLM 更友好 | ❌ 使用简单 JSON | 🔴 **采纳** - 新增 `PromptBuilder.buildClinicalSlice()` |
| **4. 风险热力图** | 矩阵式受试者 × 访视/表单视图,颜色表示风险等级 | ❌ 未实现 | 🔴 **采纳** - 管理端新增驾驶舱页面 |
| **5. 统计卡片** | 数据质量分、严重违规数、Query 数、方案偏离数 | ❌ 未实现 | 🔴 **采纳** - 驾驶舱页面顶部 |
| **6. 智能诊断抽屉** | 左侧真实数据 + 右侧 AI 诊断可操作Query/确认/忽略) | ❌ 未实现 | 🟡 **简化采纳** - 先实现详情弹窗 |
| **7. LLM Trace 视图** | 展示发送给 LLM 的 Prompt 和思考过程 | ❌ 未实现 | 🟢 延后 - 调试阶段使用 |
| **8. 规则配置中心** | Layer 1/2/3 分层配置界面 | ✅ 已有质控规则页面 | ✅ 保持现有 |
| **9. AI 自动提取规则** | 上传 Protocol PDF 自动生成规则 | ❌ 未实现 | 🟢 延后 - 高级功能 |
| **10. qc_logs 审计轨迹** | 质控日志仅新增,保留历史记录 | ✅ 已实现 | ✅ 保持现有 |
| **11. record_summary 汇总** | 录入汇总表 upsert 模式 | ✅ 已实现 | ✅ 保持现有 |
| **12. pg-boss 防抖** | Webhook 去重机制 | ✅ 已实现 | ✅ 保持现有 |
### 2.2 LLM 格式对比
| 维度 | 当前 JSON 格式 | XML 临床切片格式 |
|------|---------------|-----------------|
| **Token 消耗** | 较多(括号、引号、嵌套) | 较少(语义化标签) |
| **LLM 理解力** | 一般(需要解析 JSON 结构) | 极强(医学叙事文本) |
| **上下文切割** | 困难(全量或无) | 简单(按 tag 切片) |
| **推理准确性** | 中等 | 高(有明确任务指令) |
| **调试友好度** | 一般 | 好XML 结构清晰) |
**当前 JSON 格式示例:**
```json
{
"projectName": "test0207",
"stats": {
"totalRecords": 13,
"passedRecords": 0,
"failedRecords": 13
},
"problemRecords": [
{
"recordId": "1",
"status": "FAIL",
"issues": [...]
}
]
}
```
**XML 临床切片格式示例:**
```xml
<task>核查该患者是否符合研究入排标准</task>
<protocol_criteria>
1. 年龄 16-35 岁。
2. 月经周期规律28±7天
3. VAS 评分 ≥ 4 分。
4. 签署知情同意书。
</protocol_criteria>
<patient_slice tag="#demographics, #screening">
- 出生日期2003-01-07当前年龄 22 岁)✅
- 月经周期45 天 ⚠️ 超出范围
- VAS 评分:未填写 ⚠️
- 知情同意:未签署 ❌
</patient_slice>
<instruction>
请一步步推理,对比患者数据与标准。如发现异常,说明具体哪条标准被违反。
</instruction>
```
---
## 三、架构方案确认
### 3.1 方案 A确认采用
**核心思路:渐进式改进,增加"质控全览图"按钮**
```
运营管理端 → IIT 项目管理 → 项目详情页
├── REDCap 配置 (Tab)
├── 质控规则 (Tab)
├── 通知设置 (Tab)
├── 知识库 (Tab)
└── [⚡一键全量质控] [📊一键全量汇总] [🔍质控全览图]
全新页面(全屏驾驶舱)
/admin/iit-projects/:id/cockpit
```
**优势:**
1. 不破坏现有系统架构
2. 配置与监控职责分离
3. 全屏展示更多内容
4. 开发成本可控
### 3.2 驾驶舱页面布局
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ ← 返回项目配置 test0207 - CRA 智能监查驾驶舱 ⚡全量质控 📄导出报告 │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐│
│ │ 总体数据质量分 │ │ 严重违规 │ │ 待确认 Query │ │ 录入完成率 ││
│ │ │ │ (Critical) │ │ (Major) │ │ ││
│ │ 0 /100 │ │ 13 条 │ │ 0 条 │ │ 14% ││
│ │ ████░░░░░░░░ │ │ 需立即处理 │ │ │ │ 7个表单/1个完成││
│ └────────────────┘ └────────────────┘ └────────────────┘ └────────────────┘│
├─────────────────────────────────────────────────────────────────────────────┤
│ 受试者风险全景图 (Risk Heatmap) │
│ ────────────────────────────────────────────────────────────────────────── │
│ 🟢 无异常 🟡 疑问(Query) 🔴 严重违规 ⚪ 未开始 │
│ ────────────────────────────────────────────────────────────────────────── │
│ 记录ID │ 入组状态 │ 人口学信息 │ 病史诊断 │ 知情同意 │ 入排标准 │ CMSS │ ...│
│ ───────┼─────────┼───────────┼─────────┼─────────┼─────────┼──────┼─────│
│ 1 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
│ 2 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
│ 3 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
│ ... │ ... │ ... │ ... │ ... │ ... │ ... │ ... │
│ 13 │ 入组中 │ 🟢 │ ⚪ │ 🔴 │ 🔴 │ ⚪ │ ⚪ │
└─────────────────────────────────────────────────────────────────────────────┘
│ 点击红色单元格
┌─────────────────────────────────────────────────────────────────────────────┐
│ 侧滑抽屉:记录 1 - 入排标准详情 │
├─────────────────────────────────────────────────────────────────────────────┤
│ 【质控问题】 │
│ ❌ 年龄不在 25-35 岁范围内当前22岁
│ ❌ 月经周期不在 21-35 天范围内当前45天
│ ❌ VAS 评分 < 4 分(当前:空值) │
│ ❌ 未签署知情同意书 │
│ │
│ 【原始数据】 │
│ age: 22 | menstrual_cycle: 45 | vas_score: null | informed_consent: 0 │
│ │
│ [发送 Query] [确认违规] [忽略] │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 四、分阶段开发计划
### 阶段 1LLM 格式优化P0 - 优先级最高)
**目标:提升 AI 回答准确性,减少幻觉**
| 任务 | 描述 | 工作量 | 优先级 |
|------|------|--------|--------|
| 1.1 创建 PromptBuilder 类 | 实现 `buildClinicalSlice()` 方法,生成 XML 格式 | 2h | P0 |
| 1.2 修改 ChatService | 在质控查询时使用 PromptBuilder 格式化数据 | 1.5h | P0 |
| 1.3 添加自然语言摘要 | 返回结果增加 `summary` 字段,便于 LLM 直接引用 | 1h | P0 |
| 1.4 测试验证 | 企业微信端测试 AI 回答准确性 | 1h | P0 |
**技术实现:**
```typescript
// backend/src/modules/iit-manager/services/PromptBuilder.ts
export class PromptBuilder {
/**
* 构建 XML 临床切片格式
*/
static buildClinicalSlice(params: {
task: string;
criteria: string[];
patientData: Record<string, any>;
tags?: string[];
instruction?: string;
}): string {
const { task, criteria, patientData, tags = [], instruction } = params;
return `
<task>${task}</task>
<protocol_criteria>
${criteria.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}
</protocol_criteria>
<patient_slice${tags.length > 0 ? ` tag="${tags.join(', ')}"` : ''}>
${Object.entries(patientData)
.map(([k, v]) => ` - ${k}: ${v ?? '未填写'}`)
.join('\n')}
</patient_slice>
${instruction ? `<instruction>\n${instruction}\n</instruction>` : ''}
`.trim();
}
/**
* 构建质控结果摘要(自然语言)
*/
static buildQcSummary(stats: {
projectName: string;
totalRecords: number;
passRate: number;
topIssues: Array<{ issue: string; count: number }>;
}): string {
const { projectName, totalRecords, passRate, topIssues } = stats;
const issueText = topIssues
.slice(0, 3)
.map(i => `${i.issue}${i.count}条)`)
.join('、');
return `项目 ${projectName} 共有 ${totalRecords} 条记录,` +
`质控通过率 ${passRate.toFixed(1)}%。` +
(topIssues.length > 0 ? `主要问题包括:${issueText}` : '暂无质控问题。');
}
}
```
---
### 阶段 2管理端 UI 增强P0
**目标:提供可视化质控驾驶舱**
| 任务 | 描述 | 工作量 | 优先级 |
|------|------|--------|--------|
| 2.1 添加"质控全览图"按钮 | 在 IitProjectDetailPage 增加按钮 | 0.5h | P0 |
| 2.2 创建驾驶舱页面骨架 | IitQcCockpitPage.tsx + 路由配置 | 1h | P0 |
| 2.3 实现统计卡片组件 | 4 个卡片质量分、违规数、Query 数、完成率 | 1.5h | P0 |
| 2.4 实现风险热力图组件 | 矩阵式表格,颜色表示风险等级 | 3h | P0 |
| 2.5 实现详情抽屉组件 | 点击单元格展示问题详情 | 2h | P1 |
| 2.6 后端 API热力图数据 | 按记录×表单聚合质控状态 | 1.5h | P0 |
**新增文件清单:**
```
frontend-v2/src/modules/admin/
├── pages/
│ └── IitQcCockpitPage.tsx # 驾驶舱主页面
├── components/
│ ├── QcStatCards.tsx # 统计卡片组件
│ ├── RiskHeatmap.tsx # 风险热力图组件
│ └── QcDetailDrawer.tsx # 详情抽屉组件
backend/src/modules/admin/iit-projects/
├── iitQcCockpitController.ts # 驾驶舱数据 API
└── iitQcCockpitRoutes.ts # 路由定义
```
---
### 阶段 3变量标签系统P1
**目标:支持按语义标签切片数据**
| 任务 | 描述 | 工作量 | 优先级 |
|------|------|--------|--------|
| 3.1 扩展数据库表 | `iit_field_metadata` 增加 `tags` 字段 | 0.5h | P1 |
| 3.2 管理端标签编辑 | 质控规则页面支持为字段打标签 | 2h | P1 |
| 3.3 REDCap 同步时自动打标签 | 根据表单名推断默认标签 | 1.5h | P2 |
| 3.4 PromptBuilder 按标签切片 | 只加载指定标签的字段 | 1h | P1 |
**数据库变更:**
```sql
-- 扩展 iit_field_metadata 表
ALTER TABLE iit_schema.field_metadata
ADD COLUMN tags TEXT[] DEFAULT '{}';
-- 示例数据
UPDATE iit_schema.field_metadata
SET tags = ARRAY['#demographics', '#screening']
WHERE field_name IN ('age', 'date_of_birth', 'sex');
UPDATE iit_schema.field_metadata
SET tags = ARRAY['#consent', '#ethics']
WHERE field_name = 'informed_consent';
```
---
### 阶段 4高级功能P2 - 延后)
| 任务 | 描述 | 工作量 | 优先级 |
|------|------|--------|--------|
| 4.1 LLM Trace 视图 | 展示发送给 LLM 的 Prompt | 3h | P2 |
| 4.2 AI 自动提取规则 | 上传 Protocol PDF 自动生成规则 | 8h | P3 |
| 4.3 Layer 2 AI 逻辑引擎 | 复杂医学逻辑判断 | 10h | P3 |
| 4.4 导出监查报告 | 生成 PDF/Word 格式报告 | 4h | P2 |
---
## 五、开发优先级总结
| 优先级 | 阶段 | 核心任务 | 预计工时 |
|--------|------|----------|----------|
| **P0** | 阶段 1 | LLM 格式优化PromptBuilder + ChatService | 5.5h |
| **P0** | 阶段 2 | 管理端 UI驾驶舱 + 统计卡片 + 热力图) | 9.5h |
| **P1** | 阶段 3 | 变量标签系统 | 5h |
| **P2** | 阶段 4 | 高级功能(延后) | 25h+ |
**MVP 阶段(阶段 1 + 2总工时~15 小时**
---
## 六、验收标准
### 6.1 阶段 1 验收
- [ ] 企业微信问"质控情况"AI 回答格式清晰、无幻觉
- [ ] AI 回答包含具体问题和记录数
- [ ] 日志中可看到 XML 格式的 Prompt
### 6.2 阶段 2 验收
- [ ] 点击"质控全览图"按钮可进入驾驶舱页面
- [ ] 统计卡片正确显示质量分、违规数、完成率
- [ ] 热力图正确显示记录×表单的质控状态
- [ ] 点击红色单元格可查看问题详情
### 6.3 阶段 3 验收
- [ ] 字段可配置语义标签
- [ ] PromptBuilder 支持按标签过滤数据
- [ ] AI 查询时只加载相关字段
---
## 七、风险与依赖
| 风险 | 影响 | 缓解措施 |
|------|------|----------|
| 热力图数据量大 | 页面卡顿 | 分页加载、虚拟滚动 |
| XML 格式 Token 计算 | 超出 LLM 上下文限制 | 按标签切片、限制字段数 |
| REDCap 表单结构多变 | 热力图列不固定 | 动态渲染、表单配置 |
---
## 八、相关文档
| 文档 | 说明 |
|------|------|
| [06-实时质控系统开发计划.md](./06-实时质控系统开发计划.md) | 质控后端架构 |
| [CRA Agent 深度设计方案](../01-需求分析/CRA%20Agent%20(临床监查)%20深度设计与展现方案.md) | 技术方案参考 |
| [质控管理原型图](../01-需求分析/质控管理原型图.html) | UI 原型参考 |
---
**文档维护人:** AI Assistant
**创建时间:** 2026-02-08
**下次评审:** 阶段 1 完成后