專案

一般

配置概況

動作

Bug #397

進行中
SC

修正 Direct-Map 實測缺陷:兩段式即時出碼、覆蓋率補漏 1,987 組、手部側別遺失

Bug #397: 修正 Direct-Map 實測缺陷:兩段式即時出碼、覆蓋率補漏 1,987 組、手部側別遺失

是由 Sashiba Chou約 13 小時 前加入.

狀態:
New
優先權:
Normal
被分派者:
-
開始日期:
2026-08-01
完成日期:
完成比例:

0%

預估工時:

概述

Direct-Map 實測回饋修正輪(v0.6.2)

背景

票 A–D 上線後,實際在畫面上操作時陸續發現一批缺陷。共通症狀是「明明在圖上點了,卻還要等 AI,而且 AI 還會亂加碼」,與 Direct-Map 的設計目的相違。本票把這輪實測抓到的問題一次收斂,並針對每一個根因加上護欄,避免同類問題再犯。

實測回報的問題:

  1. 表定的確定碼要等 AI 跑完(~3.3 秒)才一起出現
  2. AI 會把已由表定出碼的傷再編一次,且給出不同且較差的碼
    (表定「肩鎖關節脫臼」S43.102A,AI 另出肩關節脫臼 S43.005A)
  3. 檢視頁的中文描述欄空白、英文欄夾雜中文
  4. Head: 2nd degree burn 查不到表 → 落給 AI 猜
  5. 骨盆/髖特寫、特寫圖「未指定」按鈕的傷情查不到表(84 + 7 個部位)
  6. 純點選、沒有任何備註的病歷,仍會呼叫 AI
  7. 右手閉鎖性骨折被編成 S62.90XA「未明示側性」(ICD 明明有右側碼 S62.91XA)
  8. 兩張圖上的「ICD-10 快查」仍是全 AI,沒有享受到查表直出

變更內容

1 兩段式出碼 + 純點選跳過 AI

  • /predict_icd10 新增 table_only:只查對照表、完全不呼叫 LLM
  • 前端先打 table_only 立即渲染確定碼,第二段才跑 AI(實測 0.1s vs 3.3s)
  • leftover 為空且無自由文字(機轉描述/傷情備註)→ 第二段直接不發,畫面顯示「全部傷情皆由圖上標記直接對應,未使用 AI」
  • lifespan 加 directmap.warmup() 預載對照表與 73,681 筆碼描述

2 快查也走兩段式(本輪新增)

  • 新檔 frontend/src/lib/icd-extract.ts:兩段式邏輯抽成共用函式
  • 三個呼叫點(檢視頁籤、軟組織快查、骨骼快查)共用同一份實作,避免其中一處改了另外兩處沒跟上
  • 兩張圖的「ICD-10」按鈕:秒開視窗顯示確定碼,只有需要時才跑 AI

3 AI 不再重複編碼(三道防線)

  • Stage 1 prompt 附「ALREADY CODED — DO NOT OUTPUT」清單(治本:LLM 直接不抽該傷,也更快)
  • _matches_resolved 補中文詞段比對(表單選項是中文,AI 原樣抄回時英文詞比對會漏)+ 字首 5 碼容忍 humerushumeral
  • 端點碼級去重(首選碼已由表定出過 → 整條丟棄);legacy pipeline 同步套用

4 燒傷標籤正規化

  • backend 自行正規化(認得 2nd degree burn / Burn 2nd / second…)
  • 只寫 Burn 未選程度 → 出 ICD 未指定程度碼,不讓 AI 猜(soft 表新增 Burn-unspec 組)

5 描述欄修正

  • _icd_desc()name_zh 把「英文 中文」合併欄拆回兩欄
  • 檢視頁加「確定」綠徽章

6 覆蓋率窮舉稽核(新測試 directmap_coverage_audit.py)

直接讀前端原始碼枚舉「兩張圖所有部位 × 所有 UI 傷情選項」全跑 resolver。

  • 第一輪抓到 84 組未出碼:PELVIS_HIP_ZONES 宣告在 SoftTissueTab.tsx 而非 BodySvgPaths,產生器只掃後者 → 骨盆/髖特寫從未進表;另補手足整體骨、骨盆未指定側、髖部燒傷落 T24.x0x
  • 第二輪抓到 7 個動態虛擬部位:特寫圖「未指定」按鈕由 makeUnspecifiedPart() 產生,不在任何 zone 陣列裡 → 這正是「Pelvis (Unspecified) 燒傷」落給 AI、進而冒出右前胸壁擦傷/女性生殖器燒傷/陰莖裂傷的根因
  • 結果:1,987 / 1,987 組全部出碼

7 手部側別遺失 + 根因護欄

  • hand_bones 修正為分側:右 S62.91XA / 左 S62.92XA(開放版 …B 同步)
  • 根因:第一輪補建時比照掌骨/指骨標成不分側,但那兩者是 ICD 本身沒有側別碼,手部整體不是
  • 產生器新增「側別稽核 2」:無側別列把命中碼描述裡的每個 unspecified 逐一換成 right,查得到字面相同的碼就報錯;白名單僅限已審核的中線構造(胸骨/薦骨/骨盆)與 ICD 本身無側碼者(掌骨/指骨)
  • 同規則寫進 directmap_assert.py(13b / 13c),兩道擋

護欄自身踩過坑:比對索引一開始用整個 description 欄,但該欄是「英文 + 中文」合併字串,精確比對永遠不命中 → 回報 0 筆是假綠。改成只取英文段後,用已知壞案 S62.90XA 反測確實抓得到 S62.91XA,才確認有效。新增稽核必須先用已知壞案反測。

驗收標準

項目 結果
smoke_test(含新增 7.0b/7.0c) 53 PASS / 0 FAIL
對照表斷言 directmap_assert.py 38 PASS(新增 13b/13c)
resolver 單元 directmap_resolver_test.py 28 PASS
覆蓋率稽核 directmap_coverage_audit.py 1,987 / 1,987 出碼
快查兩段式 e2e 7 PASS
AI-skip e2e / 兩段式 UI e2e 7 PASS / 7 PASS
票 C/D e2e、關節 e2e 13 PASS / 14 PASS
typecheck / lint 乾淨(僅既有 warning)

實測驗證(使用者回報案例):

  • 「Chest 擦傷 + Abdomen 挫傷 + Pelvis(未指定)二度燒傷 + 右髖挫傷 + 恥骨裂傷」→ 6 碼全確定、leftover 為空、AI 完全不跑
  • 「Right Hand: Closed fracture」→ S62.91XA 右側腕及手部骨折

測試維護規約

  • smoke_test.py 新增 7.0b(table_only 查表段不跑 LLM、leftover 為空)與 7.0c(右手骨折須出右側碼)
  • directmap_coverage_audit.py 列為前端圖層/傷情選項變更時的必跑項目
  • 表或產生器變更 → directmap_assert.py 須同票更新並全 PASS

版本

v0.6.1v0.6.2(CHANGELOG 已補;變更皆為使用者可感知:即時出碼、未使用 AI 提示、快查加速、手部側別修正)

沒有任何資料可供顯示

動作

匯出至 PDF Atom