class_docstr: RagModel.
  
  The RagModel operates in the following phases:
  1) retrieve:    given a tokenized query, return relevant documents
  2) expand:      given queries and documents, expand the inputs n_docs times,
                  concatenating each document with a relevant context
  3) encode:      given expanded input, encode into encoder representations
  4) decoding:    given encoder outputs, compute n_docs decoder representations for
                  each batch item.
  5) marginalize: given the decoded representations, marginalize over the documents
  appropriately.
  
  The RagModel overloads the `encoder` and `decoder` attributes of your standard
  `TorchGeneratorModel` to accomplish the five phases above.
docstr: Add document tokens to input tokens.
  
  :param input:
      original input tokens
  :param input_lengths:
      original input lengths
  :param top_docs:
      list of n_docs top documents for each input sequence
  :param max_num_docs:
      maximum number of docs out of all examples
  :param right_padded:
      whether the input is right padded.
  
  :return (tokens, lengths):
      return expanded token vectors & corresponding lengths
docstr_tok: ["Add","document","tokens","to","input","tokens",".",":","param","input",":","original","input","tokens",":","param","input_lengths",":","original","input","lengths",":","param","top_docs",":","list","of","n_docs","top","documents","for","each","input","sequence",":","param","max_num_docs",":","maximum","number","of","docs","out","of","all","examples",":","param","right_padded",":","whether","the","input","is","right","padded",".",":","return","(","tokens",",","lengths",")",":","return","expanded","token","vectors","&","corresponding","lengths"]
code: def concat_docs_and_input(
      self,
      input: torch.LongTensor,
      input_lengths: torch.LongTensor,
      top_docs: List[List[Document]],
      max_num_docs: int,
      right_padded: bool = True,
  ) -> torch.LongTensor:
      """
      Add document tokens to input tokens.
  
      :param input:
          original input tokens
      :param input_lengths:
          original input lengths
      :param top_docs:
          list of n_docs top documents for each input sequence
      :param max_num_docs:
          maximum number of docs out of all examples
      :param right_padded:
          whether the input is right padded.
  
      :return (tokens, lengths):
          return expanded token vectors & corresponding lengths
      """
      max_len = self.expanded_input_truncate
      expanded_input = []
      for i, docs in enumerate(top_docs):
          for rank in range(len(docs)):
              input_i = input[i, :]
              doc = docs[rank]
              doc_tokens = self.dict.txt2vec(doc.get_passage_str())
              if (
                  self.generation_model == "bart"
                  and self.n_extra_positions <= 0
              ):
                  # move SOS to start of passage since we append question to end
                  input_i = input_i[1:]
                  sample_doc_tokens = torch.LongTensor(
                      [self.start_idx] + doc_tokens
                  ).to(input)
              else:
                  sample_doc_tokens = torch.LongTensor(doc_tokens).to(
                      input
                  )
  
              if self.n_extra_positions <= 0:
                  # Prepend document to text
                  input_i_len = input_lengths[i]
                  new_input_length = min(
                      self.expanded_input_truncate
                      - self.min_doc_token_length,
                      input_i_len,
                  )
                  if right_padded:
                      input_i = input_i[
                          input_i_len - new_input_length : input_i_len
                      ]
                  else:
                      input_i = input_i[
                          input_i.size(0) - new_input_length :
                      ]
  
                  doc_max_len = max(max_len - len(input_i), 0)
                  sample_doc_tokens = sample_doc_tokens[:doc_max_len]
                  expanded_input.append(
                      torch.cat([sample_doc_tokens, input_i])[:max_len]
                  )
              else:
                  # Append Document to text
                  sample_doc_tokens = sample_doc_tokens[:max_len]
                  input_i_new = input_i.new(
                      self.n_positions - self.n_extra_positions
                  ).fill_(self.pad_idx)
                  input_i_new[
                      input_i_new.size(0) - input_i.size(0) :
                  ] = input_i
                  expanded_input.append(
                      torch.cat([input_i_new, sample_doc_tokens])
                  )
          # append extra null inputs if there are diff # of docs per input
          expanded_input += [
              input[i, :].new(input[i, :].size()).fill_(self.pad_idx)
          ] * (max_num_docs - len(docs))
      expanded_input, _ = padded_tensor(
          expanded_input,
          fp16friendly=self.fp16 and right_padded,
          max_len=max_len if self.n_extra_positions <= 0 else None,
          pad_idx=self.pad_idx,
          left_padded=not right_padded,
      )
      expanded_input = expanded_input.to(input.device)
      return expanded_input
  
imports: import torch
  import torch.cuda
  import torch.nn
  import torch.nn.functional
  from typing import Any, Tuple, Dict, Optional, List, Union, Type
  from parlai.agents.hugging_face.t5 import ParlaiT5Encoder, ParlaiT5Decoder, build_t5, set_device
  from parlai.agents.transformer.modules import TransformerEncoder, TransformerDecoder, get_n_positions_from_options, create_embeddings
  from parlai.core.dict import DictionaryAgent
  from parlai.core.opt import Opt
  from parlai.core.torch_generator_agent import TorchGeneratorModel
  from parlai.utils.torch import padded_tensor
  from parlai.agents.rag.retrievers import RagRetriever, retriever_factory, Document
label_desc: Use image node_id 12 for calling the RagModel obj's underlying member method code with example usage: obj.concat_docs_and_input(input, input_lengths, top_docs, max_num_docs, right_padded) and returns: expanded_input