code: def add_text(
      parser_builder: builders.BaseParserBuilder,
      decoder_builder: builders.DecoderBuilder,
      preprocessor_builder: builders.PreprocessorBuilder,
      tokenizer: tokenizers.TextTokenizer,
      is_training: bool = True,
      input_feature_name: str = "caption/string",
      output_raw_string_name: str = "raw_caption",
      output_feature_name: str = builders.TEXT_INDICES_FEATURE_NAME,
      # Text related parameters.
      prepend_bos: bool = False,
      append_eos: bool = False,
      keep_raw_string: bool = False,
      max_num_captions: int = 1,
      max_num_tokens: int = 16,
      sync_random_state: bool = False,
  ):
      """Adds functions to process text feature to builders.
  
      This function expects the input to be either a `tf.train.SequenceExample`
      (with the features in the context) or a `tf.train.Example`. The expected
      structure is (or equivalent for `tf.train.Example`):
      ```
      context {
        feature {
          key: input_feature_name
          value {
            bytes_list {
              value: "Hello world!"
              value: "This is a caption."
              ...
            }
          }
        }
      }
      ```
  
      The corresponding `builders.ExampleParserBuilder` or
      `builders.SequenceExampleParserBuilder` has to be given as parameter.
  
      Args:
        parser_builder: An instance of a `builders.BaseParserBuilder`.
        decoder_builder: An instance of a `builders.DecoderBuilder`.
        preprocessor_builder: An instance of a `builders.PreprocessorBuilder`.
        tokenizer: An instance of a tokenizer.
        is_training: Whether or not in training mode. This will be used to randomly
          sample the captions.
        input_feature_name: Name of the feature in the input `tf.train.Example` or
          `tf.train.SequenceExample`. Exposing this as an argument allows using this
          function for different text features within a single dataset.
        output_raw_string_name: Name of the raw string in the output features
          dictionary. Exposing this as an argument allows using this function for
          different text features within a single dataset.
        output_feature_name: Name of the feature in the output features dictionary.
          Exposing this as an argument allows using this function for different text
          features.
        prepend_bos: Whether to prepend BOS token.
        append_eos: Whether to append EOS token.
        keep_raw_string: Whether to keep raw string.
        max_num_captions: Maximum number of captions to keep. If there are more
          captions in the proto, only the first `max_num_captions` will be returned
          is `is_training` is set to `False`. If `is_training` is `True`, then
          `max_num_captions` will be randomly sampled. Finally if the proto contains
          less than `max_num_captions`, we pad with empty srings to make sure there
          are `max_num_captions` in total.
        max_num_tokens: Maximum number of tokens to keep from the text for each
          caption. If there are more tokens, sequence is cropped, if less, the
          caption is padded using the tokenizer pad id. The sequence is unmodified
          if max_num_tokens is None.
        sync_random_state: Whether to use stateful option to keep random operations
          in sync between different modalities. All modalities having this option
          `True` will use the same outcome in random operations used for sampling
          the captions.
      """
      # Parse text indices.
      if isinstance(
          parser_builder, builders.SequenceExampleParserBuilder
      ):
          parser_builder.parse_feature(
              feature_name=input_feature_name,
              feature_type=tf.io.VarLenFeature(dtype=tf.string),
              output_name=output_raw_string_name,
              is_context=True,
          )
      elif isinstance(parser_builder, builders.ExampleParserBuilder):
          parser_builder.parse_feature(
              feature_name=input_feature_name,
              feature_type=tf.io.VarLenFeature(dtype=tf.string),
              output_name=output_raw_string_name,
          )
  
      # Densify text tensor.
      decoder_builder.add_fn(
          fn=tf.sparse.to_dense,
          feature_name=output_raw_string_name,
          fn_name=f"{output_feature_name}_sparse_to_dense",
      )
  
      preprocessor_builder.add_fn(
          # pylint: disable=g-long-lambda
          lambda x, s=None: processors.sample_or_pad_non_sorted_sequence(
              x, max_num_captions, b"", random=is_training, state=s
          ),
          # pylint: enable=g-long-lambda
          feature_name=output_raw_string_name,
          fn_name=f"{output_feature_name}_sample_captions",
          # Use state to keep coherence between modalities if requested.
          stateful=sync_random_state,
      )
  
      preprocessor_builder.add_fn(
          fn=lambda x: format_text(  # pylint: disable=g-long-lambda
              x, output_raw_string_name, output_raw_string_name
          ),
          fn_name=f"{output_feature_name}_formatting",
      )
  
      # Tokenize the sentence.
      preprocessor_builder.add_fn(
          fn=lambda x: processors.tokenize(  # pylint: disable=g-long-lambda
              x,
              tokenizer,
              output_raw_string_name,
              output_feature_name,
              prepend_bos,
              append_eos,
              max_num_tokens,
              keep_raw_string,
          ),
          fn_name=f"{output_feature_name}_tokenization",
      )
  
      if max_num_tokens is not None:
          # Set text shape.
          shape = (max_num_captions, max_num_tokens)
          preprocessor_builder.add_fn(
              fn=lambda x: processors.set_shape(x, shape),
              feature_name=output_feature_name,
              fn_name=f"{output_feature_name}_set_shape",
          )
  
imports: import functools
  from typing import Any, Dict, Optional, Sequence
  from absl import logging
  from dmvr import builders
  from dmvr import processors
  from dmvr import tokenizers
  import numpy
  from scenic.projects.mbt.datasets.dataset_utils import _decode_spectrogram
  from scenic.projects.mbt.datasets.dataset_utils import apply_specaugment
  import tensorflow
label_desc: Use image node_id 13 for calling a global function with example usage: add_text(parser_builder, decoder_builder, preprocessor_builder, tokenizer, is_training, input_feature_name, output_raw_string_name, output_feature_name, prepend_bos, append_eos, keep_raw_string, max_num_captions, max_num_tokens, sync_random_state) without return types