
WonderLabIntroduction "Clinical data never leaves the device." This is article #93 in the Open...
"Clinical data never leaves the device."
This is article #93 in the Open Source Project of the Day series. Today's project is OpenMed — a local-first healthcare AI library built by HuggingFace researcher Maziyar Panahi, designed specifically for clinical text processing without cloud data movement.
The standard healthcare AI workflow sends patient data to a cloud vendor and receives structured results back. That's a persistent compliance exposure point. HIPAA, GDPR, and national data protection laws place specific constraints on how patient data moves, and "sending it to the cloud" often hits hard limits for healthcare organizations before the conversation even starts.
OpenMed brings the processing on-device instead: over 1,000 biomedical NLP models that run locally, no network calls, no external API keys, deployable from Python services to iOS apps.
OpenMed is a local-first healthcare AI toolkit positioned as "turning clinical text into structured insight without your data leaving the secure environment."
The core capability is not generative AI — it's encoder Transformers (BERT, ELECTRA, DeBERTa families) doing extraction and classification. The paper (arXiv:2508.01630) reports state-of-the-art performance on 10 of 12 biomedical NER benchmarks.
Clinical text input
↓
Local model inference (BERT/ELECTRA/DeBERTa)
↓
┌──────────────────────────────────────────┐
│ NER: identify diseases, drugs, genes │
│ PII de-identification: detect and mask │
│ Relation extraction: entity semantics │
└──────────────────────────────────────────┘
↓
Structured output (data never left the device)
Clinical text structuring
Patient data de-identification
[NAME]), replace (Faker-backed surrogates), hash, date-shiftiOS and macOS medical app development
Enterprise healthcare system integration
Install:
# CPU
pip install openmed
# Apple Silicon (MLX acceleration)
pip install openmed[mlx]
# CUDA GPU
pip install openmed[cuda]
Clinical NER:
from openmed import analyze_text
# Disease detection
result = analyze_text(
"Patient started on imatinib for CML.",
model_name="disease_detection_superclinical"
)
# {entities: [{text: "CML", label: "DISEASE", start: 30, end: 33}], ...}
# Drug detection
result = analyze_text(
"Prescribed metformin 500mg twice daily for type 2 diabetes.",
model_name="pharma_detection_superclinical"
)
PII De-identification:
from openmed import deidentify
text = "Patient John Smith (DOB: 1985-03-15, SSN: 123-45-6789) was admitted..."
# Masking
result = deidentify(text, method="mask")
# "Patient [NAME] (DOB: [DATE], SSN: [SSN]) was admitted..."
# Faker replacement (readable text, fully anonymized)
result = deidentify(text, method="replace")
# "Patient Michael Johnson (DOB: 1972-08-22, SSN: 987-65-4321) was admitted..."
Batch processing:
from openmed import BatchProcessor
processor = BatchProcessor(
operation="extract_pii",
model_name="pii_superclinical_large",
on_progress=lambda p: print(f"{p:.0%} complete")
)
results = processor.run([record1, record2, record3, ...])
Swift/iOS:
import OpenMedKit
let analyzer = OpenMedNER(model: .diseaseDetectionSuperClinical)
let result = try await analyzer.analyze("Patient presents with hypertension and T2DM")
// result.entities: [{text: "hypertension", label: "DISEASE"}, {text: "T2DM", label: "DISEASE"}]
| Model | Domain | Parameters | HuggingFace Downloads |
|---|---|---|---|
disease_detection_superclinical |
Diseases/conditions | 434M | 104K |
pharma_detection_superclinical |
Drugs/compounds | 434M | — |
pii_superclinical_large |
PII identifiers | 434M | — |
chemical_detection_electramed |
Chemicals | 33M | 117K |
anatomy_detection_electramed |
Anatomy | 109M | — |
genomic_detection_pubmed |
Genes/genomics | 109M | 103K |
oncology_detection_multimed |
Oncology entities | 568M | 102K |
This is the most consequential technical choice in OpenMed's design.
Generative LLMs (GPT-4, Claude, etc.) have a fundamental problem in medical text tasks: their outputs are not deterministic. Ask a generative model to do PII detection and it might, in some inputs, reproduce a patient's name in its output, or hallucinate a drug name that doesn't appear in the source text. For clinical applications, that's not an acceptable failure mode.
Encoder-only transformers doing NER are a classification problem: assign each token a label from a fixed set. These models produce deterministic outputs for a given input, generate no new tokens (so no hallucination), run locally with parameter counts between 33M and 568M, and produce auditable results with explicit source positions. For healthcare work, those properties outweigh the ability to generate fluent prose.
OpenMed's PII detection is more than running a NER model. There are several layers on top:
Context-aware detection: Keyword boosting within a 100-character window around candidates. A number sequence following SSN: gets a higher confidence score than an identical number sequence with no label nearby.
Checksum validation: Reduces false positives for structured identifier formats.
Smart Entity Merging: Solves the subword tokenization fragmentation problem. BERT-family models split "O'Brien" into ["O", "'", "Brien"]. The entity merging logic reassembles these fragments into complete entities, preventing incomplete PII detection results.
Three Privacy Filter variants:
┌──────────────────────────────────────────────────────┐
│ OpenMed Runtime │
├────────────────┬─────────────────┬───────────────────┤
│ Python / MLX │ Swift │ Docker / FastAPI │
│ │ OpenMedKit │ │
│ • CPU │ • macOS │ • REST API │
│ • CUDA │ • iOS │ • Batch endpoints │
│ • Apple MLX │ • iPadOS │ • Model lifecycle │
│ │ │ /models/loaded │
│ 24-33x faster │ PHI stays on │ /models/unload │
│ vs CPU PyTorch│ device │ keep_alive │
└────────────────┴─────────────────┴───────────────────┘
↑ ↑
Shared MLX model files (including 8-bit variants)
The Swift and Python paths share the same MLX model files. A hospital system can run Python-based server inference while running OpenMedKit on-device on iPads using the same model artifacts, with no separate model maintenance.
v1.2.0 introduced zero-shot interfaces that don't require pre-defined entity categories:
from openmed import zero_shot_ner
# Custom entity labels, not bound to pretrained NER categories
result = zero_shot_ner(
text="The patient's creatinine level was 2.3 mg/dL, suggesting CKD.",
labels=["LAB_VALUE", "UNIT", "CONDITION"]
)
# Identifies "2.3 mg/dL" as LAB_VALUE, "CKD" as CONDITION
from openmed import extract_relations
# Extract semantic relationships between entities
relations = extract_relations(
text="Metformin was prescribed for type 2 diabetes.",
entity_pairs=[("DRUG", "DISEASE")]
)
# [{drug: "Metformin", relation: "prescribed_for", disease: "type 2 diabetes"}]
For clinical entities outside the coverage of any pretrained NER model, zero-shot provides a flexible escape hatch.
OpenMed's models use domain-adaptive pre-training (DAPT) combined with LoRA fine-tuning:
For practitioners who want to fine-tune on their own data, these numbers are significant: no multi-GPU cluster required, a single consumer GPU and a few hours.
| Version | Date | Key Changes |
|---|---|---|
| v1.0.0 | Apr 2026 | First stable release, MLX backend, Swift package |
| v1.2.0 | Apr 2026 | Zero-shot NER/classification/relation extraction, iOS Scan Demo |
| v1.4.0 | May 2026 | Multilingual Privacy Filter, 16 languages |
| v1.5.0 | May 2026 | Arabic/Japanese/Turkish PII, 247 registered models |
| v1.5.2 | May 2026 | Security hardening, trust_remote_code defaults to False |
| v1.5.5 | Jun 2026 | Batch PII, REST model lifecycle management, 13 README translations |
OpenMed addresses a problem with a specific shape: medical NLP, where data cannot move off the device.
That constraint is optional in many industries and legally mandatory in many healthcare contexts. OpenMed turns the constraint into an architecture: encoder models for deterministic classification, MLX for local acceleration, a Swift package for mobile native integration, checksum validation to reduce false positives, Smart Entity Merging to handle tokenization fragments. Each layer addresses a real engineering problem that shows up in clinical text processing.
For developers building healthcare AI applications, or researchers working on clinical text, OpenMed is among the most complete local-first options in the current open-source ecosystem. The PII de-identification capabilities and multilingual support also have direct relevance outside healthcare — anywhere sensitive data requires processing without cloud movement: finance, legal, insurance, public records.
Explore PrimeSkills — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.
Welcome to my Homepage for more useful insights and interesting products.