System zur Trendanalyse von Gesundheitscheck-Indikatoren
Zweck
Vereinheitlicht die Analyse mehrjähriger Gesundheitscheck-Berichte (elektronische PDFs, gescannte Dokumente, Fotos) in eine standardisierte Zeitreihe von Indikatoren und erstellt einen Trendanalysebericht sowie ein interaktives Gesundheitsmanagement-Dashboard. Vollständig lokale Verarbeitung, automatische Anonymisierung, dynamische Erweiterung (neue Berichte hinzufügen und Pipeline neu starten).
Triggerwörter
- Mehrjährige Gesundheitsberichte / Jährliche Gesundheitsberichte
- Digitalisierung von Gesundheitsdaten / Analyse von Gesundheitscheck-Daten / Parsen von Gesundheitsberichten
- Indikatorentrends / Trendanalyse von Indikatoren
- Vergleich jährlicher Gesundheitsindikatoren / Jährlicher Vergleich / Jährliche Veränderungen
- Laborbericht-Analyse / Interpretation von Laborberichten
- Gescannte Gesundheitsberichte / OCR für Gesundheitsberichte
- Gesundheitsberichte als Fotos / Mit dem Handy aufgenommene Gesundheitsberichte
- Gesundheitsmanagement-Dashboard / Visuelles Dashboard / Gesundheitsdaten-Übersicht
- Blutzuckertrend / Blutzuckerveränderungen / Erhöhte Harnsäure / Lipid-Trend / Blutdruck-Trend
- Abnormale Indikatoren / Interpretation abnormaler Indikatoren
- Neuen Gesundheitsbericht hinzufügen / Neues Jahresdaten integrieren
- Anonymisierung von Gesundheitsdaten / Anonymisierter Datensatz / Teilbarer Datensatz
Umgebungsvorbereitung
# Abhängigkeiten (bereits installiert überspringbar): pymupdf erforderlich; Pillow (Foto-Kombination), pyobjc-framework-Vision/Quartz (OCR, nur macOS) optional
export REPORT_DIR=/pfad/zu/gesundheitsberichten # Berichtsverzeichnis (enthält PDFs oder Jahresordner + JPGs)
export WORK_DIR=/pfad/zu/arbeitsdaten # Arbeitsdatenverzeichnis (erstellt automatisch data/ und output/)
export PY=/pfad/zu/python # Empfohlen: Python-Interpreter mit Abhängigkeiten
Schritt 0 (Erster Schritt in jeder neuen Sitzung, obligatorisch):
$PY scripts/check_deps.py # Ein-Klick-Check: Was fehlt, welche Skripte betroffen, wie installieren
$PY scripts/check_deps.py --json # Maschinenlesbar, für Automatisierung
Exit-Code 0 = Erforderliche Abhängigkeiten vollständig, einsatzbereit; 1 = Erforderliche Abhängigkeiten fehlen (Hauptablauf blockiert, gemäß Anleitung installieren); Fehlende optionale Abhängigkeiten betreffen nur das entsprechende Eingabeformat, blockieren jedoch nicht den Hauptpfad der elektronischen PDFs.
Ausführungsablauf
Alle Skripte unterstützen --help; Parameter haben Vorrang vor Umgebungsvariablen; Ausführung ohne Parameter = Verhalten der Umgebungsvariablen beibehalten.
- Eingabeformat identifizieren: Durchlaufe
REPORT_DIR*.pdfmit Textschicht im Stammverzeichnis → Elektronische Version (verarbeitet durchparse_reports.py)*.pdfohne Textschicht im Stammverzeichnis → Gescannte Dokumente (verarbeitet durchvision_ocr.py+extract.py)- Jahres-Unterverzeichnis
YYYYGesundheitsberichte/*.JPG→ Fotos (kombiniert durchmake_year_pdfs.py→ OCR →extract.py)
- Elektronische PDFs parsen (Koordinaten-Lokalisierungsmethode, Spaltengrenzen siehe
references/解析与口径.md):$PY scripts/parse_reports.py # → data/reports_raw.json $PY scripts/parse_reports.py --year 2027 --dry-run # Einzelnes Testjahr, ohne zu schreiben - Fotos zu PDF kombinieren + OCR + Extraktion (falls JPG-Verzeichnisse / gescannte Dokumente vorhanden):
$PY scripts/make_year_pdfs.py --year 2015-2020 # Mehrere JPGs pro Jahr → Ein PDF (horizontale Aufnahmen automatisch korrigieren) $PY scripts/vision_ocr.py <pdf> data/ocr_2022.json # OCR für gescannte Dokumente / Fotos → JSON mit Koordinaten $PY scripts/extract.py --year 2022 # OCR-Ergebnisse → Indikatoren (Strategie automatisch ermittelt) $PY scripts/extract.py --years 2015-2020 # Mehrjähriges dict-basiertes OCR (Abkürzung + Referenzbereich ableiten)extract.pyist nach Jahr parametrisiert, kein Code-Änderung für neue Jahre erforderlich: Legedata/ocr_<Jahr>.jsonab und rufe direkt--year <Jahr>auf. Standard-Strategieauto(Eingabe-JSON oberste Ebene ist dict →abbr, list →row), Überschreibung mit--strategymöglich. - Normalisierung + Datensatzaufbau (Namens-/Einheiten-Mapping, Dirty-Data-Filterung, automatische OCR-Injektion, Erstellung anonymer Version):
Ausgabe$PY scripts/build_dataset.pydata/dataset_std.json(vollständige Version, lokal kontrolliert) +data/anonymized/anonymized_dataset_anon_shareable.json(anonymisierte Version, separates Unterverzeichnis + schreibgeschützt 444 + teilbar) - Trendanalyse (Abnormale Indikatoren basierend auf aktuellem Referenzbereich, signifikante Veränderungen ≥20 % oder ≥30 % der Referenzbreite, Verbesserung/Verschlechterung, Fokus auf die letzten drei Jahre):
$PY scripts/trend_analysis.py # Standardmäßig letzte drei Jahre $PY scripts/trend_analysis.py --focus-years 2020,2023,2026 - Generierung der Ergebnisse:
$PY scripts/report_generator.py # output/体检指标趋势分析报告.md (Standardmäßig **mit** Textanonymisierung) $PY scripts/build_dashboard.py # output/health_dashboard.html (Einzeldatei, offline)
Leitfaden zum Hinzufügen neuer Berichte
Beim Hinzufügen eines neuen Jahres-Gesundheitscheck-Berichts, folge dem entsprechenden Zweig entsprechend des Formats (siehe references/新报告接入指南.md für Details):
- Bericht ablegen: Lege
*.pdfim Stammverzeichnis vonREPORT_DIRab, oder erstelle ein JahresverzeichnisYYYYGesundheitsberichte/für JPGs - Format identifizieren: Prüfe die Textschicht des PDFs (
get_text()-Länge >0 = Elektronisch)- Elektronisch → Führe direkt
parse_reports.pyaus; bei Spaltengrenzen-Problemen zuerst eine Seite Koordinaten-Sample drucken - Gescannt/Foto →
make_year_pdfs.py→vision_ocr.py→extract.py --year <Jahr>(kein neues Skript pro Jahr erstellen)
- Elektronisch → Führe direkt
- Wörterbuch ergänzen (falls nicht erfasste Indikatoren): Füge einen Eintrag zu
NAME_MAPinindicator_dict.pyhinzu (Logs unterdata/unrecognized)$PY scripts/indicator_dict.py --search 尿酸 # Prüfen, ob bereits erfasst (inkl. Aliasse) $PY scripts/indicator_dict.py --validate # Selbsttest der Wörterbuch-Integrität (fehlerhafte Aliasse/doppelte Schlüssel) $PY scripts/indicator_dict.py --count # Aktuelle Gesamtanzahl der Standardindikatoren - Pipeline neu starten: build_dataset → trend_analysis → report_generator → build_dashboard
- Abnahme: Prüfen, ob das neue Jahr in
trend_analysis.json["years"]und in der Dashboard-Zeitleiste erscheint; Stichprobenartig 3 Schlüsselindikatoren-Werte mit dem Bericht abgleichen; Anonymisierte Version generieren und verifizieren
Schlüsselregeln
- Datenschutz-Hardconstraint (Null Toleranz): Vollständig lokal, keinerlei ausgehende Netzwerkaufrufe im Skill; Nach Abschluss muss die anonymisierte Version generiert und verifiziert werden (kein Name/Ausweis/Telefon/Adresse/Krankenhaus); Teilen nur über
data/anonymized/anonymized_dataset_anon_shareable.json(strikt getrennt vom vollständigen Datensatzdataset_std.jsonin separatem Verzeichnis, schreibgeschützt 444, um versehentliches Teilen der vollständigen Version zu verhindern) - Anonymisierungsprüfung vor dem Schreiben:
_write_anon_verified()inbuild_dataset.pyist der einzige Ausgang für die anonymisierte Version – Zuerst im Speicher prüfen, erst danach schreiben. Nach dem Schreiben wird die anonymisierte Version sofort auf schreibgeschützt 444 gesetzt. Wenn die Prüfung nach dem Schreiben erfolgt, könnten bereits PII-enthaltende Dateien auf der Festplatte sein und nicht mehr geändert werden,[FAIL]wäre dann nur eine nachträgliche Warnung. Umgehung dieses Ausgangs durch direkten Aufruf von_write_anon()ist verboten;--skip-verifynur zur Fehlersuche, Ergebnisse nicht teilbar - Anonymisierung des Berichtstextes:
mask_identity_textinreport_generator.pyist standardmäßig aktiviert (maskiert Institutionennamen, Arztnamen, Telefonnummern, Ausweisnummern);--no-maskdeaktiviert, nur zum lokalen Abgleich des Originaltexts, Ergebnisse auf keinen Fall teilen - Neues Jahres hinzufügen: Bericht in
REPORT_DIRablegen → Schritte 2–6 erneut ausführen; Nicht erfasste Indikatoren werden unterdata/unrecognizedprotokolliert, ein Eintrag in derNAME_MAPvonindicator_dict.pygenügt - OCR-Daten-Lokalisierung: OCR-extrahierte Indikatoren werden nur für Diagramme verwendet (grau Ⓞ markiert), nicht für die Signifikanz-Beurteilung von Veränderungen, um Verunreinigung der Statistik zu vermeiden
- Trend-Fokus: Gesamttrend und Vergleich von erstem zu letztem Jahr basieren nur auf den Fokusjahren (Standardmäßig die letzten drei Jahre, überschreibbar mit
--focus-years); historische Daten dienen nur als Anzeigehintergrund - Konsistenz der Referenzbereiche: Abnormale Beurteilung verwendet den im aktuellen Bericht angegebenen Referenzbereich (automatische Anpassung bei Reagenswechsel, z.B. direkte Bilirubin ab 2025 0.0–4.0 → 1.7–6.8)
Ergebnisse
output/体检指标趋势分析报告.md— Indikator-Zusammenfassungstabelle, Hervorhebung abnormaler Werte, autoritative Interpretation, geschichtete Empfehlungen (Lebensstil/Ernährung/Bewegung/Arztbesuch-Indikationen), Methodikoutput/health_dashboard.html— Gesundheitsübersicht, Gruppierung nach Verbesserung/Verschlechterung, Liniendiagramme mit Referenzbereich, Zeitspannenwechsel (Einzeldatei, keine externen Abhängigkeiten)data/anonymized/anonymized_dataset_anon_shareable.json— Teilbarer, anonymisierter Datensatz
Skriptübersicht
| Skript | Zweck | Hauptparameter |
|---|---|---|
check_deps.py | Abhängigkeits-Check (Schritt 0) | --json --quiet |
parse_reports.py | Parsen elektronischer PDFs | --report-dir --data-dir --year --out --dry-run |
make_year_pdfs.py | JPG zu PDF pro Jahr | --report-dir --year --out-dir --dry-run |
vision_ocr.py | OCR für gescannte Dokumente/Fotos | pdf out (Positionsparameter) --dpi --quiet |
extract.py | OCR-Ergebnisse → Indikatoren (parametrisiert) | --year --strategy --ocr-json --out --data-dir --quiet |
build_dataset.py | Normalisierung + anonyme Version | --work-dir --data-dir --out --skip-verify --dry-run |
trend_analysis.py | Trendbewertung | --work-dir --focus-years --out --dry-run |
report_generator.py | Markdown-Bericht | --work-dir --out --no-mask --dry-run |
build_dashboard.py | HTML-Dashboard | --work-dir --data-dir --out --quiet |
indicator_dict.py | Indikator-Wörterbuch (importiert) | --list --search --count --validate --category (nur bei direkter Ausführung wirksam) |
Exit-Codes einheitlich drei Zustände: 0 Erfolg / 1 Laufzeitfehler / 2 Parameter- oder Voraussetzungsfehler.
Referenzdokumente
| Dokument | Inhalt |
|---|---|
references/新报告接入指南.md | Vollständige Schritte und Fehlerbehebung für neue Formate/Jahre |
references/解析与口径.md | Spaltengrenzen-Koordinaten und Referenzbereichsdefinitionen für elektronische PDFs |
references/OCR方法学.md | OCR-Strategien für gescannte Dokumente/Fotos, Abkürzungs-Mapping-Tabelle-Pflege |
evals/ | 8 Regressionstests (inkl. 3 Datenschutz-Checkpoints), ausführbar mit eval_loop.py --run |
Anwendungsbeispiel (Vollständige Sitzung)
Benutzer: „Füge den Gesundheitscheck-Bericht für 2027 hinzu und aktualisiere die Trendanalyse.“
- Schritt 0:
python3 scripts/check_deps.py→ Erforderliche Abhängigkeiten vollständig - Prüfe
REPORT_DIR: Neue DateiGesundheitsbericht_270510004567.pdfgefunden (elektronisch, Textschicht vollständig) - Stichprobenartige Überprüfung der Spaltengrenzen: Drucke Koordinaten einer Seite, stimmen mit
references/解析与口径.mdüberein → Keine Anpassung erforderlich - Pipeline ausführen:
export REPORT_DIR=Gesundheitsberichte WORK_DIR=/pfad/zu/arbeit 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 - Parsing-Logs zeigen: Neues Jahr 98 Indikatoren, 1 nicht erkannter Name →
indicator_dict.py --searchbestätigt nicht erfasst, 1 Zeile inNAME_MAPergänzen, dannbuild_dataset.pyerneut ausführen - Abnahme:
trend_analysis.json["years"]enthält 2027; Dashboard-Zeitleiste zeigt 2027; Stichprobenartig Blutzucker/Cholesterin/BMI-Werte mit Bericht abgleichen;grepder anonymisierten Version zeigt keine identifizierenden Informationen - Auslieferung: Dem Benutzer den Pfad des Berichts und Dashboards mitteilen; Änderungen und Empfehlungen für abnormale Indikatoren 2027 erklären
Kostenreduktionsdisziplin (während der Ausführung obligatorisch)
- Stichprobe zuerst: Vor dem Parsen eines neuen Formats zuerst eine Seite Koordinaten-Sample drucken, um Spaltengrenzen zu bestätigen, dann vollständige Verarbeitung (vermeidet vollständigen Datei-Dump)
- Ausgabe komprimieren: Debug-Befehle einheitlich mit
| head -N/python -czur präzisen Extraktion, keine vollständigen großen JSON-Dateien cat - Sub-Agenten-Isolation: Große Dateien lesen/Format-Erkennung an Explore-Sub-Agenten delegieren, Haupt-Thread erhält nur Schlussfolgerungen
- Verifizierung nur einmal finaler Screenshot, Zwischeniterationen mit DOM/JS-Checks ersetzen
Changelog
| Version | Datum | Änderungen |
|---|---|---|
| 1.1.0 | 2026-08-29 | Zentrale Engineering-Überholung: ① Alle 10 Skripte unterstützen --help + argparse + drei Exit-Codes (vorher 0/10, schlechtester Wert); ② Neues check_deps.py für Abhängigkeits-Selbsttest und als Schritt 0; ③ Die hartkodierten jahresspezifischen extract_2015_2020.py / extract_2022.py wurden zu parametrisiertem extract.py --year zusammengeführt (neue Jahre erfordern keine Code-Änderung, Ausgabeformat feldgenau identisch mit alten Skripten); ④ Neues Kapitel ## Triggerwörter mit 12 Einträgen + evals/ 8 Regressionstests (inkl. 3 Datenschutz-Checkpoints); ⑤ Datenschutz-Reparatur: Anonymisierte Version jetzt „zuerst im Speicher prüfen, danach schreiben“ (vorher: nach dem Schreiben prüfen – bei PII-Treffer waren identitätshaltige Dateien bereits auf der Platte und schreibgeschützt, [FAIL] war nur nachträgliche Warnung); ⑥ Reparatur von toten Code in trend_analysis.py der Messpunkte verlor (measurement_items wurde nach Anhängen zurückgesetzt, jetzt dedupliziert nach Key) |
| 1.0.3 | 2026-08-23 | P2 M-1 Überholung (Skill-Sicherheit): Strikte Isolation der anonymisierten Version – anonymized_dataset.json → data/anonymized/anonymized_dataset_anon_shareable.json (separates Unterverzeichnis + schreibgeschützt 444 + _anon_shareable-Namensmarkierung), um Vermischung von vollständiger und anonymisierter Version und versehentliches Teilen zu verhindern; build_dataset.py hat neues _write_anon() (tmp+replace atomares Schreiben + chmod 444); Datenschutzerklärung in report_generator.py aktualisiert |
| 1.0.2 | 2026-08-17 | P1-Überholung: build_dataset.py am Ende neues verify_anonymized automatische Prüfung (Regex-Scan nach Ausweis/Telefon/E-Mail/Krankenhausname, bei Treffer Fehler und Abbruch) |
| 1.0.1 | 2026-08-17 | P0-Überholung: report_generator.py neues mask_identity_text Anonymisierungsfunktion (Telefon/Ausweis/Arztname maskiert + Institution generalisiert), Zusammenfassungs-/Fazit-Textanzeige-Ebene anonymisiert; Datenschutzerklärung mit tatsächlicher Ausgabe abgeglichen |
| 1.0.0 | 2026-08-16 | Erstversion: System zur Trendanalyse von Gesundheitscheck-Indikatoren |