eyeMark - extractie pipeline

Manuals

Manuals

Read the manuals linked to your installs and account.

eyeMark - extractie pipeline

Beschrijving en technische achtergrond van de backend pipeline in eyeMark die de extractie van de EMR data voor zich neemt.

Overzicht

Verwerkingsketting — Geluidsfragment → EMR Staging

Versie: 0.10.x Bijgewerkt: juni 2026

Productie-opmerking: Gemini Vertex AI (consolidation_enabled = true) is actief in de huidige deploymentomgeving. Stappen die als "optioneel" in de broncode zijn geïmplementeerd (configuratiebewakers), zijn in productie altijd ingeschakeld.


Schematisch overzicht

flowchart TD classDef agent fill:#dbeafe,stroke:#3b82f6 classDef db fill:#dcfce7,stroke:#16a34a classDef flutter fill:#fef9c3,stroke:#ca8a04 classDef step fill:#f3f4f6,stroke:#9ca3af F1(["Flutter UI\naudio + metadata"]):::flutter F1 -->|"POST /transcribe"| TR_OPTS subgraph FASE1["① Transcriptie"] TR_OPTS["vocabulary & opties laden\nspecialty config\nvocabulary_terms\nabbreviations"]:::step TR_OPTS --> AAI & WH & OAI AAI["AssemblyAI\nprimair + diarisatie"]:::agent WH["Whisper gpt-4o-audio\nparallel"]:::agent OAI["gpt-4o-transcribe\nparallel"]:::agent AAI & WH & OAI --> REPAIR["segment repair\nhallucination guard\nmultichannel fallback"]:::step REPAIR --> GEM1["Gemini consolidatie\nVertex AI\nraw+whisper+openai\n→ 1 transcript"]:::agent GEM1 --> DB1[("DB: transcripts\ntranscript_id · raw\nwhisper · openai\ngemini · segments")]:::db end DB1 -->|"transcript_id · transcripts · segments"| F2([Flutter]):::flutter F2 -->|"POST /diarize"| DIA_Q subgraph FASE2["② Diarisatie"] DIA_Q{"opname type?"} DIA_Q -->|"multichannel"| D_CH["kanaalmapping\ngeen LLM"]:::step DIA_Q -->|"mono · 1 spreker"| D_DEF["default dokter\ngeen LLM"]:::step DIA_Q -->|"mono · multi-spreker"| D_P1["LLM pass 1\nrol A/B/C\n→ dokter/patient"]:::agent D_P1 --> D_P2["LLM pass 2\nper-segment verfijning"]:::agent D_CH & D_DEF & D_P2 --> DB2[("DB: transcripts\nlabelled_segments_json")]:::db end DB2 -->|"segments: speaker · role · text"| F3(["Flutter\nbouwt diarized_transcript"]):::flutter F3 -->|"POST /extract-fields\n5 transcripts · fields[]"| S1 subgraph FASE3["③ Veldextractie"] S1["1 · BCFI namen laden\nophthalmic_names\ngeneral_names"]:::step S1 --> S2["2 · ASR-correcties\nalle 5 transcripts\nvocabulary_asr_corrections"]:::step S2 --> S3["3 · Fuzzy normalisatie\ntranscripts\nLevenshtein ≤ 2 · fonetisch"]:::step S3 --> S4["4 · Gemini consolidatie\nVertex AI\nraw+whisper+openai\n→ gemini_transcript"]:::agent S4 --> S5["5 · LLM EXTRACTIE\n[primary]\ngpt-4o\nraw + diarized\n→ veldwaarden"]:::agent S5 --> S6["6 · LLM EXTRACTIE\n[consensus]\ngpt-4o\nwhisper+openai+gemini\n→ ontbrekende velden"]:::agent S6 --> S7["7 · Post-extractie\nfuzzy normalisatie\nop veldwaarden"]:::step S7 --> S8["8 · Bracket stripping"]:::step S8 --> S9["9 · Hallucination check\nophthalmic meds\nvs transcripts"]:::step S9 --> S10["10 · Reclassificatie\nsystemische meds\noft_med_od/os\n→ algemene_medicatie"]:::step S10 --> S11["11 · Veldcorrecties\nreplace regex\ntranscript_validate"]:::step end S11 -->|"JSON veldwaarden\n+ applied_corrections"| F4(["Flutter\nEMR staging preview"]):::flutter F4 --> ARTS["arts reviewt\n+ bevestigt"] ARTS --> EMR[("eyeFile / Corilus")]:::db

Fase 1 — Transcriptie (POST /transcribe)

Invoer

ParameterTypeVerplichtBeschrijving
filemultipart bytesjaAudio (wav, mp3, m4a, …)
specialty_idstringneeSpecialisatie-ID voor taalconfig + vocabulary
patient_namestringneeNaam patiënt (Whisper-hint, segmentlabeling)
multi_channelboolneeTweekanaals opname (mikrofoon per persoon)
doctor_channeluint8neeKanaalnummer van de arts (0 of 1)

Kennisbronnen geladen

  • Specialty config (SpecialtyStore): whisper_language, whisper_vocabulary — bepaalt ASR-taal en domeinvocabulaire
  • DB `vocabulary_terms`: toegevoegd aan Whisper prompt + AssemblyAI keyterms
  • DB `vocabulary_abbreviations`: omgezet naar spelling-hints voor custom_spelling
  • Optioneel: patient_name → Whisper system-prompt hint, custom spelling

Transcriptie-agenten (parallel via tokio::join!)

AgentModel / ServiceRolFallback
AssemblyAIUniversal-2Primaire transcriptie + diarisatiesegmenten—
Whispergpt-4o-audio-previewParallelle transcriptie + segment-repairFallback als AAI faalt
gpt-4o-transcribegpt-4o-transcribeTweede parallelle transcriptie (sterker bij medisch)Overgeslagen bij fout

Hallucination guard

  • is_hallucination_loop(text, min_repeat=2, min_len=50/120): herhalende tekst verworpen
  • Whisper wordt niet gebruikt voor segment-repair als zelf een herhalingsloop is

Gemini consolidatie

  • Actief via GEMINI_PROJECT_ID + consolidation_enabled: true (zie productie-opmerking bovenaan)
  • Input: raw (AAI) + whisper + openai transcripten
  • Output: één gefuseerd, gecorrigeerd transcript (sterker medisch Nederlands)
  • Enkel uitgevoerd als minstens één extra transcript aanwezig is

Opgeslagen in DB (transcripts)

transcript (diarized), raw_transcript_text, diarization_segments_json, whisper_transcript, openai_transcript, gemini_transcript, multi_channel, doctor_channel

Response naar Flutter

{
  "transcript_id": 42,
  "transcript": "Dokter: …  Patient: …",
  "segments": [{"speaker": "A", "text": "…", "start": 0.0, "end": 3.2}],
  "raw_transcript": "…",
  "whisper_transcript": "…",
  "openai_transcript": "…",
  "gemini_transcript": "…"
}

Fase 2 — Diarisatie (POST /diarize)

Invoer

{ "transcript_id": 42, "multi_channel": false, "doctor_channel": null, "patient_name": "Jan Jansen" }

Verwerkingslogica

multichannel opname?
  ja → kanaalmapping direct → [dokter, patient] (geen LLM)
  nee → 1 spreker? → default dokter (geen LLM)
        meerdere sprekers →
          Pass 1 LLM (llm-client, gpt-4o):
            "Wijs rol toe: A/B/C → dokter / patient / begeleider"
          Pass 2 LLM (llm-client, gpt-4o):
            per-segment verfijning op basis van inhoud en context
          dedup_dokters + promote_second_patient (cleanup)

LLM-agenten

AgentGebruikt bijModel
state.llmDiarisatie pass 1 + 2Geconfigureerd via LLM_MODEL (gpt-4o)

Opgeslagen in DB

transcripts.labelled_segments_json bijgewerkt

Response naar Flutter

{
  "transcript_id": 42,
  "segments": [
    {"speaker": "dokter", "role": "Dokter", "text": "Goedemiddag.", "start": 0.0, "end": 1.2},
    {"speaker": "Jan Jansen", "role": "Patient", "text": "Dag dokter.", "start": 1.5, "end": 2.8}
  ]
}

Flutter bouwt hieruit de diarized_transcript (spreker-gelabelde platte tekst) voor de extractiestap.


Fase 3 — Veldextractie (POST /extract-fields)

Invoer

{
  "raw_transcript": "…",
  "diarized_transcript": "dokter: … patient: …",
  "whisper_transcript": "…",
  "openai_transcript": "…",
  "gemini_transcript": "…",
  "fields": [
    { "emr_field_id": "visus_od", "field": "Visus OD", "field_type": "direct",
      "description": "…", "keywords": ["…"], "subfields": [] }
  ],
  "general_instructions": "…",
  "extraction_rules": ["…"],
  "consensus_instructions": "…",
  "consensus_rules": ["…"]
}

Veldtype concept wordt voor de LLM-call uitgefilterd (Flutter-only velden).

Stap-voor-stap pipeline

[1] BCFI medicatienamen laden

Één DB-call naar medication_names (cache van de dagelijkse BCFI-scraper):

  • ophthalmic_names (ATC S01 — oogheelkundig)
  • general_names (overige)

Wordt gebruikt in stappen 3, 7, 9, 10.

[2] ASR-correcties (pre-LLM)

  • Bron: DB vocabulary_asr_corrections (actief = 1, op id ASC)
  • Alle 5 transcripts worden gecorrigeerd: raw, diarized, whisper, openai, gemini
  • Case-insensitief exact-string vervangen (eigen replace_ci implementatie)
  • Toegevoegd aan applied_corrections[] in response

[3] Fuzzy normalisatie (pre-LLM)

  • Algoritme: Levenshtein ≤ 2 op woord-tokens + fonetische fallback (Dutch phonetic key)
  • Transcripts: raw, diarized, whisper, openai (vóór Gemini)
  • Doel: fonetisch gelijkaardige ASR-varianten van medicatienamen corrigeren (bv. "hilogel" → "Hylogel")
  • Bron: ophthalmic_names

[4] Gemini consolidatie (pre-LLM)

  • Actief (zie productie-opmerking bovenaan)
  • Input: raw + whisper + openai (na stappen 2+3)
  • Output: gemini_transcript (overschrijft de gemini_transcript uit de request)
  • Na consolidatie: ook fuzzy normalisatie op het nieuwe gemini-transcript

[5] Primary LLM extractie

ComponentInhoud
Agentextract_llm — gpt-4o via OpenAI Chat API
System promptgeneral_instructions + extraction_rules + free_text_notes + ophthalmic hint (40 namen, spellingreferentie)
User promptraw_transcript + diarized_transcript + veldspecificaties (emr_field_id, beschrijving, keywords, subfields)
OutputRuwe JSON string — geparsed via parse_and_normalise()

Velden die ontbreken in LLM-output worden als null genormaliseerd.

[6] Consensus extractie

Uitgevoerd als: minstens één extra transcript (whisper/openai/gemini) aanwezig én consensus_instructions niet leeg. In productie is Gemini altijd aanwezig, waardoor consensus altijd actief is.

ComponentInhoud
Agentextract_llm (gpt-4o)
System promptconsensus_instructions + consensus_rules + "velden zonder consensus weglaten"
User promptwhisper + openai + gemini transcripten + veldspecificaties
MergestrategieConsensus vult null-velden; niet-null primary blijft intact; extra termen → [toevoeging]

[7] Post-extractie fuzzy normalisatie

Toepassen op de veldwaarden (niet op transcripts). Corrigeert medicatienamen die de LLM in licht afwijkende spelling retourneerde.

[8] Bracket stripping

Verwijdert [annotaties] die de LLM toevoegt als trailing toelichting aan een waarde (bv. "0.8 [beste gecorrigeerde visus]" → "0.8"). Wordt ook na consensus-merge toegepast.

[9] Hallucination check — ophthalmic medicatie

Voor oftalmologische_medicatie_od en _os:

  • Als de waarde een bekende ophthalmic naam bevat maar deze niet (case-insensitief) in de gecorrigeerde transcripts voorkomt → waarde → null
  • Bron: ophthalmic_names, gecorrigeerde transcripts (raw + whisper + openai + gemini)

[10] Reclassificatie systemische medicatie (nieuw in v0.10)

Voor oftalmologische_medicatie_od en _os:

waarde aanwezig?
  ja → is het een ophthalmic naam? → behoud
       is het een general naam?    → verplaats naar algemene_medicatie (append ", ")
       onherkenbaar?               → null

Bron: ophthalmic_names + general_names

[11] Veldcorrecties — final stage (nieuw in v0.10)

  • Bron: DB field_corrections (actief = 1, gefilterd op emr_field, gesorteerd op id ASC)
  • Per veld: eerst alle replace-regels, dan transcript_validate
TypeWerking
replaceregex::replace_all(value, pattern, replacement) — ongeldige regex: skip met warn
transcript_validateCase-insensitieve substring-check in gecorrigeerde transcripts; niet gevonden → null

Response naar Flutter

{
  "results": {
    "visus_od": "0.8",
    "biomicroscopie_od": "Normaal voorste oogsegment",
    "oftalmologische_medicatie_od": "Hylogel",
    "algemene_medicatie": "Metformine"
  },
  "model_used": "gpt-4o-2024-08-06",
  "consensus_applied": true,
  "consensus_transcript_count": 2,
  "applied_corrections": [
    { "pattern": "hilogel", "replacement": "Hylogel", "count": 1 }
  ],
  "gemini_transcript": "…"
}

Kennisbronnen — overzichtstabel

BronGeladen doorGebruikt inBeheer
`vocabulary_terms`POST /transcribeWhisper prompt + AssemblyAI keytermsGET/POST /vocabulary/terms
`vocabulary_abbreviations`POST /transcribecustom_spelling hints voor ASRGET/POST /vocabulary/abbreviations
`vocabulary_asr_corrections`POST /extract-fields stap 2ASR pre-correctie alle transcriptsGET/POST /vocabulary/asr-corrections
`medication_names` (BCFI)POST /extract-fields stap 1Fuzzy normalisatie, hallucination check, reclassificatieDagelijkse scraper via POST /admin/bcfi-refresh
`agent_instructions`Flutter (bij opbouw request)LLM system prompt (general_instructions, extraction_rules, free_text_notes)GET/PUT /vocabulary/agent-instructions
`emr_fields`Flutter (bij opbouw request)Veldspecificaties (type, beschrijving, keywords, subfields)GET/POST /vocabulary/emr-fields
`field_corrections`POST /extract-fields stap 11Post-extractie regex + transcript-validatieGET/POST /vocabulary/field-corrections
`field_mappings`Flutter (triage)Veldomschrijvingen voor triage-LLMGET/POST /vocabulary/field-mappings
`triage_rules`Flutter (triage)Triageregels voor urgentiebepalingGET/POST /vocabulary/triage-rules
Specialty configPOST /transcribeTaal + vocabulaire per specialisatieGET /config/specialties

BCFI scraper

  • Draait dagelijks via scheduler
  • Haalt ATC-hiërarchie op van bcfi.be (HTML/CSV)
  • Slaat ophthalmic_json (S01) + general_json op in medication_names tabel (single-row cache)
  • Trigger handmatig: POST /admin/bcfi-refresh

Betrokken LLM-agenten

AgentConfiguratieFases
`state.llm`Env LLM_MODEL (gpt-4o)Diarisatie pass 1 + 2
`state.extract_llm`Env EXTRACT_LLM_MODEL (gpt-4o)Veldextractie primary + consensus
AssemblyAIEnv ASSEMBLYAI_API_KEYTranscriptie + diarisatiesegmenten
WhisperEnv OPENAI_API_KEY + WHISPER_MODELParallelle transcriptie + segment-repair
gpt-4o-transcribeEnv OPENAI_API_KEY + OPENAI_TRANSCRIBE_MODELParallelle transcriptie
Gemini (Vertex AI)Env GEMINI_PROJECT_ID + service account JSONTranscript consolidatie (optioneel)

Foutafhandeling & degradatie

SituatieGedrag
AssemblyAI onbereikbaarWhisper als fallback (mits beschikbaar), anders HTTP 500
Whisper herhalingsloopResultaat verworpen, AAI-segmenten behouden
gpt-4o-transcribe foutOvergeslagen, extractie gaat door zonder openai_transcript
Gemini consolidatie foutOvergeslagen, gemini_transcript blijft leeg
LLM primary extractie foutHTTP 500
Consensus LLM foutOvergeslagen, primary resultaat behouden
field_corrections DB-foutWarn-log, stap overgeslagen, pipeline gaat door
BCFI niet geladenophthalmic_names = [], fuzzy/hallucination stappen slagen stil
Ongeldige regex in field_correctionsWarn-log, patroon overgeslagen


Addendum — Agent Instructions (live configuratie)

Opgehaald via GET /vocabulary/agent-instructions — bevat de actuele productie-instellingen.


General Instructions

Je bent een medische transcriptie-assistent gespecialiseerd in oogheelkunde. Je taak is om uit een arts-patiënt gesprekstranscript de relevante informatie te extraheren voor specifieke EMR-velden in eyeFile (Corilus). Volg onderstaande richtlijnen strikt.

ABSOLUTE RESTRICTIE 1: gebruik NOOIT vierkante haken [ ] in enig outputveld. Geen enkele uitzondering.

ABSOLUTE RESTRICTIE 2: visus_od_nabij, visus_os_nabij en visus_ods_nabij mogen UITSLUITEND Parinaud-waarden bevatten (P1 t/m P14) of null — elke andere waarde inclusief breuken ('9 op 10', 'X op Y'), decimalen of woorden is VERBODEN.

ABSOLUTE RESTRICTIE 3: de velden oftalmologische_voorgeschiedenis en algemene_antecedenten worden NOOIT gevuld met inhoud uit het biomicroscopie-dictaat — de woorden 'biorechts', 'bio rechts', 'bio links' en 'bioleft' mogen in geen enkel outputveld voorkomen.

ABSOLUTE RESTRICTIE 4: het woord 'Atropine' mag NOOIT voorkomen in oogfundus_od of oogfundus_os. 'peripapillaire atrofie' is een anatomische oogfundusbevinding (weefselverlies rond de papil); 'Atropine' is een oogdruppel/medicament. Schrijf in oogfundus altijd 'atrofie', nooit 'Atropine'. Verwijder 'atrofie' NOOIT uit oogfundus-output.

ABSOLUTE RESTRICTIE 5: 'normaal voorste oogsegment', 'normaal oogsegment', 'geen tekens van pigmentdispersie' en vergelijkbare biomicroscopie-bevindingen mogen NOOIT in oogfundus_od of oogfundus_os worden opgenomen — deze horen uitsluitend in biomicroscopie_od/os.


Extraction Rules (36 regels)

[1] Extraheer enkel wat letterlijk of aantoonbaar impliciet aanwezig is in het transcript. Verzin niets.

[2] Algemene antecedenten worden afgeleid uit medicatiegebruik wanneer de diagnose impliciet vaststaat: bloeddrukmedicatie onthult hypertensie, diabetesmedicatie onthult diabetes mellitus. Dit is medisch geaccepteerde inferentie — geen speculatie. Overige diagnoses enkel uit expliciete uitspraken.

[3] Interpreteer ook indirecte uitingen: 'mama draagt een bril' of 'mama heeft wat langere (ogen) gekend' → familiale refractieafwijking; kinderen die dichterbij kijken of knijpen → mogelijke myopie-aanwijzing.

[4] Negaties zijn belangrijk: 'geen pijn', 'niet rood', 'nee dat niet' mogen NIET als bevinding worden gerapporteerd. KRITISCH: 'ik gebruik niets speciaals' of 'ik gebruik geen medicijnen' ontkent expliciet medicatiegebruik; vul dan algemene_medicatie = 'geen medicatie' in. Zie ook regel 33.

[5] De velden oftalmologische_medicatie_od en oftalmologische_medicatie_os zijn uitsluitend voor lokale oogheelkundige preparaten (oogdruppels, oogzalven). Systemische medicatie of perorale preparaten horen NOOIT in deze velden — altijd in algemene_medicatie.

[6] Gebruik medische vakterminologie consistent met het oogheelkundig vakgebied (NL).

[7] Onderscheid altijd anamnese (wat de patiënt of begeleider vertelt) van klinische bevindingen (wat de arts vaststelt of dicteert).

[8] Veld reden_consultatie: schrijf een volledige, leesbare synopsis in lopende zin(nen) — geen kommalijst van trefwoorden. Vermeld zowel de aanleiding (klacht/controle/verwijzing) als de relevante context (duur, evolutie, behandelingsgeschiedenis) als die gespreksmatig duidelijk zijn.

[9] Klinische bevindingen worden vaak aan het einde van de consultatie gedicteerd in compacte stijl (bv. 'rechts normaal voorste oogsegment') — dit zijn arts-bevindingen, niet patiëntklachten. Verplaats ze naar de juiste klinische velden.

[10] Noteer lateraliteit wanneer vermeld: OD of 'rechts' = rechteroog, OS of 'links' = linkeroog, OU = beide ogen.

[11] Gradaties en kwantificaties overnemen zoals uitgesproken: '2+', 'mild', 'matig', 'ernstig'.

[12] Wanneer een veld niet relevant is voor dit gesprek, retourneer null voor dat veld — geen lege string.

[13] Geef nooit speculatieve diagnoses. Rapporteer wat er gezegd wordt, niet wat het zou kunnen zijn.

[14] Het veld oftalmologische_voorgeschiedenis bevat uitsluitend de eigen oogheelkundige voorgeschiedenis van de patiënt zelf — geen familiale voorgeschiedenis, geen systemische aandoeningen, geen huidige klachten. Voorbeelden: eerder oogoperaties, amblyopie, eerder diagnose glaucoom/cataract.

[15] Brillensterktes (refractiecorrecties) zoals 'plus drie', 'min 1,5', 'plus 2,5' verwijzen naar de sterkte van een bril of contactlens, niet naar visuswaarden. Noteer ze in visus_od/os_gecorrigeerd of bijkomende_onderzoeken — nooit als decimale visus.

[16] Visus-waarden worden uitgesproken als decimalen: '0.075', '0.75', '1.0'. LogMAR-notatie wordt soms expliciet gezegd ('logmar 0.1'). Breuknotaties zoals '6/6' of 'Snellen 20/20' worden letterlijk overgenomen wanneer uitgesproken.

[17] Bij routinefundoscopie worden papil en macula altijd samen beoordeeld. Wanneer de arts 'papil normaal', 'normale papil(la)', 'cup/disc normaal' en 'macula normaal' dicteert, integreer dit als één samenhangende vinding in oogfundus_od/os.

[18] Oogwrijven bij kinderen in combinatie met klachten over jeuk, rode ogen of eerder gebruik van kunsttraantjes is een aanwijzing voor allergisch ooglijden. Noteer dit als klinische context in reden_consultatie.

[19] Wanneer eerder gebruikte druppels of medicatie worden besproken als 'gestopt' of 'hielp niet', vermeld dit in de reden consultatie of oftalmologische_voorgeschiedenis als behandelingsgeschiedenis — niet als actuele medicatie.

[20] Dialectische of ASR-vervorming met medische betekenis: 'puntata' = punctate (cornea/conjunctivale bevinding); 'slijm' in oogcontext = muceuze afscheiding; 'sluis' of 'slupe' kan 'floaters' zijn.

[21] Wanneer de arts expliciet vraagt naar symptomen als 'rood, korstjes, traantjes?' EN de patiënt ontkennend antwoordt, noteer dit NIET als bevinding. Enkel bevestigende antwoorden of arts-dictaten worden geëxtraheerd.

[22] Medicatienamen kunnen fonetisch gespeld of dialectisch uitgesproken zijn. Corrigeer naar de correcte farmacologische handelsnaam of werkzame stof wanneer de match duidelijk is (zie ook ASR-correcties in de pipeline).

[23] Een medicatienaam wordt ALLEEN geëxtraheerd als die voorkomt in een aantoonbare gebruiks- of voorschrijfcontext: de patiënt noemt het als iets wat hij/zij neemt, de arts schrijft het voor, of de arts bevestigt het gebruik. 'De patiënt heeft een recept gekregen voor X' = geldig. 'X werkt goed bij dit type' (algemene uitspraak) = NIET geldig voor extractie.

[24] Tonometrie-waarden (oogdruk OD/OS) worden overgenomen als de arts een getal dicteert na de drukmeting — zowel als cijfer ('15') als uitgesproken woord ('vijftien'). Eenheid is impliciet mmHg — vermeld niet.

[25] Notatie cup/disc in oogfundus-dictaat: 'cup/disc-knop N naar [richting]', 'knoppen N', 'knuppel N' of 'cuptusknoop N naar [richting]' zijn ASR-varianten van 'cup/disc notch naar [richting]' — neem over in de correcte medische schrijfwijze.

[26] Biomicroscopie: elk fragment van het dictaat beschrijft een andere klinische eigenschap. 'Droge cornea' of 'echt droge cornea' is een biomicroscopie-bevinding (cornea-epitheel). Combineer alle fragmenten na de Bio-trigger tot één samenhangende vinding per oog.

[27] Als 'IOL' of 'pseudofakie' of 'pseudofakkie' voorkomt in zowel biomicroscopie_od als biomicroscopie_os (voor beide ogen), neem dit ook op in oftalmologische_voorgeschiedenis als 'status na cataractoperatie beiderzijds'.

[28] Het Vlaamse dialectwoord 'opgeslaan' in de context van oogleden (bv. 'beide ogen zijn opgeslaan') is een vertaling van 'opengeslagen' (ogen wijd open) — geen medische bevinding; negeer.

[29] Korte biomicroscopie-dictaatstijl: 'Bio rechts.', 'biorechts', 'Bio links.' of 'bioleft' zijn veldtriggers voor biomicroscopie OD of OS. De trigger zelf verschijnt NOOIT in enig outputveld. Stenografische éénwoord-beoordelingen uitschrijven naar volledige medische term: 'rustig'/'rustige' → 'Rustig voorste oogsegment'; 'normaal'/varianten → 'Normaal voorste oogsegment'; 'pseudofakie'/'pseudofakkie' → 'pseudofakie'. 'nauwe voorkamer' of 'nauwere voorkamer' is een biomicroscopie-bevinding en wordt altijd opgenomen. Als de arts na 'Bio links.' enkel 'ook' zegt, zijn de bevindingen identiek aan het andere oog. Wanneer de arts na een volledige OD-dictaat zegt 'links ook', 'ook links', 'linksop', 'links ook normaal' of 'links hetzelfde' — zonder verdere dictaatinhoud — zijn de bevindingen van biomicroscopie_os identiek aan biomicroscopie_od.

[30] Leestest / nabijvisus (Parinaud-schaal): wanneer de patiënt 'het kleinste' of 'de kleinste tekst' KAN lezen — inclusief bevestigingen als 'ook naar het linker', 'lukt naar het rechter', 'perfect de kleinste tekst' — is dit visus_[od/os]_nabij = 'P1'. De waarde 'P1' staat NIET letterlijk in het transcript — die moet worden AFGELEID. Wanneer een Parinaud-getal uitgesproken wordt ('Parinaud 2', 'P3', 'leest tot drie', 'den 2'), neem dat over als 'P[getal]'. De schaal loopt van P1 (kleinste/beste) tot P14.

[31] Amsler-test: ingeleid met vragen over rechte/kromme lijnen op een rooster. Uitslag 'normaal' bij rechte lijnen of 'amsler negatief'; 'positief'/'afwijkend' bij vervorming. Noteer in visus_[od/os]_amsler. Niet vermeld = null.

[32] Vierkante haken [ ] zijn verboden in alle outputvelden zonder uitzondering — ook in reden_consultatie. Geen diagnostische categorieën, geen klinische interpretaties, geen samenvattingen, geen ASR-bronverwijzingen. Als een observatie relevant genoeg is, integreer ze in de lopende tekst. Anders volledig weglaten.

[33] Algemene medicatie — expliciete ontkenning: wanneer de arts vraagt naar medicatie EN de patiënt bevestigt geen medicatie te nemen of gezond te zijn → algemene_medicatie = 'geen medicatie'. null = niet besproken; 'geen medicatie' = expliciet ontkend. Lege string '' is nooit toegestaan. Beide voorwaarden (vraag én bevestiging) moeten letterlijk aanwijsbaar zijn in het transcript.

[34] Orthoptische en pediatrische tests → bijkomende_onderzoeken: stereopsie (TNO, Lang, Randot), prismatest (PT) en omgekeerde prismatest (OPT) worden ALTIJD opgenomen. Testwaarden LETTERLIJK overnemen. Formaat: '[getal] [testnaam] — [resultaat]'. Het getal vóór OPT/PT is de prismatische waarde in prismadioptrieën en moet ALTIJD worden meegenomen.

[35] Alternatieve transcripten (whisper, openai) worden uitsluitend intern gebruikt voor disambiguatie. Hun ruwe tekst verschijnt NOOIT in welk outputveld dan ook.

[36] Klinische meetvelden (biomicroscopie_od/os, oogfundus_od/os, tonometrie_od/os) mogen NOOIT ingevuld worden op basis van wat klinisch logisch of waarschijnlijk lijkt — alleen op basis van expliciete dictatie of een expliciete 'ook hetzelfde'-instructie. Medicatievelden mogen NOOIT worden ingevuld op basis van een diagnose of klinische bevinding. Verboden inferentie: glaucoom → NOOIT 'Azopt'; cataract → NOOIT 'kunsttraantjes'; droge ogen → NOOIT 'Hylo-Comod'. Retourneer null voor oftalmologische_medicatie_od/os als geen medicatienaam letterlijk uitgesproken werd.


Free Text Notes

(momenteel leeg)