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:
2026-02-08 21:22:11 +08:00
parent 45c7b32dbb
commit 7a299e8562
51 changed files with 10638 additions and 184 deletions

View 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无法解释原因。"
#### **❌ 缺陷 2Token 冗余 (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要输出 MapMap\<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 (聚合)**,并消除冗余文本。