def featurize_query_and_docs(self, query, docs, model_timestamp):
    """Converts query and candidates into a set of final features for training.

    Args:
      query: a Query object.
      docs: a list of Documents.
      model_timestamp: Optional integer module export time for this example.

    Returns:
      features: a dict with the structure specified by
        self.query_and_docs_feature_structure.
    """
    # Features for the query embedder.
    query_features = self.featurize_query(query, fmt='bert_inputs')

    # Features for the document embedder.
    doc_features = batch_namedtuples(
        [self.featurize_document(d, fmt='bert_inputs') for d in docs])

    # Features for masked language model.
    query_mask_features = self.mask_query(query)

    # We need to shift all indices by 1 because we will add a [CLS] token in
    # front of the query tokens.
    mlm_positions = [i + 1 for i in query_mask_features['mask_indices']]
    mlm_mask = [1] * len(mlm_positions)
    mlm_targets = query_mask_features['masked_token_ids']

    def as_fixed_length_tensor(seq, seq_len):
      result = truncate_or_pad(seq, seq_len, pad_val=0)
      return tf.constant(result)

    mlm_mask = as_fixed_length_tensor(mlm_mask, self.max_masks)
    mlm_positions = as_fixed_length_tensor(mlm_positions, self.max_masks)
    mlm_targets = as_fixed_length_tensor(mlm_targets, self.max_masks)

    # Features for the reader.
    query_ids = query_mask_features['token_ids_after_masking']
    query_ids = query_ids[:self.query_seq_len - 2]

    joint_inputs_list = []
    for doc in docs:
      # Note that we ignore the doc title for this step.
      doc_ids = doc.body_token_ids
      doc_ids = doc_ids[:self.candidate_seq_len - 2]

      joint_inputs = bert_format(
          input_seqs=[query_ids, doc_ids],
          max_seq_len=self.query_seq_len + self.candidate_seq_len,
          cls_id=self.tokenizer.cls_id,
          sep_id=self.tokenizer.sep_id)
      joint_inputs_list.append(joint_inputs)

    joint_features = batch_namedtuples(joint_inputs_list)

    # NOTE: this feature is currently not used.
    candidate_labels = tf.zeros(len(docs))

    features = {
        'query_inputs': query_features,
        'candidate_inputs': doc_features,
        'joint_inputs': joint_features,
        'mlm_positions': mlm_positions,
        'mlm_mask': mlm_mask,
        'mlm_targets': mlm_targets,
        'candidate_labels': candidate_labels,
        'export_timestamp': tf.constant(model_timestamp),
    }

    return features
Converts query and candidates into a set of final features for training.

    Args:
      query: a Query object.
      docs: a list of Documents.
      model_timestamp: Optional integer module export time for this example.

    Returns:
      features: a dict with the structure specified by
        self.query_and_docs_feature_structure.
    
language/realm/featurization.py