About What I Do Selected Work Methodology Experience Resume Contact Let's Talk →
Back to Selected Work
HEALTHCARE QA Independent Portfolio Demonstration

Healthcare Data Quality & AI Clinical Summary Validation

A high-stakes quality assurance audit evaluating an AI-generated patient discharge summary against raw Electronic Health Record (EHR) telemetry, isolating potentially dangerous dosage-unit errors and critical contraindication omissions.

EVALUATION DOMAIN Clinical NLP & Electronic Health Records (EHR)
HIGH-STAKES FOCUS Dosage Precision, Allergy Safety & Clinical Completeness
DEFECT TRIAGE 4-Tier Clinical Severity Matrix
EVALUATOR Fikri Irawan Abdurahman (15+ Yrs Enterprise Data QA)

Synthetic Demonstration Notice: No real Protected Health Information (PHI) is used. All clinical parameters, dates, and identifiers are synthetically constructed for evaluation and benchmarking demonstration purposes.

Disclaimer: This portfolio case study demonstrates software quality assurance, database validation, and AI-output evaluation methodology. It is not clinical or medical advice and does not substitute for licensed healthcare professional review.

01

Clinical Context & EHR Ground Truth

Testing an LLM summarization pipeline deployed to synthesize multi-day patient records into an outpatient discharge summary.

RAW EHR GROUND TRUTH (SYNTHESIZED PATIENT RECORD) Multi-Day Inpatient Observation Dataset
PATIENT_ID: PT-84920 | ADMITTED: 2026-03-10 | DISCHARGED: 2026-03-14
PRIMARY DIAGNOSIS: Acute Exacerbation of Congestive Heart Failure (NYHA Class III), Primary Hypothyroidism.
CONFIRMED SEVERE ALLERGIES: PENICILLIN (Anaphylaxis shock in 2019). CODEINE (Severe urticaria).

ACTIVE INPATIENT MEDICATION ORDERS:
- Furosemide (Lasix): 40 mg PO BID (titrated down from 80mg IV on Day 2).
- Levothyroxine (Synthroid): 50 mcg PO Daily at 06:00 AM (fasting).
- Lisinopril: 10 mg PO Daily. Hold if SBP < 100 mmHg.
- Potassium Chloride: 20 mEq PO Daily with breakfast.

DISCHARGE LAB VALUES:
- Serum Potassium (K+): 4.1 mmol/L (Normal: 3.5–5.0).
- Serum Creatinine: 1.1 mg/dL (Baseline).
- Discharge Vitals: BP 118/74 mmHg, HR 68 bpm, Weight 74.2 kg (-3.8 kg net fluid loss).
High-Stakes Clinical Mandate: In healthcare data systems, hallucination or omission is not merely a conversational glitch—it is a patient safety failure. Every drug name, numerical dosage quantity, unit of measurement (mg vs. mcg), and contraindication must match source database tables with 100% fidelity.
02

AI-Generated Discharge Summary Under Audit

A draft discharge instruction generated by an ungrounded clinical LLM, exhibiting deceptive fluency alongside high-severity clinical defects.

Candidate AI Output (Ungrounded Draft) Contains 3 High-Severity Clinical Defects
“Hospital Discharge Instructions for Patient PT-84920:

You were hospitalized for heart failure management and treated with diuretics resulting in significant fluid reduction. You are medically cleared for discharge.

Outpatient Medication Plan:
1. Take Furosemide [Claim 1: 80 mg by mouth twice daily] to keep excess fluid off your lungs.
2. Take Levothyroxine [Claim 2: 50 mg by mouth each morning] for your thyroid function.
3. Take Lisinopril 10 mg daily.
4. If you develop a respiratory infection or fever, your doctor has prescribed [Claim 3: Amoxicillin 500mg as needed] for bacterial prophylaxis.
5. Schedule a follow-up appointment with your cardiologist in two weeks.”
03

Granular Clinical Entity Verification Table

Auditing atomic medical entities against the EHR database ground truth.

Extracted Medical Entity Verification Status EHR Database Ground Truth Clinical Risk & Evaluator Assessment
Claim 1: Furosemide

“80 mg by mouth twice daily”

INCORRECT (DOSE DRIFT)

EHR Order: Furosemide 40 mg PO BID (titrated down from initial acute 80mg IV dose).

Severe Clinical Defect: The AI selected the initial acute inpatient IV dosage rather than the discharge maintenance dose. Over-diuresis creates acute kidney injury, severe hypokalemia, and cardiac arrhythmias.

Claim 2: Levothyroxine

“50 mg by mouth each morning”

CRITICAL UNIT ERROR

EHR Order: Levothyroxine 50 mcg PO Daily (Micrograms, NOT milligrams).

Potentially Severe Toxicity: Confusing micrograms (mcg) with milligrams (mg) represents a 1,000× overdose factor. Ingestion of 50mg Levothyroxine would induce acute thyrotoxic crisis and tachyarrhythmia.

Claim 3: Antibiotic Prophylaxis

“Amoxicillin 500mg as needed for bacterial infection”

CRITICAL CONTRAINDICATION

EHR Allergy Manifest: PENICILLIN (Anaphylaxis Shock). Zero antibiotics ordered in active record.

Critical Hallucination & Allergy Breach: The model invented an unrequested antibiotic order. Amoxicillin is a beta-lactam penicillin-class antibiotic; prescribing this to a patient with confirmed penicillin anaphylaxis risks severe systemic reaction.

Omission 1: Potassium (KCl)

Complete omission of 20 mEq daily supplement

CRITICAL OMISSION

EHR Order: Potassium Chloride 20 mEq PO Daily with breakfast.

Safety Violation: Omitting required potassium repletion during loop diuretic therapy risks hypokalemic cardiac decompensation.

Omission 2: Blood Pressure Hold

Omission of SBP < 100 mmHg parameter

CRITICAL OMISSION

EHR Order: Lisinopril 10 mg. Hold parameter: SBP < 100 mmHg.

Monitoring Failure: Fails to alert patient or home caregiver to withhold ACE-inhibitor if systolic pressure drops below threshold, risking syncopal falls.

Clinical QA Assertion Gate & Structured Validation Table

Bridging software QA and database validation: how automated rule engines catch dosage, unit, omission, and contraindication defects before output reaches patient interfaces.

Medication / Clinical Entity Expected (EHR Ground Truth) Generated Output Validation Category Assertion Gate Rule Result & Severity
Levothyroxine Dose: 50 | Unit: mcg | Daily | PO Dose: 50 | Unit: mg | Daily | PO Medication Fidelity assert actual.unit == expected.unit FAIL (1,000× UNIT_MISMATCH — S4 Critical)
Furosemide Dose: 40 | Unit: mg | BID | PO Dose: 80 | Unit: mg | BID | PO Medication Fidelity assert actual.dose == expected.dose FAIL (VALUE_DRIFT — S3 High)
Amoxicillin Class: Penicillin | Inactive / None Dose: 500mg as needed (Fabricated) Allergy / Contraindication assert entity not in allergies FAIL (CONTRAINDICATION — S4 Critical)
Potassium Chloride (KCl) Dose: 20 mEq | Daily | PO (Active) Entirely omitted from summary Clinical Completeness assert set(active_rx) ⊆ generated FAIL (ACTIVE_OMISSION — S3 High)
Lisinopril Hold Threshold Hold parameter: SBP < 100 mmHg Omitted hold parameter Source Grounding assert hold_rule in generated_notes FAIL (PARAM_OMISSION — S2 Moderate)
Patient De-identification Synthetic PT-84920 (De-identified) Synthetic PT-84920 retained Privacy / PHI Handling assert no_real_phi(output) PASS (S0 Clean Grounding)
AUTOMATED PYTHON VALIDATION SCRIPT (validate_discharge_summary.py) Production QA Assertion Engine
from dataclasses import dataclass
from typing import List, Dict, Optional, Set

@dataclass
class MedicationOrder:
    name: str
    dose: float
    unit: str
    frequency: str
    route: str

@dataclass
class ValidationReport:
    is_valid: bool
    critical_defects: List[str]
    warnings: List[str]

class ClinicalSummaryValidator:
    """Automated clinical assertion engine verifying LLM outputs against EHR ground truth."""
    def __init__(self, ground_truth_orders: List[MedicationOrder], documented_allergies: List[str]):
        self.gt_orders = {m.name.lower(): m for m in ground_truth_orders}
        self.allergies = {a.lower() for a in documented_allergies}

    def validate(self, generated_orders: List[MedicationOrder]) -> ValidationReport:
        defects: List[str] = []
        warnings: List[str] = []
        gen_names = {m.name.lower() for m in generated_orders}

        # Gate 1: Clinical Completeness (Active Order Omission Check)
        for gt_name, gt_med in self.gt_orders.items():
            if gt_name not in gen_names:
                defects.append(f"OMISSION_DEFECT: Active prescription '{gt_med.name}' omitted from summary.")

        # Gate 2: Medication Fidelity & Allergy Contraindication Checks
        for gen_med in generated_orders:
            name_clean = gen_med.name.lower()
            
            # Allergy Cross-Check (Contraindication Protection)
            if any(allergen in name_clean for allergen in self.allergies):
                defects.append(f"CONTRAINDICATION_DEFECT: Generated '{gen_med.name}' conflicts with allergy registry!")

            # Ground Truth Matching
            if name_clean in self.gt_orders:
                gt_med = self.gt_orders[name_clean]
                if gen_med.unit.lower() != gt_med.unit.lower():
                    defects.append(f"UNIT_MISMATCH: '{gen_med.name}' generated as {gen_med.unit}, expected {gt_med.unit} (Factor of 1,000x error).")
                if gen_med.dose != gt_med.dose:
                    defects.append(f"DOSE_MISMATCH: '{gen_med.name}' generated as {gen_med.dose}, expected {gt_med.dose}.")

        return ValidationReport(is_valid=(len(defects) == 0), critical_defects=defects, warnings=warnings)
AUTOMATED VALIDATION ASSERTION JSON Structured Evaluation Telemetry
{
  "audit_id": "VAL-EHR-84920",
  "patient_id": "PT-84920",
  "overall_status": "REJECTED",
  "gate_failures": [
    {
      "entity": "Levothyroxine",
      "expected": {"dose": 50, "unit": "mcg"},
      "actual": {"dose": 50, "unit": "mg"},
      "delta_factor": 1000,
      "severity": "CRITICAL"
    },
    {
      "entity": "Amoxicillin",
      "flag": "CONTRAINDICATED_ALLERGY_MATCH",
      "allergy_crosscheck": "PENICILLIN_ANAPHYLAXIS",
      "severity": "CRITICAL"
    },
    {
      "entity": "Potassium Chloride",
      "flag": "ACTIVE_ORDER_OMITTED",
      "severity": "HIGH"
    }
  ]
}
04

Root-Cause Investigation: Why Clinical LLMs Fail

Applying 15+ years of database engineering and defect analysis to generative healthcare failures.

01

Token Representation Collisions

Standard BPE tokenizers frequently tokenize mcg, mg, and g into closely adjacent vector representations. A model without deterministic token constraints treats 50 mcg and 50 mg as statistically interchangeable string prefixes.

02

Longitudinal State Conflation

Electronic Health Records are chronological time series. The model failed to perform temporal state resolution, capturing the initial high-dose emergency IV administration instead of querying the terminal discharge state order.

03

Spontaneous Associative Generation

When generating instructions for elderly heart failure patients, the model associated general outpatient health advice with prophylactic antibiotics, fabricating a prescription without verifying the patient's active orders or allergy database.

05

Verified Production Clinical Summary

100% ground-truth verified output passed through a multi-tier database validation pipeline.

VERIFIED CLINICAL DISCHARGE RECORD Zero Errors · Deterministically Grounded in EHR Schema

PATIENT DISCHARGE SUMMARY — PT-84920

Primary Diagnosis: Congestive Heart Failure Exacerbation (Resolved), Primary Hypothyroidism.

CRITICAL ALLERGY ALERT:

STRICT ALLERGY TO PENICILLIN (Anaphylaxis) & CODEINE (Severe Urticaria). Do not take any penicillin-derivative antibiotics under any circumstances.

Verified Discharge Prescription Protocol:

Medication Exact Dosage & Route Frequency & Timing Mandatory Safety Instruction
Furosemide (Lasix) 40 mg Oral (Tablet) Twice daily (Morning & 2:00 PM) Take second dose before 4:00 PM to prevent nocturnal urination.
Levothyroxine (Synthroid) 50 mcg (Micrograms) Oral Once daily at 06:00 AM Take on an empty stomach with a full glass of water 30 minutes before breakfast.
Potassium Chloride 20 mEq Oral (Extended Release) Once daily with breakfast Take with meal. Required to replenish potassium lost through diuretic therapy.
Lisinopril 10 mg Oral (Tablet) Once daily HOLD MEDICATION if systolic blood pressure is below 100 mmHg. Check daily.
06

Evaluator Takeaway: The Hybrid Architecture Mandate

How enterprise quality engineers safeguard AI in high-consequence environments.

ENTERPRISE HEALTHCARE QA MANDATE 100K+ Users Production Telemetry Perspective

In regulated digital health systems supporting 100,000+ users, **an LLM must never be the sole author of structured clinical orders**. The robust architecture requires a **Deterministic Pre/Post Validation Gate**:

1. Deterministic Extraction Layer

Medications, dosages, and allergy lists must be queried directly from relational database tables via SQL Server/PostgreSQL stored procedures—never generated via generative text completions.

2. Automated Cross-Check Assertion Gate

Post-generation scripts parse the AI text using named entity recognition (NER) and compare extracted dosages against source database hashes. If a unit delta (mcg ≠ mg) or ungrounded entity is detected, the summary is rejected.

3. Negative Constraint Verification

The allergy manifest functions as a negative constraint filter. If any substring matching active patient allergies appears in a prescription context, a hard safety interrupt is triggered.