src/transformers/models/layoutlmv3/modeling_tf_layoutlmv3.py/TFLayoutLMv3MainLayer/call
class TFLayoutLMv3MainLayer:    def call(
        self,
        input_ids: tf.Tensor | None = None,
        bbox: tf.Tensor | None = None,
        attention_mask: tf.Tensor | None = None,
        token_type_ids: tf.Tensor | None = None,
        position_ids: tf.Tensor | None = None,
        head_mask: tf.Tensor | None = None,
        inputs_embeds: tf.Tensor | None = None,
        pixel_values: tf.Tensor | None = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
        training: bool = False,
    ) -> Union[
        TFBaseModelOutput,
        Tuple[tf.Tensor],
        Tuple[tf.Tensor, tf.Tensor],
        Tuple[tf.Tensor, tf.Tensor, tf.Tensor],
    ]:
        # This method can be called with a variety of modalities:
        # 1. text + layout
        # 2. text + layout + image
        # 3. image
        # The complexity of this method is mostly just due to handling of these different modalities.

        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
        )
        return_dict = return_dict if return_dict is not None else self.config.return_dict

        if input_ids is not None:
            input_shape = tf.shape(input_ids)
            batch_size = input_shape[0]
            seq_length = input_shape[1]
        elif inputs_embeds is not None:
            input_shape = tf.shape(inputs_embeds)
            batch_size = input_shape[0]
            seq_length = input_shape[1]
        elif pixel_values is not None:
            batch_size = tf.shape(pixel_values)[0]
        else:
            raise ValueError("You have to specify either input_ids or inputs_embeds or pixel_values")

        # Determine which integer dtype to use.
        if input_ids is not None:
            int_dtype = input_ids.dtype
        elif bbox is not None:
            int_dtype = bbox.dtype
        elif attention_mask is not None:
            int_dtype = attention_mask.dtype
        elif token_type_ids is not None:
            int_dtype = token_type_ids.dtype
        else:
            int_dtype = tf.int32

        if input_ids is not None or inputs_embeds is not None:
            if attention_mask is None:
                attention_mask = tf.ones((batch_size, seq_length), dtype=int_dtype)
            if token_type_ids is None:
                token_type_ids = tf.zeros((batch_size, seq_length), dtype=int_dtype)
            if bbox is None:
                bbox = tf.zeros((batch_size, seq_length, 4), dtype=int_dtype)

            embedding_output = self.embeddings(
                input_ids=input_ids,
                bbox=bbox,
                position_ids=position_ids,
                token_type_ids=token_type_ids,
                inputs_embeds=inputs_embeds,
                training=training,
            )

        final_bbox = None
        final_position_ids = None
        if pixel_values is not None:
            # embed image
            visual_embeddings = self.embed_image(pixel_values)

            # calculate attention mask
            visual_attention_mask = tf.ones((batch_size, tf.shape(visual_embeddings)[1]), dtype=int_dtype)
            if attention_mask is None:
                attention_mask = visual_attention_mask
            else:
                attention_mask = tf.concat([attention_mask, visual_attention_mask], axis=1)

            # calculate bounding boxes
            if self.config.has_spatial_attention_bias:
                visual_bbox = self.calculate_visual_bbox(batch_size, int_dtype)
                if bbox is None:
                    final_bbox = visual_bbox
                else:
                    final_bbox = tf.concat([bbox, visual_bbox], axis=1)

            # calculate position IDs
            if self.config.has_relative_attention_bias or self.config.has_spatial_attention_bias:
                visual_position_ids = tf.range(0, tf.shape(visual_embeddings)[1], dtype=int_dtype)
                visual_position_ids = tf.expand_dims(visual_position_ids, axis=0)
                visual_position_ids = tf.tile(visual_position_ids, [batch_size, 1])

                if input_ids is not None or inputs_embeds is not None:
                    position_ids = tf.expand_dims(tf.range(0, seq_length, dtype=int_dtype), axis=0)
                    position_ids = tf.tile(position_ids, [batch_size, 1])
                    final_position_ids = tf.concat([position_ids, visual_position_ids], axis=1)
                else:
                    final_position_ids = visual_position_ids

            # calculate embeddings
            if input_ids is None and inputs_embeds is None:
                embedding_output = visual_embeddings
            else:
                embedding_output = tf.concat([embedding_output, visual_embeddings], axis=1)
            embedding_output = self.LayerNorm(embedding_output)
            embedding_output = self.dropout(embedding_output, training=training)

        elif self.config.has_relative_attention_bias or self.config.has_spatial_attention_bias:
            if self.config.has_relative_attention_bias:
                position_ids = tf.expand_dims(tf.range(0, seq_length, dtype=int_dtype), axis=0)
                position_ids = tf.tile(position_ids, [batch_size, 1])
                final_position_ids = position_ids

            if self.config.has_spatial_attention_bias:
                final_bbox = bbox

        extended_attention_mask = self.get_extended_attention_mask(attention_mask)

        # Prepare head mask if needed
        # 1.0 in head_mask indicate we keep the head
        # attention_probs has shape batch_size x num_heads x seq_length x seq_length
        # input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]
        # and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]
        head_mask = self.get_head_mask(head_mask)

        encoder_outputs = self.encoder(
            embedding_output,
            bbox=final_bbox,
            position_ids=final_position_ids,
            attention_mask=extended_attention_mask,
            head_mask=head_mask,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )

        sequence_output = encoder_outputs[0]

        if not return_dict:
            return (sequence_output,) + encoder_outputs[1:]

        return TFBaseModelOutput(
            last_hidden_state=sequence_output,
            hidden_states=encoder_outputs.hidden_states,
            attentions=encoder_outputs.attentions,
        )

        return TFBaseModelOutput(
            last_hidden_state=sequence_output,
            hidden_states=encoder_outputs.hidden_states,
            attentions=encoder_outputs.attentions,
        )