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

> Discover how to enable MLX automatic fallback on non-Apple hardware in OpenMed. Learn how OpenMed intelligently routes MLX-only models for seamless operation across diverse platforms.

- Repository: [Maziyar Panahi/openmed](https://github.com/maziyarpanahi/openmed)
- Tags: how-to-guide
- Published: 2026-06-11

---

**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`](https://github.com/maziyarpanahi/openmed/blob/main/openmed/core/backends.py).

## How Platform Detection Gates MLX Execution

The fallback mechanism begins with platform-specific detection logic. In [`openmed/core/backends.py`](https://github.com/maziyarpanahi/openmed/blob/main/openmed/core/backends.py), the `MLXBackend.is_available()` method (lines 82-90) performs a hard platform check before attempting any imports.

```python

# 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`](https://github.com/maziyarpanahi/openmed/blob/main/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:**

```python
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:**

```python

# 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:**

```python

# 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`](https://github.com/maziyarpanahi/openmed/blob/main/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`](https://github.com/maziyarpanahi/openmed/blob/main/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`](https://github.com/maziyarpanahi/openmed/blob/main/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`](https://github.com/maziyarpanahi/openmed/blob/main/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.