code: def convert_text_to_bert_features(
      text, bert_tokenizer, max_seq_length, doc_stride
  ):
      """Helper function to convert text to BERT features.
      # The convention in BERT is:
          # (a) For sequence pairs:
          #  tokens:   [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]
          #  type_ids: 0   0  0    0    0     0       0 0    1  1  1  1   1 1
          # (b) For single sequences:
          #  tokens:   [CLS] the dog is hairy . [SEP]
          #  type_ids: 0   0   0   0  0     0 0
      """
      tok_to_orig_index = []
      all_doc_tokens = []
      for i, token in enumerate(text):
          sub_tokens = bert_tokenizer.wordpiece_tokenizer.tokenize(
              token.lower()
          )
          for sub_ in sub_tokens:
              tok_to_orig_index.append(i)
              all_doc_tokens.append(sub_)
  
      # The -2 accounts for [CLS] and [SEP]
      max_tokens_for_doc = max_seq_length - 2
  
      # We can have documents that are longer than the maximum sequence length.
      # To deal with this we do a sliding window approach, where we take chunks
      # of the up to our max length with a stride of `doc_stride`.
      _DocSpan = namedtuple(
          "DocSpan", ["start", "length"]
      )  # pylint: disable=invalid-name
      doc_spans = []
      start_offset = 0
      while start_offset < len(all_doc_tokens):
          length = len(all_doc_tokens) - start_offset
          if length > max_tokens_for_doc:
              length = max_tokens_for_doc
          doc_spans.append(_DocSpan(start=start_offset, length=length))
          if start_offset + length == len(all_doc_tokens):
              break
          start_offset += min(length, doc_stride)
  
      out_features = []
      for doc_span_index, doc_span in enumerate(doc_spans):
          tokens = []
          token_to_orig_map = {}
          token_to_orig_map_matrix = []
          # token_is_max_context = {}
          segment_ids = []
          tokens.append("[CLS]")
          segment_ids.append(0)
  
          for i in range(doc_span.length):
              split_token_index = doc_span.start + i
              token_to_orig_map[len(tokens)] = tok_to_orig_index[
                  split_token_index
              ]
  
              is_max_context = _check_is_max_context(
                  doc_spans, doc_span_index, split_token_index
              )
              # token_is_max_context[len(tokens)] = is_max_context
              tmp_vec = np.zeros(len(text))
              if is_max_context:
                  tmp_vec[tok_to_orig_index[split_token_index]] = 1
              token_to_orig_map_matrix.append(tmp_vec)
              tokens.append(all_doc_tokens[split_token_index])
              segment_ids.append(0)
          tokens.append("[SEP]")
          segment_ids.append(0)
  
          input_ids = bert_tokenizer.convert_tokens_to_ids(tokens)
  
          # The mask has 1 for real tokens and 0 for padding tokens. Only real
          # tokens are attended to.
          input_mask = [1] * len(input_ids)
  
          feature = BertInputFeatures(
              doc_span_index=doc_span_index,
              tokens=tokens,
              token_to_orig_map=token_to_orig_map,
              token_to_orig_map_matrix=token_to_orig_map_matrix,
              input_ids=input_ids,
              input_mask=input_mask,
              segment_ids=segment_ids,
          )
          out_features.append(feature)
      return out_features
  
file_path: graph4nlp/graph4nlp/pytorch/modules/utils/bert_utils.py
imports: from collections import namedtuple
  import numpy
  import torch
label_desc: Use image node_id 2 for calling a global function with example usage: convert_text_to_bert_features(text, bert_tokenizer, max_seq_length, doc_stride) and returns: out_features