Bug #296
進行中ICD-10 燒傷 subsite 編碼錯誤 + 程度未展開;牙齒 lost/loose/缺失 漏抓或誤編
100%
概述
來源: 使用者回饋 docs/icd10_feedback_2026-06-20.json(id 12–19)
現象
軟組織圖點選燒傷、或最終病歷查詢 ICD-10 時,細部位燒傷被編到錯誤碼,且未列出各程度;部分牙齒外傷漏抓或誤編成口腔撕裂。
輸入(body-map / 病歷) 系統原本給的碼 應給¶
19 Upper Lip: Burn T28.0XXA 口及咽燒傷(內部) T20.02/12/22/32XA 唇(各程度)
18 Right Eye: Burn T20.05XA 頭皮 T26.00/01XA 眼瞼及眼周
17 Right Ear: Burn T28.411A 耳鼓膜(原文未提耳膜) T20.011/111/211/311A 耳(非耳膜)
16 Head: Burn T20.x5 頭皮 + T28.419 耳膜(污染) T20.00/10/20/30XA 頭面未明示部位
15 Upper Teeth: (缺失) S01.512A 口腔撕裂 S03.2XXA 牙脫位
14 Upper Teeth: (loose) S01.512A 口腔撕裂 S03.2XXA 牙脫位
13 Lower Teeth: (lost) (完全無診斷碼,Stage1 漏抓) S03.2XXA 牙脫位
12 Upper Teeth: (斷裂; fracture) S02.5XXA 正確 但「只用中文『牙齒斷裂』」時無任何碼
附帶觀察:在軟組織圖快查與最終病歷查詢會給出不一致結果(例如 eye 快查正確、病歷錯;Head (Back) 快查錯、病歷正確)。
根因
燒傷 subsite 流失:body-map 已知精確 subsite(upper lip / right eye…),但被攤平成自由文字 → Stage1 LLM 把部位粗化成 20 詞受控詞(head/face)→ faceted_search 沒有 subsite 過濾,只能靠 embedding 相似度猜,於是猜錯(唇→口咽、眼→頭皮、耳→耳膜)。快查與病歷送入的文字不同 + LLM 非確定性 → 兩者結果不一致。
無程度展開機制:程式碼從未有「未提程度→列 unspecified/一/二/三度」的邏輯。
牙齒守門字表不全:Stage1 note-level 守門只認 鬆動/脫落/掉牙/knocked out,未含英文 lost/loose/missing 與中文 缺失/掉,導致 (lost) 漏抓、(loose)/(缺失) 掉回口腔撕裂。
修正內容
燒傷 subsite 直通解析 resolve_burn_subsite()(backend/rag_service.py):以逐字 subsite(取自 evidence + raw_text)對應確定 ICD 碼,繞過 embedding + LLM 排序;快查與病歷兩條路徑共用同一 resolver,免前端改動。
程度展開:機械字串替換(ICD 燒傷碼度數位固定)。僅分度家族(T20–T25)展開為「未明示/一/二/三度」;無分度家族(T26 眼瞼、T28 內部)只給單碼。四肢/軀幹燒傷(tier2)將 faceted_search top1 的未明示程度碼展四度。明示程度時只給該度單碼。
防呆:純英文字以 \b 字界比對,避免 forearm 子字串 ear 誤判為耳。backend/scripts/faceted_search_proto.py 同步(離線可測)。
牙齒守門擴充:新增 lost/loose/missing/缺失/掉/luxat,僅在病歷含牙齒詞(teeth/tooth/牙)時生效,避免混合病歷的 lost/loose 污染其他傷情守門;Stage1 prompt 補字。中文「牙齒斷裂」→ S02.5、loose/lost/missing → S03.2。
影響檔案
backend/rag_service.py
backend/scripts/faceted_search_proto.py
backend/benchmark/icd10_benchmark_faceted.json(+15 燒傷反例)
backend/benchmark/icd10_benchmark_2026-06-20.json(新,回歸守門)
backend/benchmark/fixtures_2026-06-20.json(新)
backend/benchmark/icd10_benchmark_2026-06-16.json(fb#5 改綁 code prefix,原綁 LLM 命名為 flaky)
測試(綁碼段不綁 LLM 命名)
離線 run_faceted_benchmark.py:45/45
live icd10_benchmark_2026-06-20.json:18/18(feedback 12–19 全綠)
live 回歸:06-19 15/15、06-12 24/24、06-16 13/13
真實混合病歷(燒傷 + 撕裂 + 流鼻血 + 純徵象)+ 經 HTTP(port 8001)皆驗證無跨項污染
未涵蓋(後續)
P3 前端:軟組織圖牙齒部位改顯示 Fracture / Loosening / Avulsion(後端已能吃自由文字,前端 picker 屬 UX,待醫師拍板標籤用詞)→ 另開 ticket。
沒有任何資料可供顯示