class_docstr: Relation Classifier to predict the relation between two entities.
  
  Task
  ----
  Relation Classification (RC) is the task of identifying the semantic relation between two entities in a text.
  In contrast to (end-to-end) Relation Extraction (RE), RC requires pre-labelled entities.
  
  Example:
  --------
  For the `founded_by` relation from `ORG` (head) to `PER` (tail) and the sentence
  "Larry Page and Sergey Brin founded Google .", we extract the relations
  - founded_by(head='Google', tail='Larry Page') and
  - founded_by(head='Google', tail='Sergey Brin').
  
  Architecture
  ------------
  The Relation Classifier Model builds upon a text classifier.
  The model generates an encoded sentence for each entity pair
  in the cross product of all entities in the original sentence.
  In the encoded representation, the entities in the current entity pair are masked/marked with control tokens.
  (For an example, see the docstrings of different encoding strategies, e.g. :class:`TypedEntityMarker`.)
  Then, for each encoded sentence, the model takes its document embedding and puts the resulting
  text representation(s) through a linear layer to get the class relation label.
  
  The implemented encoding strategies are taken from this paper by Zhou et al.: https://arxiv.org/abs/2102.01373
  
  .. warning::
      Currently, the model has no multi-label support.
class_docstr_tok: ["Relation","Classifier","to","predict","the","relation","between","two","entities",".","Task","--","--","Relation","Classification","(","RC",")","is","the","task","of","identifying","the","semantic","relation","between","two","entities","in","a","text",".","In","contrast","to","(","end-to-end",")","Relation","Extraction","(","RE",")",",","RC","requires","pre-labelled","entities",".","Example",":","--","--","--","--","For","the","`","founded_by","`","relation","from","`","ORG","`","(","head",")","to","`","PER","`","(","tail",")","and","the","sentence","''","Larry","Page","and","Sergey","Brin","founded","Google",".","``",",","we","extract","the","relations","-","founded_by","(","head='Google","'",",","tail='Larry","Page","'",")","and","-","founded_by","(","head='Google","'",",","tail='Sergey","Brin","'",")",".","Architecture","--","--","--","--","--","--","The","Relation","Classifier","Model","builds","upon","a","text","classifier",".","The","model","generates","an","encoded","sentence","for","each","entity","pair","in","the","cross","product","of","all","entities","in","the","original","sentence",".","In","the","encoded","representation",",","the","entities","in","the","current","entity","pair","are","masked\/marked","with","control","tokens",".","(","For","an","example",",","see","the","docstrings","of","different","encoding","strategies",",","e.g",".",":","class",":","`","TypedEntityMarker","`",".",")","Then",",","for","each","encoded","sentence",",","the","model","takes","its","document","embedding","and","puts","the","resulting","text","representation","(","s",")","through","a","linear","layer","to","get","the","class","relation","label",".","The","implemented","encoding","strategies","are","taken","from","this","paper","by","Zhou","et","al",".",":","https",":","\/\/arxiv.org\/abs\/2102.01373","..","warning",":",":","Currently",",","the","model","has","no","multi-label","support","."]
docstr: Returns a new Sentence object with masked/marked head and tail spans according to the encoding strategy.
  
  If provided, the encoded sentence also has the corresponding gold label annotation from :attr:`~label_type`.
  
  Args:
      head: The head Entity
      tail: The tail Entity
      gold_label: An optional gold label of the induced relation by the head and tail entity
  
  Returns: The EncodedSentence with Gold Annotations
docstr_tok: ["Returns","a","new","Sentence","object","with","masked\/marked","head","and","tail","spans","according","to","the","encoding","strategy",".","If","provided",",","the","encoded","sentence","also","has","the","corresponding","gold","label","annotation","from",":","attr",":","`","~label_type","`",".","Args",":","head",":","The","head","Entity","tail",":","The","tail","Entity","gold_label",":","An","optional","gold","label","of","the","induced","relation","by","the","head","and","tail","entity","Returns",":","The","EncodedSentence","with","Gold","Annotations"]
code: def _encode_sentence(
      self,
      head: _Entity,
      tail: _Entity,
      gold_label: Optional[str] = None,
  ) -> EncodedSentence:
      """Returns a new Sentence object with masked/marked head and tail spans according to the encoding strategy.
  
      If provided, the encoded sentence also has the corresponding gold label annotation from :attr:`~label_type`.
  
      Args:
          head: The head Entity
          tail: The tail Entity
          gold_label: An optional gold label of the induced relation by the head and tail entity
  
      Returns: The EncodedSentence with Gold Annotations
      """
      # Some sanity checks
      original_sentence: Sentence = head.span.sentence
      assert (
          original_sentence is tail.span.sentence
      ), "The head and tail need to come from the same sentence."
  
      # Pre-compute non-leading head and tail tokens for entity masking
      non_leading_head_tokens: List[Token] = head.span.tokens[1:]
      non_leading_tail_tokens: List[Token] = tail.span.tokens[1:]
  
      # We can not use the plaintext of the head/tail span in the sentence as the mask/marker
      # since there may be multiple occurrences of the same entity mentioned in the sentence.
      # Therefore, we use the span's position in the sentence.
      encoded_sentence_tokens: List[str] = []
      for token in original_sentence:
          if token is head.span[0]:
              encoded_sentence_tokens.append(
                  self.encoding_strategy.encode_head(
                      head.span, head.label
                  )
              )
  
          elif token is tail.span[0]:
              encoded_sentence_tokens.append(
                  self.encoding_strategy.encode_tail(
                      tail.span, tail.label
                  )
              )
  
          elif all(
              token is not non_leading_entity_token
              for non_leading_entity_token in itertools.chain(
                  non_leading_head_tokens, non_leading_tail_tokens
              )
          ):
              encoded_sentence_tokens.append(token.text)
  
      # Create masked sentence
      encoded_sentence: EncodedSentence = EncodedSentence(
          " ".join(encoded_sentence_tokens),
          use_tokenizer=SpaceTokenizer(),
      )
  
      if gold_label is not None:
          # Add gold relation annotation as sentence label
          # Using the sentence label instead of annotating a separate `Relation` object is easier to manage since,
          # during prediction, the forward pass does not need any knowledge about the entities in the sentence.
          encoded_sentence.add_label(
              typename=self.label_type, value=gold_label, score=1.0
          )
      encoded_sentence.copy_context_from_sentence(original_sentence)
      return encoded_sentence
  
imports: import itertools
  import logging
  import typing
  from abc import ABC, abstractmethod
  from pathlib import Path
  from typing import Any, Dict, Iterator, List, NamedTuple, Optional, Sequence, Set, Tuple, Union, cast
  import torch
  from torch.utils.data.dataset import Dataset
  import flair
  from flair.data import Corpus, Dictionary, Label, Relation, Sentence, Span, Token, _iter_dataset
  from flair.datasets import DataLoader, FlairDatapointDataset
  from flair.embeddings import DocumentEmbeddings, TransformerDocumentEmbeddings
  from flair.tokenization import SpaceTokenizer
label_desc: Use image node_id 4 for calling the RelationClassifier obj's underlying member method code with example usage: obj._encode_sentence(head, tail, gold_label) and returns: encoded_sentence