14 天LLM 的 prompt 與回應留存可查
3 值true · false · null,缺資料不猜
4 次每條條文的修正預算,三段共用
292 + 77backend 與 frontend 測試
管線
七個步驟,每一步之間都有程式檢查
引文要在原文裡、節點定義要合法、整份 IR 要通過 validateIr。哪一塊出錯,就只修那一塊。
- 01匯入貼上條文,或上傳 PDF、docx,取出要分析的條文。
- 02拆解逐字引文 → 原子條件 → AND/OR/NOT 群組,分三段擷取。
- 03覆核每個條件一次小呼叫,只帶它引用的引文,對照原文並正規化數值。
- 04審核醫師逐條件接受、退回或標為不適用,再做整條簽核。
- 05產生每個條件一個 Boolean parameter,defines 組合邏輯,編譯成 ELM。
- 06驗證逐一覆寫 parameter,用 cql-execution 執行,和 IR 三值邏輯的結果比對。
- 07匯出CQL、ELM、證據契約與 fixtures,以條文或整份文件打包。
01 · 引文驗證
每個條件都指回原文
LLM 先抄下逐字引文,再從引文拆出條件。找不到逐字對應的引文,會標成待核,不會自動通過。
閱讀文件 →查得到的依據比對時忽略空白與全半形;修不好的引文記成「N 筆引文待核」,分析不會因此失敗。
02 · 單條件重新分析
只重跑有疑問的條件
覺得某個條件拆錯了,可以只對它重新呼叫 LLM。結果走一般的邏輯修改流程,其他條件不受影響。
閱讀文件 →查得到的依據被改動的條件,審核決定標為失效;沒動到的條件,決定保留。
03 · 邏輯畫布
在畫布上改邏輯
編輯、新增、移動條件,群組在 AND/OR/NOT 之間切換。一存檔,CQL 重新產生、消融驗證重跑。
閱讀文件 →查得到的依據存檔帶 baseHash:期間有人先存,就回 409,不會互相覆蓋。
04 · renderCql
CQL 由 IR 產生
每個原子條件一個 Boolean parameter,群組變成 define。不需要 FHIR retrieve 就能評估,證據由外部 adapter 填入。
讀懂產生的 CQL →查得到的依據邏輯一存檔,CQL 重新產生、消融驗證重跑;畫面上看到的就是會匯出的。
05 · 消融驗證
每個情境都實際執行一次
cql-engine 把 CQL 編譯成 ELM,cql-execution 逐一覆寫 parameter 執行;每個結果都要和 IR 三值邏輯的預期一致,才算通過。
讀懂產生的 CQL →查得到的依據證據不足時回 insufficient-data,而不是猜一個答案。
06 · 定點修正
只修出錯的那一塊
拆解分三段擷取:引文、條件、群組。每段都先過程式檢查,出錯的部分有專屬的修正步驟,其他部分不重跑;一條條文最多修 4 次,三段共用。
讀懂產生的 CQL →查得到的依據截斷的 JSON 絕不自動補括號;解析失敗就把錯誤位置回丟給模型重問。
Clause_Sample.cqlrenderCql 產出 · 節錄
library Clause_Sample version '1.0.0'
using FHIR version '4.0.1'1
標頭
library 是這份邏輯的名稱和版本;using FHIR 宣告它用 FHIR R4 的資料模型。
parameter "C1" Boolean default null
parameter "C2" Boolean default null
parameter "C3" Boolean default null
parameter "C4" Boolean default null2
輸入:一個條件一個參數
C1–C4 各是一個 Boolean 參數,預設是 null。證據轉接器查過病歷後填入 true 或 false,查不到就維持 null。
context Patient
define "Criterion C1":
"C1"
// Criterion C2–C4 follow the same pattern
define "Group G1":
"Criterion C1"
and "Criterion C2"
and "Group G2"
define "Group G2":
"Criterion C3"
or "Criterion C4"
define "Eligibility":
"Group G1"3
邏輯:把條件組起來
define 替一段運算取名字。and、or 的組法和審核畫面上的 G1、G2 一樣。context Patient 表示每個 define 都針對一位病人計算。
define "Eligibility Status":
if "Eligibility" is true then 'eligible'
else if "Eligibility" is false then 'ineligible'
else 'insufficient-data'4
結果:三種狀態
用 is true、is false 分出符合、不符合和資料不足。缺資料不會被算成「不符合」。
治理
上線之後也管得住
一次簽核只對應一個版本的邏輯。誰在什麼時候改了什麼,都查得到。
- 三種角色admin、reviewer、viewer。viewer 看得到全部頁面,但不能分析、簽核或改邏輯。
- 修改即失效被改動的條件與整條簽核標為失效,條文狀態依剩下的決定重新推導。
- 鎖定與退回已核准的條文由 reviewer 退回重審;已鎖定的只有 admin 能解鎖。
- 全部留痕修改、退回、重跑都寫入 audit_log;LLM 的 prompt 與回應保留 14 天。
- 不會互相覆蓋存檔帶 baseHash。兩個人同時編輯,後存的會收到 409,而不是蓋掉前一個人的修改。
- 忠實度檢查反向編譯(round-trip)對照產出與原條文;邏輯一改就標為過期,待手動重跑。
快速開始
完整安裝說明 →三步,在本機跑起來
- 1先換掉預設值上線前必做複製
.env.example,設定JWT_SECRET,並更換所有預設密碼。 - 2起整套服務
$ docker compose up -d $ cd frontend && npm ci $ npm run dev - 3打開工作台在 管理 → LLM 設定 加入模型 profile,就能貼上第一份條文。:5173工作台(前端開發):8081整套(經 nginx)