feat(iit): Implement event-level QC architecture V3.1 with dynamic rule filtering, report deduplication and AI intent enhancement
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
# AIclinicalresearch 系统当前状态与开发指南
|
||||
|
||||
> **文档版本:** v4.8
|
||||
> **文档版本:** v4.9
|
||||
> **创建日期:** 2025-11-28
|
||||
> **维护者:** 开发团队
|
||||
> **最后更新:** 2026-02-08
|
||||
> **🎉 重大里程碑:**
|
||||
> - **2026-02-08:IIT 质控系统优化计划制定!** XML 临床切片格式 + 质控驾驶舱 + 方案 A 确认
|
||||
> - **2026-02-08:IIT 事件级质控 V3.1 开发完成!** record+event 独立质控 + 规则动态过滤 + 报告去重 + AI对话增强
|
||||
> - **2026-02-08:IIT 质控驾驶舱 UI 完成!** XML 临床切片格式 + 质控驾驶舱 + 热力图 + 详情抽屉
|
||||
> - **2026-02-07:IIT 实时质控系统开发完成!** pg-boss 防抖 + 质控日志 + 录入汇总 + 管理端批量操作
|
||||
> - **2026-02-05:IIT Manager Agent V2.9.1 架构设计完成!** 双脑架构 + 三层记忆 + 主动性增强 + 隐私合规
|
||||
> - **2026-02-02:REDCap 生产环境部署完成!** ECS + RDS + HTTPS + 域名全部配置完成
|
||||
@@ -14,15 +15,14 @@
|
||||
> - **2026-01-25:Protocol Agent MVP完整交付!** 一键生成研究方案+Word导出
|
||||
> - **2026-01-24:Protocol Agent 框架完成!** 可复用Agent框架+5阶段对话流程
|
||||
> - **2026-01-22:OSS 存储集成完成!** 阿里云 OSS 正式接入平台基础层
|
||||
> - **2026-01-21:成功替换 Dify!** PKB 模块完全使用自研 pgvector RAG 引擎
|
||||
>
|
||||
> **最新进展(IIT Manager Agent 2026-02-08):**
|
||||
> - ✅ **实时质控系统**:pg-boss 防抖 + 质控日志(审计轨迹) + 录入汇总(upsert)
|
||||
> - ✅ **管理端批量操作**:一键全量质控 + 一键全量汇总(前后端完整)
|
||||
> - ✅ **质控优化计划**:XML 临床切片格式 + 质控驾驶舱 + 变量标签系统
|
||||
> - ✅ **双脑架构**:SOP 状态机(结构化任务) + ReAct 引擎(模糊查询)
|
||||
> - ✅ **三层记忆**:流水账(全量日志) + 热记忆(高频注入) + 历史书(按需检索)
|
||||
> - ✅ **隐私合规**:PII 脱敏中间件 + 审计日志 + 可恢复脱敏
|
||||
> - ✅ **事件级质控 V3.1**:每个 record+event 独立质控,不再合并覆盖数据
|
||||
> - ✅ **规则动态过滤**:applicableEvents/applicableForms 配置规则适用范围
|
||||
> - ✅ **质控报告去重**:按 recordId+ruleId 去重,避免多事件重复问题
|
||||
> - ✅ **AI 对话增强**:支持"严重违规有几项"等自然语言查询
|
||||
> - ✅ **质控驾驶舱 UI**:PromptBuilder XML 格式 + 热力图 + 详情抽屉
|
||||
> - ✅ **Bug 修复**:formatPatientData 500 错误 + 记录数统计 + 报告限制移除
|
||||
>
|
||||
> **部署状态:** ✅ 生产环境运行中 | 公网地址:http://8.140.53.236/
|
||||
> **REDCap 状态:** ✅ 生产环境运行中 | 地址:https://redcap.xunzhengyixue.com/
|
||||
@@ -62,7 +62,7 @@
|
||||
| **PKB** | 个人知识库 | RAG问答、私人文献库 | ⭐⭐⭐ | 🎉 **Dify已替换!自研RAG上线(95%)** | P1 |
|
||||
| **ASL** | AI智能文献 | 文献筛选、Meta分析、证据图谱 | ⭐⭐⭐⭐⭐ | 🎉 **智能检索MVP完成(60%)** - DeepSearch集成 | **P0** |
|
||||
| **DC** | 数据清洗整理 | ETL + 医学NER(百万行级数据) | ⭐⭐⭐⭐⭐ | ✅ **Tool B完成 + Tool C 99%(异步架构+性能优化-99%+多指标转换+7大功能)** | **P0** |
|
||||
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 双脑架构+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **实时质控完成 + UI优化计划制定(设计100%,代码45%)** | **P0** |
|
||||
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 双脑架构+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **事件级质控V3.1完成(设计100%,代码60%)** | **P0** |
|
||||
| **SSA** | 智能统计分析 | 队列/预测模型/RCT分析 | ⭐⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
|
||||
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程、Word导出 | ⭐⭐⭐⭐ | ✅ **开发完成(95%)** | P3 |
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# IIT Manager Agent模块 - 当前状态与开发指南
|
||||
|
||||
> **文档版本:** v2.2
|
||||
> **文档版本:** v2.4
|
||||
> **创建日期:** 2026-01-01
|
||||
> **维护者:** IIT Manager开发团队
|
||||
> **最后更新:** 2026-02-08 🎉 **质控系统 UI 与 LLM 格式优化计划制定完成!**
|
||||
> **最后更新:** 2026-02-08 🎉 **事件级质控架构 V3.1 开发完成!**
|
||||
> **重大里程碑:**
|
||||
> - ✅ 2026-02-08:**事件级质控架构 V3.1 完成**(record+event 独立质控 + 规则动态过滤 + 报告去重 + AI对话增强)
|
||||
> - ✅ 2026-02-08:**质控驾驶舱 UI 开发完成**(PromptBuilder XML 格式 + 驾驶舱页面 + 热力图 + 详情抽屉)
|
||||
> - ✅ 2026-02-08:**质控系统优化计划制定**(XML 临床切片格式 + 质控驾驶舱设计 + 方案 A 确认)
|
||||
> - ✅ 2026-02-07:**实时质控系统开发完成**(pg-boss防抖 + 质控日志 + 录入汇总 + 管理端批量操作)
|
||||
> - ✅ 2026-02-05:**V2.9.1 完整开发计划发布**(双脑架构 + 三层记忆 + 主动性增强 + 隐私合规)
|
||||
@@ -44,11 +46,11 @@ IIT Manager Agent(研究者发起试验管理助手)是一个基于企业微
|
||||
- AI能力:DeepSeek/Qwen + 自研 RAG
|
||||
|
||||
### 当前状态
|
||||
- **开发阶段**:🎉 **实时质控系统核心功能开发完成!待端到端测试**
|
||||
- **开发阶段**:🎉 **事件级质控架构 V3.1 开发完成!基本测试通过**
|
||||
- **整体完成度**:
|
||||
- **基础设施**:85%(REDCap + 企业微信 + AI 对话 + 实时质控)
|
||||
- **基础设施**:95%(REDCap + 企业微信 + AI 对话 + 实时质控 + 驾驶舱 UI + 事件级质控)
|
||||
- **架构设计**:100%(V2.9.1 完整开发计划发布)
|
||||
- **代码实现**:45%(实时质控系统已实现)
|
||||
- **代码实现**:60%(实时质控系统 + 驾驶舱 UI + 事件级质控 V3.1 已实现)
|
||||
|
||||
#### ✅ 已完成功能(基础设施)
|
||||
- ✅ 数据库Schema创建(iit_schema,9个表 = 原5个 + 新增4个质控表)
|
||||
@@ -77,6 +79,26 @@ IIT Manager Agent(研究者发起试验管理助手)是一个基于企业微
|
||||
- ✅ **自动化工具设计**(AutoMapper REDCap Schema 对齐)
|
||||
- ✅ **模块化开发文档**(6 份专项文档)
|
||||
|
||||
#### ✅ 已完成功能(质控驾驶舱 UI - 2026-02-08)
|
||||
- ✅ **PromptBuilder 类**(XML 临床切片格式构建器,减少 LLM 幻觉)
|
||||
- ✅ **ChatService 优化**(集成 PromptBuilder,使用 XML 格式化数据)
|
||||
- ✅ **质控驾驶舱页面**(IitQcCockpitPage.tsx,全屏展示模式)
|
||||
- ✅ **统计卡片组件**(QcStatCards.tsx,4 个核心指标)
|
||||
- ✅ **风险热力图组件**(RiskHeatmap.tsx,受试者×表单矩阵视图)
|
||||
- ✅ **详情抽屉组件**(QcDetailDrawer.tsx,含 LLM Trace 视图)
|
||||
- ✅ **驾驶舱后端 API**(iitQcCockpitService + Controller + Routes)
|
||||
- ✅ **前端类型定义**(qcCockpit.ts,完整的 TypeScript 类型)
|
||||
|
||||
#### ✅ 已完成功能(事件级质控 V3.1 - 2026-02-08)
|
||||
- ✅ **事件级质控架构**(每个 record+event 独立质控,不再合并数据)
|
||||
- ✅ **规则动态过滤**(applicableEvents/applicableForms 配置规则适用范围)
|
||||
- ✅ **RedcapAdapter 增强**(getAllRecordsByEvent + getFormEventMapping + getEvents)
|
||||
- ✅ **SkillRunner 重构**(按 record+event 执行 + filterApplicableRules)
|
||||
- ✅ **质控报告去重**(按 recordId+ruleId 去重,避免多事件重复问题)
|
||||
- ✅ **报告自动刷新**(导出 XML 前自动获取最新数据)
|
||||
- ✅ **AI 意图识别增强**(支持"严重违规有几项"等自然语言查询)
|
||||
- ✅ **Bug 修复**(formatPatientData 500 错误 + 记录数统计 + 报告限制移除)
|
||||
|
||||
#### ⏳ 待实施功能(按 Phase 规划)
|
||||
| Phase | 内容 | 优先级 | 状态 |
|
||||
|-------|------|--------|------|
|
||||
@@ -914,10 +936,11 @@ npx ts-node src/modules/iit-manager/test-wechat-push.ts
|
||||
---
|
||||
|
||||
> **提示**:本文档反映IIT Manager Agent模块的最新真实状态,每个里程碑完成后必须更新!
|
||||
> **最后更新**:2026-01-03 22:30
|
||||
> **当前进度**:Day 1-3 + Phase 1.5完成(60%)| 下一步:Phase 2 Function Calling + Dify知识库
|
||||
> **最后更新**:2026-02-08 22:00
|
||||
> **当前进度**:事件级质控 V3.1 完成(60%)| 下一步:Phase 3 ReAct 引擎 + 流水账
|
||||
> **重要文档**:
|
||||
> - [Phase 1.5开发完成记录](./06-开发记录/Phase1.5-AI对话集成REDCap完成记录.md) ⭐⭐⭐⭐⭐
|
||||
> - [事件级质控开发记录](./06-开发记录/2026-02-08-事件级质控与报告优化开发记录.md) ⭐⭐⭐⭐⭐
|
||||
> - [实时质控系统开发记录](./06-开发记录/2026-02-07-实时质控系统开发记录.md) ⭐⭐⭐⭐⭐
|
||||
> - [REDCap对接技术方案与实施指南](./04-开发计划/REDCap对接技术方案与实施指南.md) ⭐⭐⭐⭐⭐
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# **CRA Agent 业务逻辑与执行架构书**
|
||||
|
||||
**文档目的:** 基于用户定义的 5 大规则体系,构建标准化的 CRA 智能监查工作流。
|
||||
|
||||
**适用版本:** IIT Manager Agent V2.9.1
|
||||
|
||||
**创建日期:** 2026-02-07
|
||||
|
||||
## **🏛️ 一、 规则体系定义 (The 5 Pillars)**
|
||||
|
||||
我们将规则分为两类引擎执行,以平衡成本与智能。
|
||||
|
||||
| 编号 | 规则类型 | 执行引擎 | 来源方式 | 典型示例 |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| **1** | **变量质控** | **Hard Engine** (代码) | 自动从 Metadata 同步 | 空值检查、数值范围 (0\<BMI\<50)、逻辑跳转 |
|
||||
| **2** | **入排标准** | **AI Engine** (LLM) | AI 解析 Protocol \+ 人工确认 | 确诊时间 \< 3个月、实验室指标符合入组线 |
|
||||
| **3** | **方案偏离 (PD)** | **Hybrid** (混合) | 人工配置逻辑 | 访视超窗 (Date2 \- Date1 \> 28+3)、禁用药物使用 |
|
||||
| **4** | **AE 事件** | **AI Engine** (LLM) | 预置医学 Prompt | Lab 异常值 vs AE 记录一致性检查 (SAE Reconciliation) |
|
||||
| **5** | **伦理合规** | **Hard Engine** (代码) | 预置逻辑 | 知情同意书签署日期 \> 访视 1 日期 |
|
||||
|
||||
## **🔄 二、 智能监查工作流 (The Workflow)**
|
||||
|
||||
### **Step 1: 触发与范围界定 (Trigger)**
|
||||
|
||||
* **触发源**:
|
||||
* **自动触发**:Webhook (REDCap 数据录入) 或 Cron (每日凌晨)。
|
||||
* **人工触发**:用户点击“立即监查”。
|
||||
* **范围优化**:使用 **增量检查 (Incremental Check)**。只对新录入或变更的数据及其相关联规则进行检查。
|
||||
|
||||
### **Step 2: 漏斗式质控执行 (Funnel Execution)**
|
||||
|
||||
为每个受试者执行以下管道:
|
||||
|
||||
1. **Level 1: 阻断性检查 (Blocking)**
|
||||
* 检查伦理 (ICF) 和 关键变量缺失。
|
||||
* *如果 Fail*:直接标记为 Critical,**中止后续 AI 检查**(省钱)。
|
||||
2. **Level 2: 基础清洗 (Cleaning)**
|
||||
* 运行所有变量质控规则 (Hard Rules)。
|
||||
* 生成基础错误日志。
|
||||
3. **Level 3: AI 深度监查 (AI Reasoning)**
|
||||
* 组装 Context (XML+Markdown)。
|
||||
* 调用 LLM 检查 入排、PD、AE。
|
||||
* **输出证据链**:{ "status": "FAIL", "reason": "...", "evidence": { "var": "alt", "val": 150 } }
|
||||
|
||||
### **Step 3: 结果汇总 (Aggregation)**
|
||||
|
||||
更新 iit\_qc\_project\_stats 和 iit\_record\_summary 表。
|
||||
|
||||
* 生成 **风险热力图 (Risk Heatmap)** 数据源。
|
||||
|
||||
### **Step 4: 双模报告输出 (Dual-Mode Reporting)**
|
||||
|
||||
* **Mode A: 人类阅读版 (Interactive UI)**
|
||||
* 热力图 \+ 诊断卡片。
|
||||
* 支持 **“确认/忽略”** 操作 (Query Loop)。
|
||||
* **Mode B: LLM 阅读版 (Context Protocol)**
|
||||
* XML 结构化数据,包含统计摘要 \+ 严重问题清单 \+ 证据链。
|
||||
|
||||
### **Step 5: 智能问答 (Q\&A Loop)**
|
||||
|
||||
* 用户提问 \-\> ContextBuilder 提取 Mode B 报告 \-\> LLM 回答。
|
||||
* *场景*:“帮我列出所有疑似未报 AE 的患者。”
|
||||
|
||||
## **💡 三、 关键增强点**
|
||||
|
||||
1. **SDV 边界声明**:明确系统仅进行“逻辑一致性监查”,无法核对原始病历真伪。
|
||||
2. **人机回环 (HITL)**:所有 AI 生成的复杂规则(入排/PD),必须经过人工 **"Review & Activate"** 才能生效。
|
||||
3. **三态管理**:质控结果包含 Pending (AI 疑似), Confirmed (人工确认), Ignored (人工忽略)。
|
||||
|
||||
## **✅ 结论**
|
||||
|
||||
该方案逻辑闭环,技术可行。通过引入 **漏斗执行** 和 **人机回环**,可有效解决成本与准确性问题。
|
||||
@@ -0,0 +1,200 @@
|
||||
# **基于 Skills 的 CRA 规则配置实施指南**
|
||||
|
||||
**文档目的:** 定义如何通过 iit\_skills 表配置化实现 CRA 的 5 大核心工作(变量质控、入排、PD、AE、伦理)。
|
||||
|
||||
**适用版本:** IIT Manager Agent V2.9.1
|
||||
|
||||
**创建日期:** 2026-02-07
|
||||
|
||||
## **🏗️ 核心概念:Skill \= 规则容器**
|
||||
|
||||
在我们的架构中,**Skill (技能)** 是一个可执行的最小业务单元。它定义了:
|
||||
|
||||
1. **触发条件**:什么时候跑?(Webhook/Cron)
|
||||
2. **执行引擎**:用哪个引擎跑?(Hard/Soft)
|
||||
3. **配置数据**:具体规则是什么?(JSON/Prompt)
|
||||
4. **数据依赖**:需要哪些数据?(Tags)
|
||||
|
||||
### **数据库模型映射 (iit\_skills)**
|
||||
|
||||
我们复用并扩展 V2.6 计划中的 iit\_skills 表设计:
|
||||
|
||||
model IitSkill {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project\_id")
|
||||
name String // e.g., "入排标准核查"
|
||||
type String // 'HARD\_RULE' | 'LLM\_CHECK' | 'HYBRID'
|
||||
|
||||
// 触发配置
|
||||
triggerType String @map("trigger\_type") // 'WEBHOOK' | 'CRON' | 'MANUAL'
|
||||
cronExpr String? @map("cron\_expr") // 如果是定时任务
|
||||
|
||||
// 核心配置 (JSONB)
|
||||
// 包含:Prompts, JSONLogic, Thresholds
|
||||
config Json
|
||||
|
||||
// 数据依赖 (智能路由用)
|
||||
// 告诉 ContextBuilder 需要加载哪些 Tag
|
||||
requiredTags String\[\] @map("required\_tags") // e.g., \['\#lab', '\#demographics'\]
|
||||
|
||||
isEnabled Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@map("iit\_skills")
|
||||
@@schema("iit\_schema")
|
||||
}
|
||||
|
||||
## **🛠️ 五大规则的 Skill 实现方案**
|
||||
|
||||
我们通过配置不同类型的 Skill 来覆盖 CRA 的所有工作。
|
||||
|
||||
### **1\. 变量质控 Skill (Type: HARD\_RULE)**
|
||||
|
||||
**对应需求:** 针对每个变量,构建数据质控规则。
|
||||
|
||||
* **场景**:空值检查、数值范围、逻辑跳转。
|
||||
* **配置来源**:Rule Studio (Layer 1\) 自动生成。
|
||||
* **Config 结构**:
|
||||
{
|
||||
"engine": "HardRuleEngine",
|
||||
"rules": \[
|
||||
{ "field": "age", "op": "between", "args": \[18, 80\] },
|
||||
{ "field": "bmi", "op": "lt", "args": \[50\] }
|
||||
\]
|
||||
}
|
||||
|
||||
* **执行**:Node.js 直接计算,毫秒级响应。
|
||||
|
||||
### **2\. 入排标准 Skill (Type: LLM\_CHECK)**
|
||||
|
||||
**对应需求:** 针对是否符合入排标准,建立医学逻辑规则。
|
||||
|
||||
* **场景**:复杂的医学判断(如:病理确诊时间 \< 3个月)。
|
||||
* **配置来源**:Rule Studio (Layer 3\) AI 提取 \+ 人工确认。
|
||||
* **数据依赖**:\['\#demographics', '\#lab', '\#history'\]
|
||||
* **Config 结构**:
|
||||
{
|
||||
"engine": "SoftRuleEngine",
|
||||
"model": "deepseek-v3",
|
||||
"system\_prompt": "你是一个医学监查员...",
|
||||
"checks": \[
|
||||
{
|
||||
"id": "I-03",
|
||||
"desc": "肝肾功能正常 (ALT/AST \< 2.5 ULN)",
|
||||
"prompt\_template": "基于以下实验室数据 {{\#lab}},判断..."
|
||||
}
|
||||
\]
|
||||
}
|
||||
|
||||
### **3\. 方案偏离 Skill (Type: HYBRID)**
|
||||
|
||||
**对应需求:** 针对是否出现方案偏离,建立核查规则。
|
||||
|
||||
* **场景**:访视超窗、漏做检查。
|
||||
* **配置来源**:Rule Studio (Layer 2\) 逻辑构建器。
|
||||
* **Config 结构**:
|
||||
{
|
||||
"engine": "HybridEngine",
|
||||
"logic": {
|
||||
"if": \[
|
||||
{ "date\_diff": \["$V2.date", "$V1.date"\] },
|
||||
{ "\>": 31 }, // 28 \+ 3
|
||||
"FAIL",
|
||||
"PASS"
|
||||
\]
|
||||
}
|
||||
}
|
||||
|
||||
### **4\. AE 监测 Skill (Type: LLM\_CHECK)**
|
||||
|
||||
**对应需求:** 针对是否出现 AE 事件,建立核查规则。
|
||||
|
||||
* **场景**:SAE Reconciliation(Lab 异常 vs AE 记录)。
|
||||
* **数据依赖**:\['\#lab', '\#ae'\]
|
||||
* **Config 结构**:
|
||||
{
|
||||
"engine": "SoftRuleEngine",
|
||||
"task": "AE\_RECONCILIATION",
|
||||
"prompt": "对比 \<lab\_data\> 中的 Grade 3+ 异常值与 \<ae\_data\> 记录,找出未报告的 AE。"
|
||||
}
|
||||
|
||||
### **5\. 伦理合规 Skill (Type: HARD\_RULE)**
|
||||
|
||||
**对应需求:** 针对是否出现伦理问题,建立规则。
|
||||
|
||||
* **场景**:ICF 日期逻辑。
|
||||
* **Config 结构**:
|
||||
{
|
||||
"engine": "HardRuleEngine",
|
||||
"rule": {
|
||||
"op": "date\_before",
|
||||
"a": "$icf\_date",
|
||||
"b": "$first\_visit\_date"
|
||||
},
|
||||
"severity": "CRITICAL"
|
||||
}
|
||||
|
||||
## **⏰ 三大触发时机详解 (Trigger Strategy)**
|
||||
|
||||
我们将质控规则的执行时机划分为“实时、定时、人工”黄金三角,以平衡时效性与成本。
|
||||
|
||||
### **1\. 🟢 实时触发 (Real-time / Webhook)**
|
||||
|
||||
* **触发源**:REDCap DET (Data Entry Trigger)。CRC 保存任意表单时触发。
|
||||
* **执行范围**:**单点切片 (Micro-Batch)**。
|
||||
* 仅针对 **当前受试者 (Current Record)**。
|
||||
* 仅加载 **与当前表单相关** 的 Skill (通过 formName 过滤)。
|
||||
* *例如:录入“血常规”单,系统只检查 \#lab 相关规则,不会检查人口学。*
|
||||
* **核心价值**:**阻断错误**。在 CRC 记忆犹新时(秒级)推送企微提醒,纠正成本最低。
|
||||
* **成本策略**:默认优先跑 **Hard Rules**。涉及核心安全指标(如 AE)时才触发 Soft Rules (LLM)。
|
||||
|
||||
### **2\. 🔵 定时触发 (Scheduled / Cron)**
|
||||
|
||||
* **触发源**:pg-boss Cron Job。每日凌晨 (e.g., 02:00) 执行。
|
||||
* **执行范围**:**全量扫描 (Full Scan)**。
|
||||
* 针对 **所有活跃受试者**。
|
||||
* 重点运行 **跨表逻辑** (如一致性检查) 和 **时间敏感型规则** (如访视超窗 PD)。
|
||||
* **核心价值**:**发现隐患**。捕捉“因时间流逝而产生的问题”(如昨天未超窗,今天超窗)和“漏录问题”。
|
||||
* **成本策略**:使用 **增量标记**。若数据 Hash 未变且无时间规则,跳过 LLM 检查。
|
||||
|
||||
### **3\. 🟠 人工触发 (Manual / On-Demand)**
|
||||
|
||||
* **触发源**:管理端 "一键全量质控" 或 "单受试者重跑" 按钮。
|
||||
* **执行范围**:**按需全量**。
|
||||
* 针对选定的受试者范围。
|
||||
* 运行 **所有启用** 的 Skill。
|
||||
* **核心价值**:**合规审计与验证**。用于项目初始化清洗、规则调整后的验证、或上级核查前的自查。
|
||||
|
||||
## **🔄 调度与执行:Skill Runner**
|
||||
|
||||
我们不需要为每个规则写死代码,而是实现一个通用的 **SkillRunner**。
|
||||
|
||||
### **执行流程**
|
||||
|
||||
1. **触发 (Trigger)**:
|
||||
* Webhook 收到数据 \-\> 触发 SkillRunner.runByTrigger('WEBHOOK', projectId, recordId, formName)
|
||||
* Cron Job 到点 \-\> 触发 SkillRunner.runByTrigger('CRON', projectId)
|
||||
* 人工点击 \-\> 触发 SkillRunner.runByTrigger('MANUAL', projectId)
|
||||
2. **加载 (Load)**:
|
||||
* Runner 从 iit\_skills 表加载所有启用的 Skill。
|
||||
* **过滤**:如果是 WEBHOOK 触发,仅加载与当前 formName 关联的 Skill。
|
||||
3. **路由 (Route)**:
|
||||
* 根据 Skill 的 type 分发给对应的 Engine (HardRuleEngine 或 SoftRuleEngine)。
|
||||
4. **上下文构建 (Context)**:
|
||||
* 如果需要 LLM,调用 ContextBuilder,传入 Skill 定义的 requiredTags,只拉取相关数据。
|
||||
5. **结果聚合 (Aggregate)**:
|
||||
* 收集所有 Skill 的执行结果,存入 iit\_qc\_logs。
|
||||
|
||||
## **✅ 结论:对当前计划的影响**
|
||||
|
||||
你的 **V2.6 开发计划** 非常稳健,只需要在细节上明确 Skill 的定义即可。
|
||||
|
||||
**建议调整:**
|
||||
|
||||
1. **Phase 1**:重点设计 iit\_skills 的 JSON Schema,确保它能容纳上述 5 种类型的配置。
|
||||
2. **Phase 2**:实现 SkillRunner,作为连接 SOP 和 Engine 的中间件。
|
||||
|
||||
**总结**:通过 SKILLS 配置化,你的系统就像一个\*\*“可插拔的乐高玩具”\*\*。
|
||||
|
||||
* 如果明天要加一个“肿瘤评估 (RECIST)”规则,你只需要新增一个 Skill,完全不用改后端代码。
|
||||
* 这正是 SaaS 化产品的核心竞争力。
|
||||
@@ -338,18 +338,33 @@ WHERE field_name = 'informed_consent';
|
||||
|
||||
## 六、验收标准
|
||||
|
||||
### 6.1 阶段 1 验收
|
||||
### 6.1 阶段 1 验收 ✅ **已完成 (2026-02-08)**
|
||||
|
||||
- [ ] 企业微信问"质控情况",AI 回答格式清晰、无幻觉
|
||||
- [ ] AI 回答包含具体问题和记录数
|
||||
- [ ] 日志中可看到 XML 格式的 Prompt
|
||||
- [x] 企业微信问"质控情况",AI 回答格式清晰、无幻觉
|
||||
- [x] AI 回答包含具体问题和记录数
|
||||
- [x] 日志中可看到 XML 格式的 Prompt
|
||||
|
||||
### 6.2 阶段 2 验收
|
||||
**完成的文件:**
|
||||
- `backend/src/modules/iit-manager/services/PromptBuilder.ts` - XML 临床切片格式构建器
|
||||
- `backend/src/modules/iit-manager/services/ChatService.ts` - 集成 PromptBuilder,优化 LLM 格式
|
||||
|
||||
- [ ] 点击"质控全览图"按钮可进入驾驶舱页面
|
||||
- [ ] 统计卡片正确显示质量分、违规数、完成率
|
||||
- [ ] 热力图正确显示记录×表单的质控状态
|
||||
- [ ] 点击红色单元格可查看问题详情
|
||||
### 6.2 阶段 2 验收 ✅ **已完成 (2026-02-08)**
|
||||
|
||||
- [x] 点击"质控全览图"按钮可进入驾驶舱页面
|
||||
- [x] 统计卡片正确显示质量分、违规数、完成率
|
||||
- [x] 热力图正确显示记录×表单的质控状态
|
||||
- [x] 点击红色单元格可查看问题详情
|
||||
|
||||
**完成的文件:**
|
||||
- `frontend-v2/src/modules/admin/pages/IitQcCockpitPage.tsx` - 驾驶舱主页面
|
||||
- `frontend-v2/src/modules/admin/pages/IitQcCockpitPage.css` - 驾驶舱样式
|
||||
- `frontend-v2/src/modules/admin/components/qc-cockpit/QcStatCards.tsx` - 统计卡片组件
|
||||
- `frontend-v2/src/modules/admin/components/qc-cockpit/RiskHeatmap.tsx` - 风险热力图组件
|
||||
- `frontend-v2/src/modules/admin/components/qc-cockpit/QcDetailDrawer.tsx` - 详情抽屉组件
|
||||
- `frontend-v2/src/modules/admin/types/qcCockpit.ts` - 类型定义
|
||||
- `backend/src/modules/admin/iit-projects/iitQcCockpitService.ts` - 驾驶舱数据服务
|
||||
- `backend/src/modules/admin/iit-projects/iitQcCockpitController.ts` - 驾驶舱 API 控制器
|
||||
- `backend/src/modules/admin/iit-projects/iitQcCockpitRoutes.ts` - 驾驶舱路由
|
||||
|
||||
### 6.3 阶段 3 验收
|
||||
|
||||
|
||||
583
docs/03-业务模块/IIT Manager Agent/04-开发计划/08-CRA智能质控引擎开发计划.md
Normal file
583
docs/03-业务模块/IIT Manager Agent/04-开发计划/08-CRA智能质控引擎开发计划.md
Normal file
@@ -0,0 +1,583 @@
|
||||
# CRA 智能质控引擎开发计划
|
||||
|
||||
> **版本:** V1.0
|
||||
> **日期:** 2026-02-08
|
||||
> **基于:** V2.6 综合开发计划、CRA Agent 业务逻辑与执行架构书、Skills 配置实施指南
|
||||
> **核心目标:** 实现基于规则的智能质控引擎 + 报告驱动的 LLM 问答
|
||||
|
||||
---
|
||||
|
||||
## 📋 目录
|
||||
|
||||
1. [背景与目标](#1-背景与目标)
|
||||
2. [架构设计](#2-架构设计)
|
||||
3. [五大规则体系](#3-五大规则体系)
|
||||
4. [当前代码现状](#4-当前代码现状)
|
||||
5. [开发任务清单](#5-开发任务清单)
|
||||
6. [数据库设计补充](#6-数据库设计补充)
|
||||
7. [验收标准](#7-验收标准)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
### 1.1 业务需求
|
||||
|
||||
针对 CRA(临床研究助理)的质控工作,基于 REDCap 系统的数据结构,建立以下规则体系:
|
||||
|
||||
| 编号 | 规则类型 | 说明 | 来源 |
|
||||
|------|----------|------|------|
|
||||
| 1 | 变量质控 | 针对每个变量的数据校验(空值、范围、格式) | 自动从 Metadata 同步 |
|
||||
| 2 | 入排标准 | 判断是否符合入组/排除标准 | AI 解析 Protocol + 人工确认 |
|
||||
| 3 | 方案偏离 (PD) | 检测访视超窗、漏做检查等 | 人工配置逻辑 |
|
||||
| 4 | AE 事件 | 检测未报告的不良事件 | 预置医学 Prompt |
|
||||
| 5 | 伦理合规 | ICF 签署时间、隐私保护等 | 预置硬规则 |
|
||||
|
||||
### 1.2 核心目标
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🎯 目标:报告驱动的智能质控 │
|
||||
│ │
|
||||
│ 后台预计算 → 生成结构化报告 → LLM 阅读报告 → 回答用户问题 │
|
||||
│ │
|
||||
│ ✅ 快速(报告已预生成) │
|
||||
│ ✅ 全面(后台执行所有规则) │
|
||||
│ ✅ 省钱(LLM 只做阅读理解) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.3 与 V2.6 计划的关系
|
||||
|
||||
本计划是 V2.6 综合开发计划的**专项实施细化**,聚焦于:
|
||||
- Phase 1 的 `HardRuleEngine` 深化
|
||||
- Phase 2 的 `SoftRuleEngine` 实现
|
||||
- Phase 4 的 `SchedulerService` 和 `ReportService` 实现
|
||||
|
||||
---
|
||||
|
||||
## 2. 架构设计
|
||||
|
||||
### 2.1 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 触发层 (Trigger) │
|
||||
├──────────────────┬──────────────────┬───────────────────────────┤
|
||||
│ 🟢 Webhook │ 🔵 Cron │ 🟠 Manual │
|
||||
│ REDCap DET │ 每日凌晨 │ 一键全量质控 │
|
||||
│ 单记录实时 │ 全量扫描 │ 按需执行 │
|
||||
└──────────────────┴──────────────────┴───────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🎯 SkillRunner (调度器) │
|
||||
│ │
|
||||
│ 1. 加载启用的 Skills │
|
||||
│ 2. 根据 triggerType 过滤 │
|
||||
│ 3. 路由到对应 Engine │
|
||||
│ 4. 聚合结果 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────┼─────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||||
│ HardRuleEngine │ │ SoftRuleEngine │ │ HybridEngine │
|
||||
│ (已实现 ✅) │ │ (待实现 ❌) │ │ (待实现 ❌) │
|
||||
│ │ │ │ │ │
|
||||
│ - 变量质控 │ │ - 入排标准 │ │ - 方案偏离 │
|
||||
│ - 伦理合规 │ │ - AE 检测 │ │ - Hard + Soft │
|
||||
│ │ │ │ │ │
|
||||
│ JSON Logic │ │ LLM 推理 │ │ 条件分支 │
|
||||
└──────────────────┘ └──────────────────┘ └──────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 📊 结果存储 & 报告生成 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ iit_qc_logs → 详细质控日志 │
|
||||
│ iit_qc_project_stats → 项目统计摘要 │
|
||||
│ iit_qc_report (新) → LLM 友好的结构化报告 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 💬 用户问答 (实时) │
|
||||
│ │
|
||||
│ 用户提问 → ContextBuilder 加载报告 → LLM 阅读 → 回答 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 漏斗式执行策略
|
||||
|
||||
为每个受试者执行以下管道,**分级检查,逐层深入**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Level 1: 阻断性检查 (Blocking) │
|
||||
│ - 伦理合规 (ICF 日期) │
|
||||
│ - 关键字段缺失 │
|
||||
│ 如果 FAIL → 直接标记 Critical,跳过后续 AI 检查(省钱) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Level 2: 基础清洗 (Hard Rules) │
|
||||
│ - 所有变量质控规则 │
|
||||
│ - 生成基础错误日志 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Level 3: AI 深度监查 (Soft Rules) │
|
||||
│ - 入排标准判断 │
|
||||
│ - 方案偏离检测 │
|
||||
│ - AE 事件核查 │
|
||||
│ - 输出证据链 │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 五大规则体系
|
||||
|
||||
### 3.1 规则类型与执行引擎
|
||||
|
||||
| 编号 | 规则类型 | 执行引擎 | 触发时机 | 典型示例 |
|
||||
|------|----------|----------|----------|----------|
|
||||
| 1 | 变量质控 | HardRuleEngine | 实时 + 定时 | 空值检查、0 < BMI < 50 |
|
||||
| 2 | 入排标准 | SoftRuleEngine | 定时 + 人工 | 确诊时间 < 3个月 |
|
||||
| 3 | 方案偏离 | HybridEngine | 定时 | 访视超窗 (Date2 - Date1 > 28+3) |
|
||||
| 4 | AE 事件 | SoftRuleEngine | 定时 | Lab 异常 vs AE 记录一致性 |
|
||||
| 5 | 伦理合规 | HardRuleEngine | 实时 | ICF 签署日期 > 首次访视 |
|
||||
|
||||
### 3.2 Skill 配置示例
|
||||
|
||||
#### 3.2.1 变量质控 Skill (HARD_RULE)
|
||||
|
||||
```json
|
||||
{
|
||||
"skillType": "VARIABLE_QC",
|
||||
"name": "变量质控",
|
||||
"type": "HARD_RULE",
|
||||
"triggerType": "webhook",
|
||||
"config": {
|
||||
"engine": "HardRuleEngine",
|
||||
"rules": [
|
||||
{
|
||||
"id": "VQ-001",
|
||||
"name": "年龄范围检查",
|
||||
"field": "age",
|
||||
"formName": "demographics",
|
||||
"logic": { "and": [{ ">=": [{ "var": "age" }, 18] }, { "<=": [{ "var": "age" }, 80] }] },
|
||||
"message": "年龄必须在 18-80 岁之间",
|
||||
"severity": "error",
|
||||
"category": "lab_values"
|
||||
},
|
||||
{
|
||||
"id": "VQ-002",
|
||||
"name": "BMI 范围检查",
|
||||
"field": "bmi",
|
||||
"formName": "demographics",
|
||||
"logic": { "and": [{ ">": [{ "var": "bmi" }, 0] }, { "<": [{ "var": "bmi" }, 50] }] },
|
||||
"message": "BMI 值异常",
|
||||
"severity": "warning",
|
||||
"category": "lab_values"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2.2 入排标准 Skill (LLM_CHECK)
|
||||
|
||||
```json
|
||||
{
|
||||
"skillType": "INCLUSION_EXCLUSION",
|
||||
"name": "入排标准核查",
|
||||
"type": "LLM_CHECK",
|
||||
"triggerType": "cron",
|
||||
"config": {
|
||||
"engine": "SoftRuleEngine",
|
||||
"model": "deepseek-v3",
|
||||
"systemPrompt": "你是一个专业的临床研究监查员,负责核查受试者是否符合入组标准。",
|
||||
"checks": [
|
||||
{
|
||||
"id": "IE-001",
|
||||
"name": "确诊时间核查",
|
||||
"promptTemplate": "基于以下数据,判断受试者的确诊时间是否在 3 个月内:\n{{#demographics}}\n{{#medical_history}}\n\n请给出判断结果 (PASS/FAIL) 和理由。",
|
||||
"requiredTags": ["#demographics", "#medical_history"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredTags": ["#demographics", "#medical_history", "#lab"]
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2.3 伦理合规 Skill (HARD_RULE)
|
||||
|
||||
```json
|
||||
{
|
||||
"skillType": "ETHICS_COMPLIANCE",
|
||||
"name": "伦理合规检查",
|
||||
"type": "HARD_RULE",
|
||||
"triggerType": "webhook",
|
||||
"config": {
|
||||
"engine": "HardRuleEngine",
|
||||
"level": "blocking",
|
||||
"rules": [
|
||||
{
|
||||
"id": "EC-001",
|
||||
"name": "知情同意书签署时间",
|
||||
"field": ["icf_date", "first_visit_date"],
|
||||
"logic": { "<=": [{ "var": "icf_date" }, { "var": "first_visit_date" }] },
|
||||
"message": "知情同意书签署日期必须早于或等于首次访视日期",
|
||||
"severity": "error",
|
||||
"category": "ethics"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前代码现状
|
||||
|
||||
### 4.1 已实现组件 ✅
|
||||
|
||||
| 组件 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| `IitSkill` 表 | `prisma/schema.prisma` | 已定义,支持 triggerType |
|
||||
| `IitFieldMapping` 表 | `prisma/schema.prisma` | 字段映射表 |
|
||||
| `HardRuleEngine` | `engines/HardRuleEngine.ts` | 基于 JSON Logic,支持 formName 过滤 |
|
||||
| `QcService` | `services/QcService.ts` | 基础查询服务 |
|
||||
| `PromptBuilder` | `services/PromptBuilder.ts` | XML Clinical Slice 格式 |
|
||||
| `RedcapAdapter` | `adapters/RedcapAdapter.ts` | REDCap API 适配 |
|
||||
| QC Cockpit UI | `frontend-v2/.../IitQcCockpitPage.tsx` | 热力图 + 详情抽屉 |
|
||||
| 字段元数据同步 | `iitProjectService.syncMetadata` | 含 Form Labels |
|
||||
|
||||
### 4.2 缺失组件 ❌
|
||||
|
||||
| 组件 | 优先级 | 依赖 | 说明 |
|
||||
|------|--------|------|------|
|
||||
| `SoftRuleEngine` | P0 | LLMFactory | LLM 推理引擎 |
|
||||
| `HybridEngine` | P1 | HardRule + SoftRule | 混合执行引擎 |
|
||||
| `SkillRunner` | P0 | 所有 Engine | 规则调度器 |
|
||||
| `QcReportService` | P0 | SkillRunner | LLM 友好报告生成 |
|
||||
| `iit_qc_report` 表 | P0 | - | 报告存储 |
|
||||
| 定时调度 | P1 | pg-boss / node-cron | Cron 触发 |
|
||||
| 增量检查 | P2 | - | 数据 Hash 策略 |
|
||||
| Rule Studio UI | P2 | - | 规则配置界面 |
|
||||
| 默认规则配置 | P0 | - | 5 大规则的初始 JSON |
|
||||
|
||||
---
|
||||
|
||||
## 5. 开发任务清单
|
||||
|
||||
### Phase 1: 核心引擎 (Week 1)
|
||||
|
||||
| 任务 | 优先级 | 预估 | 产出 |
|
||||
|------|--------|------|------|
|
||||
| 1.1 实现 `SoftRuleEngine` | P0 | 2天 | LLM 推理引擎 |
|
||||
| 1.2 实现 `SkillRunner` | P0 | 1天 | 规则调度器 |
|
||||
| 1.3 扩展 `IitSkill` Schema | P0 | 0.5天 | 添加 `requiredTags` 字段 |
|
||||
| 1.4 创建默认规则配置 | P0 | 1天 | 5 大规则的 Seed 数据 |
|
||||
|
||||
#### 1.1 SoftRuleEngine 设计
|
||||
|
||||
```typescript
|
||||
// backend/src/modules/iit-manager/engines/SoftRuleEngine.ts
|
||||
|
||||
export interface SoftRuleCheck {
|
||||
id: string;
|
||||
name: string;
|
||||
promptTemplate: string;
|
||||
requiredTags: string[];
|
||||
}
|
||||
|
||||
export interface SoftRuleResult {
|
||||
checkId: string;
|
||||
status: 'PASS' | 'FAIL' | 'UNCERTAIN';
|
||||
reason: string;
|
||||
evidence: Record<string, any>;
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
export class SoftRuleEngine {
|
||||
private projectId: string;
|
||||
private llmClient: LLMClient;
|
||||
|
||||
async execute(
|
||||
recordId: string,
|
||||
data: Record<string, any>,
|
||||
checks: SoftRuleCheck[]
|
||||
): Promise<SoftRuleResult[]>;
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 SkillRunner 设计
|
||||
|
||||
```typescript
|
||||
// backend/src/modules/iit-manager/engines/SkillRunner.ts
|
||||
|
||||
export class SkillRunner {
|
||||
/**
|
||||
* 按触发类型执行 Skills
|
||||
*/
|
||||
async runByTrigger(
|
||||
triggerType: 'webhook' | 'cron' | 'manual',
|
||||
projectId: string,
|
||||
options?: {
|
||||
recordId?: string; // webhook 时必传
|
||||
formName?: string; // webhook 时过滤相关规则
|
||||
}
|
||||
): Promise<SkillRunResult>;
|
||||
|
||||
/**
|
||||
* 执行单个 Skill
|
||||
*/
|
||||
private async executeSkill(
|
||||
skill: IitSkill,
|
||||
recordId: string,
|
||||
data: Record<string, any>
|
||||
): Promise<SkillResult>;
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 2: 报告系统 (Week 2)
|
||||
|
||||
| 任务 | 优先级 | 预估 | 产出 |
|
||||
|------|--------|------|------|
|
||||
| 2.1 设计 `iit_qc_report` 表 | P0 | 0.5天 | 报告存储 Schema |
|
||||
| 2.2 实现 `QcReportService` | P0 | 2天 | 报告生成服务 |
|
||||
| 2.3 集成到 Cockpit UI | P1 | 1天 | 报告查看入口 |
|
||||
| 2.4 实现 LLM 问答集成 | P1 | 1天 | 基于报告回答 |
|
||||
|
||||
#### 2.2 QcReportService 设计
|
||||
|
||||
```typescript
|
||||
// backend/src/modules/iit-manager/services/QcReportService.ts
|
||||
|
||||
export interface QcReport {
|
||||
projectId: string;
|
||||
generatedAt: Date;
|
||||
summary: {
|
||||
totalRecords: number;
|
||||
criticalIssues: number;
|
||||
pendingQueries: number;
|
||||
passRate: number;
|
||||
};
|
||||
criticalList: QcIssue[];
|
||||
warningList: QcIssue[];
|
||||
llmFriendlyXml: string; // LLM 阅读版
|
||||
}
|
||||
|
||||
export class QcReportService {
|
||||
/**
|
||||
* 生成项目质控报告
|
||||
*/
|
||||
async generateReport(projectId: string): Promise<QcReport>;
|
||||
|
||||
/**
|
||||
* 获取缓存的报告(用于 LLM 问答)
|
||||
*/
|
||||
async getCachedReport(projectId: string): Promise<string>;
|
||||
|
||||
/**
|
||||
* 构建 LLM 友好的 XML 报告
|
||||
*/
|
||||
private buildLlmXmlReport(stats: ProjectStats, issues: QcIssue[]): string;
|
||||
}
|
||||
```
|
||||
|
||||
#### LLM 阅读版报告格式
|
||||
|
||||
```xml
|
||||
<qc_report project="PD-001" generated="2026-02-08T10:00:00Z">
|
||||
<summary>
|
||||
<total_records>50</total_records>
|
||||
<critical_issues>3</critical_issues>
|
||||
<pending_queries>12</pending_queries>
|
||||
<pass_rate>85.2%</pass_rate>
|
||||
</summary>
|
||||
|
||||
<critical_list>
|
||||
<issue record="P001" rule="EC-001" severity="RED">
|
||||
<description>知情同意书签署日期(2026-01-15)晚于首次访视(2026-01-10)</description>
|
||||
<evidence>
|
||||
<field name="icf_date">2026-01-15</field>
|
||||
<field name="first_visit_date">2026-01-10</field>
|
||||
</evidence>
|
||||
</issue>
|
||||
<issue record="P003" rule="IE-001" severity="RED">
|
||||
<description>受试者确诊时间超过入组标准(确诊日期距入组已超过3个月)</description>
|
||||
<evidence>
|
||||
<field name="diagnosis_date">2025-10-01</field>
|
||||
<field name="enrollment_date">2026-02-01</field>
|
||||
</evidence>
|
||||
</issue>
|
||||
</critical_list>
|
||||
|
||||
<warning_list>
|
||||
<issue record="P007" rule="VQ-002" severity="YELLOW">
|
||||
<description>BMI 值偏高(42.5),请核实</description>
|
||||
</issue>
|
||||
</warning_list>
|
||||
|
||||
<by_form>
|
||||
<form name="人口学" total="50" pass="48" fail="2" />
|
||||
<form name="实验室检查" total="150" pass="142" fail="8" />
|
||||
</by_form>
|
||||
</qc_report>
|
||||
```
|
||||
|
||||
### Phase 3: 定时调度 (Week 3)
|
||||
|
||||
| 任务 | 优先级 | 预估 | 产出 |
|
||||
|------|--------|------|------|
|
||||
| 3.1 集成 node-cron | P1 | 0.5天 | 定时任务框架 |
|
||||
| 3.2 实现 Cron 触发逻辑 | P1 | 1天 | 定时全量质控 |
|
||||
| 3.3 实现增量检查 | P2 | 1天 | 数据 Hash 跳过 |
|
||||
| 3.4 实现 Webhook 触发 | P2 | 1天 | REDCap DET 集成 |
|
||||
|
||||
### Phase 4: 规则配置 UI (Week 4)
|
||||
|
||||
| 任务 | 优先级 | 预估 | 产出 |
|
||||
|------|--------|------|------|
|
||||
| 4.1 Rule Studio 页面框架 | P2 | 1天 | 规则列表 + 详情 |
|
||||
| 4.2 规则编辑器 | P2 | 2天 | JSON 可视化编辑 |
|
||||
| 4.3 规则测试功能 | P2 | 1天 | 单条规则验证 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据库设计补充
|
||||
|
||||
### 6.1 扩展 IitSkill 表
|
||||
|
||||
```prisma
|
||||
model IitSkill {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
skillType String @map("skill_type")
|
||||
name String
|
||||
description String?
|
||||
|
||||
// 规则类型
|
||||
ruleType String @default("HARD_RULE") @map("rule_type") // 'HARD_RULE' | 'LLM_CHECK' | 'HYBRID'
|
||||
|
||||
// 执行级别
|
||||
level String @default("normal") // 'blocking' | 'normal'
|
||||
|
||||
// 核心配置
|
||||
config Json @db.JsonB
|
||||
|
||||
// 数据依赖(智能路由用)
|
||||
requiredTags String[] @map("required_tags") // 新增:e.g., ['#lab', '#demographics']
|
||||
|
||||
// 触发配置
|
||||
triggerType String @default("webhook") @map("trigger_type")
|
||||
cronSchedule String? @map("cron_schedule")
|
||||
|
||||
isActive Boolean @default(true) @map("is_active")
|
||||
priority Int @default(100) // 新增:执行优先级
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([projectId, skillType], map: "unique_iit_skill_project_type")
|
||||
@@index([projectId], map: "idx_iit_skill_project")
|
||||
@@index([isActive, triggerType], map: "idx_iit_skill_active_trigger")
|
||||
@@map("skills")
|
||||
@@schema("iit_schema")
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 新增 IitQcReport 表
|
||||
|
||||
```prisma
|
||||
/// 质控报告存储表 - 存储预生成的 LLM 友好报告
|
||||
model IitQcReport {
|
||||
id String @id @default(uuid())
|
||||
projectId String @map("project_id")
|
||||
|
||||
// 报告类型
|
||||
reportType String @default("daily") @map("report_type") // 'daily' | 'weekly' | 'on_demand'
|
||||
|
||||
// 统计摘要
|
||||
summary Json @db.JsonB // { totalRecords, criticalIssues, pendingQueries, passRate }
|
||||
|
||||
// 详细问题列表
|
||||
issues Json @db.JsonB // [{ record, rule, severity, description, evidence }]
|
||||
|
||||
// LLM 友好的 XML 报告
|
||||
llmReport String @map("llm_report") @db.Text
|
||||
|
||||
// 报告生成时间
|
||||
generatedAt DateTime @default(now()) @map("generated_at")
|
||||
|
||||
// 报告有效期
|
||||
expiresAt DateTime? @map("expires_at")
|
||||
|
||||
@@index([projectId, reportType], map: "idx_qc_report_project_type")
|
||||
@@index([generatedAt], map: "idx_qc_report_generated")
|
||||
@@map("qc_reports")
|
||||
@@schema("iit_schema")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
### 7.1 功能验收
|
||||
|
||||
| 功能 | 验收标准 |
|
||||
|------|----------|
|
||||
| 变量质控 | 单记录质控 < 100ms;批量 50 记录 < 2s |
|
||||
| 入排标准 | LLM 判断准确率 > 90%;单记录 < 3s |
|
||||
| 报告生成 | 50 记录的项目报告生成 < 5s |
|
||||
| LLM 问答 | 基于报告回答延迟 < 2s |
|
||||
| 定时任务 | 每日凌晨自动执行,连续 7 天无故障 |
|
||||
|
||||
### 7.2 性能指标
|
||||
|
||||
| 指标 | 目标值 |
|
||||
|------|--------|
|
||||
| HardRuleEngine 执行时间 | < 100ms / 记录 |
|
||||
| SoftRuleEngine 执行时间 | < 3s / 记录 |
|
||||
| 报告加载时间 | < 200ms |
|
||||
| 端到端问答延迟 | < 3s |
|
||||
|
||||
### 7.3 业务验收
|
||||
|
||||
- [ ] CRA 可以通过 Cockpit 查看所有严重问题
|
||||
- [ ] 点击问题可以查看详细数据和证据
|
||||
- [ ] 用户可以通过对话询问质控问题,LLM 基于报告回答
|
||||
- [ ] 定时任务每日自动执行,生成最新报告
|
||||
- [ ] 规则可以通过配置界面增删改
|
||||
|
||||
---
|
||||
|
||||
## 8. 风险与应对
|
||||
|
||||
| 风险 | 影响 | 应对措施 |
|
||||
|------|------|----------|
|
||||
| LLM 判断不准确 | 入排/AE 检测误报 | 三态管理(Pending → 人工确认) |
|
||||
| 规则配置复杂 | 用户上手困难 | 提供预置规则模板 |
|
||||
| 数据量大时性能下降 | 质控变慢 | 增量检查 + 分批执行 |
|
||||
| REDCap Webhook 不稳定 | 实时质控失效 | 定时任务兜底 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 参考文档
|
||||
|
||||
- [CRA Agent 业务逻辑与执行架构书](../02-技术设计/CRA%20Agent%20业务逻辑与执行架构书%20(1).md)
|
||||
- [基于 Skills 的 CRA 规则配置实施指南](../02-技术设计/docs_03-业务模块_IIT%20Manager%20Agent_02-技术设计_11-基于Skills的CRA规则配置实施指南.md)
|
||||
- [V2.6 综合开发计划](./IIT%20Manager%20Agent%20V2.6%20综合开发计划.md)
|
||||
- [02-核心引擎实现指南](./02-核心引擎实现指南.md)
|
||||
|
||||
---
|
||||
|
||||
**文档维护人**:AI Agent
|
||||
**最后更新**:2026-02-08
|
||||
|
||||
### 更新日志
|
||||
|
||||
| 版本 | 日期 | 更新内容 |
|
||||
|------|------|----------|
|
||||
| V1.0 | 2026-02-08 | 初始版本,基于方案审查和代码分析 |
|
||||
@@ -0,0 +1,122 @@
|
||||
# **LLM 交互协议与 Prompt 最佳实践指南**
|
||||
|
||||
**文档目的:** 定义“质控报告”的标准上下文格式,并提供配套的 System Prompt,以消除幻觉、确保回复准确性。
|
||||
|
||||
**适用版本:** IIT Manager Agent V2.9.1
|
||||
|
||||
**创建日期:** 2026-02-08
|
||||
|
||||
## **🧠 一、 核心原理:为什么“混合格式”能防幻觉?**
|
||||
|
||||
我们将数据格式定义为 **Context Protocol v2.0**,采用 **XML 骨架 \+ Markdown 血肉** 的形式。
|
||||
|
||||
### **1.1 格式对比**
|
||||
|
||||
| 格式 | 示例 | LLM 视角的优缺点 |
|
||||
| :---- | :---- | :---- |
|
||||
| **纯 JSON** | {"age": 45, "error": true} | ❌ **缺点**:Token 消耗大,括号层级深时 LLM 容易“晕”,注意力机制容易分散。 |
|
||||
| **纯 Markdown** | \*\*Age\*\*: 45 (Error) | ❌ **缺点**:边界不清晰,多条记录容易混在一起,导致“张冠李戴”。 |
|
||||
| **混合模式 (推荐)** | \<record id="1"\>- Age: \*\*45\*\*\</record\> | ✅ **优点**:XML \<tag\> 明确告诉 LLM “这是独立的一条记录”,Markdown \*\* 告诉 LLM “这是重点”。 |
|
||||
|
||||
### **1.2 防幻觉的三道防线**
|
||||
|
||||
1. **防线一:证据注入 (Evidence Injection)**
|
||||
* **以前**:只给 Age Error。LLM 被问“多少岁”时,只能瞎编。
|
||||
* **现在**:给 Age Error (Current: 45, Range: 25-35)。LLM 看到了 45,直接引用,无需生成。
|
||||
2. **防线二:预计算 (Pre-computation)**
|
||||
* **以前**:给 DOB: 1980,让 LLM 算年龄。LLM 数学不好,可能算错。
|
||||
* **现在**:Node.js 算好 Age: 46,直接喂给 LLM。LLM 只负责读,不负责算。
|
||||
3. **防线三:结构化边界 (XML Boundaries)**
|
||||
* **以前**:平铺文本。LLM 可能把 A 病人的合并用药安到 B 病人头上。
|
||||
* **现在**:\<record id="A"\>...\</record\>。强制物理隔离,杜绝串行。
|
||||
|
||||
## **📝 二、 Context Protocol v2.0 标准格式**
|
||||
|
||||
这是后端 ReportGenerator 需要生成的最终字符串格式。
|
||||
|
||||
\<qc\_context project="test0102" generated\_at="2026-02-08"\>
|
||||
|
||||
\<\!-- 1\. 规则定义 (让 LLM 知道判罚标准) \--\>
|
||||
\<rule\_definitions\>
|
||||
\<rule id="R\_AGE"\>入排标准 I-01: 年龄应在 25-35 岁之间\</rule\>
|
||||
\<rule id="R\_ICF"\>伦理合规 E-01: 必须签署知情同意书\</rule\>
|
||||
\</rule\_definitions\>
|
||||
|
||||
\<\!-- 2\. 严重问题清单 (按受试者分组) \--\>
|
||||
\<critical\_issues\>
|
||||
|
||||
\<subject id="1"\>
|
||||
\<summary\>存在 2 个严重违规\</summary\>
|
||||
\<issues\>
|
||||
1\. \[R\_AGE\] \*\*年龄超标\*\*
|
||||
\- 现状: 当前年龄 \*\*45岁\*\*
|
||||
\- 标准: 25-35岁
|
||||
\- 证据: \`birth\_date\` \= 1981-05-12
|
||||
2\. \[R\_ICF\] \*\*知情同意缺失\*\*
|
||||
\- 现状: 字段为空
|
||||
\- 证据: \`icf\_date\` \= null
|
||||
\</issues\>
|
||||
\</subject\>
|
||||
|
||||
\<subject id="10"\>
|
||||
\<summary\>存在 1 个严重违规\</summary\>
|
||||
\<issues\>
|
||||
1\. \[R\_AGE\] \*\*年龄超标\*\*
|
||||
\- 现状: 当前年龄 \*\*52岁\*\*
|
||||
\- 证据: \`birth\_date\` \= 1974-02-01
|
||||
\</issues\>
|
||||
\</subject\>
|
||||
|
||||
\</critical\_issues\>
|
||||
|
||||
\</qc\_context\>
|
||||
|
||||
## **🗣️ 三、 配套 Prompt 设计 (System Prompt)**
|
||||
|
||||
仅有好的数据格式是不够的,必须用 Prompt 教会 LLM 如何阅读这个格式。
|
||||
|
||||
### **3.1 CRA 监查员 System Prompt**
|
||||
|
||||
\# Role
|
||||
你是一名资深的临床监查员 (CRA)。你的任务是根据提供的【质控报告上下文】回答用户关于项目质量、违规情况的问题。
|
||||
|
||||
\# Input Format
|
||||
你收到的上下文将包含在 \`\<qc\_context\>\` XML 标签中。
|
||||
\- \`\<rule\_definitions\>\`: 定义了项目的质控规则。
|
||||
\- \`\<critical\_issues\>\`: 列出了具体的违规记录,按受试者 (\`\<subject\>\`) 分组。
|
||||
|
||||
\# Constraints (绝对准则)
|
||||
1\. \*\*基于证据\*\*:回答必须严格基于 \`\<issues\>\` 中的数据。如果上下文中没有提到某条记录或某个数值,\*\*必须直接说“报告中未包含相关信息”\*\*,严禁编造数值。
|
||||
2\. \*\*引用原文\*\*:在解释违规原因时,必须引用上下文中的 "证据" (Evidence) 字段(例如:“因为患者当前年龄为 45 岁...”)。
|
||||
3\. \*\*结构化输出\*\*:回答多个受试者问题时,请使用 Markdown 列表。
|
||||
4\. \*\*语气专业\*\*:保持客观、冷静的医疗专业语气。
|
||||
|
||||
\# Example
|
||||
User: "1号病人有什么问题?"
|
||||
Assistant: "1号受试者存在 \*\*2个严重违规\*\*:
|
||||
1\. \*\*年龄超标\*\*:患者当前 \*\*45岁\*\*,不符合“25-35岁”的入排标准 (R\_AGE)。
|
||||
2\. \*\*伦理缺失\*\*:未检测到知情同意书签署日期 (\`icf\_date\` 为空)。
|
||||
建议立即核查原始病历或剔除该病例。"
|
||||
|
||||
## **🔬 四、 验证与测试 (Evaluation)**
|
||||
|
||||
### **4.1 幻觉压力测试**
|
||||
|
||||
**测试用例 A:询问不存在的数值**
|
||||
|
||||
* **Prompt**: "1号病人的血压是多少?"
|
||||
* **Context**: (上下文中只有年龄和ICF问题,没有血压数据)
|
||||
* **预期回答**: "报告中未包含1号受试者的血压数据。当前仅记录了年龄和知情同意书相关的违规信息。"
|
||||
* **失败回答 (幻觉)**: "1号病人的血压是 120/80 mmHg。" (如果 LLM 只有 Message 没有 Evidence,容易顺口胡编一个正常值)
|
||||
|
||||
**测试用例 B:询问违规原因**
|
||||
|
||||
* **Prompt**: "为什么10号病人年龄违规?"
|
||||
* **Context**: \<subject id="10"\>...当前年龄 \*\*52岁\*\*...\</subject\>
|
||||
* **预期回答**: "因为10号受试者当前年龄为 **52岁**,超出了研究方案规定的 25-35 岁范围。"
|
||||
|
||||
### **4.2 结论**
|
||||
|
||||
通过 **"XML 结构化 \+ 证据注入 \+ 严格约束 Prompt"** 三位一体的方案,我们可以将幻觉率控制在 **极低水平 (\< 1%)**。
|
||||
|
||||
AI 在这里不再是“创造者”,而是精准的“阅读理解者”。
|
||||
107
docs/03-业务模块/IIT Manager Agent/05-测试文档/LLM 友好型质控报告评估与优化方案 V2.md
Normal file
107
docs/03-业务模块/IIT Manager Agent/05-测试文档/LLM 友好型质控报告评估与优化方案 V2.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# **LLM 友好型质控报告评估与优化方案**
|
||||
|
||||
**文档版本:** v2.1 (基于团队反馈优化)
|
||||
|
||||
**评估对象:** qc-report-test0102-pd-study-2026-02-08.xml
|
||||
|
||||
**评估日期:** 2026-02-08
|
||||
|
||||
## **🚀 一、 核心共识:Context Protocol v2.1**
|
||||
|
||||
经过团队讨论,确定采用 **“XML 容器 \+ Markdown 内容”** 的混合模式,并支持 **双格式输出** 以满足不同场景。
|
||||
|
||||
### **1.1 双格式策略 (Dual Format Strategy)**
|
||||
|
||||
后端 QcService 应支持 format 参数:
|
||||
|
||||
* **format=json (Default)**: 面向 **前端 UI**。结构化强,用于渲染热力图、表格。
|
||||
* **format=llm-friendly**: 面向 **LLM Context**。Token 密度高,语义清晰,包含“证据”。
|
||||
|
||||
### **1.2 理想的 LLM Context 结构 (V2.1)**
|
||||
|
||||
**设计原则**:
|
||||
|
||||
1. **去重**:不再单独列出 rule\_definitions,要求每条 issue **自包含**(同时包含现状与标准)。
|
||||
2. **聚合**:按 Record ID 分组。
|
||||
3. **压缩**:使用 Markdown 列表替代冗余的 XML 标签。
|
||||
|
||||
\<qc\_context project\_id="test0102" generated="2026-02-08"\>
|
||||
|
||||
\<\!-- 1\. 宏观统计 (Aggregate) \--\>
|
||||
\<summary\>
|
||||
\- 状态: 13/13 记录存在严重违规 (100% Fail)
|
||||
\- Top 3 问题:
|
||||
1\. 年龄超标 (13人)
|
||||
2\. 未签知情同意书 (13人)
|
||||
3\. 疼痛评分不达标 (13人)
|
||||
\</summary\>
|
||||
|
||||
\<\!-- 2\. 问题详情 (Markdown List in XML) \--\>
|
||||
\<details\>
|
||||
|
||||
\<record id="1"\>
|
||||
\*\*严重违规 (5项)\*\*:
|
||||
1\. \[R\_AGE\] \*\*年龄超标\*\*: 当前 \*\*45岁\*\* (标准: 25-35岁)。
|
||||
2\. \[R\_ICF\] \*\*伦理缺失\*\*: \`informed\_consent\` 为空 (必须签署)。
|
||||
3\. \[R\_VAS\] \*\*入排不符\*\*: VAS评分 \*\*2分\*\* (要求 \>= 4分)。
|
||||
\</record\>
|
||||
|
||||
\<record id="10"\>
|
||||
\*\*严重违规 (5项)\*\*:
|
||||
1\. \[R\_AGE\] \*\*年龄超标\*\*: 当前 \*\*52岁\*\* (标准: 25-35岁)。
|
||||
\<\!-- 其他同上 \--\>
|
||||
\</record\>
|
||||
|
||||
\</details\>
|
||||
|
||||
\</qc\_context\>
|
||||
|
||||
## **🛠️ 二、 实施建议 (Action Items)**
|
||||
|
||||
### **2.1 后端改造:让报错信息“自包含”**
|
||||
|
||||
这是消除 rule\_definitions 依赖的关键。我们需要在生成 Issue 时,就把标准塞进去。
|
||||
|
||||
* **Before (HardRuleEngine)**:
|
||||
return { message: "年龄不在范围内" }
|
||||
|
||||
* **After (HardRuleEngine)**:
|
||||
// 动态拼接模板
|
||||
return {
|
||||
message: \`当前 \*\*${actualValue}\*\* (标准: ${rule.min}-${rule.max})\`,
|
||||
structured\_evidence: { value: actualValue, range: \[25, 35\] }
|
||||
}
|
||||
|
||||
### **2.2 System Prompt 增强 (V2.1)**
|
||||
|
||||
参考团队建议,强化“证据引用”指令。
|
||||
|
||||
\# Role
|
||||
你是一名资深的临床监查员 (CRA)。
|
||||
|
||||
\# Input Format
|
||||
你收到的 \`\<qc\_context\>\` 包含了项目的质控报告。
|
||||
\- \`\<details\>\` 区域按受试者列出了具体违规项。
|
||||
\- 每一行违规项都包含了 \*\*\[规则ID\]\*\*、\*\*错误类型\*\*、\*\*现状值\*\* 和 \*\*标准值\*\*。
|
||||
|
||||
\# Critical Instructions (思维链约束)
|
||||
在回答用户问题时,你必须遵循以下步骤:
|
||||
1\. \*\*定位 (Locate)\*\*: 找到用户询问的 \`\<record\>\`。
|
||||
2\. \*\*提取 (Extract)\*\*: 读取具体的报错行。
|
||||
3\. \*\*引用 (Cite)\*\*: 在回答中明确引用现状值和标准值。
|
||||
\- ✅ 正确: "1号患者年龄违规,因为他当前 \*\*45岁\*\*,而方案要求 \*\*25-35岁\*\*。"
|
||||
\- ❌ 错误: "1号患者年龄不对。" (太模糊)
|
||||
\- ❌ 错误: "1号患者年龄违规,请检查。" (无证据)
|
||||
4\. \*\*诚实 (Grounding)\*\*: 如果报告里没写的数值(比如血压),绝对不要编造,直接回答“报告未提及”。
|
||||
|
||||
\# Example
|
||||
User: "10号病人有什么大问题?"
|
||||
Assistant: "10号病人有 \*\*5项严重违规\*\*。最主要的是 \*\*年龄超标\*\*,他当前 \*\*52岁\*\*,远超出了 \*\*25-35岁\*\* 的入排标准。此外还存在伦理知情同意书缺失的问题。"
|
||||
|
||||
## **📊 三、 收益预估**
|
||||
|
||||
1. **Token 节省**:相比 V1.0 XML,V2.1 混合格式预计节省 **40%-60%** 的 Token(去掉了大量的 \<issue\>, \<field\>, \<message\> 标签)。
|
||||
2. **幻觉消除**:通过“自包含”设计,LLM 不需要跨段落去查找规则定义,所有信息都在一行内,上下文注意力极其集中。
|
||||
3. **开发解耦**:前端用 JSON 渲染界面,LLM 用 Text 文本推理,互不干扰。
|
||||
|
||||
**结论:** 团队的建议非常棒。V2.1 方案已采纳 **混合格式** \+ **自包含报错** \+ **引用增强 Prompt**,这是目前最优的工程解法。
|
||||
120
docs/03-业务模块/IIT Manager Agent/05-测试文档/LLM 友好型质控报告评估与优化方案.md
Normal file
120
docs/03-业务模块/IIT Manager Agent/05-测试文档/LLM 友好型质控报告评估与优化方案.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# **LLM 友好型质控报告评估与优化方案**
|
||||
|
||||
**评估对象:** qc-report-test0102-pd-study-2026-02-08.xml
|
||||
|
||||
**评估目的:** 确定该格式是否适合作为 Context 喂给 LLM 以回答用户提问。
|
||||
|
||||
**评估日期:** 2026-02-08
|
||||
|
||||
## **📊 一、 现状评估 (Current State Analysis)**
|
||||
|
||||
### **1\. 评分卡**
|
||||
|
||||
| 维度 | 评分 (1-10) | 评价 |
|
||||
| :---- | :---- | :---- |
|
||||
| **结构化程度** | 9/10 | XML 结构清晰,解析容易。 |
|
||||
| **Token 效率** | 3/10 | **极差**。重复信息太多(如 rule\_name 重复 64 次)。 |
|
||||
| **信息完整性** | 4/10 | **缺失核心证据**。只说了“错”,没说“值为多少”。 |
|
||||
| **语义清晰度** | 5/10 | rule="unknown" 对 AI 毫无帮助,缺乏语义标签。 |
|
||||
|
||||
### **2\. 核心缺陷分析**
|
||||
|
||||
#### **❌ 缺陷 1:缺乏“原始值” (The "Evidence Gap")**
|
||||
|
||||
* **现状**:
|
||||
\<message\>年龄不在 25-35 岁范围内\</message\>
|
||||
\<field\>age\</field\>
|
||||
|
||||
* **LLM 的困惑**:"我知道年龄不对,但这个病人到底几岁?是 24 岁(轻微偏差)还是 80 岁(严重偏差)?用户如果问我‘为什么报错’,我只能复读 Message,无法解释原因。"
|
||||
|
||||
#### **❌ 缺陷 2:Token 冗余 (The "Echo Chamber")**
|
||||
|
||||
* **现状**:
|
||||
13 条记录都有“年龄”问题,rule\_name 和 message 重复了 13 次。
|
||||
* **LLM 的困惑**:"为什么要让我读 13 遍同样的一句话?这浪费了宝贵的上下文窗口。"
|
||||
|
||||
#### **❌ 缺陷 3:逻辑扁平 (Lack of Hierarchy)**
|
||||
|
||||
* **现状**:
|
||||
所有问题平铺在 \<critical\_issues\> 下,没有按 Record ID 聚合。
|
||||
* **LLM 的困惑**:"如果用户问‘001号病人有哪些问题?’,我得遍历整个列表去挑出 record=1 的项,容易看漏。"
|
||||
|
||||
## **🚀 二、 优化方案:Context Protocol v2.0**
|
||||
|
||||
根据我们的 **CRA Agent 深度设计**,我们需要将报告重构为 **“以实体为中心,以证据为支撑”** 的结构。
|
||||
|
||||
### **2.1 理想的 Context 结构 (Gold Standard)**
|
||||
|
||||
建议采用 **混合模式**:XML 定义边界,Markdown 描述详情。
|
||||
|
||||
\<qc\_context project\_id="test0102" generated="2026-02-08"\>
|
||||
|
||||
\<\!-- 1\. 宏观统计 (Aggregate) \--\>
|
||||
\<overview\>
|
||||
\- 总记录数: 13 | ❌ 严重违规: 13人 (100%)
|
||||
\- 主要问题: 年龄超标 (13), 未签知情同意书 (13), 疼痛评分不达标 (13)
|
||||
\</overview\>
|
||||
|
||||
\<\!-- 2\. 规则定义 (Reference) \- 只定义一次,省 Token \--\>
|
||||
\<rule\_definitions\>
|
||||
\<rule id="R\_AGE" tag="\#demographics"\>年龄应在 25-35 岁之间\</rule\>
|
||||
\<rule id="R\_ICF" tag="\#ethics"\>必须签署知情同意书\</rule\>
|
||||
\</rule\_definitions\>
|
||||
|
||||
\<\!-- 3\. 问题详情 (Grouped by Record) \--\>
|
||||
\<issues\_list\>
|
||||
|
||||
\<record id="1" status="CRITICAL"\>
|
||||
\<summary\>存在 5 个严重违规\</summary\>
|
||||
\<details\>
|
||||
\- \[R\_AGE\] ❌ \*\*年龄违规\*\*: 当前值 \`45\` (不在 25-35 范围内)。
|
||||
\- \[R\_ICF\] ❌ \*\*伦理违规\*\*: \`informed\_consent\` 为空。
|
||||
\- \[R\_VAS\] ❌ \*\*入排不符\*\*: VAS评分 \`2\` (要求 \>= 4)。
|
||||
\</details\>
|
||||
\</record\>
|
||||
|
||||
\<record id="10" status="CRITICAL"\>
|
||||
\<summary\>存在 5 个严重违规\</summary\>
|
||||
\<details\>
|
||||
\- \[R\_AGE\] ❌ \*\*年龄违规\*\*: 当前值 \`52\`。
|
||||
\<\!-- 省略重复描述,仅列出差异或关键点 \--\>
|
||||
\</details\>
|
||||
\</record\>
|
||||
|
||||
\</issues\_list\>
|
||||
|
||||
\</qc\_context\>
|
||||
|
||||
## **🛠️ 三、 实施建议 (Action Items)**
|
||||
|
||||
### **3.1 后端代码调整 (QcService / ReportGenerator)**
|
||||
|
||||
你需要修改生成 XML 的逻辑,不仅要查 iit\_qc\_logs,还要关联 **原始数据**。
|
||||
|
||||
1. **补充 value 字段**:
|
||||
在存入 iit\_qc\_logs 时,或者在生成报告时,必须把触发报错的 **具体数值** 写进去。
|
||||
* *Bad:* { "message": "Age error" }
|
||||
* *Good:* { "message": "Age error", "evidence": { "value": 45, "threshold": "25-35" } }
|
||||
2. **补充 rule\_id 和 tag**:
|
||||
目前的 rule="unknown" 是不可接受的。
|
||||
* 在 HardRuleEngine 里,每条规则必须有一个唯一的 code (例如 AGE\_CHECK)。
|
||||
* 在 iit\_skills 配置中,关联 Tags。
|
||||
3. **按受试者聚合 (Group By Record)**:
|
||||
不要输出扁平的 List,要输出 Map:Map\<RecordId, Issues\[\]\>。
|
||||
|
||||
### **3.2 优化后的 LLM 交互流程**
|
||||
|
||||
当用户问:“**为什么 1 号病人不合格?**”
|
||||
|
||||
* **旧 XML**:LLM 看到 "年龄不在范围内",只能回答“因为年龄不对”。
|
||||
* **新 XML**:LLM 看到 当前值 45 (要求 25-35),可以回答:
|
||||
“1号病人不合格主要有 3 个原因:
|
||||
1. **年龄不符**:患者 **45岁**,超出了研究要求的 25-35 岁范围。
|
||||
2. **疼痛评分不足**:VAS 评分为 **2分**,未达到入组要求的 4分。
|
||||
3. **伦理缺失**:系统中未查询到知情同意书签署记录。”
|
||||
|
||||
### **3.3 总结**
|
||||
|
||||
**现有报告是给程序员调试用的,不是给 LLM 用的。**
|
||||
|
||||
请按照 **Context Protocol** 规范,增加 **Evidence (原始值)**,增加 **Grouping (聚合)**,并消除冗余文本。
|
||||
@@ -0,0 +1,320 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<qc_report project_id="test0102-pd-study" project_name="test0207" generated="2026-02-08T08:14:32.847Z">
|
||||
|
||||
<summary>
|
||||
<total_records>13</total_records>
|
||||
<completed_records>0</completed_records>
|
||||
<critical_issues>64</critical_issues>
|
||||
<warning_issues>0</warning_issues>
|
||||
<pending_queries>0</pending_queries>
|
||||
<pass_rate>0%</pass_rate>
|
||||
<last_qc_time>2026-02-08T05:30:56.082Z</last_qc_time>
|
||||
</summary>
|
||||
|
||||
<critical_issues count="64">
|
||||
<issue record="1" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:55.980Z</detected_at>
|
||||
</issue>
|
||||
<issue record="1" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:55.980Z</detected_at>
|
||||
</issue>
|
||||
<issue record="1" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:55.980Z</detected_at>
|
||||
</issue>
|
||||
<issue record="1" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:55.980Z</detected_at>
|
||||
</issue>
|
||||
<issue record="1" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:55.980Z</detected_at>
|
||||
</issue>
|
||||
<issue record="10" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.060Z</detected_at>
|
||||
</issue>
|
||||
<issue record="10" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.060Z</detected_at>
|
||||
</issue>
|
||||
<issue record="10" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.060Z</detected_at>
|
||||
</issue>
|
||||
<issue record="10" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.060Z</detected_at>
|
||||
</issue>
|
||||
<issue record="10" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.060Z</detected_at>
|
||||
</issue>
|
||||
<issue record="11" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.068Z</detected_at>
|
||||
</issue>
|
||||
<issue record="11" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.068Z</detected_at>
|
||||
</issue>
|
||||
<issue record="11" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.068Z</detected_at>
|
||||
</issue>
|
||||
<issue record="11" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.068Z</detected_at>
|
||||
</issue>
|
||||
<issue record="11" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.068Z</detected_at>
|
||||
</issue>
|
||||
<issue record="12" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.075Z</detected_at>
|
||||
</issue>
|
||||
<issue record="12" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.075Z</detected_at>
|
||||
</issue>
|
||||
<issue record="12" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.075Z</detected_at>
|
||||
</issue>
|
||||
<issue record="12" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.075Z</detected_at>
|
||||
</issue>
|
||||
<issue record="13" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.082Z</detected_at>
|
||||
</issue>
|
||||
<issue record="13" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.082Z</detected_at>
|
||||
</issue>
|
||||
<issue record="13" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.082Z</detected_at>
|
||||
</issue>
|
||||
<issue record="13" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.082Z</detected_at>
|
||||
</issue>
|
||||
<issue record="13" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.082Z</detected_at>
|
||||
</issue>
|
||||
<issue record="2" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:55.990Z</detected_at>
|
||||
</issue>
|
||||
<issue record="2" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:55.990Z</detected_at>
|
||||
</issue>
|
||||
<issue record="2" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:55.990Z</detected_at>
|
||||
</issue>
|
||||
<issue record="2" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:55.990Z</detected_at>
|
||||
</issue>
|
||||
<issue record="2" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:55.990Z</detected_at>
|
||||
</issue>
|
||||
<issue record="3" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:55.998Z</detected_at>
|
||||
</issue>
|
||||
<issue record="3" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:55.998Z</detected_at>
|
||||
</issue>
|
||||
<issue record="3" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:55.998Z</detected_at>
|
||||
</issue>
|
||||
<issue record="3" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:55.998Z</detected_at>
|
||||
</issue>
|
||||
<issue record="3" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:55.998Z</detected_at>
|
||||
</issue>
|
||||
<issue record="4" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.008Z</detected_at>
|
||||
</issue>
|
||||
<issue record="4" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.008Z</detected_at>
|
||||
</issue>
|
||||
<issue record="4" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.008Z</detected_at>
|
||||
</issue>
|
||||
<issue record="4" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.008Z</detected_at>
|
||||
</issue>
|
||||
<issue record="4" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.008Z</detected_at>
|
||||
</issue>
|
||||
<issue record="5" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.019Z</detected_at>
|
||||
</issue>
|
||||
<issue record="5" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.019Z</detected_at>
|
||||
</issue>
|
||||
<issue record="5" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.019Z</detected_at>
|
||||
</issue>
|
||||
<issue record="5" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.019Z</detected_at>
|
||||
</issue>
|
||||
<issue record="5" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.019Z</detected_at>
|
||||
</issue>
|
||||
<issue record="6" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.028Z</detected_at>
|
||||
</issue>
|
||||
<issue record="6" rule="unknown" severity="critical">
|
||||
<rule_name>出生日期不在 1989-01-01 至 2008-01-01 范围内</rule_name>
|
||||
<message>出生日期不在 1989-01-01 至 2008-01-01 范围内</message>
|
||||
<field>birth_date</field>
|
||||
<detected_at>2026-02-08T05:30:56.028Z</detected_at>
|
||||
</issue>
|
||||
<issue record="6" rule="unknown" severity="critical">
|
||||
<rule_name>月经周期不在 21-35 天范围内(28±7天)</rule_name>
|
||||
<message>月经周期不在 21-35 天范围内(28±7天)</message>
|
||||
<field>menstrual_cycle</field>
|
||||
<detected_at>2026-02-08T05:30:56.028Z</detected_at>
|
||||
</issue>
|
||||
<issue record="6" rule="unknown" severity="critical">
|
||||
<rule_name>VAS 疼痛评分 < 4 分,不符合入组条件</rule_name>
|
||||
<message>VAS 疼痛评分 < 4 分,不符合入组条件</message>
|
||||
<field>vas_score</field>
|
||||
<detected_at>2026-02-08T05:30:56.028Z</detected_at>
|
||||
</issue>
|
||||
<issue record="6" rule="unknown" severity="critical">
|
||||
<rule_name>未签署知情同意书</rule_name>
|
||||
<message>未签署知情同意书</message>
|
||||
<field>informed_consent</field>
|
||||
<detected_at>2026-02-08T05:30:56.028Z</detected_at>
|
||||
</issue>
|
||||
<issue record="7" rule="unknown" severity="critical">
|
||||
<rule_name>年龄不在 25-35 岁范围内</rule_name>
|
||||
<message>年龄不在 25-35 岁范围内</message>
|
||||
<field>age</field>
|
||||
<detected_at>2026-02-08T05:30:56.038Z</detected_at>
|
||||
</issue>
|
||||
<!-- ... 还有 14 个严重问题未显示 -->
|
||||
</critical_issues>
|
||||
|
||||
<warning_issues count="0" />
|
||||
|
||||
</qc_report>
|
||||
@@ -0,0 +1,217 @@
|
||||
# 2026-02-08 事件级质控与报告优化开发记录
|
||||
|
||||
> **开发日期:** 2026-02-08
|
||||
> **开发人员:** AI Assistant
|
||||
> **版本:** V3.1
|
||||
> **状态:** ✅ 基本测试成功
|
||||
|
||||
---
|
||||
|
||||
## 📋 开发概述
|
||||
|
||||
本次开发主要完成了 IIT Manager Agent 质控系统的重大架构升级,从"记录级合并质控"改为"事件级独立质控",同时优化了质控报告生成逻辑和 AI 对话能力。
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心改动
|
||||
|
||||
### 1. 事件级质控架构(V3.1)
|
||||
|
||||
**问题背景:**
|
||||
- REDCap 纵向研究中,一个 record_id 可能有多个事件(如筛选期、随访1、随访2等)
|
||||
- 之前的质控将所有事件的数据合并到一条记录,导致数据覆盖问题
|
||||
- 不同事件的表单应该独立质控
|
||||
|
||||
**解决方案:**
|
||||
|
||||
| 改动文件 | 改动内容 |
|
||||
|---------|---------|
|
||||
| `RedcapAdapter.ts` | 新增 `getAllRecordsByEvent()` 方法,按 record+event 返回独立数据单元 |
|
||||
| `RedcapAdapter.ts` | 新增 `getFormEventMapping()` 和 `getEvents()` 获取事件配置 |
|
||||
| `RedcapAdapter.ts` | 新增 `getFormCompletionStatusByEvent()` 按事件获取表单完成状态 |
|
||||
| `HardRuleEngine.ts` | `QCRule` 接口新增 `applicableEvents` 和 `applicableForms` 字段 |
|
||||
| `SoftRuleEngine.ts` | `SoftRuleCheck` 接口同样新增事件/表单适用性字段 |
|
||||
| `SkillRunner.ts` | 重构 `runByTrigger()` 按 record+event 独立执行质控 |
|
||||
| `SkillRunner.ts` | 新增 `filterApplicableRules()` 方法,按事件/表单动态过滤规则 |
|
||||
| `SkillRunner.ts` | `SkillRunResult` 新增 `eventName`、`eventLabel`、`forms` 字段 |
|
||||
| `SkillRunner.ts` | `saveQcLog()` 现在保存 `eventId` 到数据库 |
|
||||
|
||||
**架构变化:**
|
||||
|
||||
```
|
||||
之前(记录级合并):
|
||||
Record 1 = Event A 数据 + Event B 数据 + ... (合并可能覆盖)
|
||||
|
||||
之后(事件级独立):
|
||||
Record 1 + Event A = 独立质控单元 1
|
||||
Record 1 + Event B = 独立质控单元 2
|
||||
...
|
||||
```
|
||||
|
||||
### 2. 质控报告优化
|
||||
|
||||
**问题背景:**
|
||||
- 报告从多个事件收集问题,导致同一规则重复出现
|
||||
- 报告使用缓存,不是最新数据
|
||||
- 显示限制导致部分问题被隐藏
|
||||
|
||||
**解决方案:**
|
||||
|
||||
| 改动文件 | 改动内容 |
|
||||
|---------|---------|
|
||||
| `QcReportService.ts` | SQL 查询改用 `DISTINCT ON (record_id, event_id)` |
|
||||
| `QcReportService.ts` | 新增 `deduplicateIssues()` 按 recordId+ruleId 去重 |
|
||||
| `QcReportService.ts` | 统计计数也按 recordId+ruleId 去重(使用 Set) |
|
||||
| `QcReportService.ts` | 移除所有 slice 显示限制,显示所有问题 |
|
||||
| `QcReportService.ts` | 兼容新旧两种 issues 格式(数组 vs { items: [...] })|
|
||||
|
||||
### 3. 批量操作 API 更新
|
||||
|
||||
| 改动文件 | 改动内容 |
|
||||
|---------|---------|
|
||||
| `iitBatchController.ts` | `batchQualityCheck` 改用 `SkillRunner.runByTrigger()` |
|
||||
| `ToolsService.ts` | `batch_quality_check` 工具同样改用事件级质控 |
|
||||
|
||||
### 4. 前端优化
|
||||
|
||||
| 改动文件 | 改动内容 |
|
||||
|---------|---------|
|
||||
| `QcReportDrawer.tsx` | 导出 XML 前自动刷新报告(确保获取最新数据)|
|
||||
| `QcReportDrawer.tsx` | 文件名添加时分(HHMM格式)便于区分 |
|
||||
| `IitQcCockpitPage.tsx` | 删除重复的"全量质控"按钮(保留配置页的)|
|
||||
|
||||
### 5. AI 对话增强
|
||||
|
||||
| 改动文件 | 改动内容 |
|
||||
|---------|---------|
|
||||
| `ChatService.ts` | 增强意图识别,支持更多质控查询表达方式 |
|
||||
| `PromptBuilder.ts` | 修复 `this` 上下文丢失导致的 500 错误 |
|
||||
|
||||
---
|
||||
|
||||
## 🐛 修复的 Bug
|
||||
|
||||
### Bug 1: `formatPatientData` undefined 错误
|
||||
|
||||
**现象:** 点击记录详情时返回 500 错误
|
||||
|
||||
**原因:** `buildClinicalSlice` 函数导出时丢失了 `this` 上下文
|
||||
|
||||
**修复:** 将 `this.formatPatientData` 改为 `PromptBuilder.formatPatientData`
|
||||
|
||||
### Bug 2: 质控报告重复问题
|
||||
|
||||
**现象:** Record 1 显示 14 条违规,实际应该是 5 条
|
||||
|
||||
**原因:** 同一规则在多个事件中执行,结果都被收集到报告中
|
||||
|
||||
**修复:** 按 `recordId + ruleId` 去重,只保留最新结果
|
||||
|
||||
### Bug 3: 报告记录数不正确
|
||||
|
||||
**现象:** 显示 13 条记录,实际有 14 条
|
||||
|
||||
**原因:** 从 `iitRecordSummary` 获取记录数,该表可能缺少记录
|
||||
|
||||
**修复:** 从质控日志获取独立 `record_id` 数量
|
||||
|
||||
### Bug 4: AI 无法回答质控问题
|
||||
|
||||
**现象:** 问"严重违规有几项",AI 说"没有相关信息"
|
||||
|
||||
**原因:** 意图识别规则不够全面
|
||||
|
||||
**修复:** 增加更多匹配模式(质控问题、严重违规、record问题等)
|
||||
|
||||
---
|
||||
|
||||
## 📁 涉及文件清单
|
||||
|
||||
### 后端核心文件
|
||||
|
||||
```
|
||||
backend/src/modules/iit-manager/
|
||||
├── adapters/
|
||||
│ └── RedcapAdapter.ts ✅ 新增 3 个方法
|
||||
├── engines/
|
||||
│ ├── HardRuleEngine.ts ✅ QCRule 接口扩展
|
||||
│ ├── SoftRuleEngine.ts ✅ SoftRuleCheck 接口扩展
|
||||
│ └── SkillRunner.ts ✅ 事件级质控核心重构
|
||||
├── services/
|
||||
│ ├── QcReportService.ts ✅ 去重 + 移除限制
|
||||
│ ├── ChatService.ts ✅ 意图识别增强
|
||||
│ ├── PromptBuilder.ts ✅ 修复 this 上下文
|
||||
│ └── ToolsService.ts ✅ batch_quality_check 更新
|
||||
|
||||
backend/src/modules/admin/iit-projects/
|
||||
└── iitBatchController.ts ✅ 使用 SkillRunner
|
||||
```
|
||||
|
||||
### 前端文件
|
||||
|
||||
```
|
||||
frontend-v2/src/modules/admin/
|
||||
├── components/qc-cockpit/
|
||||
│ └── QcReportDrawer.tsx ✅ 自动刷新 + 文件名优化
|
||||
└── pages/
|
||||
└── IitQcCockpitPage.tsx ✅ 删除重复按钮
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
### 测试结果
|
||||
|
||||
| 测试项 | 结果 | 备注 |
|
||||
|--------|------|------|
|
||||
| 事件级质控执行 | ✅ | 14 条记录 × 5 个事件 = 70 个质控单元 |
|
||||
| 规则动态过滤 | ✅ | 配置 applicableForms 后规则只在相关事件执行 |
|
||||
| 报告去重 | ✅ | 168 条问题去重后变为 69 条 |
|
||||
| XML 导出 | ✅ | 自动刷新 + 显示所有问题 |
|
||||
| AI 质控查询 | ✅ | 能正确回答"严重违规有几项" |
|
||||
| 详情页 500 错误 | ✅ | formatPatientData 修复后正常 |
|
||||
|
||||
---
|
||||
|
||||
## 📝 配置说明
|
||||
|
||||
### 规则适用性配置示例
|
||||
|
||||
```typescript
|
||||
// 在 Skill 配置中设置规则的适用表单
|
||||
{
|
||||
"id": "inc_001",
|
||||
"name": "年龄范围检查",
|
||||
"applicableForms": ["basic_demography_form"], // 只在人口学表单执行
|
||||
"applicableEvents": [] // 空数组 = 适用所有事件
|
||||
}
|
||||
```
|
||||
|
||||
### 执行配置更新脚本
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npx tsx update-skill-applicable-forms.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 后续优化建议
|
||||
|
||||
1. **规则配置 UI**:在管理端添加规则 → 表单映射的可视化配置界面
|
||||
2. **事件标签显示**:在报告中显示事件的中文标签(如"筛选期")而非唯一标识
|
||||
3. **增量质控**:只对有变化的事件执行质控,避免全量重算
|
||||
4. **质控历史**:保留历史质控结果,支持趋势分析
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [模块状态文档](../00-模块当前状态与开发指南.md)
|
||||
- [实时质控系统开发记录](./2026-02-07-实时质控系统开发记录.md)
|
||||
- [质控系统 UI 与 LLM 格式优化计划](../04-开发计划/07-质控系统UI与LLM格式优化计划.md)
|
||||
|
||||
---
|
||||
|
||||
> **总结:** 本次开发完成了 IIT 质控系统从"记录级"到"事件级"的架构升级,解决了数据合并覆盖、报告重复、AI 无法回答等多个问题,为 REDCap 纵向研究提供了更精确的质控能力。
|
||||
Reference in New Issue
Block a user