healthcare-cdss-patterns

healthcare-cdss-patterns

熱門

臨床決策支援系統(CDSS)開發模式。藥物交互作用檢查、劑量驗證、臨床評分(NEWS2、qSOFA)、警示嚴重度分類,以及與電子病歷工作流程的整合。

23萬星標
3.5萬分支
更新於 2026/7/20
SKILL.md
readonlyread-only
name
healthcare-cdss-patterns
description

臨床決策支援系統(CDSS)開發模式。藥物交互作用檢查、劑量驗證、臨床評分(NEWS2、qSOFA)、警示嚴重度分類,以及與電子病歷工作流程的整合。

version
1.0.0

醫療 CDSS 開發模式

用於建置可整合至電子病歷工作流程的臨床決策支援系統之模式。CDSS 模組關乎病人安全,對偽陰性零容忍。

使用時機

  • 實作藥物交互作用檢查
  • 建置劑量驗證引擎
  • 實作臨床評分系統(NEWS2、qSOFA、APACHE、GCS)
  • 設計異常臨床值的警示系統
  • 建置含安全檢查的醫囑輸入
  • 整合檢驗結果判讀與臨床情境

運作方式

CDSS 引擎是一個無副作用的純函式庫。輸入臨床資料,輸出警示。這使其完全可測試。

三個主要模組:

  1. checkInteractions(newDrug, currentMeds, allergies) — 檢查新藥物與目前用藥及已知過敏原。回傳依嚴重度排序的 InteractionAlert[]。使用 DrugInteractionPair 資料模型。
  2. validateDose(drug, dose, route, weight, age, renalFunction) — 根據體重、年齡及腎功能調整規則驗證處方劑量。回傳 DoseValidationResult
  3. calculateNEWS2(vitals) — 從 NEWS2Input 計算國家早期預警評分 2。回傳 NEWS2Result,包含總分、風險等級及升級處理指引。
EMR 使用者介面
  ↓ (使用者輸入資料)
CDSS 引擎(純函式,無副作用)
  ├── 藥物交互作用檢查器
  ├── 劑量驗證器
  ├── 臨床評分(NEWS2、qSOFA 等)
  └── 警示分類器
  ↓ (回傳警示)
EMR 使用者介面(內嵌顯示警示,若為重大則阻擋)

藥物交互作用檢查

interface DrugInteractionPair {
  drugA: string;           // 學名
  drugB: string;           // 學名
  severity: 'critical' | 'major' | 'minor';
  mechanism: string;
  clinicalEffect: string;
  recommendation: string;
}

function checkInteractions(
  newDrug: string,
  currentMedications: string[],
  allergyList: string[]
): InteractionAlert[] {
  if (!newDrug) return [];
  const alerts: InteractionAlert[] = [];
  for (const current of currentMedications) {
    const interaction = findInteraction(newDrug, current);
    if (interaction) {
      alerts.push({ severity: interaction.severity, pair: [newDrug, current],
        message: interaction.clinicalEffect, recommendation: interaction.recommendation });
    }
  }
  for (const allergy of allergyList) {
    if (isCrossReactive(newDrug, allergy)) {
      alerts.push({ severity: 'critical', pair: [newDrug, allergy],
        message: `Cross-reactivity with documented allergy: ${allergy}`,
        recommendation: '未經過敏諮詢請勿開立' });
    }
  }
  return alerts.sort((a, b) => severityOrder(a.severity) - severityOrder(b.severity));
}

交互作用配對必須是雙向的:若藥物 A 與藥物 B 有交互作用,則藥物 B 也與藥物 A 有交互作用。

劑量驗證

interface DoseValidationResult {
  valid: boolean;
  message: string;
  suggestedRange: { min: number; max: number; unit: string } | null;
  factors: string[];
}

function validateDose(
  drug: string,
  dose: number,
  route: 'oral' | 'iv' | 'im' | 'sc' | 'topical',
  patientWeight?: number,
  patientAge?: number,
  renalFunction?: number
): DoseValidationResult {
  const rules = getDoseRules(drug, route);
  if (!rules) return { valid: true, message: '無可用驗證規則', suggestedRange: null, factors: [] };
  const factors: string[] = [];

  // 安全考量:若規則需要體重但體重遺漏,則阻擋(而非通過)
  if (rules.weightBased) {
    if (!patientWeight || patientWeight <= 0) {
      return { valid: false, message: `Weight required for ${drug} (mg/kg drug)`,
        suggestedRange: null, factors: ['weight_missing'] };
    }
    factors.push('weight');
    const maxDose = rules.maxPerKg * patientWeight;
    if (dose > maxDose) {
      return { valid: false, message: `Dose exceeds max for ${patientWeight}kg`,
        suggestedRange: { min: rules.minPerKg * patientWeight, max: maxDose, unit: rules.unit }, factors };
    }
  }

  // 年齡調整(當規則定義年齡區間且提供年齡時)
  if (rules.ageAdjusted && patientAge !== undefined) {
    factors.push('age');
    const ageMax = rules.getAgeAdjustedMax(patientAge);
    if (dose > ageMax) {
      return { valid: false, message: `Exceeds age-adjusted max for ${patientAge}yr`,
        suggestedRange: { min: rules.typicalMin, max: ageMax, unit: rules.unit }, factors };
    }
  }

  // 腎功能調整(當規則定義 eGFR 區間且提供 eGFR 時)
  if (rules.renalAdjusted && renalFunction !== undefined) {
    factors.push('renal');
    const renalMax = rules.getRenalAdjustedMax(renalFunction);
    if (dose > renalMax) {
      return { valid: false, message: `Exceeds renal-adjusted max for eGFR ${renalFunction}`,
        suggestedRange: { min: rules.typicalMin, max: renalMax, unit: rules.unit }, factors };
    }
  }

  // 絕對最大值
  if (dose > rules.absoluteMax) {
    return { valid: false, message: `Exceeds absolute max ${rules.absoluteMax}${rules.unit}`,
      suggestedRange: { min: rules.typicalMin, max: rules.absoluteMax, unit: rules.unit },
      factors: [...factors, 'absolute_max'] };
  }
  return { valid: true, message: '在範圍內',
    suggestedRange: { min: rules.typicalMin, max: rules.typicalMax, unit: rules.unit }, factors };
}

臨床評分:NEWS2

interface NEWS2Input {
  respiratoryRate: number; oxygenSaturation: number; supplementalOxygen: boolean;
  temperature: number; systolicBP: number; heartRate: number;
  consciousness: 'alert' | 'voice' | 'pain' | 'unresponsive';
}
interface NEWS2Result {
  total: number;           // 0-20
  risk: 'low' | 'low-medium' | 'medium' | 'high';
  components: Record<string, number>;
  escalation: string;
}

評分表必須完全符合皇家內科醫學會的規格。

警示嚴重度與使用者介面行為

嚴重度 使用者介面行為 臨床醫師需採取的行動
重大 阻擋動作。不可關閉的對話框。紅色。 必須記錄覆寫原因才能繼續
主要 內嵌警告橫幅。橘色。 必須確認後才能繼續
次要 內嵌資訊提示。黃色。 僅供知悉,無需行動

重大警示絕不能自動關閉或實作為快訊通知。覆寫原因必須儲存在稽核軌跡中。

測試 CDSS(對偽陰性零容忍)

describe('CDSS — 病人安全', () => {
  INTERACTION_PAIRS.forEach(({ drugA, drugB, severity }) => {
    it(`detects ${drugA} + ${drugB} (${severity})`, () => {
      const alerts = checkInteractions(drugA, [drugB], []);
      expect(alerts.length).toBeGreaterThan(0);
      expect(alerts[0].severity).toBe(severity);
    });
    it(`detects ${drugB} + ${drugA} (reverse)`, () => {
      const alerts = checkInteractions(drugB, [drugA], []);
      expect(alerts.length).toBeGreaterThan(0);
    });
  });
  it('blocks mg/kg drug when weight is missing', () => {
    const result = validateDose('gentamicin', 300, 'iv');
    expect(result.valid).toBe(false);
    expect(result.factors).toContain('weight_missing');
  });
  it('handles malformed drug data gracefully', () => {
    expect(() => checkInteractions('', [], [])).not.toThrow();
  });
});

通過標準:100%。單一遺漏的交互作用即為病人安全事件。

反模式

  • 讓 CDSS 檢查變成可選或可跳過,而未記錄原因
  • 將交互作用檢查實作為快訊通知
  • 對藥物或臨床資料使用 any 型別
  • 硬編碼交互作用配對,而非使用可維護的資料結構
  • 在 CDSS 引擎中靜默捕捉錯誤(必須大聲呈現失敗)
  • 當體重不可得時跳過體重基礎驗證(必須阻擋,而非通過)

範例

範例 1:藥物交互作用檢查

const alerts = checkInteractions('warfarin', ['aspirin', 'metformin'], ['penicillin']);
// [{ severity: 'critical', pair: ['warfarin', 'aspirin'],
//    message: '出血風險增加', recommendation: '避免合併使用' }]

範例 2:劑量驗證

const ok = validateDose('paracetamol', 1000, 'oral', 70, 45);
// { valid: true, suggestedRange: { min: 500, max: 4000, unit: 'mg' } }

const bad = validateDose('paracetamol', 5000, 'oral', 70, 45);
// { valid: false, message: '超過絕對最大值 4000mg' }

const noWeight = validateDose('gentamicin', 300, 'iv');
// { valid: false, factors: ['weight_missing'] }

範例 3:NEWS2 評分

const result = calculateNEWS2({
  respiratoryRate: 24, oxygenSaturation: 93, supplementalOxygen: true,
  temperature: 38.5, systolicBP: 100, heartRate: 110, consciousness: 'voice'
});
// { total: 13, risk: 'high', escalation: '緊急臨床評估。考慮轉入加護病房。' }