TL;DR
核心觀點:在臨床場域,LLM 最安全的角色不是「決策者」,而是「翻譯者」。
我設計了一套三層架構:本地規則 → 結構化注入 → LLM 引用。LLM 只負責把規則引擎判定的結構化結果,轉成使用者能讀懂的自然語言。LLM 不做臨床判斷。
這個策略大幅降低幻覺風險,但也限制了 LLM 在規則覆蓋不到的模糊地帶的應用。
為什麼臨床 LLM 整合是高風險題目
過去兩年,LLM 在醫療場域的研究爆炸式成長:Med-PaLM 在 USMLE 考試獲得醫師等級表現、ChatGPT 寫病歷被多項研究證實準確度高、多模態模型可以閱讀放射影像報告。這些研究讓人興奮,但實務上把 LLM 整合進真實 CDSS 的人不多,原因有三:
風險 1:幻覺(Hallucination)
LLM 會以高度自信的口吻給出錯誤資訊。在一般場景頂多尷尬,在醫療場景可能致命。Med-HALT (Pal et al., EMNLP 2023) 的研究顯示,即使是專為醫療調過的模型,在罕見疾病問題上仍有 10–20% 的幻覺率。
風險 2:可解釋性
醫師需要解釋臨床決策的來源。LLM 的「我覺得是這個診斷」沒有來源 = 醫師無法說明、無法承擔責任。
風險 3:監管不確定性
LLM 在許多國家還沒被認證為醫材。把 LLM 嵌入決策支援工具可能讓系統落入醫材法規範。
我的設計:三層架構
我在 ClinCalc 與 ExClinCalc 兩套已上線系統中,採用以下架構:
Layer 1: 本地規則引擎(Local Knowledge Base)
↓
Layer 2: 結構化脈絡注入(Structured Context Injection)
↓
Layer 3: LLM 推論 + 強制引用(LLM Inference + Citation)
Layer 1:本地規則引擎
所有「臨床判定」都先過規則引擎。
// ClinCalc 中的 KDIGO 分期判定
function stageCKD(eGFR: number, albuminuria: 'A1' | 'A2' | 'A3'): CKDStage {
if (eGFR >= 90) return albuminuria === 'A1' ? null : 'G1' + albuminuria
if (eGFR >= 60) return albuminuria === 'A1' ? null : 'G2' + albuminuria
if (eGFR >= 45) return 'G3a' + albuminuria
if (eGFR >= 30) return 'G3b' + albuminuria
if (eGFR >= 15) return 'G4' + albuminuria
return 'G5' + albuminuria
}
這段程式碼依 KDIGO 2024 國際指引寫成。判定不交給 LLM。ExClinCalc 中也類似:12 組關鍵藥物交互作用是規則表,不是 LLM 推論。
Layer 2:結構化脈絡注入
判定結果用結構化格式傳給 LLM:
const context = {
patient_data: { eGFR: 45, albuminuria: 'A2' },
diagnosis: {
stage: 'CKD G3a-A2',
source: 'KDIGO 2024',
confidence: 'rule-based',
},
rule_applied: 'KDIGO 2024 stage classification table'
}
const prompt = `
請將以下結構化臨床判定結果,翻譯成適合一般民眾閱讀的中文說明。
你只能引用以下提供的資料,不得添加額外臨床判斷。
[判定結果]
${JSON.stringify(context)}
[輸出格式]
1. 一句話總結(白話)
2. 數值意義(為什麼這個分期)
3. 建議下一步(從以下選項擇一:「諮詢家醫」「諮詢腎臟科」「3 個月後追蹤」)
`
注意:
- LLM 只看到結構化資料 + 規則來源
- LLM 不看到原始病歷文字、其他病人資料
- LLM 的輸出格式是受限的(只能從預設選項選下一步)
Layer 3:LLM 推論 + 強制引用
LLM 的回應必須引用 Layer 1/2 提供的資料。前端做最後一道驗證:如果 LLM 引用了 context 沒有的 source,或提出不在預設選項內的建議 → 顯示「需醫師確認」標籤、不顯示 LLM 內容。
隱私的副效果
「先規則後 LLM」設計讓原始病人資料不離本地:病人輸入體檢數值留在瀏覽器 + Cloudflare Workers 邊緣,規則引擎在 Workers 跑,傳給 Gemini 的 prompt 只有結構化判定結果。
原始 eGFR 數值 ──[本地]──> 規則判定 ──[結構化]──> Gemini API
↑
看到的只是「CKD G3a」
不是「江先生的 eGFR=45」
這個架構同時降低幻覺風險與隱私風險。一個設計決定解決兩個問題。
真實代價:規則引擎覆蓋不到的地方
「先規則後 LLM」最大的限制在於:規則引擎覆蓋不到的問題,LLM 也無能為力。例:
- 病人問「我這個檢查報告整體看起來怎樣?」(綜合判斷,不是單一指標)
- 病人問「我覺得最近很累跟我的 CKD 有關嗎?」(症狀-診斷連結)
- 病人問「我下次回診要問醫師什麼?」(個人化諮詢)
這些問題規則引擎處理不了。我目前的策略是:標示「需醫師確認」+ 不讓 LLM 自由生成。代價:使用者覺得 AI「能做的事不多」。
開放問題:研究方向
問題 1:「先規則後 LLM」可推廣嗎?
這個策略在 KDIGO 分期、藥物交互檢查上可行。在「鑑別診斷」「症狀分析」這類本質上模糊的任務上,可能不夠。可能的研究:對不同類型臨床任務量化「規則 vs LLM 角色比例」的最佳配置。
問題 2:規則引擎更新跟不上指引變動
KDIGO 2024 跟 KDIGO 2012 的分期標準有實質差異。指引每幾年更新一次。我的規則庫怎麼追上? 可能的研究:用 RAG 把臨床指引當動態 KB,讓 LLM 不只是翻譯,也能對接最新指引。
問題 3:LLM 引用驗證的盲點
我的 Layer 3 驗證是「LLM 引用的 source 必須在 context 裡」。但 LLM 可能引用了 source,內容卻偏離 source。可能的研究:用第二個 LLM 做「事實一致性檢查」(meta-checker)。
問題 4:使用者信任 vs 使用者賦能的張力
過於保守的 LLM 介入 → 使用者覺得「AI 能做的事少」→ 信任不會建立。過於積極 → 幻覺風險。可能的研究:使用者研究方法量測「對 LLM 的信任」如何隨 disclosure 透明度變化。
為什麼我把這個架構開源
完整實作在 ClinCalc 與 ExClinCalc on GitHub。
我相信 LLM 在醫療場域的安全應用不是純學術研究問題,而是工程設計問題。學界很多研究停留在「LLM 在 USMLE 考幾分」,業界缺的是「實際運作的整合架構」。希望這個 case study 能給其他想做類似系統的人一個起點。
結論
「先規則後 LLM」是我目前認為的安全 LLM-CDSS 整合最佳實踐:
- 規則引擎做臨床判定(可解釋、可稽核)
- LLM 做翻譯(可讀性、自然語言)
- 強制引用 + 驗證(避免幻覺)
- 副作用:隱私保護(原始資料不離本地)
這個策略不完美。它的限制是規則覆蓋率。要超越這個限制,需要的是更精細的研究 ── 而不是更強的 LLM。
文獻
- Pal, A., et al. (2023). Med-HALT: Medical Domain Hallucination Test for Large Language Models. EMNLP.
- Singhal, K., et al. (2023). Large language models encode clinical knowledge. Nature 620(7972).
- KDIGO 2024 Clinical Practice Guideline. Kidney International, 105(4S).