---
description: Per-version migration guide for RF-DETR. Covers breaking changes and deprecated APIs for each release series.
---

# Migration Guide

Read each section between your current version and your target — every section covers
only the delta between two adjacent releases.

```
1.4.x  →  1.5 →  1.6  →  1.7  →  1.8  →  1.9
```

You can apply all changes in one go; working through sections one release at a time
and verifying between each step is optional but makes failures easier to isolate.
Deprecated APIs emit a `DeprecationWarning` until the version marked for removal.
See the [Changelog](../changelog.md) for the full list of changes in each release.

---

## Upgrade 1.8 → 1.9

### Breaking changes

!!! warning "Breaking: `albumentations` and `kornia` extras merged into `augment`"

    **PyPI extras renamed.** Default training/validation/prediction/export augmentations now use
    torchvision-native transforms, so `[train]` no longer installs Albumentations. Custom CPU
    (Albumentations) and GPU (Kornia) augmentation both live behind a single new `augment` extra.

    | Old extra                                | New extra               |
    | ---------------------------------------- | ----------------------- |
    | `rfdetr[train]` (implied albumentations) | `rfdetr[train,augment]` |
    | `rfdetr[kornia]`                         | `rfdetr[augment]`       |

    ```bash
    # Before
    pip install 'rfdetr[train]'    # bundled albumentations
    pip install 'rfdetr[kornia]'

    # After
    pip install 'rfdetr[train,augment]'   # custom aug_config or GPU backend
    pip install 'rfdetr[augment]'
    ```

!!! note "`augmentation_backend` values renamed"

    `augmentation_backend="tv"` and `"albu"` are renamed to `"torchvision"` and
    `"albumentations"`. The old strings (and `"gpu"`) still work as aliases, so no code
    changes are required — see [Augmentation Backend Values](../learn/train/augmentations.md#augmentation-backend-values)
    for the full accepted set.

!!! warning "Breaking: default resize interpolation changed — pixel values and mAP may shift"

    The default resize backend changed from Albumentations (cv2 `INTER_LINEAR`, no antialias) to
    torchvision (`BILINEAR` + `antialias=True`). Resized pixel values differ slightly from previous
    versions, and mAP may drift on existing benchmarks. **This affects training as well as
    validation and test preprocessing** — not just the training split.

    To restore the previous pixel-exact behaviour:

    ```bash
    pip install 'rfdetr[augment]'
    ```

    ```python
    from rfdetr.datasets.aug_configs import AUG_CONFIG

    train_config = TrainConfig(aug_config=AUG_CONFIG, ...)
    ```

    Installing `rfdetr[augment]` alone is **not** sufficient to pin this behaviour — with
    Albumentations installed, `augmentation_backend="auto"`/`"cpu"` (the default) auto-selects
    Albumentations for you, but identical code on a machine without `[augment]` installed silently
    falls back to torchvision instead. The only setting that pins resize behaviour regardless of
    what is installed is:

    ```python
    train_config = TrainConfig(augmentation_backend="torchvision", ...)
    ```

### Removed

The following APIs were deprecated in earlier releases and are removed as of v1.9. Update your code before upgrading.

!!! warning "Removed: `rfdetr.util.*` and `rfdetr.deploy.*` import paths"

    Deprecated since v1.6, removed in v1.9. Use the canonical replacements listed in the [Upgrade 1.5 → 1.6](#upgrade-15--16) section.

    ```python
    # These imports now raise ImportError; update to the canonical paths
    from rfdetr.util.coco_classes import COCO_CLASSES  # → rfdetr.assets.coco_classes
    from rfdetr.util.misc import get_rank  # → rfdetr.utilities
    from rfdetr.deploy import export_onnx  # → rfdetr.export.main
    ```

!!! warning "Removed: `build_namespace(model_config, train_config)`"

    Deprecated since v1.7, removed in v1.9. Use `build_model_from_config` and `build_criterion_from_config` instead.

!!! warning "Removed: `load_pretrain_weights(nn_model, model_config, train_config)` with `train_config`"

    Deprecated since v1.7, removed in v1.9. Drop the `train_config` positional argument.

!!! warning "Removed: `start_epoch` kwarg in `train()`"

    Deprecated since v1.7, removed in v1.9. PyTorch Lightning resumes automatically via `resume=`.

!!! warning "Removed: `do_benchmark` kwarg in `train()`"

    Deprecated since v1.7, removed in v1.9. Use the `rfdetr.export.benchmark` module instead.

!!! warning "Removed: `callbacks` dict kwarg in `train()`"

    Deprecated since v1.7, removed in v1.9. Pass PTL `Callback` objects directly via the Lightning API instead.

!!! warning "Removed: misplaced config fields"

    The following `TrainConfig` and `ModelConfig` fields moved to their correct config class in v1.7; the deprecated compatibility shims are removed in v1.9. Passing one of these fields on its old config class now raises a pydantic validation error:

    | Field               | Removed from  | Use in        |
    | ------------------- | ------------- | ------------- |
    | `group_detr`        | `TrainConfig` | `ModelConfig` |
    | `ia_bce_loss`       | `TrainConfig` | `ModelConfig` |
    | `segmentation_head` | `TrainConfig` | `ModelConfig` |
    | `num_select`        | `TrainConfig` | `ModelConfig` |
    | `cls_loss_coef`     | `ModelConfig` | `TrainConfig` |

!!! warning "Removed: `RFDETRLarge` silent fallback to deprecated Large config"

    `RFDETRLarge()` no longer catches checkpoint/config incompatibility errors and silently retries with `RFDETRLargeDeprecatedConfig`. Loading legacy deprecated-Large weights through `RFDETRLarge` now raises the original `ValueError`/`RuntimeError` instead of falling back. `RFDETRLargeDeprecated` itself is unaffected — use it directly to load those checkpoints.

    ```python
    # Before (silently retried with the deprecated config and logged a warning)
    model = RFDETRLarge(pretrain_weights="old_large_checkpoint.pth")

    # After
    from rfdetr import RFDETRLargeDeprecated

    model = RFDETRLargeDeprecated(pretrain_weights="old_large_checkpoint.pth")
    ```

### Deprecated in v1.9 → Remove in v1.11

!!! note "Deprecated: `RFDETR.optimize_for_inference()` renamed to `RFDETR.inference()`"

    **`optimize_for_inference(compile=..., batch_size=..., dtype=..., inplace=...)`** — renamed to
    `inference()` with the same signature.

    ```python
    # Before (deprecated)
    model.optimize_for_inference(dtype=torch.float16)

    # After
    model.inference(dtype=torch.float16)
    ```

!!! note "Deprecated: `TrainConfig.lr_drop` and `TrainConfig.lr_min_factor`"

    **`lr_drop` / `lr_min_factor`** — pass them through `lr_scheduler_kwargs` instead. For the managed
    `"step"` / `"cosine"` presets the fields are still folded into `lr_scheduler_kwargs` (with a
    `FutureWarning`); set with an explicit scheduler they are inert and warn.

    ```python
    # Before (deprecated)
    TrainConfig(lr_scheduler="step", lr_drop=80, lr_min_factor=0.1)

    # After
    TrainConfig(lr_scheduler="step", lr_scheduler_kwargs={"lr_drop": 80, "min_factor": 0.1})
    ```

---

## Upgrade 1.7 → 1.8

### Breaking changes

!!! note "Breaking in v1.8.2: default keypoint schema changed to active-first `[17]`"

    New checkpoints created from v1.8.2 onwards use `class_id=0` for person. Legacy `[0, 17]` checkpoints
    are still supported — RF-DETR auto-detects the schema from the checkpoint at load time.

    If your post-processing code offsets class IDs by 1 (common for background-first models), update it:

    ```python
    # Before (background-first [0, 17]: person was at class_id=1)
    class_name = "person" if detection.class_id == 1 else "other"

    # After (active-first [17]: person is at class_id=0)
    class_name = "person" if detection.class_id == 0 else "other"
    ```

    Use `detection.data["class_name"]` for schema-agnostic name resolution.

!!! warning "Breaking: `rfdetr.datasets.aug_config` renamed to `rfdetr.datasets.aug_configs`"

    The augmentation config module was renamed (singular → plural). If you import from it directly:

    ```python
    # Before
    from rfdetr.datasets.aug_config import AUG_AGGRESSIVE

    # After
    from rfdetr.datasets.aug_configs import AUG_AGGRESSIVE
    ```

    All preset constants (`AUG_AGGRESSIVE`, `AUG_CONSERVATIVE`, etc.) are unchanged.

!!! warning "Breaking: `supervision>=0.29.0` now required"

    Required for `sv.KeyPoints` support. `pip install rfdetr==1.8.0` pulls this automatically.
    If another dependency pins `supervision<0.29.0`, resolve the conflict manually.

!!! warning "Breaking: `pyDeprecate` constraint narrowed to `>=0.9,<0.10`"

    Was `>=0.6,<0.8`. If another package pins an older version, resolve with:

    ```bash
    pip install "rfdetr==1.8.0" "pyDeprecate>=0.9,<0.10"
    ```

---

## Upgrade 1.6 → 1.7

### Breaking changes

!!! warning "Breaking: `peft` removed from the default install"

    LoRA fine-tuning now requires the `lora` extra. If you use LoRA adapters during
    training, update your install command.

    ```bash
    # Before
    pip install rfdetr

    # After
    pip install 'rfdetr[lora]'
    ```

!!! warning "Breaking: `predict()` stores source image in `detections.metadata`"

    **`predict()` stores the source image in `detections.metadata`, not `detections.data`.**

    ```python
    # Before (1.6.4 and earlier)
    source = detections.data["source_image"]

    # After
    source = detections.metadata["source_image"]
    ```

!!! warning "Breaking: `pyDeprecate` constraint changed to `>=0.6,<0.8`"

    Was `>=0.3,<0.6`. If another package pins an older version, resolve with:

    ```bash
    pip install "rfdetr==1.7.0" "pyDeprecate>=0.6,<0.8"
    ```

### Deprecated in v1.7 → Remove in v1.9

!!! note "Deprecated: `build_namespace()` split into two functions"

    **`build_namespace(model_config, train_config)`** — use `build_model_from_config` or
    `build_criterion_from_config` instead.

    ```python
    # Before (deprecated)
    from rfdetr.models import build_namespace

    ns = build_namespace(model_config, train_config)

    # After
    from rfdetr.models import build_model_from_config, build_criterion_from_config

    model = build_model_from_config(model_config)
    criterion = build_criterion_from_config(model_config, train_config)
    ```

!!! note "Deprecated: `load_pretrain_weights()` no longer takes `train_config`"

    **`load_pretrain_weights(nn_model, model_config, train_config)`** — drop the
    `train_config` positional argument.

    ```python
    # Before (deprecated)
    from rfdetr.models import load_pretrain_weights

    load_pretrain_weights(nn_model, model_config, train_config)

    # After
    from rfdetr.models import load_pretrain_weights

    load_pretrain_weights(nn_model, model_config)
    ```

!!! note "Deprecated: config fields moved between `ModelConfig` and `TrainConfig`"

    **Config fields placed in the wrong config object.** Move them as shown:

    | Field               | Was in        | Move to       |
    | ------------------- | ------------- | ------------- |
    | `group_detr`        | `TrainConfig` | `ModelConfig` |
    | `ia_bce_loss`       | `TrainConfig` | `ModelConfig` |
    | `segmentation_head` | `TrainConfig` | `ModelConfig` |
    | `num_select`        | `TrainConfig` | `ModelConfig` |
    | `cls_loss_coef`     | `ModelConfig` | `TrainConfig` |

    ```python
    # Before (deprecated)
    train_config = TrainConfig(group_detr=13, cls_loss_coef=2.0)

    # After
    model_config = ModelConfig(group_detr=13)
    train_config = TrainConfig(cls_loss_coef=2.0)
    ```

### Deprecated in v1.7 → Remove in v2.0

!!! note "Deprecated: `RFDETRBase` replaced by size-specific classes"

    **`RFDETRBase`** defaulted to the small variant and is replaced by size-specific
    classes. Choose the variant that matches your previous model size. If you used
    `RFDETRBase()` without arguments, switch to `RFDETRSmall()`.

    ```python
    # Before (deprecated)
    from rfdetr import RFDETRBase

    model = RFDETRBase()

    # After — pick one
    from rfdetr import RFDETRNano, RFDETRSmall, RFDETRMedium, RFDETRLarge

    model = RFDETRSmall()
    ```

!!! note "Deprecated: `RFDETRSegPreview` replaced by size-specific segmentation classes"

    **`RFDETRSegPreview`** defaulted to the small variant and is replaced by size-specific
    segmentation classes. If you used `RFDETRSegPreview()` without arguments, switch to
    `RFDETRSegSmall()`.

    ```python
    # Before (deprecated)
    from rfdetr import RFDETRSegPreview

    model = RFDETRSegPreview()

    # After — pick one
    from rfdetr import RFDETRSegNano, RFDETRSegSmall, RFDETRSegMedium, RFDETRSegLarge

    model = RFDETRSegSmall()
    ```

---

## Upgrade 1.5 → 1.6

### Breaking changes

!!! warning "Breaking: `transformers` minimum version raised to `>=5.1.0`"

    **`transformers` minimum version raised to `>=5.1.0,<6.0.0`.**

    Projects pinned to `transformers<5.0.0` must upgrade. If upgrading is not possible,
    pin `rfdetr<1.6.0`.

    ```bash
    pip install 'transformers>=5.1.0,<6.0.0'
    ```

!!! warning "Breaking: PyPI extras renamed"

    **PyPI extras renamed.**

    Update your `pip install` commands and `requirements*.txt` files.

    | Old extra            | New extra         |
    | -------------------- | ----------------- |
    | `rfdetr[metrics]`    | `rfdetr[loggers]` |
    | `rfdetr[onnxexport]` | `rfdetr[onnx]`    |

    ```bash
    # Before
    pip install 'rfdetr[metrics]'
    pip install 'rfdetr[onnxexport]'

    # After
    pip install 'rfdetr[loggers]'
    pip install 'rfdetr[onnx]'
    ```

!!! warning "Breaking: `draw_synthetic_shape()` now returns a tuple"

    **`draw_synthetic_shape()` now returns `(image, polygon)` instead of `image`.**

    Update every call site that unpacks only the image.

    ```python
    # Before
    img = draw_synthetic_shape(...)

    # After
    img, polygon = draw_synthetic_shape(...)
    ```

### Deprecated in v1.6 → Removed in v1.8

!!! note "Deprecated: `simplify` and `force` arguments in `RFDETR.export()`"

    **`RFDETR.export(..., simplify=..., force=...)`** — both arguments are no-ops.
    Remove them from your calls.

    ```python
    # Before (deprecated)
    model.export("model.onnx", simplify=True, force=True)

    # After
    model.export("model.onnx")
    ```

### Deprecated in v1.6 → Remove in v1.9

!!! note "Deprecated: `rfdetr.util.*` and `rfdetr.deploy.*` import paths"

    Backward-compatibility shims are still active but emit `DeprecationWarning` on import.
    Replace with the canonical paths listed in the table below.

    | Deprecated module                 | Canonical replacement              |
    | --------------------------------- | ---------------------------------- |
    | `rfdetr.util.coco_classes`        | `rfdetr.assets.coco_classes`       |
    | `rfdetr.util.misc`                | `rfdetr.utilities`                 |
    | `rfdetr.util.logger`              | `rfdetr.utilities.logger`          |
    | `rfdetr.util.box_ops`             | `rfdetr.utilities.box_ops`         |
    | `rfdetr.util.files`               | `rfdetr.utilities.files`           |
    | `rfdetr.util.package`             | `rfdetr.utilities.package`         |
    | `rfdetr.util.get_param_dicts`     | `rfdetr.training.param_groups`     |
    | `rfdetr.util.drop_scheduler`      | `rfdetr.training.drop_schedule`    |
    | `rfdetr.util.visualize`           | `rfdetr.visualize.data`            |
    | `rfdetr.deploy`                   | `rfdetr.export`                    |
    | `rfdetr.models.segmentation_head` | `rfdetr.models.heads.segmentation` |

    **Examples:**

    ```python
    # Before (deprecated)
    from rfdetr.util.coco_classes import COCO_CLASSES
    from rfdetr.util.misc import get_rank, get_world_size, is_main_process, save_on_master
    from rfdetr.util.logger import get_logger
    from rfdetr.util.box_ops import box_cxcywh_to_xyxy, generalized_box_iou
    from rfdetr.util.get_param_dicts import get_param_dict
    from rfdetr.util.drop_scheduler import drop_scheduler
    from rfdetr.util.visualize import save_gt_predictions_visualization
    from rfdetr.deploy import export_onnx
    from rfdetr.models.segmentation_head import SegmentationHead

    # After
    from rfdetr.assets.coco_classes import COCO_CLASSES
    from rfdetr.utilities.distributed import get_rank, get_world_size, is_main_process, save_on_master
    from rfdetr.utilities.logger import get_logger
    from rfdetr.utilities.box_ops import box_cxcywh_to_xyxy, generalized_box_iou
    from rfdetr.training.param_groups import get_param_dict
    from rfdetr.training.drop_schedule import drop_scheduler
    from rfdetr.visualize.data import save_gt_predictions_visualization
    from rfdetr.export.main import export_onnx
    from rfdetr.models.heads.segmentation import SegmentationHead
    ```

---

## Upgrade 1.4 → 1.5

### Breaking changes

!!! warning "Breaking: `ModelConfig` rejects unknown keyword arguments"

    **`ModelConfig` now raises `ValidationError` on unknown keyword arguments.**

    Previously, unrecognised fields were silently ignored. Remove or rename any
    unrecognised keys you pass to `ModelConfig(...)`.

    ```python
    # Before — silently accepted
    config = ModelConfig(unknown_field=True)

    # Now raises ValidationError — remove the unknown key
    config = ModelConfig()
    ```

### Deprecated in v1.5 → Removed in v1.7

!!! note "Deprecated: `OPEN_SOURCE_MODELS` replaced by `ModelWeights` enum"

    **`OPEN_SOURCE_MODELS` constant** — use the `ModelWeights` enum instead. A
    `DeprecationWarning` is emitted on access. See the
    [API reference](../reference/rfdetr.md) for available enum values.

    ```python
    # Before (deprecated)
    from rfdetr import OPEN_SOURCE_MODELS

    # After
    from rfdetr.assets.model_weights import ModelWeights
    ```
