體檢指標趨勢分析系統
用途
將多年度、多型態(電子 PDF / 掃描件 / 照片)的體檢報告統一解析為標準化指標時間序列,產出趨勢分析報告 + 互動式健康管理工作台。全本地處理、自動脫敏、動態擴展(新增報告重跑流水線即可)。
觸發詞
- 歷年體檢報告 / 多年度體檢報告 / 歷年的體檢報告 / 歷年體檢
- 體檢報告數據化 / 體檢數據解析 / 體檢報告解析
- 體檢指標趨勢 / 指標趨勢分析 / 指標趨勢
- 歷年體檢指標對比 / 體檢指標對比 / 逐年對比 / 逐年變化
- 化驗單分析 / 化驗單解讀 / 檢驗報告分析
- 體檢報告掃描件 / 掃描件體檢報告 / 掃描件 OCR
- 體檢報告照片 / 照片版體檢報告 / 手機拍的體檢報告
- 健康管理工作台 / 健康管理看板 / 健康數據看板 / 可視化看板
- 血糖趨勢 / 血糖變化 / 尿酸偏高 / 血脂趨勢 / 血壓趨勢
- 體檢異常指標 / 異常指標解讀 / 指標異常
- 新增體檢報告 / 新報告接入 / 加入新一年體檢
- 體檢數據脫敏 / 脫敏數據集 / 脫敏版 / 可分享數據集
環境準備
# 依賴(已裝可跳過):pymupdf 必需;Pillow(照片合成)、pyobjc-framework-Vision/Quartz(OCR,僅 macOS)可選
export REPORT_DIR=/path/to/體檢報告目錄 # 報告存放目錄(含 PDF 或 年度文件夾+JPG)
export WORK_DIR=/path/to/工作數據目錄 # 數據產物目錄(自動建 data/ 與 output/)
export PY=/path/to/python # 建議用帶依賴的 python 解釋器
Step 0(每個新會話第一步,必做):
$PY scripts/check_deps.py # 一鍵體檢:缺什麼、影響哪幾個腳本、怎麼裝
$PY scripts/check_deps.py --json # 機器可讀,供自動化消費
退出碼 0 = 必需依賴齊全可開工;1 = 缺必需依賴(主流程走不通,按提示裝);可選依賴缺失只影響對應輸入型態,不阻斷電子版 PDF 主路徑。
執行流程
所有腳本均支援 --help,參數優先於環境變數;不帶參數運行 = 沿用環境變數的原有行為。
- 識別輸入型態:遍歷
REPORT_DIR- 根目錄
*.pdf含文字層 → 電子版(parse_reports.py處理) - 根目錄
*.pdf無文字層 → 掃描件(vision_ocr.py+extract.py) - 年度子目錄
YYYY體檢報告/*.JPG→ 照片版(make_year_pdfs.py合成 → OCR →extract.py)
- 根目錄
- 解析電子版 PDF(座標定位法,列邊界見
references/解析與口徑.md):$PY scripts/parse_reports.py # → data/reports_raw.json $PY scripts/parse_reports.py --year 2027 --dry-run # 單年份試跑,不寫盤 - 照片版合成 PDF + OCR + 提取(如存在 JPG 目錄 / 掃描件):
$PY scripts/make_year_pdfs.py --year 2015-2020 # 年度多張 JPG → 單份 PDF(橫拍自動旋轉校正) $PY scripts/vision_ocr.py <pdf> data/ocr_2022.json # 掃描件/照片 OCR → 帶座標 JSON $PY scripts/extract.py --year 2022 # OCR 結果 → 指標(策略自動判定) $PY scripts/extract.py --years 2015-2020 # 多年份 dict 型 OCR(縮寫+參考範圍反推)extract.py依年份參數化,新年份無需改程式碼:放入data/ocr_<年份>.json後直接--year <年份>。 策略預設auto(輸入 JSON 頂層為 dict →abbr,為 list →row),可用--strategy強制。 - 歸一化 + 構建數據集(名稱/單位映射、髒數據過濾、OCR 自動注入、生成脫敏版):
產出$PY scripts/build_dataset.pydata/dataset_std.json(完整版,本地受控)+data/anonymized/anonymized_dataset_anon_shareable.json(脫敏版,獨立子目錄 + 唯讀 444 + 可分享) - 趨勢分析(當年口徑判定異常、顯著變化 ≥20% 或 ≥參考寬度 30%、趨好/趨壞、近三年聚焦):
$PY scripts/trend_analysis.py # 預設近三年 $PY scripts/trend_analysis.py --focus-years 2020,2023,2026 - 生成交付物:
$PY scripts/report_generator.py # output/體檢指標趨勢分析報告.md(預設**開啟**正文脫敏) $PY scripts/build_dashboard.py # output/health_dashboard.html(單檔案離線)
新報告接入指南
新增年度體檢報告時,按型態走對應分支(詳見 references/新報告接入指南.md):
- 放入報告:
REPORT_DIR根目錄放*.pdf,或建年度目錄YYYY體檢報告/放 JPG - 識別型態:檢查 PDF 文字層(
get_text()長度 >0 = 電子版)- 電子版 → 直接跑
parse_reports.py;列邊界異常時先列印 1 頁座標樣本 - 掃描件/照片 →
make_year_pdfs.py→vision_ocr.py→extract.py --year <年份>(不要新建依年份的腳本)
- 電子版 → 直接跑
- 補字典(如有未收錄指標):
indicator_dict.py的NAME_MAP補一行映射(日誌見data/unrecognized)$PY scripts/indicator_dict.py --search 尿酸 # 查是否已收錄(含別名) $PY scripts/indicator_dict.py --validate # 自檢字典完整性(懸空別名/重複鍵) $PY scripts/indicator_dict.py --count # 當前標準指標總數 - 重跑流水線:build_dataset → trend_analysis → report_generator → build_dashboard
- 驗收:確認新年份出現在
trend_analysis.json["years"]與工作台時間軸;抽樣 3 個關鍵指標數值與報告一致;生成並校驗脫敏版
關鍵規則
- 隱私硬約束(零容忍):全程本地,技能內不含任何外發網路呼叫;任務完成必須生成並校驗脫敏版(不含姓名/證件號碼/電話/地址/醫院),分享只用
data/anonymized/anonymized_dataset_anon_shareable.json(與完整版dataset_std.json分目錄強隔離、唯讀 444,防止誤分享完整版) - 脫敏校驗先於寫盤:
build_dataset.py的_write_anon_verified()是脫敏版落盤的唯一出口——先在記憶體校驗、通過後才寫盤。脫敏版落盤即設唯讀 444,若校驗在寫盤之後,命中身份資訊時帶 PII 的檔案已留在磁碟且改不動,[FAIL]只是事後告警。禁止繞過該出口直接呼叫_write_anon();--skip-verify僅供排查,產物不可分享 - 報告正文脫敏:
report_generator.py的mask_identity_text預設開啟(機構名稱、醫師姓名、手機號碼、身份證號碼遮罩);--no-mask才關閉,僅供本地核對原文,生成物切勿分享 - 新增年度報告:放入
REPORT_DIR→ 重跑 2→6 步即可;字典未收錄指標在data/unrecognized記錄,補indicator_dict.py的NAME_MAP一行即可 - OCR 數據定位:OCR 提取的指標只用於圖表展示(灰色 Ⓞ 標註),不參與顯著變化判定,避免污染統計
- 趨勢聚焦:整體趨勢與首末對比僅基於聚焦年份(預設近三年,可用
--focus-years覆蓋),歷史數據僅作展示背景 - 口徑一致性:異常判定用當年報告自帶參考範圍(試劑更換自動適應,如直接膽紅素 2025 年起 0.0–4.0 → 1.7–6.8)
交付物
output/體檢指標趨勢分析報告.md— 指標彙總表、異常高亮、權威解讀、分層建議(生活方式/飲食/運動/就醫指徵)、方法學output/health_dashboard.html— 健康總覽、趨好/趨壞分組篩選、折線圖+參考範圍帶、時間跨度切換(單檔案、無外部依賴)data/anonymized/anonymized_dataset_anon_shareable.json— 可分享脫敏數據集
腳本一覽
| 腳本 | 用途 | 主要參數 |
|---|---|---|
check_deps.py | 依賴自檢(Step 0) | --json --quiet |
parse_reports.py | 電子版 PDF 解析 | --report-dir --data-dir --year --out --dry-run |
make_year_pdfs.py | 年度 JPG → PDF | --report-dir --year --out-dir --dry-run |
vision_ocr.py | 掃描件/照片 OCR | pdf out(位置參數)--dpi --quiet |
extract.py | OCR 結果 → 指標(參數化) | --year --strategy --ocr-json --out --data-dir --quiet |
build_dataset.py | 歸一化 + 脫敏版 | --work-dir --data-dir --out --skip-verify --dry-run |
trend_analysis.py | 趨勢判定 | --work-dir --focus-years --out --dry-run |
report_generator.py | Markdown 報告 | --work-dir --out --no-mask --dry-run |
build_dashboard.py | HTML 工作台 | --work-dir --data-dir --out --quiet |
indicator_dict.py | 指標字典(被 import) | --list --search --count --validate --category(僅在直接運行時生效) |
退出碼統一為三態:0 成功 / 1 運行期失敗 / 2 參數或前置條件不滿足。
參考文件
| 文件 | 內容 |
|---|---|
references/新報告接入指南.md | 新型態/新年份報告接入的完整步驟與排錯 |
references/解析與口徑.md | 電子版 PDF 的列邊界座標、口徑定義 |
references/OCR方法學.md | 掃描件/照片 OCR 策略、縮寫映射表維護 |
evals/ | 8 條回歸評測(含 3 條隱私防線),eval_loop.py --run 可跑 |
使用示例(一次完整會話)
用戶:「幫我把 2027 年體檢報告加進去,更新趨勢分析。」
- Step 0:
python3 scripts/check_deps.py→ 必需依賴齊全 - 檢查
REPORT_DIR:發現新檔案體檢報告_270510004567.pdf(電子版,文字層完整) - 小樣本確認列邊界:列印 1 頁座標,與
references/解析與口徑.md一致 → 無需調整 - 跑流水線:
export REPORT_DIR=體檢報告 WORK_DIR=/path/to/work python3 scripts/parse_reports.py python3 scripts/build_dataset.py python3 scripts/trend_analysis.py python3 scripts/report_generator.py python3 scripts/build_dashboard.py - 解析日誌顯示:新年度 98 項指標,1 個未識別名 →
indicator_dict.py --search確認未收錄,在NAME_MAP補 1 行後重跑 build_dataset - 驗收:
trend_analysis.json["years"]含 2027;工作台時間軸出現 2027;抽樣血糖/血脂/BMI 數值與報告一致;grep脫敏版無身份資訊 - 交付:報告 + 工作台路徑告知用戶;說明 2027 年各異常指標的變化與建議
降本紀律(執行時強制)
- 小樣本先行:解析新格式前先列印 1 頁座標樣本確認列邊界,再全量處理(避免整檔案 dump)
- 輸出壓縮:除錯命令統一
| head -N/python -c精準提取,禁止整檔案 cat 大 JSON - 子代理隔離:大檔案讀取/格式探測交給 Explore 子代理,主執行緒只收結論
- 驗證只做一次最終截圖,中間迭代用 DOM/JS 檢查替代
Changelog
| 版本 | 日期 | 變更 |
|---|---|---|
| 1.1.0 | 2026-08-29 | 工程化集中整改:① 全部 10 腳本支援 --help + argparse + 退出碼三態(整改前 0/10,全場最差);② 新增 check_deps.py 依賴自檢並寫入 Step 0;③ 依年份硬編碼的 extract_2015_2020.py / extract_2022.py 合併為參數化 extract.py --year(新年份接入不再改程式碼,輸出格式與舊腳本逐欄位一致);④ 新增 ## 觸發詞 章節 12 條 + evals/ 8 條回歸(含 3 條隱私防線用例);⑤ 隱私修復:脫敏版改為「先記憶體校驗、通過後才寫盤」(原為寫盤後校驗,命中 PII 時帶身份資訊的檔案已落盤且唯讀,[FAIL] 只是事後告警);⑥ 修復 trend_analysis.py 遺失測量項的死程式碼(measurement_items 追加後被重置,改為按 key 去重) |
| 1.0.3 | 2026-08-23 | P2 M-1 整改(技能安全):脫敏版強隔離——anonymized_dataset.json → data/anonymized/anonymized_dataset_anon_shareable.json(獨立子目錄 + 唯讀 444 + _anon_shareable 命名標記),防止完整版與脫敏版混放誤分享;build_dataset.py 新增 _write_anon()(tmp+replace 原子寫入 + chmod 444);report_generator 隱私聲明路徑同步 |
| 1.0.2 | 2026-08-17 | P1 整改:build_dataset.py 末尾新增 verify_anonymized 自動校驗(身份證/手機號/郵箱/醫院名正則掃描,命中即報錯退出) |
| 1.0.1 | 2026-08-17 | P0 整改:report_generator.py 新增 mask_identity_text 脫敏函式(手機號/身份證/醫師署名遮罩 + 機構泛化),小結/結論文字展示層脫敏;隱私聲明與實際輸出對齊 |
| 1.0.0 | 2026-08-16 | 初版:體檢指標趨勢分析系統 |