4. 规则引擎核心原理

规则引擎的性能与可维护性,取决于它如何把“规则”变成“可执行的匹配网络”,以及如何在规则数量增长、事实频繁变化时避免全量重算。医疗场景中,一条临床提醒规则可能同时依赖患者年龄、诊断编码、检验结果、用药记录和过敏史,若每次插入一条新检验值都重新扫描全部规则,系统很快会不可用。Rete 算法正是为解决这类“多规则、多事实、频繁变化”问题而设计的匹配算法。

Rete 网络:把规则编译成匹配结构

Rete 的核心思想是用空间换时间:把每条规则的条件拆成若干模式(pattern),相同模式只保留一份,形成有向无环的匹配网络。典型节点包括:

  • 根节点与类型节点:按事实类型(如 Patient、LabResult、MedicationOrder)分流,避免不同类型事实互相干扰。
  • Alpha 节点:对单个事实做条件过滤,例如 LabResult.code == "K" && LabResult.value > 5.5。满足条件的事实进入 Alpha 记忆(Alpha Memory)。
  • Beta 节点(Join 节点):把两个或多个 Alpha 记忆中的事实按关联条件连接,例如“同一患者的检验结果”与“该患者的用药记录”做 join。
  • Terminal 节点:规则所有条件都满足时,产生一个激活(Activation),进入议程(Agenda)等待触发。

当一条新事实插入工作内存(Working Memory)时,Rete 不会重新评估所有规则,而是让该事实沿网络向下传播,只更新受影响的 Alpha 记忆和 Join 结果。这就是增量匹配:插入、修改、撤回事实都只触发局部传播。对于撤回,Rete 需要维护带计数或令牌(token)的记忆结构,确保某条事实被移除时,依赖它的激活也被正确撤销,避免“幽灵激活”。

Rete 增量匹配网络与冲突消解流程 工作内存 Patient(P001, 68) LabResult(K, 6.2) MedicationOrder(螺内酯) 插入 / 修改 / 撤回 类型节点分流 Alpha: K > 5.5 Alpha Memory Alpha: 保钾利尿剂 Alpha Memory Beta Join 同一 patientId 时间窗 24h Terminal 产生 Activation R-高钾风险提醒 议程 Agenda(冲突集) Activation A: R-高钾风险提醒 salience=100 Activation B: R-常规复查提醒 salience=10 Activation C: R-用药教育 salience=50 冲突消解策略 优先级 → 特异性 → 最近使用 → 随机 选中 A 触发,其余保留或撤销 增量传播要点 • 新事实仅沿相关路径传播,不全量重算 • Alpha Memory 缓存单事实过滤结果 • Beta Memory 缓存 join 中间结果 • 撤回事实需撤销对应 token 与激活 • 共享节点越多,规则集越大收益越明显 • 注意:时间窗、否定条件会削弱共享性 需评估是否退化为近似全量匹配

规则集与决策表:两种表达,同一执行语义

规则集是规则的集合,通常按业务域分组,例如“高钾风险规则集”“抗菌药物规则集”。规则集的价值在于可整体启用、停用、版本化和灰度。决策表则是规则集的表格化表达:每一行是一条规则,每一列是一个条件或动作。医疗规则中大量存在“条件组合 → 结论”的映射,例如:

规则ID血钾eGFR用药结论优先级
R-HK-01> 6.0任意任意紧急高钾提醒100
R-HK-025.5 ~ 6.0< 60保钾利尿剂高钾风险提醒80
R-HK-035.5 ~ 6.0≥ 60无复查建议30

决策表在编译时会被展开为等价规则,因此执行语义与手写规则一致。它的优势是可审计、易评审:临床专家能直接检查每一行的条件与结论,而不必阅读代码。但要注意条件列的“任意”与“空值”语义必须明确,否则会出现规则覆盖或漏判。

规则流与优先级:控制规则的执行顺序

规则流(Rule Flow)用有向图描述规则集或规则组的执行顺序,常见节点包括开始、规则任务、分支、合并、结束。它解决的是“先做什么、再做什么”的问题,例如先执行“数据完整性校验规则集”,再执行“临床风险规则集”,最后执行“提醒生成规则集”。

优先级(salience)则作用于议程内部,决定同一时刻多个激活的触发顺序。数值越大越先触发。实践中建议:规则流管阶段,优先级管阶段内顺序,避免把所有顺序都压在优先级上导致难以维护。

冲突消解策略:从冲突集中选出唯一激活

当多个规则同时满足条件时,议程中会出现冲突集。冲突消解策略负责选出下一个触发的激活。常用策略包括:

  • 优先级:按 salience 降序,最直观,但容易滥用。
  • 特异性:条件更具体、约束更多的规则优先,避免通用规则压过专用规则。
  • 最近使用:优先触发最近被更新的事实相关规则,适合实时监测。
  • 随机:用于避免固定顺序带来的偏差,但医疗场景慎用。

在医疗规则中,通常采用“优先级 + 特异性”组合:紧急提醒优先级最高,同级时更具体的规则先触发。若规则之间存在互斥结论,应在设计阶段通过规则流或条件约束消除冲突,而不是依赖运行时随机选择。

规则版本与灰度发布:让规则变更可控

规则是临床知识,会随指南更新而变更。规则版本管理要求每次发布都有唯一版本号、变更说明、生效时间和回滚点。灰度发布则让新版本先作用于小流量或特定科室,观察触发率、误报率和临床反馈,再逐步扩大范围。

一个可操作的灰度方案是:规则集版本 V2 先对 5% 的住院患者生效,同时记录 V1 与 V2 的“影子触发”结果,对比两者差异。若 V2 的误报率未显著上升且覆盖了预期的新场景,再按 20%、50%、100% 逐步放量。回滚时只需将规则集版本切回 V1,无需重新部署应用。

规则版本与灰度发布的关键指标:规则命中率、误报率、漏报率、平均触发延迟、回滚耗时。灰度期间应同时保留旧版本结果用于对比,避免“只看新版本”导致判断偏差。
Rete 网络的增量匹配依赖事实的撤回与更新语义。若业务代码只插入不撤回,Alpha/Beta 记忆会持续膨胀,最终导致内存泄漏和匹配变慢。医疗数据中检验结果被修正、医嘱被取消时,必须显式撤回旧事实。

综合来看,Rete 算法解决“匹配效率”,规则集与决策表解决“表达与评审”,规则流与优先级解决“执行顺序”,冲突消解解决“同时满足时选谁”,版本与灰度解决“变更可控”。这五者共同构成规则引擎从编写到上线的完整闭环。理解它们之间的分工,才能在医疗规则平台中既保证性能,又保证临床安全。