跳转至

Migrate from OpenMed 1.9 to 2.0

This guide covers the public compatibility boundary from v1.9.1 to v2.0.0. The Python comparison is static: it parses the exported openmed/ surface without importing the package or executing application code.

Run the same comparison locally:

python scripts/release/api_surface_diff.py \
  v1.9.1 HEAD \
  --json api-surface-diff.json \
  --check docs/migration/1.9-to-2.0.md

Compatibility result

The static Python API inventory grows from 14,488 to 20,538 symbols:

  • 6,050 public symbols are added.
  • No public symbol is removed or renamed.
  • No existing callable signature is narrowed.
  • No existing symbol is newly marked with @deprecated.

The REST contract retains the same 15 paths and 12 component schemas as v1.9.1. Swift, Kotlin/Android, JavaScript, CLI, configuration, label, and evidence contracts require separate review because the Python AST comparison does not inspect them.

Upgrade checklist

  1. Upgrade the application to openmed==1.9.1 and clear existing warnings.
  2. Install openmed==2.0.0 with only the optional extras the application uses.
  3. Add DEVICE to any exhaustive canonical-label enum or policy switch.
  4. Re-run privacy, leakage, span-offset, and direct-identifier recall tests using synthetic fixtures in every deployed language and script.
  5. Re-run any custom MCP client, CLI JSON, Swift, Android, or evidence-schema decoding tests.
  6. Keep model files and restricted clinical terminologies outside the package; v2 does not bundle gated datasets or licensed vocabularies.

Stable root API

The documented v1 imports remain available:

from openmed import OpenMedConfig, analyze_text, deidentify, extract_pii

AnalyzeResult mapping access and to_dict() remain the compatibility bridge for callers that still need the legacy dictionary-shaped payload:

result = analyze_text("Synthetic clinical note")
entities = result["entities"]
payload = result.to_dict()

No before/after replacement snippet is required for a removed or deprecated Python symbol because the static comparison found neither category.

Canonical labels

OpenMed 2.0 adds DEVICE for clinical equipment and procedure extraction. Code that accepts arbitrary canonical-label strings needs no change. Code that models labels as a closed enum must add the value:

# v1: an exhaustive application-owned set
ALLOWED_LABELS = {"PROCEDURE", "BODY_SITE"}

# v2: include the additive canonical label
ALLOWED_LABELS = {"PROCEDURE", "BODY_SITE", "DEVICE"}

Policy profiles shipped with OpenMed already include the canonical v2 label set. Revalidate application-owned profiles that enumerate every label.

Language packs and model routing

The language-pack catalog is now the shared source of truth for model-backed languages, deterministic identifier-only capabilities, locales, and optional Indic routes.

Pattern-only language packs do not silently claim a default neural model. Pass an explicit model when combining one with model-backed inference:

from openmed import extract_pii

result = extract_pii(
    "Synthetic Afrikaans note",
    lang="af",
    model_name="OpenMed/privacy-filter-multilingual",
)

For deterministic identifier checks without a model, use the language-specific patterns and safety-sweep APIs documented for the pack. Validate the chosen model against local fixtures before deployment; accepting an explicit model identifier is not an accuracy claim for every language.

Optional dependencies

OpenMed 2.0 adds focused extras instead of making network or large-model runtimes mandatory:

pip install "openmed[zh]==2.0.0"          # Chinese segmentation/normalization
pip install "openmed[indic]==2.0.0"       # Indic text utilities
pip install "openmed[lid]==2.0.0"         # optional token language ID
pip install "openmed[integrity]==2.0.0"   # signed artifact verification
pip install "openmed[openmrs]==2.0.0"     # OpenMRS handoffs
pip install "openmed[scrubadub]==2.0.0"   # scrubadub adapter
pip install "openmed[prefect]==2.0.0"     # Prefect batch flows

The optional MCP integration now targets mcp>=1.27,<2. Re-run client handshake and tool-schema tests if an application pinned an older MCP runtime. The optional AWQ extra is supported on Linux, and its dependency combination is intentionally isolated from incompatible GLiNER environments. The ONNX and multimodal extras now require the fixed ONNX 1.21+ line and use spaCy 3.8.9+; they are intentionally isolated from the scispaCy extra because scispaCy's NumPy ABI constraint is incompatible with the secure ONNX route. Install and run those adapters in separate environments when an application needs both.

CLI and MCP

CLI commands now expose consistent --json success and error envelopes. Human output remains the default. Automation should select JSON explicitly and inspect the structured error code rather than scraping prose:

openmed models list --json
openmed gates preview \
  --candidate artifacts/release-candidate.json \
  --baseline-store gates/baseline.json \
  --strict \
  --json

The new openmed-mcp entry point renders tools from the same typed registry used by documentation and schema-drift tests. MCP clients should refresh cached tool schemas so annotations and structured outputs are recognized.

Structured and clinical additions

The openmed.structured, openmed.clinical, openmed.interop, openmed.risk, and openmed.eval namespaces add flowsheets, lab panels, discharge structures, radiology extraction, longitudinal linking, relation extraction, privacy risk, and signed release-readiness evidence. These additions do not replace the stable root de-identification API.

Structured-data release workflows now require an explicit disposition for every source column and distinguish advisory quasi-identifier discovery from reviewed release policy. Reference-population k-map, exact-linkage risk, and delta-presence require an explicit caller-supplied population and thresholds; the library does not infer that an available table represents the attack population. Existing text-only de-identification calls are unaffected.

Clinical outputs remain assistive and require qualified review. They must not auto-trigger diagnosis, treatment, billing, or other clinical decisions.

Swift, Android, and JavaScript

  • Swift adds watchOS and visionOS targets, grapheme-safe scalar span parity, and compact on-device segmentation without removing existing OpenMedKit APIs.
  • Indic or combined v2 segmenter bundles now declare segmenter/ICU.txt as a required, digest-bound license resource and use the SPDX expression ICU or MIT AND ICU. Regenerate any pre-release v2 converted artifacts whose manifests used ICU-1.8.1; current Python and OpenMedKit validators reject bundles without the complete notice.
  • Android adds OpenMedSpan and descriptive EntityPrediction metadata. The existing artifact remains com.github.maziyarpanahi:openmed:v2.0.0.
  • The npm package remains the unscoped package openmed and keeps ESM and CommonJS exports at version 2.0.0.
  • The OpenAPI path and schema set is unchanged; regenerate generated clients only to pick up the release metadata.

Release evidence

V2 release readiness combines a signed extraction/model gate report, this migration guide, a machine-readable API comparison, the public clinical disclaimer, and a named passing golden-suite report. A missing candidate report is not a passing gate.

Do not treat build hashes as proof of model quality. Validate model-specific recall, critical leakage, quantization deltas, device behavior, and span-integrity evidence independently.