專案

一般

配置概況

動作

Feature #318

進行中
SC

改善 ICD-10 檢索準確度:向量庫 cosine 正規化重建(方案A)+ L1 hybrid 字面比對 + 回歸測試基準

Feature #318: 改善 ICD-10 檢索準確度:向量庫 cosine 正規化重建(方案A)+ L1 hybrid 字面比對 + 回歸測試基準

是由 Sashiba Chou29 天 前加入.

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

0%

預估工時:

概述

改善 ICD-10 檢索準確度:向量庫 cosine 正規化重建(方案A)+ L1 hybrid 字面比對 + 回歸測試基準

背景

#317 遺留「快查排名偏差」問題,根因已查明並實測確認兩層:

  1. 向量庫層:ChromaDB(73,681 筆)存未正規化 embedding、以原始 L2 距離排序 → 描述越短向量 norm 越小、越靠近原點,形成萬用近鄰(hub)效應。實測:查 abrasion 時 A46 Erysipelas(丹毒,norm 2.51)排 #4,語意正確的 S50.311A(norm 4.6)反被壓過。
  2. 檢索策略層:「查詢詞一字不差就在描述裡」的查詢也全交給向量 → epistaxis 明明就是 R04.0 的描述原文,卻被拼字相近的 N45.1 Epididymitis(副睪丸炎)壓過,排不進前五。

快查(/search_icd10)與外傷 pipeline(/predict_icd10 legacy 路徑)共用同一向量庫,本次修正同時影響兩者。另收編部署機移回的 1,100 案例 golden dataset 作為回歸基準,所有改動均有改前/改後量化對照。

變更內容

方案A:向量庫 cosine 正規化重建(rag_service.py)

  • icd10_codes collection 重建:cosine metric(hnsw:space: cosine)+ 寫入端 normalize_embeddings=True,73,681 筆全庫重 embed(模型不變:paraphrase-multilingual-MiniLM-L12-v2)。
  • 查詢端 search_codes() 同步加 normalize_embeddings=True(與 collection metric 成對,單邊改會得到錯誤排名)。
  • 門檻掃描:全程式碼無硬編碼距離門檻(distance 僅排序/顯示用),免改。
  • faceted collection(icd10_codes_faceted)未動(其查詢端原本就 normalize)。

L1 hybrid 字面比對(main.py + Icd10SearchPage.tsx)

  • /search_icd10 檢索改為三層:① 代碼前綴(原有)→ ② L1 字面比對(新增) → ③ 語意向量(原有,補剩餘名額)。
  • 字面比對規則:英文 = 縮寫展開後查詢詞全部整詞出現於描述;中文 = 原始輸入為 zh 描述子字串。描述越短排越前(越接近純概念)。全碼表單詞索引 _icd_literal_index() 常駐記憶體,單次查詢 30~60ms。
  • 前端命中標示新增「字面」徽章(代碼=綠 / 字面=藍 / 語意=灰)。

回歸測試套件(backend/tests/,新收編)

  • golden_dataset.json:1,100 筆 ER 外傷案例含標準答案(部署機移回)+ 既有 /predict_icd10 回歸腳本 + 2026-03-30 legacy 基準(76.8% code recall)存 baseline_2026-03-30/
  • benchmark_vector_search.py:純向量層 benchmark(無 LLM、確定性),自動偵測 collection metric;改前/改後結果 JSON 一併入庫。後續評估任何新 embedding 模型(如 SapBERT)只需跑一次 --label 對照。

文件

  • ICD10_Vector_DB_Improvement_Options.md:方案 A~D 決策文件 + 本次執行結果(量化對照與殘餘問題歸屬)。
  • docs/https-deployment-plan.md(部署機移回,未實作待辦)、docs/system-architecture-2026-03.md(系統快照,已加現況註記)。
  • .gitignorebackend/chroma_db_backup*/(向量庫備份目錄,避免誤 commit)。

量化結果(1,100 案例 / 1,837 期望碼)

指標 改前 raw-L2 方案A cosine +L1 hybrid
exact recall@5(向量層/端點層) 10.4% 11.4% 16.0%(+54%)
exact recall@50(向量層) 30.8% 32.3%
family recall@30(向量層) 60.6% 63.0%
family recall@5 46.8% 46.3% 45.5%(持平)

驗收標準

  • epistaxis / nosebleedR04.0 字面命中排第一(改前排不進前五)。
  • abrasion / contusion / 擦傷(單字查詢)→ 前五全為合理字面命中(改前為 Tetany/噯氣等 hub 垃圾)。
  • erysipelas / 丹毒 → A46 穩居第一且距離差距拉開;A46 不再出現於 abrasion 前五(hub 病灶已除)。
  • 長查詢無退步:abrasion of right elbow → S50.311A 字面直中。
  • 縮寫鏈路正常:DKA → 展開 diabetic ketoacidosis → E08~E13 系列(字面找不到時正確退回語意)。
  • 向量層 benchmark 整體無退步(exact@50 +1.5pp、family@30 +2.4pp、MRR +5.6%)。
  • 前端 tsc --noEmit 零型別錯誤;查詢延遲 30~60ms。

部署注意(重要)

  • 程式碼與向量庫必須成對更新:部署機 pull 新程式碼後,須刪除舊 icd10_codes collection 讓其自動重建(首次啟動重算 73,681 筆約 10~25 分鐘,期間 API 無回應為正常),不可拿新程式碼配舊 L2 庫
  • 改動前備份:backend/chroma_db_backup_2026-07-03/(git 外);回滾 = 備份目錄換回 + git revert,兩者一起。

已知限制 / 後續

  • 純向量端殘餘 hub 雜訊:單字查詢在「字面比對接手」後已無實際影響,但根因(MiniLM 嵌入空間 anisotropy)屬模型本身限制。
  • 下一步(另案):方案 D 換 embedding 模型評估(候選 SapBERT 多語版/BGE-M3),用本次入庫的 benchmark 直接對照;建獨立 collection A/B,不動現用庫。

沒有任何資料可供顯示

動作

匯出至 PDF Atom