code: def convert_squad_example_to_feature(
      example: SquadExample,
      tokenizer: BaseTokenizerWithVocab,
      is_training: bool,
  ):
      """
      Convert a SquadExample object to a SquadFeature object with the designated tokenizer.
  
      There are accually few examples can not be converted properly with token level tokenization,
      due to the ground-truth are given by the start position and the answer text, and some examples
      are annotated with wrong labels. Thus, attribute unreliable_span and token_answer_mismatch are
      used to indicate these senarios.
  
      Parameters
      ----------
      example
          A single squad example
      tokenizer
          The trained tokenizer
      is_training
          Whether to deal with the training case
      Returns
      -------
      feature
          A SquadFeature
      """
      context_text = example.context_text
      answer_text = example.answer_text
      query_text = example.query_text
      context_token_ids, offsets = tokenizer.encode_with_offsets(
          context_text, int
      )
      query_token_ids = tokenizer.encode(query_text, int)
      gt_answer_text = answer_text
      gt_span_start_pos, gt_span_end_pos = None, None
      token_answer_mismatch = False
      unreliable_span = False
      np_offsets = np.array(offsets)
      if is_training and not example.is_impossible:
          assert (
              example.start_position >= 0 and example.end_position >= 0
          )
          # We convert the character-level offsets to token-level offsets
          # Also, if the answer after tokenization + detokenization is not the same as the original
          # answer, we try to localize the answer text and do a rematch
          candidates = [(example.start_position, example.end_position)]
          all_possible_start_pos = {example.start_position}
          find_all_candidates = False
          lower_idx, upper_idx = None, None
          first_lower_idx, first_upper_idx = None, None
          while len(candidates) > 0:
              start_position, end_position = candidates.pop()
              # Match the token offsets
              token_start_ends = match_tokens_with_char_spans(
                  np_offsets, np.array([[start_position, end_position]])
              )
              lower_idx = int(token_start_ends[0][0])
              upper_idx = int(token_start_ends[0][1])
              if not find_all_candidates:
                  first_lower_idx = lower_idx
                  first_upper_idx = upper_idx
              # The new start pos and end_pos are the lower_idx and upper_idx
              sliced_answer = context_text[
                  offsets[lower_idx][0] : offsets[upper_idx][1]
              ]
              norm_sliced_answer = normalize_answer(sliced_answer)
              norm_answer = normalize_answer(answer_text)
              if norm_sliced_answer != norm_answer:
                  if not find_all_candidates:
                      # Try to find a better start+end of the answer and insert all positions to the
                      # candidates
                      find_all_candidates = True
                      pos = context_text.find(answer_text)
                      while pos != -1:
                          if pos not in all_possible_start_pos:
                              all_possible_start_pos.add(pos)
                              candidates.append(
                                  (pos, pos + len(answer_text))
                              )
                          pos = context_text.find(answer_text, pos + 1)
                  elif len(candidates) == 0:
                      token_answer_mismatch = True
                      lower_idx = first_lower_idx
                      upper_idx = first_upper_idx
                      if int_float_regex.match(answer_text):
                          # Find an integer/float and the sample won't be reliable.
                          # The span-based approach is not suitable for this scenario and we will
                          # set the unreliable span flag.
                          unreliable_span = True
              else:
                  break
  
          gt_span_start_pos = lower_idx
          gt_span_end_pos = upper_idx
  
      feature = SquadFeature(
          qas_id=example.qas_id,
          query_token_ids=query_token_ids,
          context_text=context_text,
          context_token_ids=context_token_ids,
          context_token_offsets=offsets,
          is_impossible=example.is_impossible,
          token_answer_mismatch=token_answer_mismatch,
          unreliable_span=unreliable_span,
          gt_answer_text=gt_answer_text,
          gt_start_pos=gt_span_start_pos,
          gt_end_pos=gt_span_end_pos,
      )
      return feature
  
imports: from typing import Optional, List, Tuple
  from collections import namedtuple
  import dataclasses
  from dataclasses import dataclass
  import re
  import numpy
  import warnings
  import os
  from tqdm.auto import tqdm
  import json
  import string
  from gluonnlp.data.tokenizers import BaseTokenizerWithVocab
  from gluonnlp.utils.preprocessing import match_tokens_with_char_spans
  from mxnet.gluon.utils import download
  import mxnet
label_desc: Use image node_id 5 for calling a global function with example usage: convert_squad_example_to_feature(example, tokenizer, is_training) and returns: feature