def compute_patch_embeddings(
    samples,
    model,
    patches_field,
    embeddings_field=None,
    force_square=False,
    alpha=None,
    handle_missing="skip",
    batch_size=None,
    num_workers=None,
    skip_failures=True,
    progress=None,
):
    """Computes embeddings for the image patches defined by ``patches_field``
    of the samples in the collection using the given model.

    This method supports all the following cases:

    -   Using an image model to compute patch embeddings for an image
        collection
    -   Using an image model to compute frame patch embeddings for a video
        collection

    The ``model`` must expose embeddings, i.e., :meth:`Model.has_embeddings`
    must return ``True``.

    If an ``embeddings_field`` is provided, the embeddings are saved to the
    samples; otherwise, the embeddings are returned in-memory.

    Args:
        samples: a :class:`fiftyone.core.collections.SampleCollection`
        model: a :class:`Model`, Hugging Face Transformers model, Ultralytics
            model, SuperGradients model, or Lightning Flash model
        patches_field: the name of the field defining the image patches in each
            sample to embed. Must be of type
            :class:`fiftyone.core.labels.Detection`,
            :class:`fiftyone.core.labels.Detections`,
            :class:`fiftyone.core.labels.Polyline`, or
            :class:`fiftyone.core.labels.Polylines`. When computing video frame
            embeddings, the "frames." prefix is optional
        embeddings_field (None): the name of a label attribute in which to
            store the embeddings
        force_square (False): whether to minimally manipulate the patch
            bounding boxes into squares prior to extraction
        alpha (None): an optional expansion/contraction to apply to the patches
            before extracting them, in ``[-1, inf)``. If provided, the length
            and width of the box are expanded (or contracted, when
            ``alpha < 0``) by ``(100 * alpha)%``. For example, set
            ``alpha = 0.1`` to expand the boxes by 10%, and set
            ``alpha = -0.1`` to contract the boxes by 10%
        handle_missing ("skip"): how to handle images with no patches.
            Supported values are:

            -   "skip": skip the image and assign its embedding as ``None``
            -   "image": use the whole image as a single patch
            -   "error": raise an error

        batch_size (None): an optional batch size to use, if the model supports
            batching
        num_workers (None): the number of workers to use when loading images.
            Only applicable for Torch models
        skip_failures (True): whether to gracefully continue without raising an
            error if embeddings cannot be generated for a sample
        progress (None): whether to render a progress bar (True/False), use the
            default value ``fiftyone.config.show_progress_bars`` (None), or a
            progress callback function to invoke instead

    Returns:
        one of the following:

        -   ``None``, if an ``embeddings_field`` is provided
        -   a dict mapping sample IDs to ``num_patches x num_dim`` arrays of
            patch embeddings, when computing patch embeddings for image
            collections and no ``embeddings_field`` is provided. If
            ``skip_failures`` is ``True`` and any errors are detected, this
            dictionary will contain ``None`` values for any samples for which
            embeddings could not be computed
        -   a dict of dicts mapping sample IDs to frame numbers to
            ``num_patches x num_dim`` arrays of patch embeddings, when
            computing patch embeddings for the frames of video collections and
            no ``embeddings_field`` is provided. If ``skip_failures`` is
            ``True`` and any errors are detected, this nested dict will contain
            missing or ``None`` values to indicate uncomputable embeddings
    """
    model = _convert_model_if_necessary(model)

    if not isinstance(model, Model):
        raise ValueError("Unsupported model type: %s" % type(model))

    if not model.has_embeddings:
        raise ValueError(
            "Model must expose embeddings; found model.has_embeddings = %s"
            % model.has_embeddings
        )

    if model.media_type != "image":
        raise ValueError(
            "This method only supports image models; found "
            "model.media_type = %s" % model.media_type
        )

    _handle_missing_supported = {"skip", "image", "error"}
    if handle_missing not in _handle_missing_supported:
        raise ValueError(
            "Unsupported handle_missing = '%s'; supported values are %s"
            % (handle_missing, _handle_missing_supported)
        )

    process_video_frames = samples.media_type == fom.VIDEO

    use_data_loader = (
        isinstance(model, (SupportsGetItem, TorchModelMixin))
        and not process_video_frames
    )

    if num_workers is not None and not use_data_loader:
        logger.warning("Ignoring unsupported `num_workers` parameter")

    if samples.media_type == fom.IMAGE:
        fov.validate_image_collection(samples)
        fov.validate_collection_label_fields(
            samples, patches_field, _ALLOWED_PATCH_TYPES
        )
    elif samples.media_type == fom.VIDEO:
        patches_field, _ = samples._handle_frame_field(patches_field)
        fov.validate_collection_label_fields(
            samples,
            samples._FRAMES_PREFIX + patches_field,
            _ALLOWED_PATCH_TYPES,
        )
    elif samples.media_type == fom.GROUP:
        raise fom.SelectGroupSlicesError((fom.IMAGE, fom.VIDEO))
    else:
        raise fom.MediaTypeError(
            "Unsupported media type '%s'" % samples.media_type
        )

    if embeddings_field is not None:
        if "." in embeddings_field:
            raise ValueError(
                "Invalid `embeddings_field=%s`. Expected a label attribute "
                "name that contains no '.'" % embeddings_field
            )

        dataset = samples._dataset
        if dataset.media_type == fom.VIDEO:
            _, embeddings_path = dataset._get_label_field_path(
                dataset._FRAMES_PREFIX + patches_field, embeddings_field
            )
            embeddings_path, _ = dataset._handle_frame_field(embeddings_path)
            if not dataset.has_frame_field(embeddings_path):
                dataset.add_frame_field(embeddings_path, fof.VectorField)
        else:
            _, embeddings_path = dataset._get_label_field_path(
                patches_field, embeddings_field
            )
            if not dataset.has_sample_field(embeddings_path):
                dataset.add_sample_field(embeddings_path, fof.VectorField)

    with contextlib.ExitStack() as context:
        if use_data_loader:
            context.enter_context(fou.SetAttributes(model, preprocess=False))

        context.enter_context(model)

        batch_size = _parse_batch_size(batch_size, model, use_data_loader)

        if process_video_frames:
            return _embed_frame_patches(
                samples,
                model,
                patches_field,
                embeddings_field,
                force_square,
                alpha,
                handle_missing,
                batch_size,
                skip_failures,
                progress,
            )

        if use_data_loader:
            return _embed_patches_data_loader(
                samples,
                model,
                patches_field,
                embeddings_field,
                force_square,
                alpha,
                handle_missing,
                batch_size,
                num_workers,
                skip_failures,
                progress,
            )

        return _embed_patches(
            samples,
            model,
            patches_field,
            embeddings_field,
            force_square,
            alpha,
            handle_missing,
            batch_size,
            skip_failures,
            progress,
        )
Computes embeddings for the image patches defined by ``patches_field``
    of the samples in the collection using the given model.

    This method supports all the following cases:

    -   Using an image model to compute patch embeddings for an image
        collection
    -   Using an image model to compute frame patch embeddings for a video
        collection

    The ``model`` must expose embeddings, i.e., :meth:`Model.has_embeddings`
    must return ``True``.

    If an ``embeddings_field`` is provided, the embeddings are saved to the
    samples; otherwise, the embeddings are returned in-memory.

    Args:
        samples: a :class:`fiftyone.core.collections.SampleCollection`
        model: a :class:`Model`, Hugging Face Transformers model, Ultralytics
            model, SuperGradients model, or Lightning Flash model
        patches_field: the name of the field defining the image patches in each
            sample to embed. Must be of type
            :class:`fiftyone.core.labels.Detection`,
            :class:`fiftyone.core.labels.Detections`,
            :class:`fiftyone.core.labels.Polyline`, or
            :class:`fiftyone.core.labels.Polylines`. When computing video frame
            embeddings, the "frames." prefix is optional
        embeddings_field (None): the name of a label attribute in which to
            store the embeddings
        force_square (False): whether to minimally manipulate the patch
            bounding boxes into squares prior to extraction
        alpha (None): an optional expansion/contraction to apply to the patches
            before extracting them, in ``[-1, inf)``. If provided, the length
            and width of the box are expanded (or contracted, when
            ``alpha < 0``) by ``(100 * alpha)%``. For example, set
            ``alpha = 0.1`` to expand the boxes by 10%, and set
            ``alpha = -0.1`` to contract the boxes by 10%
        handle_missing ("skip"): how to handle images with no patches.
            Supported values are:

            -   "skip": skip the image and assign its embedding as ``None``
            -   "image": use the whole image as a single patch
            -   "error": raise an error

        batch_size (None): an optional batch size to use, if the model supports
            batching
        num_workers (None): the number of workers to use when loading images.
            Only applicable for Torch models
        skip_failures (True): whether to gracefully continue without raising an
            error if embeddings cannot be generated for a sample
        progress (None): whether to render a progress bar (True/False), use the
            default value ``fiftyone.config.show_progress_bars`` (None), or a
            progress callback function to invoke instead

    Returns:
        one of the following:

        -   ``None``, if an ``embeddings_field`` is provided
        -   a dict mapping sample IDs to ``num_patches x num_dim`` arrays of
            patch embeddings, when computing patch embeddings for image
            collections and no ``embeddings_field`` is provided. If
            ``skip_failures`` is ``True`` and any errors are detected, this
            dictionary will contain ``None`` values for any samples for which
            embeddings could not be computed
        -   a dict of dicts mapping sample IDs to frame numbers to
            ``num_patches x num_dim`` arrays of patch embeddings, when
            computing patch embeddings for the frames of video collections and
            no ``embeddings_field`` is provided. If ``skip_failures`` is
            ``True`` and any errors are detected, this nested dict will contain
            missing or ``None`` values to indicate uncomputable embeddings
    
fiftyone/core/models.py