Feature #410
進行中SyncHUD 啟動合約 v1.1(--payload/exit 0-5)+ 對接工具三支 + 票 E A/B 回歸揪出兩個 AI prompt 缺陷
0%
概述
SyncHUD 啟動合約 v1.1 + 對接工具三支 + 票 E A/B 回歸(揪出並修好兩個 AI prompt 缺陷)¶
背景¶
本票涵蓋三塊獨立但同期完成的工作:
- 跨專案協調四輪(協調公告第 1–7 號)敲定 SyncHUD → ER_note_NG.exe 的啟動合約,並實作到底
- 對接日準備:三支 exe 打包 + 現場用工具
- 票 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" 就完全正確 —— 中英對照實測確認。
外掛版的檢傷文字全是中文,這個缺陷會直接影響現場。
修法(三次迭代,前兩次留下紀錄)¶
-
整段拿掉排除區塊 → 退步全清,但重複出碼的 bug 立刻回來(AI 又冒
S43.006A)→ 證實這段必要,退回 - 措辭改成「部位 AND 傷型都相符才排除」+ 明列反例(髕骨 vs 膝、眼瞼 vs 鼻)→ 修好 Bug 1
- 補中文詞義對照(蟲咬=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()具名部位護欄
沒有任何資料可供顯示