# AutoPipelineBlocks

[AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) est un type multi-blocs contenant des blocs qui prennent en charge différents flux de travail. Il sélectionne automatiquement les sous-blocs à exécuter en fonction de l’entrée fournie à l’exécution. Il est généralement utilisé pour regrouper plusieurs flux de travail — texte-vers-image, image-vers-image, inpaint — dans un seul pipeline pour plus de commodité.

Ce guide montre comment créer des [AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks).

Créez trois [ModularPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) pour le texte-vers-image, l'image-vers-image et l'inpainting. Ils représentent les différents flux de travail disponibles dans le pipeline.

```py
import torch
from diffusers.modular_pipelines import ModularPipelineBlocks, InputParam, OutputParam

class TextToImageBlock(ModularPipelineBlocks):
    model_name = "text2img"

    @property
    def inputs(self):
        return [InputParam(name="prompt")]

    @property
    def intermediate_outputs(self):
        return []

    @property
    def description(self):
        return "I'm a text-to-image workflow!"

    def __call__(self, components, state):
        block_state = self.get_block_state(state)
        print("running the text-to-image workflow")
        # Add your text-to-image logic here
        # For example: generate image from prompt
        self.set_block_state(state, block_state)
        return components, state
```

```py
class ImageToImageBlock(ModularPipelineBlocks):
    model_name = "img2img"

    @property
    def inputs(self):
        return [InputParam(name="prompt"), InputParam(name="image")]

    @property
    def intermediate_outputs(self):
        return []

    @property
    def description(self):
        return "I'm an image-to-image workflow!"

    def __call__(self, components, state):
        block_state = self.get_block_state(state)
        print("running the image-to-image workflow")
        # Add your image-to-image logic here
        # For example: transform input image based on prompt
        self.set_block_state(state, block_state)
        return components, state
```

```py
class InpaintBlock(ModularPipelineBlocks):
    model_name = "inpaint"

    @property
    def inputs(self):
        return [InputParam(name="prompt"), InputParam(name="image"), InputParam(name="mask")]

    @property
    def intermediate_outputs(self):
        return []

    @property
    def description(self):
        return "I'm an inpaint workflow!"

    def __call__(self, components, state):
        block_state = self.get_block_state(state)
        print("running the inpaint workflow")
        # Add your inpainting logic here
        # For example: fill masked areas based on prompt
        self.set_block_state(state, block_state)
        return components, state
```

Créez une classe [AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) qui inclut une liste des classes de sous-blocs et de leurs noms de bloc correspondants.

Vous devez également inclure `block_trigger_inputs`, une liste de noms d’entrées qui déclenchent le bloc correspondant. Si une entrée de déclenchement est fournie à l’exécution, ce bloc est sélectionné pour s’exécuter. Utilisez `None` pour spécifier le bloc par défaut à exécuter si aucune entrée de déclenchement n’est détectée.

Enfin, il est important d'inclure une `description` qui explique clairement quels déclencheurs activent quel flux de travail. Cela aide les utilisateurs à comprendre comment exécuter des flux de travail spécifiques.

```py
from diffusers.modular_pipelines import AutoPipelineBlocks

class AutoImageBlocks(AutoPipelineBlocks):
    # List of sub-block classes to choose from
    block_classes = [InpaintBlock, ImageToImageBlock, TextToImageBlock]
    # Names for each block in the same order
    block_names = ["inpaint", "img2img", "text2img"]
    # Trigger inputs that determine which block to run
    # - "mask" triggers inpaint workflow
    # - "image" triggers img2img workflow (but only if mask is not provided)
    # - if none of above, runs the text2img workflow (default)
    block_trigger_inputs = ["mask", "image", None]

    @property
    def description(self):
        return (
            "Pipeline generates images given different types of conditions!\n"
            + "This is an auto pipeline block that works for text2img, img2img and inpainting tasks.\n"
            + " - inpaint workflow is run when `mask` is provided.\n"
            + " - img2img workflow is run when `image` is provided (but only when `mask` is not provided).\n"
            + " - text2img workflow is run when neither `image` nor `mask` is provided.\n"
        )
```

Il est **très** important d'inclure une `description` afin d'éviter toute confusion quant à l'exécution d'un bloc et aux entrées requises. Bien que [AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) soit pratique, sa logique conditionnelle peut être difficile à comprendre si elle n'est pas correctement expliquée.

Créez une instance de `AutoImageBlocks`.

```py
auto_blocks = AutoImageBlocks()
```

Pour des compositions plus complexes, telles que des blocs [AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) imbriqués lorsqu'ils sont utilisés comme sous-blocs dans des pipelines plus vastes, utilisez la méthode [get_execution_blocks()](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks.get_execution_blocks) pour extraire le bloc qui est réellement exécuté en fonction de votre entrée.

```py
auto_blocks.get_execution_blocks(mask=True)
```

## ConditionalPipelineBlocks

[AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) est un cas particulier de [ConditionalPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.ConditionalPipelineBlocks). Alors que [AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) sélectionne les blocs en fonction de la présence ou non d'une entrée de déclenchement, [ConditionalPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.ConditionalPipelineBlocks) permet de sélectionner un bloc sur la base d'une logique de sélection personnalisée fournie dans la méthode `select_block`.

Voici le même exemple écrit en utilisant directement [ConditionalPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.ConditionalPipelineBlocks) :

```py
from diffusers.modular_pipelines import ConditionalPipelineBlocks

class AutoImageBlocks(ConditionalPipelineBlocks):
    block_classes = [InpaintBlock, ImageToImageBlock, TextToImageBlock]
    block_names = ["inpaint", "img2img", "text2img"]
    block_trigger_inputs = ["mask", "image"]
    default_block_name = "text2img"

    @property
    def description(self):
        return (
            "Pipeline generates images given different types of conditions!\n"
            + "This is an auto pipeline block that works for text2img, img2img and inpainting tasks.\n"
            + " - inpaint workflow is run when `mask` is provided.\n"
            + " - img2img workflow is run when `image` is provided (but only when `mask` is not provided).\n"
            + " - text2img workflow is run when neither `image` nor `mask` is provided.\n"
        )

    def select_block(self, mask=None, image=None) -> str | None:
        if mask is not None:
            return "inpaint"
        if image is not None:
            return "img2img"
        return None  # falls back to default_block_name ("text2img")
```

Les entrées listées dans `block_trigger_inputs` sont transmises en tant qu'arguments nommés à `select_block()`. Lorsque `select_block` renvoie `None`, il bascule sur `default_block_name`. Si `default_block_name` est également `None`, le bloc conditionnel entier est ignoré — ce qui est utile pour les étapes de traitement facultatives qui ne doivent s'exécuter que lorsque des entrées spécifiques sont fournies.

## Flux de travail

Les pipelines contenant des blocs conditionnels ([AutoPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.AutoPipelineBlocks) ou [ConditionalPipelineBlocks](/docs/diffusers/main/fr/api/modular_diffusers/pipeline_blocks#diffusers.ConditionalPipelineBlocks)) peuvent prendre en charge plusieurs flux de travail — par exemple, notre pipeline modulaire SDXL prend en charge une douzaine de flux de travail au sein d'un seul pipeline. Mais cela signifie aussi qu'il peut être difficile pour les utilisateurs de savoir quels flux de travail sont pris en charge et comment les exécuter. Pour les créateurs de pipelines, il est utile de pouvoir extraire uniquement les blocs pertinents pour un flux de travail spécifique.

Nous recommandons de définir un `_workflow_map` pour donner un nom à chaque workflow et lister explicitement les entrées dont il a besoin.

```py
from diffusers.modular_pipelines import SequentialPipelineBlocks

class MyPipelineBlocks(SequentialPipelineBlocks):
    block_classes = [TextEncoderBlock, AutoImageBlocks, DecodeBlock]
    block_names = ["text_encoder", "auto_image", "decode"]

    _workflow_map = {
        "text2image": {"prompt": True},
        "image2image": {"image": True, "prompt": True},
        "inpaint": {"mask": True, "image": True, "prompt": True},
    }
```

Tous nos pipelines modulaires intégrés sont dotés de flux de travail prédéfinis. La propriété `available_workflows` répertorie tous les flux de travail pris en charge :

```py
pipeline_blocks = MyPipelineBlocks()
pipeline_blocks.available_workflows
# ['text2image', 'image2image', 'inpaint']
```

Récupérez un workflow spécifique avec `get_workflow` afin d’inspecter et de déboguer un bloc spécifique qui exécute le workflow.

```py
pipeline_blocks.get_workflow("inpaint")
```

