Skip to content

feature_flags

ReasonTypeVar module-attribute

ReasonTypeVar = TypeVar('ReasonTypeVar', bound=str)

RESULT_RETURN_METHOD

Bases: StrEnum

The method of returning results from a worker.

Source code in horde_sdk/worker/feature_flags.py
class RESULT_RETURN_METHOD(StrEnum):
    """The method of returning results from a worker."""

    base64_post_back = auto()
    """Base64 post back in the 'job completed' message."""

    base64_post_back_with_url = auto()
    """Base64 post back to a given URL without results in the 'job completed' message."""

    byte_stream = auto()
    """Byte stream to a given URL without results in the 'job completed' message."""

    local_write_to_file = auto()
    """Can write to the local filesystem for jobs originating locally or within a closed environment."""

base64_post_back class-attribute instance-attribute

base64_post_back = auto()

Base64 post back in the 'job completed' message.

base64_post_back_with_url class-attribute instance-attribute

base64_post_back_with_url = auto()

Base64 post back to a given URL without results in the 'job completed' message.

byte_stream class-attribute instance-attribute

byte_stream = auto()

Byte stream to a given URL without results in the 'job completed' message.

local_write_to_file class-attribute instance-attribute

local_write_to_file = auto()

Can write to the local filesystem for jobs originating locally or within a closed environment.

WorkerFeatureFlags

Bases: ABC, BaseModel

Feature flags for a worker.

Source code in horde_sdk/worker/feature_flags.py
class WorkerFeatureFlags[ReasonTypeVar: str](ABC, BaseModel):
    """Feature flags for a worker."""

    model_config = get_default_frozen_model_config_dict()

    supported_result_return_methods: list[RESULT_RETURN_METHOD] = Field(default_factory=list)
    """The methods of returning results supported by the worker."""

    supports_threads: bool = Field(default=False)
    """Whether the worker supports threading."""

    def is_capable_of_features(self, features: GenerationFeatureFlags) -> bool:
        """Check if the worker is capable of handling the requested features.

        Args:
            features (GenerationFeatureFlags): The features to check.

        Returns:
            bool: True if the worker is capable of handling the requested features, False otherwise.
        """
        return not self.reasons_not_capable_of_features(features)

    @abstractmethod
    def get_not_capable_reason_type(self) -> type[ReasonTypeVar]:
        """Return the type of the reason for not being capable of handling the requested features.

        Returns:
            type[ReasonTypeVar]: The (python) type of the reason for not being capable of handling the requested
            features.
        """

    @abstractmethod
    def reasons_not_capable_of_features(
        self,
        features: GenerationFeatureFlags,
    ) -> list[ReasonTypeVar] | None:
        """Return a list of reasons why the worker is not capable of handling the requested features.

        Args:
            features (GenerationFeatureFlags): The features to check.

        Returns:
            list[str] | None: A list of reasons why the worker is not capable of handling the requested features,
            or None if the worker is capable.
        """

model_config class-attribute instance-attribute

model_config = get_default_frozen_model_config_dict()

supported_result_return_methods class-attribute instance-attribute

supported_result_return_methods: list[
    RESULT_RETURN_METHOD
] = Field(default_factory=list)

The methods of returning results supported by the worker.

supports_threads class-attribute instance-attribute

supports_threads: bool = Field(default=False)

Whether the worker supports threading.

is_capable_of_features

is_capable_of_features(
    features: GenerationFeatureFlags,
) -> bool

Check if the worker is capable of handling the requested features.

Parameters:

Returns:

  • bool ( bool ) –

    True if the worker is capable of handling the requested features, False otherwise.

Source code in horde_sdk/worker/feature_flags.py
def is_capable_of_features(self, features: GenerationFeatureFlags) -> bool:
    """Check if the worker is capable of handling the requested features.

    Args:
        features (GenerationFeatureFlags): The features to check.

    Returns:
        bool: True if the worker is capable of handling the requested features, False otherwise.
    """
    return not self.reasons_not_capable_of_features(features)

get_not_capable_reason_type abstractmethod

get_not_capable_reason_type() -> type[ReasonTypeVar]

Return the type of the reason for not being capable of handling the requested features.

Returns:

  • type[ReasonTypeVar]

    type[ReasonTypeVar]: The (python) type of the reason for not being capable of handling the requested

  • type[ReasonTypeVar]

    features.

Source code in horde_sdk/worker/feature_flags.py
@abstractmethod
def get_not_capable_reason_type(self) -> type[ReasonTypeVar]:
    """Return the type of the reason for not being capable of handling the requested features.

    Returns:
        type[ReasonTypeVar]: The (python) type of the reason for not being capable of handling the requested
        features.
    """

reasons_not_capable_of_features abstractmethod

reasons_not_capable_of_features(
    features: GenerationFeatureFlags,
) -> list[ReasonTypeVar] | None

Return a list of reasons why the worker is not capable of handling the requested features.

Parameters:

Returns:

  • list[ReasonTypeVar] | None

    list[str] | None: A list of reasons why the worker is not capable of handling the requested features,

  • list[ReasonTypeVar] | None

    or None if the worker is capable.

Source code in horde_sdk/worker/feature_flags.py
@abstractmethod
def reasons_not_capable_of_features(
    self,
    features: GenerationFeatureFlags,
) -> list[ReasonTypeVar] | None:
    """Return a list of reasons why the worker is not capable of handling the requested features.

    Args:
        features (GenerationFeatureFlags): The features to check.

    Returns:
        list[str] | None: A list of reasons why the worker is not capable of handling the requested features,
        or None if the worker is capable.
    """

PerBaselineFeatureFlags

Bases: BaseModel

Feature flags for a worker per baseline.

Source code in horde_sdk/worker/feature_flags.py
class PerBaselineFeatureFlags(BaseModel):
    """Feature flags for a worker per baseline."""

    model_config = get_default_frozen_model_config_dict()

    schedulers_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, list[KNOWN_IMAGE_SCHEDULERS | str]] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: [
                    KNOWN_IMAGE_SCHEDULERS.simple,
                    KNOWN_IMAGE_SCHEDULERS.normal,
                    KNOWN_IMAGE_SCHEDULERS.exponential,
                ],
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: [
                    KNOWN_IMAGE_SCHEDULERS.simple,
                ],
            },
        ],
    )
    """If set, the supported schedulers for each baseline. If unset, it is assumed that all baselines
    support all schedulers."""

    samplers_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, list[KNOWN_IMAGE_SAMPLERS | str]] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: [
                    KNOWN_IMAGE_SAMPLERS.k_lms,
                    KNOWN_IMAGE_SAMPLERS.k_dpm_2,
                    KNOWN_IMAGE_SAMPLERS.k_euler,
                ],
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: [
                    KNOWN_IMAGE_SAMPLERS.k_lms,
                ],
            },
        ],
    )
    """If set, the supported samplers for each baseline. If unset, it is assumed that all baselines
    support all samplers."""

    tiling_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: True,
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: False,
            },
        ],
    )
    """If set, the supported tiling for each baseline. If unset, it is assumed that all baselines
    support tiling."""

    hires_fix_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: True,
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: True,
                KNOWN_IMAGE_GENERATION_BASELINE.flux_1: False,
            },
        ],
    )
    """If set, the supported hires fix for each baseline. If unset, it is assumed that all baselines
    support hires fix."""

    controlnet_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: True,
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: False,
            },
        ],
    )
    """If set, support for controlnet for each baseline. If unset, it is assumed that all baselines
    support controlnets."""

    tis_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: True,
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: False,
            },
        ],
    )
    """If set, support for TIs for each baseline. If unset, it is assumed that all baselines support
    TIs."""

    loras_map: dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None = Field(
        default=None,
        examples=[
            {
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_1: True,
                KNOWN_IMAGE_GENERATION_BASELINE.stable_diffusion_xl: False,
            },
        ],
    )
    """If set, support for Loras for each baseline. If unset, it is assumed that all baselines
    support Loras."""

model_config class-attribute instance-attribute

model_config = get_default_frozen_model_config_dict()

schedulers_map class-attribute instance-attribute

schedulers_map: (
    dict[
        KNOWN_IMAGE_GENERATION_BASELINE | str,
        list[KNOWN_IMAGE_SCHEDULERS | str],
    ]
    | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: [
                simple,
                normal,
                exponential,
            ],
            stable_diffusion_xl: [simple],
        }
    ],
)

If set, the supported schedulers for each baseline. If unset, it is assumed that all baselines support all schedulers.

samplers_map class-attribute instance-attribute

samplers_map: (
    dict[
        KNOWN_IMAGE_GENERATION_BASELINE | str,
        list[KNOWN_IMAGE_SAMPLERS | str],
    ]
    | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: [k_lms, k_dpm_2, k_euler],
            stable_diffusion_xl: [k_lms],
        }
    ],
)

If set, the supported samplers for each baseline. If unset, it is assumed that all baselines support all samplers.

tiling_map class-attribute instance-attribute

tiling_map: (
    dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: True,
            stable_diffusion_xl: False,
        }
    ],
)

If set, the supported tiling for each baseline. If unset, it is assumed that all baselines support tiling.

hires_fix_map class-attribute instance-attribute

hires_fix_map: (
    dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: True,
            stable_diffusion_xl: True,
            flux_1: False,
        }
    ],
)

If set, the supported hires fix for each baseline. If unset, it is assumed that all baselines support hires fix.

controlnet_map class-attribute instance-attribute

controlnet_map: (
    dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: True,
            stable_diffusion_xl: False,
        }
    ],
)

If set, support for controlnet for each baseline. If unset, it is assumed that all baselines support controlnets.

tis_map class-attribute instance-attribute

tis_map: (
    dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: True,
            stable_diffusion_xl: False,
        }
    ],
)

If set, support for TIs for each baseline. If unset, it is assumed that all baselines support TIs.

loras_map class-attribute instance-attribute

loras_map: (
    dict[KNOWN_IMAGE_GENERATION_BASELINE | str, bool] | None
) = Field(
    default=None,
    examples=[
        {
            stable_diffusion_1: True,
            stable_diffusion_xl: False,
        }
    ],
)

If set, support for Loras for each baseline. If unset, it is assumed that all baselines support Loras.

IMAGE_WORKER_NOT_CAPABLE_REASON

Bases: StrEnum

Reasons why a worker is not capable of handling a request.

Source code in horde_sdk/worker/feature_flags.py
class IMAGE_WORKER_NOT_CAPABLE_REASON(StrEnum):
    """Reasons why a worker is not capable of handling a request."""

    clip_skip = auto()
    """The worker does not support clip skip."""

    samplers = auto()
    """The worker does not support the requested samplers."""

    schedulers = auto()
    """The worker does not support the requested schedulers."""

    tiling = auto()
    """The worker does not support tiling."""

    hires_fix = auto()
    """The worker does not support hires fix."""

    controlnets = auto()
    """The worker does not support controlnets."""

    tis = auto()
    """The worker does not support TIs."""

    loras = auto()
    """The worker does not support Loras."""

    extra_texts = auto()
    """The worker does not support extra texts."""

    extra_source_images = auto()
    """The worker does not support extra source images."""

    unsupported_baseline = auto()
    """The worker does not support the requested baseline."""

clip_skip class-attribute instance-attribute

clip_skip = auto()

The worker does not support clip skip.

samplers class-attribute instance-attribute

samplers = auto()

The worker does not support the requested samplers.

schedulers class-attribute instance-attribute

schedulers = auto()

The worker does not support the requested schedulers.

tiling class-attribute instance-attribute

tiling = auto()

The worker does not support tiling.

hires_fix class-attribute instance-attribute

hires_fix = auto()

The worker does not support hires fix.

controlnets class-attribute instance-attribute

controlnets = auto()

The worker does not support controlnets.

tis class-attribute instance-attribute

tis = auto()

The worker does not support TIs.

loras class-attribute instance-attribute

loras = auto()

The worker does not support Loras.

extra_texts class-attribute instance-attribute

extra_texts = auto()

The worker does not support extra texts.

extra_source_images class-attribute instance-attribute

extra_source_images = auto()

The worker does not support extra source images.

unsupported_baseline class-attribute instance-attribute

unsupported_baseline = auto()

The worker does not support the requested baseline.

ImageWorkerFeatureFlags

Bases: WorkerFeatureFlags[IMAGE_WORKER_NOT_CAPABLE_REASON]

Feature flags for an image worker.

Source code in horde_sdk/worker/feature_flags.py
class ImageWorkerFeatureFlags(WorkerFeatureFlags[IMAGE_WORKER_NOT_CAPABLE_REASON]):
    """Feature flags for an image worker."""

    image_generation_feature_flags: ImageGenerationFeatureFlags
    """The image generation feature flags for the worker."""

    per_baseline_feature_flags: PerBaselineFeatureFlags | None = None
    """The per baseline feature flags for the worker. This includes the supported schedulers and
    samplers for each baseline."""

    backend_clip_skip_representation: CLIP_SKIP_REPRESENTATION | None = None
    """The clip skip representation supported."""

    @override
    def get_not_capable_reason_type(self) -> type[IMAGE_WORKER_NOT_CAPABLE_REASON]:
        return IMAGE_WORKER_NOT_CAPABLE_REASON

    @override
    def reasons_not_capable_of_features(
        self,
        request: GenerationFeatureFlags,
    ) -> list[IMAGE_WORKER_NOT_CAPABLE_REASON] | None:
        """Return a list of reasons why a worker is not capable of handling a request."""
        if not isinstance(request, ImageGenerationFeatureFlags):
            logger.debug(f"Request is not an ImageGenerationFeatureFlags instance. Request type: {type(request)}")
            return None

        reasons = []

        if request.clip_skip and not self.image_generation_feature_flags.clip_skip:
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.clip_skip)

        if not self.worker_supports_requested_samplers(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.samplers)

        if not self.worker_supports_requested_schedulers(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.schedulers)

        if not self.worker_supports_requested_tiling(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.tiling)

        if not self.worker_supports_requested_hires_fix(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.hires_fix)

        if not self.worker_supports_requested_controlnets(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.controlnets)

        if not self.worker_supports_requested_tis(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.tis)

        if not self.worker_supports_requested_loras(request):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.loras)

        if request.extra_texts and not self.image_generation_feature_flags.extra_texts:
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.extra_texts)

        if request.extra_source_images and not self.image_generation_feature_flags.extra_source_images:
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.extra_source_images)

        if (
            request.baselines
            and self.image_generation_feature_flags.baselines
            and (not any(baseline in self.image_generation_feature_flags.baselines for baseline in request.baselines))
        ):
            reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.unsupported_baseline)

        return reasons if reasons else None

    def worker_supports_requested_samplers(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports the samplers requested."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.samplers_map:
            for baseline in request.baselines or []:
                if any(
                    sampler not in self.per_baseline_feature_flags.samplers_map.get(baseline, [])
                    for sampler in request.samplers
                ):
                    return False
        else:
            if any(sampler not in self.image_generation_feature_flags.samplers for sampler in request.samplers):
                return False
        return True

    def worker_supports_requested_schedulers(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports the schedulers requested."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.schedulers_map:
            for baseline in request.baselines or []:
                if any(
                    scheduler not in self.per_baseline_feature_flags.schedulers_map.get(baseline, [])
                    for scheduler in request.schedulers
                ):
                    return False
        else:
            if any(
                scheduler not in self.image_generation_feature_flags.schedulers for scheduler in request.schedulers
            ):
                return False
        return True

    def worker_supports_requested_tiling(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports tiling."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.tiling_map:
            for baseline in request.baselines or []:
                if not self.per_baseline_feature_flags.tiling_map.get(baseline, True):
                    return False
        else:
            if request.tiling and not self.image_generation_feature_flags.tiling:
                return False
        return True

    def worker_supports_requested_hires_fix(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports hires fix."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.hires_fix_map:
            for baseline in request.baselines or []:
                if not self.per_baseline_feature_flags.hires_fix_map.get(baseline, True):
                    return False
        else:
            if request.hires_fix and not self.image_generation_feature_flags.hires_fix:
                return False
        return True

    def worker_supports_requested_controlnets(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports controlnets."""
        if not request.controlnets_feature_flags:
            return True

        if not self.image_generation_feature_flags.controlnets_feature_flags:
            return False

        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.controlnet_map:
            for baseline in request.baselines or []:
                if not self.per_baseline_feature_flags.controlnet_map.get(baseline, True):
                    return False

        if (
            request.controlnets_feature_flags.image_is_control
            and not self.image_generation_feature_flags.controlnets_feature_flags.image_is_control
        ):
            return False

        if (  # noqa SIM103: For readability, we return this False directly
            request.controlnets_feature_flags.return_control_map
            and not self.image_generation_feature_flags.controlnets_feature_flags.return_control_map
        ):
            return False

        return True

    def worker_supports_requested_tis(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports TIs."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.tis_map:
            for baseline in request.baselines or []:
                if not self.per_baseline_feature_flags.tis_map.get(baseline, True):
                    return False
        else:
            if request.tis and not self.image_generation_feature_flags.tis:
                return False
        return True

    def worker_supports_requested_loras(
        self,
        request: ImageGenerationFeatureFlags,
    ) -> bool:
        """Return True if the worker supports Loras."""
        if self.per_baseline_feature_flags and self.per_baseline_feature_flags.loras_map:
            for baseline in request.baselines or []:
                if not self.per_baseline_feature_flags.loras_map.get(baseline, True):
                    return False
        else:
            if request.loras and not self.image_generation_feature_flags.loras:
                return False
        return True

image_generation_feature_flags instance-attribute

image_generation_feature_flags: ImageGenerationFeatureFlags

The image generation feature flags for the worker.

per_baseline_feature_flags class-attribute instance-attribute

per_baseline_feature_flags: (
    PerBaselineFeatureFlags | None
) = None

The per baseline feature flags for the worker. This includes the supported schedulers and samplers for each baseline.

backend_clip_skip_representation class-attribute instance-attribute

backend_clip_skip_representation: (
    CLIP_SKIP_REPRESENTATION | None
) = None

The clip skip representation supported.

model_config class-attribute instance-attribute

model_config = get_default_frozen_model_config_dict()

supported_result_return_methods class-attribute instance-attribute

supported_result_return_methods: list[
    RESULT_RETURN_METHOD
] = Field(default_factory=list)

The methods of returning results supported by the worker.

supports_threads class-attribute instance-attribute

supports_threads: bool = Field(default=False)

Whether the worker supports threading.

get_not_capable_reason_type

get_not_capable_reason_type() -> (
    type[IMAGE_WORKER_NOT_CAPABLE_REASON]
)
Source code in horde_sdk/worker/feature_flags.py
@override
def get_not_capable_reason_type(self) -> type[IMAGE_WORKER_NOT_CAPABLE_REASON]:
    return IMAGE_WORKER_NOT_CAPABLE_REASON

reasons_not_capable_of_features

reasons_not_capable_of_features(
    request: GenerationFeatureFlags,
) -> list[IMAGE_WORKER_NOT_CAPABLE_REASON] | None

Return a list of reasons why a worker is not capable of handling a request.

Source code in horde_sdk/worker/feature_flags.py
@override
def reasons_not_capable_of_features(
    self,
    request: GenerationFeatureFlags,
) -> list[IMAGE_WORKER_NOT_CAPABLE_REASON] | None:
    """Return a list of reasons why a worker is not capable of handling a request."""
    if not isinstance(request, ImageGenerationFeatureFlags):
        logger.debug(f"Request is not an ImageGenerationFeatureFlags instance. Request type: {type(request)}")
        return None

    reasons = []

    if request.clip_skip and not self.image_generation_feature_flags.clip_skip:
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.clip_skip)

    if not self.worker_supports_requested_samplers(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.samplers)

    if not self.worker_supports_requested_schedulers(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.schedulers)

    if not self.worker_supports_requested_tiling(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.tiling)

    if not self.worker_supports_requested_hires_fix(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.hires_fix)

    if not self.worker_supports_requested_controlnets(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.controlnets)

    if not self.worker_supports_requested_tis(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.tis)

    if not self.worker_supports_requested_loras(request):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.loras)

    if request.extra_texts and not self.image_generation_feature_flags.extra_texts:
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.extra_texts)

    if request.extra_source_images and not self.image_generation_feature_flags.extra_source_images:
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.extra_source_images)

    if (
        request.baselines
        and self.image_generation_feature_flags.baselines
        and (not any(baseline in self.image_generation_feature_flags.baselines for baseline in request.baselines))
    ):
        reasons.append(IMAGE_WORKER_NOT_CAPABLE_REASON.unsupported_baseline)

    return reasons if reasons else None

worker_supports_requested_samplers

worker_supports_requested_samplers(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports the samplers requested.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_samplers(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports the samplers requested."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.samplers_map:
        for baseline in request.baselines or []:
            if any(
                sampler not in self.per_baseline_feature_flags.samplers_map.get(baseline, [])
                for sampler in request.samplers
            ):
                return False
    else:
        if any(sampler not in self.image_generation_feature_flags.samplers for sampler in request.samplers):
            return False
    return True

worker_supports_requested_schedulers

worker_supports_requested_schedulers(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports the schedulers requested.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_schedulers(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports the schedulers requested."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.schedulers_map:
        for baseline in request.baselines or []:
            if any(
                scheduler not in self.per_baseline_feature_flags.schedulers_map.get(baseline, [])
                for scheduler in request.schedulers
            ):
                return False
    else:
        if any(
            scheduler not in self.image_generation_feature_flags.schedulers for scheduler in request.schedulers
        ):
            return False
    return True

worker_supports_requested_tiling

worker_supports_requested_tiling(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports tiling.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_tiling(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports tiling."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.tiling_map:
        for baseline in request.baselines or []:
            if not self.per_baseline_feature_flags.tiling_map.get(baseline, True):
                return False
    else:
        if request.tiling and not self.image_generation_feature_flags.tiling:
            return False
    return True

worker_supports_requested_hires_fix

worker_supports_requested_hires_fix(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports hires fix.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_hires_fix(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports hires fix."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.hires_fix_map:
        for baseline in request.baselines or []:
            if not self.per_baseline_feature_flags.hires_fix_map.get(baseline, True):
                return False
    else:
        if request.hires_fix and not self.image_generation_feature_flags.hires_fix:
            return False
    return True

worker_supports_requested_controlnets

worker_supports_requested_controlnets(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports controlnets.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_controlnets(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports controlnets."""
    if not request.controlnets_feature_flags:
        return True

    if not self.image_generation_feature_flags.controlnets_feature_flags:
        return False

    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.controlnet_map:
        for baseline in request.baselines or []:
            if not self.per_baseline_feature_flags.controlnet_map.get(baseline, True):
                return False

    if (
        request.controlnets_feature_flags.image_is_control
        and not self.image_generation_feature_flags.controlnets_feature_flags.image_is_control
    ):
        return False

    if (  # noqa SIM103: For readability, we return this False directly
        request.controlnets_feature_flags.return_control_map
        and not self.image_generation_feature_flags.controlnets_feature_flags.return_control_map
    ):
        return False

    return True

worker_supports_requested_tis

worker_supports_requested_tis(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports TIs.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_tis(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports TIs."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.tis_map:
        for baseline in request.baselines or []:
            if not self.per_baseline_feature_flags.tis_map.get(baseline, True):
                return False
    else:
        if request.tis and not self.image_generation_feature_flags.tis:
            return False
    return True

worker_supports_requested_loras

worker_supports_requested_loras(
    request: ImageGenerationFeatureFlags,
) -> bool

Return True if the worker supports Loras.

Source code in horde_sdk/worker/feature_flags.py
def worker_supports_requested_loras(
    self,
    request: ImageGenerationFeatureFlags,
) -> bool:
    """Return True if the worker supports Loras."""
    if self.per_baseline_feature_flags and self.per_baseline_feature_flags.loras_map:
        for baseline in request.baselines or []:
            if not self.per_baseline_feature_flags.loras_map.get(baseline, True):
                return False
    else:
        if request.loras and not self.image_generation_feature_flags.loras:
            return False
    return True

is_capable_of_features

is_capable_of_features(
    features: GenerationFeatureFlags,
) -> bool

Check if the worker is capable of handling the requested features.

Parameters:

Returns:

  • bool ( bool ) –

    True if the worker is capable of handling the requested features, False otherwise.

Source code in horde_sdk/worker/feature_flags.py
def is_capable_of_features(self, features: GenerationFeatureFlags) -> bool:
    """Check if the worker is capable of handling the requested features.

    Args:
        features (GenerationFeatureFlags): The features to check.

    Returns:
        bool: True if the worker is capable of handling the requested features, False otherwise.
    """
    return not self.reasons_not_capable_of_features(features)

ALCHEMY_WORKER_NOT_CAPABLE_REASON

Bases: StrEnum

Reasons why a worker is not capable of handling an alchemy request.

Source code in horde_sdk/worker/feature_flags.py
class ALCHEMY_WORKER_NOT_CAPABLE_REASON(StrEnum):
    """Reasons why a worker is not capable of handling an alchemy request."""

    unsupported_upscaler = auto()
    """The worker does not support a requested upscaler."""

    unsupported_facefixer = auto()
    """The worker does not support a requested facefixer."""

    unsupported_interrogator = auto()
    """The worker does not support a requested interrogator."""

    unsupported_caption_model = auto()
    """The worker does not support a requested caption model."""

    unsupported_nsfw_detector = auto()
    """The worker does not support a requested NSFW detector."""

    unsupported_misc = auto()
    """The worker does not support a requested miscellaneous feature."""

unsupported_upscaler class-attribute instance-attribute

unsupported_upscaler = auto()

The worker does not support a requested upscaler.

unsupported_facefixer class-attribute instance-attribute

unsupported_facefixer = auto()

The worker does not support a requested facefixer.

unsupported_interrogator class-attribute instance-attribute

unsupported_interrogator = auto()

The worker does not support a requested interrogator.

unsupported_caption_model class-attribute instance-attribute

unsupported_caption_model = auto()

The worker does not support a requested caption model.

unsupported_nsfw_detector class-attribute instance-attribute

unsupported_nsfw_detector = auto()

The worker does not support a requested NSFW detector.

unsupported_misc class-attribute instance-attribute

unsupported_misc = auto()

The worker does not support a requested miscellaneous feature.

AlchemyWorkerFeatureFlags

Bases: WorkerFeatureFlags[ALCHEMY_WORKER_NOT_CAPABLE_REASON]

Feature flags for an alchemy worker.

Source code in horde_sdk/worker/feature_flags.py
class AlchemyWorkerFeatureFlags(WorkerFeatureFlags[ALCHEMY_WORKER_NOT_CAPABLE_REASON]):
    """Feature flags for an alchemy worker."""

    alchemy_feature_flags: AlchemyFeatureFlags

    @override
    def get_not_capable_reason_type(self) -> type[ALCHEMY_WORKER_NOT_CAPABLE_REASON]:
        return ALCHEMY_WORKER_NOT_CAPABLE_REASON

    @override
    def reasons_not_capable_of_features(
        self,
        request: GenerationFeatureFlags,
    ) -> list[ALCHEMY_WORKER_NOT_CAPABLE_REASON] | None:
        """Return a list of reasons why a worker is not capable of handling an alchemy request."""
        if not isinstance(request, AlchemyFeatureFlags):
            logger.debug(f"Request is not an AlchemyFeatureFlags instance. Request type: {type(request)}")
            return None

        if not self.alchemy_feature_flags:
            logger.debug("Worker does not have alchemy feature flags.")
            return None

        if not request.alchemy_types:
            logger.debug("Request does not have alchemy types.")
            return None

        reasons = []

        for alchemy_type in request.alchemy_types:
            if alchemy_type not in self.alchemy_feature_flags.alchemy_types:
                if is_upscaler_form(alchemy_type):
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_upscaler)
                elif is_facefixer_form(alchemy_type):
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_facefixer)
                elif is_interrogator_form(alchemy_type):
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_interrogator)
                elif is_caption_form(alchemy_type):
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_caption_model)
                elif is_nsfw_detector_form(alchemy_type):
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_nsfw_detector)
                else:
                    reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_misc)
        return reasons if reasons else None

alchemy_feature_flags instance-attribute

alchemy_feature_flags: AlchemyFeatureFlags

model_config class-attribute instance-attribute

model_config = get_default_frozen_model_config_dict()

supported_result_return_methods class-attribute instance-attribute

supported_result_return_methods: list[
    RESULT_RETURN_METHOD
] = Field(default_factory=list)

The methods of returning results supported by the worker.

supports_threads class-attribute instance-attribute

supports_threads: bool = Field(default=False)

Whether the worker supports threading.

get_not_capable_reason_type

get_not_capable_reason_type() -> (
    type[ALCHEMY_WORKER_NOT_CAPABLE_REASON]
)
Source code in horde_sdk/worker/feature_flags.py
@override
def get_not_capable_reason_type(self) -> type[ALCHEMY_WORKER_NOT_CAPABLE_REASON]:
    return ALCHEMY_WORKER_NOT_CAPABLE_REASON

reasons_not_capable_of_features

reasons_not_capable_of_features(
    request: GenerationFeatureFlags,
) -> list[ALCHEMY_WORKER_NOT_CAPABLE_REASON] | None

Return a list of reasons why a worker is not capable of handling an alchemy request.

Source code in horde_sdk/worker/feature_flags.py
@override
def reasons_not_capable_of_features(
    self,
    request: GenerationFeatureFlags,
) -> list[ALCHEMY_WORKER_NOT_CAPABLE_REASON] | None:
    """Return a list of reasons why a worker is not capable of handling an alchemy request."""
    if not isinstance(request, AlchemyFeatureFlags):
        logger.debug(f"Request is not an AlchemyFeatureFlags instance. Request type: {type(request)}")
        return None

    if not self.alchemy_feature_flags:
        logger.debug("Worker does not have alchemy feature flags.")
        return None

    if not request.alchemy_types:
        logger.debug("Request does not have alchemy types.")
        return None

    reasons = []

    for alchemy_type in request.alchemy_types:
        if alchemy_type not in self.alchemy_feature_flags.alchemy_types:
            if is_upscaler_form(alchemy_type):
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_upscaler)
            elif is_facefixer_form(alchemy_type):
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_facefixer)
            elif is_interrogator_form(alchemy_type):
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_interrogator)
            elif is_caption_form(alchemy_type):
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_caption_model)
            elif is_nsfw_detector_form(alchemy_type):
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_nsfw_detector)
            else:
                reasons.append(ALCHEMY_WORKER_NOT_CAPABLE_REASON.unsupported_misc)
    return reasons if reasons else None

is_capable_of_features

is_capable_of_features(
    features: GenerationFeatureFlags,
) -> bool

Check if the worker is capable of handling the requested features.

Parameters:

Returns:

  • bool ( bool ) –

    True if the worker is capable of handling the requested features, False otherwise.

Source code in horde_sdk/worker/feature_flags.py
def is_capable_of_features(self, features: GenerationFeatureFlags) -> bool:
    """Check if the worker is capable of handling the requested features.

    Args:
        features (GenerationFeatureFlags): The features to check.

    Returns:
        bool: True if the worker is capable of handling the requested features, False otherwise.
    """
    return not self.reasons_not_capable_of_features(features)