z230
This commit is contained in:
@@ -710,5 +710,53 @@
|
||||
{
|
||||
"original": "8908180402 2026-03-05 Tůma, Patrik [Žádanka IPZS] [žádanka o vyšetření zdrav. stavu, invalidita kontrolní, 517 Kč].pdf",
|
||||
"corrected": "8908180402 2026-03-05 Tůma, Patrik [Žádanka IPZS] [žádanka o vyšetření zdrav. stavu, invalidita, cílené, 517 Kč].pdf"
|
||||
},
|
||||
{
|
||||
"original": "400424003 2026-04-26 Faměra, Jiří [LZ interna] [86l, celk. zhoršení, kašel, perimaleol. otoky, flutter síní v anamnéze, EKG sinus, RTG hilová hyperemie].pdf",
|
||||
"corrected": "400424003 2026-04-26 Faměra, Jiří [LZ interna] [přivezen RZZ, 86l, celk. zhoršení, kašel, perimaleol. otoky, flutter síní v anamnéze, EKG sinus, RTG hilová hyperemie].pdf"
|
||||
},
|
||||
{
|
||||
"original": "415716459 2026-04-29 Kekrtová, Jarmila [Laboratoř] [dg. N394, D-dimery 6.99 mg/l FEU (norma 0.00-0.50), hlášeno].pdf",
|
||||
"corrected": "415716459 2026-04-29 Kekrtová, Jarmila [Laboratoř] [dg. N394, D-dimery 6.99 mgl FEU (norma 0.00-0.50), hlášeno].pdf"
|
||||
},
|
||||
{
|
||||
"original": "435720013 2026-04-29 Lišková, Jaroslava [Laboratoř] [dg. N309, glukóza 3 (↑), leukocyty 1 (↑), leukocyty sediment 37/ul (norma 0-10)].pdf",
|
||||
"corrected": "435720013 2026-04-29 Lišková, Jaroslava [Laboratoř] [dg. N309, U_glukóza 3 (↑), U_leukocyty 1 (↑), U_leukocyty sediment 37ul (norma 0-10)].pdf"
|
||||
},
|
||||
{
|
||||
"original": "436114002 2026-04-22 Petrovská, Eliška [diagnostická mamografie] [BI-RADS kat.1, normální nález, typ žlázy BI-RADS B tukově žlázový].pdf",
|
||||
"corrected": "436114002 2026-04-22 Petrovská, Eliška [mamografie] [BIRADS kat.1, normální nález, typ žlázy BIRADS B tukově žlázový].pdf"
|
||||
},
|
||||
{
|
||||
"original": "475727064 2026-04-08 Povolná, Věra [IADL test] [70 bodů – částečná nesoběstačnost v aktivitách denního života].pdf",
|
||||
"corrected": "475727064 2026-04-08 Povolná, Věra [IADL test] [50 bodů – částečná nesoběstačnost v aktivitách denního života].pdf"
|
||||
},
|
||||
{
|
||||
"original": "475727064 2026-04-06 Povolná, Věra [Barthelův test ADL] [100 bodů – nezávislý].pdf",
|
||||
"corrected": "475727064 2026-04-30 Povolná, Věra [Barthelův test ADL] [100 bodů – nezávislý].pdf"
|
||||
},
|
||||
{
|
||||
"original": "511212227 2026-04-30 Klimeš, Radko [LZ oční] [dg. H400, V PO 5/7.5, V LO +0.5 5/7.5, Tn PO 18.7 LO 22.7 mmHg, schopen řídit bez brýlí].pdf",
|
||||
"corrected": "511212227 2026-04-30 Klimeš, Radko [LZ oční] [dg. H400, V PO 57.5, V LO +0.5 57.5, Tn PO 18.7 LO 22.7 mmHg, schopen řídit bez brýlí].pdf"
|
||||
},
|
||||
{
|
||||
"original": "5657111867 2026-04-29 Kocumová, Zdeňka [Laboratoř] [cholesterol 5.40 (↑), MCV 98.9 (↑), MCH 34.1 (↑), U_hustota 1008 (↓)].pdf",
|
||||
"corrected": "5657111867 2026-04-29 Kocumová, Zdeňka [Laboratoř] [Z000, cholesterol 5.40 (↑), MCV 98.9 (↑), MCH 34.1 (↑), U_hustota 1008 (↓)].pdf"
|
||||
},
|
||||
{
|
||||
"original": "5962050149 2026-04-30 Jelínková, Eva [měření TK] [měření TK ráno i večer, hodnoty 108-133/61-76, 1 tableta 1-0-0].pdf",
|
||||
"corrected": "5962050149 2026-04-30 Jelínková, Eva [domácí měření TK] [měření TK ráno i večer, hodnoty 108-13361-76, pěkně korigovaný TK, 1 tableta 1-0-0].pdf"
|
||||
},
|
||||
{
|
||||
"original": "7602044780 2026-04-30 Suchý, Vladimír [PZ nefrologie] [SLE se sek. APS, AKI, proliferativní GN, ATN, po 1.+2. cyklu CFA Eurolupus, renální biopsie].pdf",
|
||||
"corrected": "7602044780 2026-04-30 Suchý, Vladimír [LZ nefrologie] [SLE se sek. APS, AKI, proliferativní GN, ATN, po 1.+2. cyklu CFA Eurolupus, renální biopsie].pdf"
|
||||
},
|
||||
{
|
||||
"original": "9705081617 Krob, Milan split_005.pdf",
|
||||
"corrected": "9705081617 Krob, Milan [EKG] [normální křivka].pdf"
|
||||
},
|
||||
{
|
||||
"original": "9705081617 null Krob, Milan [PZ pediatrie] [prematuritas gravis, dystrofie, psychomotorická retardace, susp. autistické rysy, ptosa, strabismus, amblyopie, tarsektomie l.dx].pdf",
|
||||
"corrected": "9705081617 2002-04-26 Krob, Milan [LZ pediatrie] [prematuritas gravis, dystrofie, psychomotorická retardace, susp. autistické rysy, ptosa, strabismus, amblyopie, tarsektomie l.dx].pdf"
|
||||
}
|
||||
]
|
||||
@@ -231,7 +231,7 @@ def build_corrections_prompt() -> str:
|
||||
|
||||
# ─── Claude Vision API ────────────────────────────────────────────────────────
|
||||
|
||||
def extract_info(pdf_path: Path) -> dict:
|
||||
def extract_info(pdf_path: Path, known_patient: str | None = None, known_rc: str | None = None) -> dict:
|
||||
print(" Převádím na obrázek...")
|
||||
suffix = pdf_path.suffix.lower()
|
||||
if suffix in (".jpg", ".jpeg", ".png"):
|
||||
@@ -248,9 +248,27 @@ def extract_info(pdf_path: Path) -> dict:
|
||||
gc.collect()
|
||||
image_b64 = base64.standard_b64encode(buf.getvalue()).decode("utf-8")
|
||||
|
||||
if known_patient and known_rc:
|
||||
# Identita pacienta je známa z názvu souboru — Claude se soustředí jen na obsah zprávy
|
||||
patient_hint = (
|
||||
f"Pacient je již znám: RČ={known_rc}, jméno={known_patient}. "
|
||||
f"Pole \"jmeno\" nastav na \"{known_patient}\" a \"rodne_cislo\" na \"{known_rc}\". "
|
||||
f"Soustřeď se hlavně na datum zprávy, typ dokumentu a klinickou poznámku.\n"
|
||||
)
|
||||
nazev_format = (
|
||||
f"\"{known_rc} {{datum_zpravy}} {known_patient} [{{typ_dokumentu}}] [{{poznamka}}].pdf\""
|
||||
)
|
||||
else:
|
||||
patient_hint = ""
|
||||
nazev_format = (
|
||||
"\"{rodne_cislo} {datum_zpravy} {Příjmení}, {Jméno} [{typ_dokumentu}] [{poznamka}].pdf\" "
|
||||
"(jméno bez titulu, RČ bez lomítka)"
|
||||
)
|
||||
|
||||
prompt = (
|
||||
load_naming_rules() +
|
||||
build_corrections_prompt() +
|
||||
patient_hint +
|
||||
"Toto je naskenovaná lékařská zpráva v češtině. "
|
||||
"Vrať JSON s těmito poli:\n"
|
||||
"- \"jmeno\": celé jméno pacienta (příjmení + jméno + případný titul)\n"
|
||||
@@ -265,9 +283,7 @@ def extract_info(pdf_path: Path) -> dict:
|
||||
"DŮLEŽITÉ: pokud zpráva obsahuje sekci \"Závěr:\" nebo \"Závěr vyšetření:\", "
|
||||
"použij VÝHRADNĚ obsah této sekce — je nejdůležitější. "
|
||||
"Teprve pokud závěr chybí, shrň obsah z celé zprávy.\n"
|
||||
"- \"nazev_souboru\": název souboru ve formátu "
|
||||
"\"{rodne_cislo} {datum_zpravy} {Příjmení}, {Jméno} [{typ_dokumentu}] [{poznamka}].pdf\" "
|
||||
"(jméno bez titulu, RČ bez lomítka)\n"
|
||||
f"- \"nazev_souboru\": název souboru ve formátu {nazev_format}\n"
|
||||
"- \"rotace\": o kolik stupňů CCW je třeba otočit obrázek aby byl text čitelně na výšku nebo šířku "
|
||||
"(hodnoty: 0, 90, 180, 270). Pokud je text již správně orientovaný, vrať 0.\n\n"
|
||||
"Pokud pole nenajdeš, použij null. Nepiš nic jiného než JSON."
|
||||
@@ -357,6 +373,19 @@ def run_variant_picker(variants_data: list) -> str | None:
|
||||
return json.loads(out).get("chosen") if out else None
|
||||
|
||||
|
||||
# ─── Detekce split názvu ──────────────────────────────────────────────────────
|
||||
|
||||
# Vzor: "7952090443 Kalousová, Eva split_001.pdf"
|
||||
_SPLIT_RE = re.compile(r"^(\d{9,10})\s+(.+?)\s+split_\d+\.pdf$", re.IGNORECASE)
|
||||
|
||||
def _parse_split_filename(name: str) -> tuple[str, str] | None:
|
||||
"""Vrátí (rc_digits, 'Příjmení, Jméno') nebo None."""
|
||||
m = _SPLIT_RE.match(name)
|
||||
if m:
|
||||
return m.group(1), m.group(2)
|
||||
return None
|
||||
|
||||
|
||||
# ─── Hlavní flow ──────────────────────────────────────────────────────────────
|
||||
|
||||
def process_file(pdf_path: Path):
|
||||
@@ -369,17 +398,27 @@ def process_file(pdf_path: Path):
|
||||
preview, geom_file = open_preview(pdf_path)
|
||||
below_y = read_preview_bottom(geom_file)
|
||||
|
||||
# 2. Claude Vision API
|
||||
# 2. Zjisti RČ a jméno — buď z názvu (split soubor) nebo přes Claude Vision API
|
||||
split = _parse_split_filename(pdf_path.name)
|
||||
if split:
|
||||
rc_from_scan, name_from_filename = split
|
||||
print(f" Split soubor — RČ z názvu: {rc_from_scan}, jméno: {name_from_filename}")
|
||||
# Claude stále voláme, ale předáme mu identitu pacienta — ať se soustředí na obsah
|
||||
info = extract_info(pdf_path, known_patient=name_from_filename, known_rc=rc_from_scan)
|
||||
# RC a jméno bereme z názvu souboru, ne z Claudovy odpovědi
|
||||
nazev = info.get("nazev_souboru") or pdf_path.name
|
||||
nazev = re.sub(r"^\d{9,10}\s+", f"{rc_from_scan} ", nazev) # přepiš RC v názvu naším
|
||||
else:
|
||||
info = extract_info(pdf_path)
|
||||
nazev = info.get("nazev_souboru") or pdf_path.name
|
||||
rc_from_scan = re.sub(r"\D", "", info.get("rodne_cislo") or "")
|
||||
|
||||
# 3. Medicus ověření + fuzzy matching RČ
|
||||
rc_from_scan = re.sub(r"\D", "", info.get("rodne_cislo") or "")
|
||||
print(f" Ověřuji v Medicus (RČ: {rc_from_scan})...")
|
||||
verif = verify_patient(rc_from_scan)
|
||||
|
||||
# Oprava RČ při fuzzy matchi
|
||||
if verif["status"] == "fuzzy" and verif.get("rc_corrected") and nazev:
|
||||
# Oprava RČ při fuzzy matchi (jen pro nesplit soubory — u split máme RC spolehlivé)
|
||||
if not split and verif["status"] == "fuzzy" and verif.get("rc_corrected") and nazev:
|
||||
nazev = nazev.replace(rc_from_scan, verif["rc_corrected"], 1)
|
||||
print(f" → RČ opraveno: {rc_from_scan} → {verif['rc_corrected']}")
|
||||
|
||||
@@ -387,6 +426,8 @@ def process_file(pdf_path: Path):
|
||||
status = verif["status"]
|
||||
patient = verif.get("patient")
|
||||
info_lines = []
|
||||
if split:
|
||||
info_lines.append(f"⚡ Split soubor — identita z názvu: {name_from_filename} | RČ {rc_from_scan}")
|
||||
if status == "ok":
|
||||
info_lines.append(f"✓ Medicus: {patient['prijmeni']} {patient['jmeno']} | RČ {patient['rodcis']}")
|
||||
elif status == "fuzzy":
|
||||
|
||||
@@ -12,7 +12,7 @@ Tato pravidla platí vždy při generování polí `poznamka` a `nazev_souboru`.
|
||||
- Pokud je datum přijetí a propuštění ve stejném měsíci, stačí: `[12–15APR2026 ...]`
|
||||
- Pokud datum hospitalizace nelze určit, druhou závorku napiš bez datumu.
|
||||
|
||||
3. Když je dokument typ "Laboratoř", do `poznamka` uváděj POUZE hodnoty mimo normu (patologické nálezy) — hodnoty v normě vynech. Osmolalitu séra nikdy nezmiňuj, ani když je mimo normu.
|
||||
3. Když je dokument typ "Laboratoř", do `poznamka` uváděj POUZE hodnoty mimo normu (patologické nálezy) — hodnoty v normě vynech. **Osmolalitu séra (Osmolalita, Osm, osmolality) NIKDY nezmiňuj — ani když je mimo normu, ani v jakékoli zkratce.** Toto je absolutní výjimka: osmolalita se do názvu souboru ani do poznámky nepíše nikdy za žádných okolností. Chybně: `C_Osmolalita 293 (↑)` — správně: tuto hodnotu zcela vynech.
|
||||
4. Pokud laboratorní výsledky obsahují glomerulární filtraci — bývá označena jako eGFR, CKD-EPI nebo CK-EPI — do `poznamka` nikdy nepiš číselnou hodnotu eGFR. Místo toho uveď pouze klasifikaci: eGFR ≥ 90 → CHRIG1, 60–89 → CHRIG2, 45–59 → CHRIG3a, 30–44 → CHRIG3b, 15–29 → CHRIG4, < 15 → CHRIG5. Klasifikaci uváděj pouze pokud je CHRIG2 nebo horší (tj. eGFR < 90) — CHRIG1 je v normě, nezmiňuj ho.
|
||||
5. Když je dokument typ "Laboratoř" a zpráva obsahuje diagnózu (dg., dg:, diagnóza), umísti ji do `nazev_souboru` jako první část druhé závorky, tedy: `[Laboratoř] [dg. XY00 - stručná poznamka]`.
|
||||
6. Zkratky a pojmenování: slovo „sono" (sonografie/ultrazvuk) piš vždy malými písmeny — `sono břicha`, `sono ŠŽ`, nikoli `SONO`. Štítnou žlázu označuj vždy zkratkou `ŠŽ`. Sonografii prsu/prsů (sono mamm., sono mamografie, sono mamma apod.) piš vždy jako `sono prsů`. Denzitometrii (DEXA, DXA, denzitometrie) piš vždy pouze jako `[DXA]` — bez prefixu LZ. Algologii piš vždy jako `[LZ léčba bolesti]`. Dermatovenerologii (dermatologie, dermatovenerologie, kožní) piš vždy jako `[LZ kožní]`. Angiologii piš vždy jako `[LZ cévní]`.
|
||||
|
||||
Reference in New Issue
Block a user