def _extract_feat(self, inputs: Union[torch.Tensor, dict],
                      modality: str) -> Tuple[torch.Tensor]:
        """Extract features from the single modality.
        Args:
            inputs (Union[torch.Tensor, dict]): A batch of inputs.
                For image, a tensor of shape (N, C, ...) in general.
                For text, a dict of tokenized text inputs.
            modality (str): Modality feature to be extracted. Only two
                options are supported.

                - ``images``: Only extract image features, mostly used for
                    inference.
                - ``texts``: Only extract text features, mostly used for
                    inference.
        Returns:
            Tuple[torch.Tensor]: The output features.
        """
        if modality == 'images':
            # extract image features
            # TODO:
            # Add layernorm inside backbone and handle the concat outside
            image_embeds = self.ln_vision_backbone(
                self.vision_backbone(inputs)[0])
            image_atts = torch.ones(
                image_embeds.size()[:-1], dtype=torch.long).to(self.device)

            query_tokens = self.query_tokens.expand(image_embeds.shape[0], -1,
                                                    -1)
            query_output = self.multimodal_backbone.bert(
                query_embeds=query_tokens,
                encoder_hidden_states=image_embeds,
                encoder_attention_mask=image_atts,
                use_cache=True,
                return_dict=True,
            )
            image_feat = F.normalize(
                self.vision_neck([query_output.last_hidden_state]), dim=-1)
            return {
                'image_embeds': image_embeds,
                'image_feat': image_feat,
                'query_output': query_output
            }
        elif modality == 'texts':
            # extract text features
            text_output = self.multimodal_backbone.bert(
                inputs.input_ids,
                attention_mask=inputs.attention_mask,
                return_dict=True,
            )
            text_embeds = text_output.last_hidden_state
            text_feat = F.normalize(
                self.text_neck([text_embeds[:, 0, :]]), dim=-1)
            return {'text_embeds': text_embeds, 'text_feat': text_feat}
        else:
            raise RuntimeError(f'Invalid modality "{modality}".')
Extract features from the single modality.
        Args:
            inputs (Union[torch.Tensor, dict]): A batch of inputs.
                For image, a tensor of shape (N, C, ...) in general.
                For text, a dict of tokenized text inputs.
            modality (str): Modality feature to be extracted. Only two
                options are supported.

                - ``images``: Only extract image features, mostly used for
                    inference.
                - ``texts``: Only extract text features, mostly used for
                    inference.
        Returns:
            Tuple[torch.Tensor]: The output features.
        
mmpretrain/models/multimodal/blip2/blip2_retriever.py