# SequentialPipelineBlocks

[SequentialPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks) là một kiểu đa khối, kết hợp các [ModularPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks) khác lại với nhau theo một trình tự. Dữ liệu chảy tuyến tính từ khối này sang khối tiếp theo bằng cách sử dụng `inputs` và `intermediate_outputs`. Mỗi khối trong [SequentialPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks) thường đại diện cho một bước trong pipeline, và bằng cách kết hợp chúng, bạn dần xây dựng nên một pipeline.

Hướng dẫn này cho bạn cách kết nối hai khối vào một [SequentialPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks).

Tạo hai [ModularPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.ModularPipelineBlocks). Khối đầu tiên, `InputBlock`, xuất ra giá trị `batch_size` và khối thứ hai, `ImageEncoderBlock`, sử dụng `batch_size` làm `inputs`.

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

class InputBlock(ModularPipelineBlocks):

    @property
    def inputs(self):
        return [
            InputParam(name="prompt", type_hint=list, description="list of text prompts"),
            InputParam(name="num_images_per_prompt", type_hint=int, description="number of images per prompt"),
        ]

    @property
    def intermediate_outputs(self):
        return [
            OutputParam(name="batch_size", description="calculated batch size"),
        ]

    @property
    def description(self):
        return "A block that determines batch_size based on the number of prompts and num_images_per_prompt argument."

    def __call__(self, components, state):
        block_state = self.get_block_state(state)
        batch_size = len(block_state.prompt)
        block_state.batch_size = batch_size * block_state.num_images_per_prompt
        self.set_block_state(state, block_state)
        return components, state
```

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

class ImageEncoderBlock(ModularPipelineBlocks):

    @property
    def inputs(self):
        return [
            InputParam(name="image", type_hint="PIL.Image", description="raw input image to process"),
            InputParam(name="batch_size", type_hint=int),
        ]

    @property
    def intermediate_outputs(self):
        return [
            OutputParam(name="image_latents", description="latents representing the image"),
        ]

    @property
    def description(self):
        return "Encode raw image into its latent presentation"

    def __call__(self, components, state):
        block_state = self.get_block_state(state)
        # Simulate processing the image
        # This will change the state of the image from a PIL image to a tensor for all blocks
        block_state.image = torch.randn(1, 3, 512, 512)
        block_state.batch_size = block_state.batch_size * 2
        block_state.image_latents = torch.randn(1, 4, 64, 64)
        self.set_block_state(state, block_state)
        return components, state
```

Kết nối hai khối bằng cách định nghĩa một [SequentialPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks). Liệt kê các instance khối trong `block_classes` và tên tương ứng của chúng trong `block_names`. Các khối được thực thi theo thứ tự xuất hiện trong `block_classes`, và dữ liệu chảy từ khối này sang khối tiếp theo thông qua [PipelineState](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_states#diffusers.modular_pipelines.PipelineState).

```py
class ImageProcessingStep(SequentialPipelineBlocks):
    """
    # auto_docstring
    """
    model_name = "my_model"
    block_classes = [InputBlock(), ImageEncoderBlock()]
    block_names = ["input", "image_encoder"]

    @property
    def description(self):
        return (
            "Process text prompts and images for the pipeline. It:\n"
            " - Determines the batch size from the prompts.\n"
            " - Encodes the image into latent space."
        )
```

Khi bạn tạo một [SequentialPipelineBlocks](/docs/diffusers/main/vi/api/modular_diffusers/pipeline_blocks#diffusers.SequentialPipelineBlocks), các thuộc tính như `inputs`, `intermediate_outputs` và `expected_components` sẽ được tự động tổng hợp từ các khối con, do đó không cần định nghĩa lại chúng.

Có một số thuộc tính bạn nên thiết lập:

- `description`: Chúng tôi khuyến nghị thêm mô tả cho khối đã lắp ráp để giải thích bước kết hợp thực hiện điều gì.
- `model_name`: Tham số này được suy ra tự động từ các khối con nhưng không phải lúc nào cũng chính xác, vì vậy bạn có thể cần ghi đè lên nó.
- `outputs`: Mặc định, giá trị này giống với `intermediate_outputs`, nhưng bạn có thể thiết lập thủ công để kiểm soát các giá trị nào xuất hiện trong tài liệu. Điều này hữu ích để chỉ hiển thị các đầu ra cuối cùng thay vì tất cả các giá trị trung gian.

Các thuộc tính này, cùng với `inputs`, `intermediate_outputs` và `expected_components` đã được tổng hợp, được sử dụng để tự động tạo ra thuộc tính `doc`.

In `ImageProcessingStep` để kiểm tra các khối con, và dùng `doc` để xem tóm tắt đầy đủ về đầu vào, đầu ra và các thành phần của khối.

```py
blocks = ImageProcessingStep()
print(blocks)
print(blocks.doc)
```

