def setup(self, class_name: str | None = None, reference_images: torch.Tensor | None = None) -> None:
        """Setup WinCLIP model with class name and/or reference images.

        The setup stage collects text and visual embeddings used during inference:
        - Text embeddings for zero-shot inference if ``class_name`` provided
        - Visual embeddings for few-shot inference if ``reference_images`` provided
        The ``k_shot`` attribute is updated based on number of reference images.

        This method is called by constructor but can also be called manually to update
        embeddings after initialization.

        Args:
            class_name (str | None, optional): Name of object class for prompt ensemble.
                Defaults to ``None``.
            reference_images (torch.Tensor | None, optional): Reference images of shape
                ``(batch_size, C, H, W)``. Defaults to ``None``.

        Examples:
            >>> model = WinClipModel()  # doctest: +SKIP
            >>> model.setup("transistor")  # doctest: +SKIP
            >>> model.text_embeddings.shape  # doctest: +SKIP
            torch.Size([2, 640])

            >>> ref_images = torch.rand(2, 3, 240, 240)  # doctest: +SKIP
            >>> model = WinClipModel()  # doctest: +SKIP
            >>> model.setup("transistor", ref_images)  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            2
            >>> model.visual_embeddings[0].shape  # doctest: +SKIP
            torch.Size([2, 196, 640])

            >>> model = WinClipModel("transistor")  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            0
            >>> model.setup(reference_images=ref_images)  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            2

            >>> model = WinClipModel(  # doctest: +SKIP
            ...     class_name="transistor",
            ...     reference_images=ref_images
            ... )
            >>> model.text_embeddings.shape  # doctest: +SKIP
            torch.Size([2, 640])
            >>> model.visual_embeddings[0].shape  # doctest: +SKIP
            torch.Size([2, 196, 640])
        """
        # update class name and text embeddings
        self.class_name = class_name or self.class_name
        if self.class_name is not None:
            self._collect_text_embeddings(self.class_name)
        # update reference images, k_shot and visual embeddings
        self.reference_images = reference_images if reference_images is not None else self.reference_images
        if self.reference_images is not None:
            self.k_shot = self.reference_images.shape[0]  # update k_shot based on number of reference images
            self._collect_visual_embeddings(self.reference_images)
Setup WinCLIP model with class name and/or reference images.

        The setup stage collects text and visual embeddings used during inference:
        - Text embeddings for zero-shot inference if ``class_name`` provided
        - Visual embeddings for few-shot inference if ``reference_images`` provided
        The ``k_shot`` attribute is updated based on number of reference images.

        This method is called by constructor but can also be called manually to update
        embeddings after initialization.

        Args:
            class_name (str | None, optional): Name of object class for prompt ensemble.
                Defaults to ``None``.
            reference_images (torch.Tensor | None, optional): Reference images of shape
                ``(batch_size, C, H, W)``. Defaults to ``None``.

        Examples:
            >>> model = WinClipModel()  # doctest: +SKIP
            >>> model.setup("transistor")  # doctest: +SKIP
            >>> model.text_embeddings.shape  # doctest: +SKIP
            torch.Size([2, 640])

            >>> ref_images = torch.rand(2, 3, 240, 240)  # doctest: +SKIP
            >>> model = WinClipModel()  # doctest: +SKIP
            >>> model.setup("transistor", ref_images)  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            2
            >>> model.visual_embeddings[0].shape  # doctest: +SKIP
            torch.Size([2, 196, 640])

            >>> model = WinClipModel("transistor")  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            0
            >>> model.setup(reference_images=ref_images)  # doctest: +SKIP
            >>> model.k_shot  # doctest: +SKIP
            2

            >>> model = WinClipModel(  # doctest: +SKIP
            ...     class_name="transistor",
            ...     reference_images=ref_images
            ... )
            >>> model.text_embeddings.shape  # doctest: +SKIP
            torch.Size([2, 640])
            >>> model.visual_embeddings[0].shape  # doctest: +SKIP
            torch.Size([2, 196, 640])
        
src/anomalib/models/image/winclip/torch_model.py