動作
Feature #393
進行中
SC
Direct-Map 票 B:Stage 0 resolver 上線 — 表單傷情查表直出確定碼,AI 退居掃尾
Feature #393:
Direct-Map 票 B:Stage 0 resolver 上線 — 表單傷情查表直出確定碼,AI 退居掃尾
狀態:
New
優先權:
Normal
被分派者:
-
開始日期:
2026-07-31
完成日期:
完成比例:
0%
預估工時:
概述
Direct-Map 票 B:Stage 0 resolver 上線 — 表單傷情查表直出確定碼,AI 退居掃尾¶
背景¶
Direct-Map 的核心價值實作:醫師在人體圖/骨骼圖點的「部位 + 傷情」,
查表直接出碼(0 秒、確定性、標 confidence=certain),AI pipeline 只處理
「note 非空 / 查表未命中 / 檢傷文字裡圖上沒標的傷」。
對照表(#390 建置、#391 雙 AI 審核定稿,1,061 列)接上 /predict_icd10。
設計:docs/icd10-directmap-design.md §4(本票同步定稿)。
變更內容¶
1. backend/directmap.py(新)— Stage 0 resolver¶
- 表載入建索引(
lru_cache,程序內只讀一次);resolve_soft/skeletal/joint/spine
- 主入口
resolve_injuries(structured, sex) → (resolved, leftover)
-
側別解析三層:id 前綴(特寫圖
left_/right_)→ id 內含_left/_right(主體圖)
→ 名稱含 left/right;另容忍_front/_back視圖後綴(同部位兩視圖共用碼) - 症狀轉挫傷(redness/tenderness/swelling/ecchymosis/deformity → 該部位 contusion)
-
不出碼也不送 AI:ROM 受限、
(Note) - note 非空 → 整筆交 AI(定案 5:想讓 AI 讀就寫 note)
-
BY_GENDER:依
sex擇一;性別未知 → 男女兩碼並陳供醫師勾選 - 同碼去重(口腔燒傷三度同碼);查表任何例外都退回 AI,不得炸 pipeline
2. backend/main.py — /predict_icd10 合併流程¶
- 增收
structured_injuries: [{kind, partId, partName, injuryType, segment?, side?, note?}]與sex
(既有fallback_injuries保留相容) - 表定碼在前 + AI 碼在後合併,同傷情去重
- AI 失敗時若已有表定碼 → 回表定碼(不讓整包歸零)
-
debug.directmap記錄 resolved / leftover_to_ai(即使 0 筆解出也留軌跡)
3. backend/rag_service.py — AI 不重判已確定的傷¶
-
predict_icd10(_faceted)增resolved_injuries:Stage1 抽出後濾除
(_matches_resolved比對傷型+側別+部位詞,非全字串 —— AI 寫法與表單字串不同也能對上) - prompt:swelling 條改為「從病歷文字推論不得編碼」(人體圖標記改由查表確定性處理)
4. 表單明確資訊不可丟(使用者實測發現,兩輪補齊)¶
D1(b)「表單沒有的資訊不假定」≠「表單有的資訊不用」。原設計漏了兩項:
-
脊椎骨折型態:表加
morphology欄。胸/腰椎壓迫性骨折 → 楔形壓迫碼(x0),
含「節位未特定」列(S32.000A/S22.000A —— 「知道是壓迫但不確定哪節」是最常見情境);
頸椎 ICD 無壓迫型 → 標NO_MORPH_IN_ICD誠實落未特定 -
開放性骨折:骨骼+脊椎表加
code_open欄(第 7 碼 A→B,建表時已驗證存在);
resolver 見 injuryType 含 open 即取用。長骨 C 級(Gustilo IIIA/B/C)未細分,交 note/AI
5. 開關與測試¶
-
ICD_DIRECTMAP=on/off(預設 off = 逐位元回到過往行為,已實測 rollback) -
backend/tests/directmap_resolver_test.py(新)27 項單元測試(不需伺服器) -
backend/tests/directmap_assert.py擴充至 36 項(新增 code_open 存在性、型態列檢查) -
backend/tests/smoke_test.py新增 7.0(結構化傷情端點檢查,開/關皆通過) -
demo_directmap.py(新)人眼可讀的示範工具,供臨床端手動驗證
驗收標準¶
- 實測 7 筆表單傷情 → 3.9 秒出 10 個確定碼(零 LLM 呼叫)
- 表定碼 + AI 掃尾:左膝擦傷由表直出、頭皮裂傷由 AI 從病歷補上,
且 AI 未重複輸出左膝 - 壓迫性骨折六候選型態一致(節位未特定排最前 + L1–L5 全為楔形壓迫)
- 開放性骨折
S42.302A → S42.302B;閉鎖性維持 A - 測試全綠:斷言 36 + 單元 27 + 端點整合 15 + smoke 51 = 129 項
-
ICD_DIRECTMAP=offrollback 實測:零確定碼、零 debug 痕跡,行為同過往
備註¶
-
部署:啟用需在
backend/.env設ICD_DIRECTMAP=on(不設=完全不影響現況);
對照表隨 repo 走,無額外資料檔需求 -
前端尚未接上:網頁點人體圖仍走純 AI 老路,要在 UI 看到「確定碼」需票 C/D
(前端改送structured_injuries) - 待辦:票 C/D 前端、
_score()具名部位護欄
沒有任何資料可供顯示
動作