專案

一般

配置概況

動作

Feature #410

進行中
SC

SyncHUD 啟動合約 v1.1(--payload/exit 0-5)+ 對接工具三支 + 票 E A/B 回歸揪出兩個 AI prompt 缺陷

Feature #410: SyncHUD 啟動合約 v1.1(--payload/exit 0-5)+ 對接工具三支 + 票 E A/B 回歸揪出兩個 AI prompt 缺陷

是由 Sashiba Chou 於 約 2 個月 前加入.

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

0%

預估工時:

概述

SyncHUD 啟動合約 v1.1 + 對接工具三支 + 票 E A/B 回歸(揪出並修好兩個 AI prompt 缺陷)

背景

本票涵蓋三塊獨立但同期完成的工作:

  1. 跨專案協調四輪(協調公告第 1–7 號)敲定 SyncHUD → ER_note_NG.exe 的啟動合約,並實作到底
  2. 對接日準備:三支 exe 打包 + 現場用工具
  3. 票 E:Direct-Map 上線後唯一還沒回答的問題 —— 「新路徑在整批真實案例上不比舊路徑差嗎?」

一、SyncHUD 啟動合約 v1.1

為什麼改啟動介面

原本是 ER_note_NG.exe <病歷號> [工號]。SyncHUD 方提出不可協商的安全鐵律:病人資料絕不進命令列(Windows 命令列任何行程都讀得到,Win32_Process.CommandLine)。我方認同 —— 本專案在 URL 上早就用同一原則(金鑰放 fragment 不放 query,不進伺服器 log)。

變更內容

  • --payload <json檔> 啟動;位置參數降級為開發測試用,由 config.json 的 allow_positional_args 控制,部署預設 false
  • payload 讀完必刪,含三種邊界:正常、解析失敗也刪(檔案含 PII,留著才是問題)、聚焦既有視窗的第二實例也刪
  • 開窗前探測 /api/health(3 秒) → 不通就不開窗,免得醫師看到一扇死窗。任何 HTTP 回應都算連得上(後端一時 5xx 不該擋醫師評估)
  • 核對不符改二選一對話框:取消 → exit 3;仍要繼續 → 完成後 exit 4
  • 降級留痕:三種降級路徑與核對不符的兩條路各記一行本機 log(%LOCALAPPDATA%\ERNotePlugin\log\plugin.log),絕不寫入病人資料
  • _issuedAt 新鮮度檢查(5 分鐘僅警告不阻擋);reg_seq=0 視同缺值;病歷號型別容忍(兩邊共用正規化函式)

Exit code 表 v1.1

code 語意 責任指向
0 正常結束(含降級模式完成) —
1 payload 無效 SyncHUD 側
2 伺服器探測失敗 伺服器/網路
3 核對不符,醫師取消 操作情境
4 核對不符,醫師繼續並完成 操作情境
5 本機 config.json 缺失/損毀 工作站安裝

code 5 是我方主動提出的缺口:合約表原本沒涵蓋「工作站設定壞掉」,暫歸 1 會讓 SyncHUD 每收到一個 1 都得先排除是不是那台工作站的問題。協調者裁示分碼。

設計界線:exit code 只反映「啟動階段」。帶回成敗即時呈現在視窗內 —— exe 開窗後會一直活著到醫師關窗,且帶回可能發生多次,不可能用 exit code 表達。


二、對接日工具(三支 exe)

產物 用途
ER_note_NG.exe (18.2 MB) 主程式
make_test_payload.exe (8.3 MB) 產測試 payload;打包成 exe 是為了消除「測試機要裝 Python」這個對接日相依風險
traumafill_probe.exe (8.3 MB) 唯讀診斷工具:跑三個查詢,輸出原始 stdout/exit code/耗時 + 主程式會怎麼判。對接日是第一次接真實 TraumaFill 管道,若落到「連不到」,現場守則是「記錄後回報、不即興修改」—— 而「跳了警告」這個記錄不足以分診

順手修掉的既有 bug:build_exe.ps1 缺 BOM

原檔是 UTF-8 無 BOM,PowerShell 5.1 以 ANSI(cp950)解析 → 中文字串亂碼 → 引號未收尾 → 腳本語法錯誤,根本打不包。部署機第一次打包必踩。已補 BOM,並已通報生態系(協調公告第 6 號採納為技術規則)。

補充實務細節:Set-Content/Add-Content 預設寫系統 ANSI,會把修好的 BOM 再弄掉,所以是用二進位方式補的。


三、票 E:330 案 A/B 回歸

設計

  • A 組(舊路徑)= 只送病歷文字 → 純 AI
  • B 組(新路徑)= 文字 + 逆向還原的表單傷情 → 對照表直出 + AI 掃尾

資料集只有病歷文字,故從 PE 段落逆向還原表單傷情(部位名稱對照直接讀前端原始碼)。還原不出來的案例 B 組退化成與 A 相同,不假造資料,並在報告中列為無鑑別力。

抓到兩個真 bug(都在 rag_service.py 的 ALREADY CODED 提示詞)

Bug 1 — 連坐壓制
清單寫「Right Knee: Laceration」→ AI 連髕骨骨折都不抽了(#533:B 的 Stage 1 只抽 1 筆,A 抽 3 筆)。同樣地清單有「鼻挫傷」→ 連眼瞼挫傷也不抽。
根因是措辭「Do NOT output them, any variation of them」講太寬。

Bug 2 — 中文專屬退化(對外掛版是直接風險)
「蟲咬」在有表定碼時被誤判成 abrasion(S50.812A 前臂擦傷)而非 open_bite(S50.862A)。同一句話用英文 "Insect bite" 就完全正確 —— 中英對照實測確認。
外掛版的檢傷文字全是中文,這個缺陷會直接影響現場。

修法(三次迭代,前兩次留下紀錄)

  1. 整段拿掉排除區塊 → 退步全清,但重複出碼的 bug 立刻回來(AI 又冒 S43.006A)→ 證實這段必要,退回
  2. 措辭改成「部位 AND 傷型都相符才排除」+ 明列反例(髕骨 vs 膝、眼瞼 vs 鼻)→ 修好 Bug 1
  3. 補中文詞義對照(蟲咬=open_bite、撕裂傷=laceration…)+ 「分類不得受此清單影響」→ 修好 Bug 2

方法論上的兩個修正

(a) 精確度必須一起看
原本只算「候選清單裡有沒有出現期望碼」,但 A 每案吐 7.5 個碼、B 只吐 6.1 個 —— 吐得多本來就容易命中。A 的清單常同時出現三種側別,那不是診斷是猜測。實測 A 精確度 22.3% / B 26.9%,已納入報告。

(b) LLM 非決定性會讓測試謊報
實測同一個請求連跑 6 次,命中率 5/6;A/A 對照(兩組送完全相同請求)57 個期望碼差了 5 個。
→ 新增 --verify N:抓到候選退步就各再跑 N 次,只有「B 從未命中、A 至少半數命中」才算真退步。實測正確濾除了多個假警報。

允收清單改為「規則式」

原本以 (案例id, 碼) 逐筆列舉,但接受的理由是結構性的 —— 實測換一批案例後,11 案新退步裡 6 案是同一個胸壁側別問題,只是編號不同。改為描述層級規則:

  • 人體圖粒度比 ICD 粗 → 落未特定碼(使用者 2026-08-02 拍板接受;需要側別時寫備註交 AI)
  • 期望碼本身即模糊碼,B 給的更精確 → 方向相反,不是退步
  • 截肢非表單傷情選項(INJURY_TYPES 九選一沒有)→ 兩組皆走 AI

同時修掉兩個測試工具自身的 bug

bug 症狀
解析漏第一筆 行首無區段標題時(left calcaneus: Closed fracture; right elbow: …),用第一個冒號切會把第一筆傷情整個吃掉 → 害 #574 左跟骨、#613 前額裂傷落到 AI 才出現差異。查證兩者表定碼正是期望碼
眼瞼未對應 ICD 的 eye 碼即眼瞼碼(eye_right + Laceration → S01.111A),人體圖也有 eye 區,是還原沒接上。#588 我一度誤判成「LLM 不穩定」

修正後還原覆蓋 200 → 224 案 / 370 筆。


驗收標準

項目 結果
smoke_test.py 53 PASS / 0 FAIL
his_plugin/shell/test_startup.py(新) 69 PASS / 0 FAIL
打包產物驗證(frozen base_dir、exit 1/2/5、config 壞時 payload 仍刪) 7 PASS
對接日測項本機演練(2-1/2-2/2-3/2-4/測項 9) 8 PASS
票 E 已知問題案例(16 案)複驗 新退步 0,11 案由規則允收
肩鎖關節脫臼去重(原本要防的 bug) 4 PASS(拿掉提示詞會回歸,已驗)
directmap_assert.py / directmap_resolver_test.py 38 / 28 PASS
directmap_coverage_audit.py 1,987 / 1,987

測試維護規約

  • directmap_ab_regression.py:對照表、resolver 或 AI prompt 變更後必須重跑;允收清單不得為了讓測試變綠而擴充,新退步若不屬既有規則一律視為回歸
  • 全 330 案單跑約 40 分鐘 / 660 次 LLM 往返,有 API 成本 —— 請先確認再跑

後續

  • 全 330 案的最終定案數字待補跑(工具修正後尚未完整重跑一次)
  • 對接日:實機對接第 2 步,由整合方排定;我方前置已就緒
  • 待辦不變:§7.1 Closed fracture 的 UX 註記、_score() 具名部位護欄

沒有任何資料可供顯示

動作

匯出至 PDF Atom