def build_flow(self, flow_steps: int) -> ff.GraphINN:
        """Build the U-shaped normalizing flow architecture.

        The flow is built in a U-shaped structure, processing features from coarse
        to fine scales:

        1. Start with input nodes matching feature extractor outputs
        2. For each scale (coarse to fine):
            - Pass through flow stage (sequence of coupling layers)
            - Split output into two parts
            - Send one part to output
            - Upsample other part and concatenate with next scale
        3. Build final flow graph combining all nodes

        Args:
            flow_steps (int): Number of coupling layers in each flow stage.

        Returns:
            ff.GraphINN: Constructed normalizing flow graph.

        See Also:
            - :meth:`build_flow_stage`: Builds individual flow stages
            - :class:`AllInOneBlock`: Individual coupling layer blocks
        """
        input_nodes = []
        for channel, s_factor in zip(
            self.feature_extractor.channels,
            self.feature_extractor.scale_factors,
            strict=True,
        ):
            input_nodes.append(
                ff.InputNode(
                    channel,
                    self.input_size[0] // s_factor,
                    self.input_size[1] // s_factor,
                    name=f"cond_{channel}",
                ),
            )

        nodes, output_nodes = [], []
        last_node = input_nodes[-1]
        for i in reversed(range(1, len(input_nodes))):
            flows = self.build_flow_stage(last_node, flow_steps)
            volume_size = flows[-1].output_dims[0][0]
            split = ff.Node(
                flows[-1],
                fm.Split,
                {"section_sizes": (volume_size // 8 * 4, volume_size - volume_size // 8 * 4), "dim": 0},
                name=f"split_{i + 1}",
            )
            output = ff.OutputNode(split.out1, name=f"output_scale_{i + 1}")
            up = ff.Node(split.out0, fm.IRevNetUpsampling, {}, name=f"up_{i + 1}")
            last_node = ff.Node([input_nodes[i - 1].out0, up.out0], fm.Concat, {"dim": 0}, name=f"cat_{i}")

            output_nodes.append(output)
            nodes.extend([*flows, split, up, last_node])

        flows = self.build_flow_stage(last_node, flow_steps)
        output = ff.OutputNode(flows[-1], name="output_scale_1")

        output_nodes.append(output)
        nodes.extend(flows)

        return ff.GraphINN(input_nodes + nodes + output_nodes[::-1])
Build the U-shaped normalizing flow architecture.

        The flow is built in a U-shaped structure, processing features from coarse
        to fine scales:

        1. Start with input nodes matching feature extractor outputs
        2. For each scale (coarse to fine):
            - Pass through flow stage (sequence of coupling layers)
            - Split output into two parts
            - Send one part to output
            - Upsample other part and concatenate with next scale
        3. Build final flow graph combining all nodes

        Args:
            flow_steps (int): Number of coupling layers in each flow stage.

        Returns:
            ff.GraphINN: Constructed normalizing flow graph.

        See Also:
            - :meth:`build_flow_stage`: Builds individual flow stages
            - :class:`AllInOneBlock`: Individual coupling layer blocks
        
src/anomalib/models/image/uflow/torch_model.py