How to Enable MLX Automatic Fallback on Non-Apple Hardware in OpenMed

OpenMed automatically routes MLX-only privacy-filter models to PyTorch when running on Linux, Windows, or Intel Macs by detecting platform availability in MLXBackend.is_available() and substituting model IDs via resolve_privacy_filter_model().

When deploying medical NLP pipelines across heterogeneous environments, portability becomes critical. The maziyarpanahi/openmed repository implements a transparent fallback system that eliminates manual configuration when moving MLX-optimized models to non-Apple hardware. This article explains how the library enables MLX automatic fallback on non-Apple hardware using the built-in backend detection mechanisms in openmed/core/backends.py.

How Platform Detection Gates MLX Execution

The fallback mechanism begins with platform-specific detection logic. In openmed/core/backends.py, the MLXBackend.is_available() method (lines 82-90) performs a hard platform check before attempting any imports.


# Conceptual implementation from openmed/core/backends.py#L82-L90

def is_available(self):
    return platform.system() == "Darwin" and _can_import_mlx()

When platform.system() != "Darwin", the method returns False, signaling that MLX acceleration is unavailable. This boolean drives all subsequent routing decisions without requiring user intervention.

Auto-Detection Logic and Backend Priority

OpenMed uses a preference-based auto-detection system. The get_backend() function (lines 42-48) iterates through a prioritized list of backends, returning the first one where is_available() evaluates to True.

Backend priority order:

  1. MLXBackend – Selected only on Apple Silicon when mlx.core imports successfully.
  2. HuggingFaceBackend – The Torch-based fallback used on Linux, Windows, and Intel Macs.

For privacy-filter specifically, select_privacy_filter_backend() (lines 92-100) adds an additional validation layer. If the requested model is an MLX-only artifact but MLXBackend().is_available() returns False, the function explicitly returns "torch" to force the fallback path.

Automatic Model Substitution for Torch Compatibility

When MLX is unavailable, resolve_privacy_filter_model() (lines 118-136) rewrites the model identifier to point to equivalent PyTorch weights. The function maintains an internal mapping via _TORCH_FALLBACK_BY_FAMILY and PRIVACY_FILTER_TORCH_FALLBACK.

Substitution example:

  • Input: "OpenMed/privacy-filter-mlx"
  • Output: "openai/privacy-filter"

During this substitution, OpenMed emits a one-time UserWarning alerting you that automatic fallback has occurred. To suppress this warning, request the Torch model directly instead of the MLX-specific path.

Pipeline Instantiation and Unified Output

The create_privacy_filter_pipeline() function (lines 146-162) orchestrates the entire fallback chain. It calls select_privacy_filter_backend() and resolve_privacy_filter_model(), then instantiates the appropriate pipeline class—either the MLX-native implementation or PrivacyFilterTorchPipeline.

Because both implementations return HuggingFace-compatible token-classification outputs, downstream code in openmed/core/quality_gates.py and other modules operates identically regardless of which backend executes the inference.

Practical Implementation Examples

The following examples demonstrate how to work with the automatic fallback system on non-Apple hardware.

Automatic fallback with warning:

from openmed.core.backends import create_privacy_filter_pipeline

# Example on a Linux machine (no MLX)

pipeline = create_privacy_filter_pipeline("OpenMed/privacy-filter-mlx")

# The call above prints a one‑time warning and internally uses the Torch model:

#   UserWarning: OpenMed: 'OpenMed/privacy-filter-mlx' is an MLX‑only artifact and

#   cannot run on this host. Substituting 'openai/privacy-filter' via Transformers.

#   To silence, request the PyTorch model directly.

# Use the pipeline exactly as you would on Apple Silicon:

result = pipeline("Patient John Doe was admitted for surgery.")
print(result)

Explicit Torch selection to avoid warnings:


# Explicitly request the Torch version to avoid the warning:

from openmed.core.backends import create_privacy_filter_pipeline

pipeline = create_privacy_filter_pipeline("openai/privacy-filter")  # direct Torch model

result = pipeline("Patient Jane Doe was discharged.")
print(result)

Checking which backend was selected:


# Demonstrating auto‑detect with `get_backend()`:

from openmed.core.backends import get_backend

backend = get_backend()          # will pick 'mlx' on Apple Silicon, otherwise 'hf'

print("Selected backend:", backend.__class__.__name__)  # -> "HuggingFaceBackend" on Linux

Summary

  • OpenMed requires zero configuration to enable MLX automatic fallback on non-Apple hardware.
  • The MLXBackend.is_available() method in openmed/core/backends.py gates all MLX functionality behind a Darwin platform check (lines 82-90).
  • select_privacy_filter_backend() automatically routes to "torch" when MLX is unavailable (lines 92-100).
  • resolve_privacy_filter_model() rewrites MLX-specific model IDs to their PyTorch equivalents (lines 118-136).
  • All pipelines return identical HuggingFace-compatible schemas regardless of whether PrivacyFilterTorchPipeline or the MLX implementation executes the inference.

Frequently Asked Questions

Does OpenMed require manual configuration to disable MLX on Linux?

No. OpenMed automatically detects the platform in MLXBackend.is_available() and routes to PyTorch without any configuration changes required from the user. The get_backend() function in openmed/core/backends.py (lines 42-48) handles the selection automatically during import or first pipeline creation.

What happens if I request an MLX-only model on a Windows machine?

The library calls resolve_privacy_filter_model() (lines 118-136) to substitute the MLX model ID with the equivalent Torch artifact—for example, "OpenMed/privacy-filter-mlx" becomes "openai/privacy-filter"—and emits a one-time UserWarning to inform you that the substitution occurred.

Can I force the MLX backend even on non-Apple hardware?

No. The is_available() check in openmed/core/backends.py (lines 82-90) prevents instantiation on non-Darwin platforms because the underlying mlx package cannot execute on non-Apple Silicon hardware. Attempting to import or initialize MLX components directly will raise import errors.

Are the outputs identical between MLX and Torch backends?

Yes. Both implementations conform to the HuggingFace token-classification schema, ensuring that openmed/core/quality_gates.py and other downstream components receive identical data structures regardless of which backend performs the inference. The create_privacy_filter_pipeline() wrapper (lines 146-162) standardizes all return formats.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →