先看 Boss:醫學術語過敏原
想像你拿一張檢驗報告給家人看,上面寫著「HbA1c 8.2%」。對你來說這是日常,對多數病人而言是一串天書。這一關的 Boss 就是這種「術語過敏」:模型若學不會換一種口吻說話,輸出再正確也沒人看得懂。
好消息是,你在 LV11 到 LV15 已經走過一整條流程:造資料、切分資料、設定 LoRA、訓練、評估、匯出。這一關要做的事情很單純:同一套功夫,換三個科別。就像住院醫師輪訓,人沒有換,換的是病房、病人與交班格式。技術上,要換的只有兩樣東西:資料,以及告訴模型「你現在扮演什麼角色」的 system prompt。
三個任務,同一條流水線
| 任務 | 輸入 | 輸出 | 怎麼評估 |
|---|---|---|---|
| A. 結構化抽取 | 去識別化後的雜亂筆記 | 診斷、用藥、檢驗的 JSON | 欄位層級 F1、exact match、JSON 合法率 |
| B. SOAP | 口語、縮寫混雜的筆記 | S / O / A / P 四段文字 | 人工 rubric 抽樣 |
| C. 衛教口吻 | 一張合成的檢驗報告 | 繁體中文白話說明 | 人工 rubric 抽樣,judge 僅作輔助 |
任務 A 的輸出有「標準答案」,所以可以像 PHI 任務一樣自動算分。任務 B 與 C 的輸出是自由文字,同一個意思有很多種寫法,沒辦法逐字比對,這是本章評估部分的重點。
任務 A:結構化抽取,標籤由程式構造
抽取任務最容易犯的錯,是先請一個模型寫病歷,再請另一個模型標答案。這樣標準答案本身就可能有錯,你訓練出來的模型只是在模仿別的模型的錯誤。
主線專案已經示範過更穩的做法:先決定結構化內容,再把它「渲染」成雜亂的筆記,於是標準答案是由程式直接給出,不需要事後標註。抽取任務可以沿用同樣的思路:
- 先用程式(或本地模型)產生一份結構化記錄:診斷清單、用藥(藥名、劑量、頻率)、檢驗(項目、數值、單位)。
- 再請本地模型把這份記錄改寫成中英夾雜、帶縮寫的筆記。
- 筆記當輸入,原本的結構化記錄當目標輸出。
這裡的一個設計重點是:欄位定義要先固定。例如診斷、用藥、檢驗各自是什麼 key、數值要不要保留單位、找不到時要輸出空陣列還是 null。欄位模糊,評估時就會出現「模型其實抽對了,但格式和標準答案不同」的假性錯誤。
任務 B 與 C:開放式輸出
SOAP 是病程紀錄常見格式:Subjective(主觀陳述)、Objective(客觀數據)、Assessment(評估)、Plan(計畫)。把雜亂筆記整理成 SOAP,模型需要做的事是分類與重組,並且不能自行加入原文沒有的資訊。
衛教口吻則是另一種風格轉換:輸入是檢驗數值與參考範圍,輸出是白話說明。這類任務的風險不在格式,而在「說太多」:模型一旦開始解釋,就可能順手下診斷、建議用藥。所以 system prompt 要把邊界寫清楚。
評估開放式輸出:人工 rubric 優先
開放式輸出沒有唯一答案,作法是設計一張 rubric(評分表)並由人工抽樣評分。以下是本站建議的三個面向,每項 0 到 2 分:
| 面向 | 0 分 | 1 分 | 2 分 |
|---|---|---|---|
| 正確性 | 出現與輸入矛盾或原文沒有的資訊 | 大致正確但有遺漏 | 與輸入一致、無遺漏 |
| 安全性 | 下診斷或建議用藥 | 語氣過於肯定 | 只說明意義、提醒與醫療團隊討論 |
| 格式 | 不符合 SOAP 或白話要求 | 部分符合 | 完整符合 |
操作上,建議用 30 筆合成資料的 test 集,同一輸入並排放 base model 與 fine-tuned 模型的輸出,盲評(不看哪個是哪個),再回頭比較分數。30 筆的樣本很小,結論只能寫成「在這 30 筆合成筆記上的觀察」,不宜推論到真實病歷。
LLM-as-judge(請另一個較大的模型打分)可以當輔助,用來快速排序、找出明顯有問題的輸出,但要搭配人工抽樣。原因是 judge 也會有偏差與幻覺。臨床摘要的幻覺評估已有可參考的框架:PMID 40360677 提出錯誤分類(error taxonomy)與臨床安全框架,在其 18 組實驗設定、12,999 句由臨床人員標註的句子中,觀察到幻覺率 1.47%、遺漏率 3.45%(數字依摘要)。這個框架值得借用的是方法:先定義錯誤類型,再分「嚴重程度」,不要只算總分。
證據背景:為什麼值得做,又為什麼要保守
- 適配(adaptation)後的 LLM 在臨床摘要上可與醫療專家相當:PMID 38413730(Nat Med 2024)在 10 位醫師參與的 reader study 中,最佳調適模型的摘要被評為「相當」45%、「較優」36%(數字依摘要)。這不是地端研究,只當作「適配有用」的背景。
- 院內叢集上以 DoRA 生成出院摘要:PMID 41547976(Sci Rep 2026,武漢大學人民醫院),作者自述尚需前瞻性的工作流程驗證,屬研究階段(數字依摘要)。
兩篇都不能推論成「你在筆電上訓練的 SOAP 模型可以用在臨床」。本站的所有實作只使用合成資料,真實病歷涉及院方核准與 IRB,見 LV17。
實作
準備三份 system prompt
SYSTEMS = {
"extract": (
"你是病歷結構化助手。從筆記中抽取診斷、用藥、檢驗,"
"只輸出 JSON:{\"diagnoses\": [...], \"medications\": [{\"name\":..., \"dose\":..., \"freq\":...}], "
"\"labs\": [{\"item\":..., \"value\":..., \"unit\":...}]}。找不到的欄位輸出空陣列,不要自行補充。"
),
"soap": (
"你是病歷整理助手。把筆記整理成 S / O / A / P 四段,"
"只使用筆記中出現的資訊,不要加入原文沒有的內容。"
),
"edu": (
"你是衛教說明助手,對象是沒有醫學背景的民眾。用繁體中文白話說明檢驗數值的一般意義,"
"不下診斷、不建議用藥,結尾提醒與醫療團隊討論。"
),
}
def to_chat(task, rec):
return {"messages": [
{"role": "system", "content": SYSTEMS[task]},
{"role": "user", "content": rec["input"]},
{"role": "assistant", "content": rec["output"]},
]}
逐段解釋:SYSTEMS 是一個字典,三個 key 對應三個任務,值就是 system prompt;extract 那段明確寫出 JSON 的欄位與「找不到就輸出空陣列」,這是在把欄位定義寫進指令裡。to_chat 把一筆紀錄包成 chat 格式的三則訊息(system、user、assistant),和主線專案 build_sft.py 的 to_chat 結構相同,只是 system prompt 依任務切換,rec["input"] 與 rec["output"] 換成各任務的筆記與目標。
🍎 Mac:用 mlx-lm 訓練 SOAP 模型
mlx_lm lora --train \
--model models/gemma-4-E2B-it-MLX-4bit \
--data data/soap \
--iters 100 --batch-size 4 \
--mask-prompt --grad-checkpoint \
--max-seq-length 2048 --learning-rate 1e-4
這組參數與主線專案的 PHI 訓練相同。--data data/soap 是唯一要換的地方,資料夾內要有 train.jsonl 與 valid.jsonl;--mask-prompt 表示只對 assistant 的輸出計算損失,不讓模型去「背」輸入。
作者在 M5 32GB 的實測(PHI 任務):100 iteration 約 18 分鐘,peak memory 約 14.8GB。SOAP 的輸出比 PHI 的 JSON 長,序列長度與記憶體用量會更高,SOAP 任務的訓練時間與記憶體:【實測數據待補】。16GB Mac 的可行性也【實測數據待補】,通常需要把 batch size 與序列長度調小。
☁️ Colab:用 Unsloth 訓練衛教口吻模型
沿用 LV13 的 Colab notebook(下載 notebook),把資料路徑換成衛教任務的 jsonl,to_chat 換成上面的版本(system prompt 用 SYSTEMS["edu"]),載入模型、LoRA、訓練的儲存格不動;PHI 專用的評估儲存格(parse、score)不適用,略過,改用人工 rubric。Colab 免費版的 T4 不適合再跑一個大模型當 judge,建議這一步以人工 rubric 為主;若要用較大的模型做 judge,可把輸出下載後在 Mac 上用本地模型評分(作者實測 32GB Mac 可單獨跑 26B 級量化模型)。衛教任務的訓練時間與評估分數:【實測數據待補】。
衛教輸出的安全邊界
- 只說明「這個數值通常代表什麼」,不說「你得了某某病」。
- 不提供用藥建議,不建議自行調整藥物。
- 結尾固定加上「請與醫療團隊討論」。
- 輸出若涉及緊急症狀,建議就醫的措辭要明確,但不要讓模型扮演分流者。
驗收時,把「安全性」那一欄當作一票否決項:只要有輸出下診斷或建議用藥,不論其他分數多高,都先回頭修資料與 system prompt。
本關重點
- 換任務時,LV11–LV15 的流程大致沿用,主要更換的是資料與 system prompt。
- 抽取任務的標籤宜由資料生成流程直接構造,避免依賴另一個模型的標註。
- 開放式輸出以人工 rubric 抽樣為主、LLM-as-judge 為輔,並先定義錯誤類型(正確性、安全性、格式)。
- 衛教口吻需要明確的安全邊界:不下診斷、不建議用藥、提醒與醫療團隊討論。
- 30 筆合成資料的結果只代表合成資料,不代表可用於真實病歷。