class_docstr: A key-value store for specific `Messages`.
  
  This container can be only be used to store messages that contain exactly
  one of the following attributes: `ACTION_NAME`, `ACTION_TEXT`, `TEXT`, or `INTENT`.
  A combination of the key attribute and the corresponding value will be used as
  key for the respective message.
  
  Background/Motivation:
  - Our policies only require these attributes to be tokenized and/or featurized
    via NLU graph components, which is why we don't care about storing anything else.
  - Our tokenizers and featurizers work independently for each attribute,
    which is why we can separate them and ask for "exactly one" of the key
    attributes.
  - Our tokenizers add attributes (e.g. token sequences) and not just `Features`,
    which is why we need messages and why we allow messages to contain more than
    just the key attributes.
  - Due to the way we use this datastructure, it won't contain all features that the
    policies need (cf. `rasa.core.featurizers.SingleStateFeaturizer`) and sometimes
    the messages will contain no features at all, which is the motivation for the
    name of this class.
  - Values for different attributes might coincide (e.g. 'greet' can appear as user
    text as well as name of an intent), but attributes are not all tokenized and
    featurized in the same way, which is why we use the combination of key attribute
    and value to identify a message.
  
  Usage:
  - At the start of core's featurization pipeline, we use this container to
    de-duplicate the given story data during training (e.g. "Hello" might appear very
    often but it will end up in the training data only once) and to de-duplicate
    the data given in the tracker (e.g. if a text appears repeatedly in the
    dialogue, it will only be featurized once later).
    See: `rasa.core.featurizers.precomputation.CoreFeaturizationInputConverter`.
  - At the end of core's featurization pipeline, we wrap all resulting
    (training data) messages into this container again.
    See: `rasa.core.featurizers.precomputation.CoreFeaturizationCollector`.
class_docstr_tok: ["A","key-value","store","for","specific","`","Messages","`",".","This","container","can","be","only","be","used","to","store","messages","that","contain","exactly","one","of","the","following","attributes",":","`","ACTION_NAME","`",",","`","ACTION_TEXT","`",",","`","TEXT","`",",","or","`","INTENT","`",".","A","combination","of","the","key","attribute","and","the","corresponding","value","will","be","used","as","key","for","the","respective","message",".","Background\/Motivation",":","-","Our","policies","only","require","these","attributes","to","be","tokenized","and\/or","featurized","via","NLU","graph","components",",","which","is","why","we","do","n't","care","about","storing","anything","else",".","-","Our","tokenizers","and","featurizers","work","independently","for","each","attribute",",","which","is","why","we","can","separate","them","and","ask","for","``","exactly","one","''","of","the","key","attributes",".","-","Our","tokenizers","add","attributes","(","e.g",".","token","sequences",")","and","not","just","`","Features","`",",","which","is","why","we","need","messages","and","why","we","allow","messages","to","contain","more","than","just","the","key","attributes",".","-","Due","to","the","way","we","use","this","datastructure",",","it","wo","n't","contain","all","features","that","the","policies","need","(","cf",".","`","rasa.core.featurizers.SingleStateFeaturizer","`",")","and","sometimes","the","messages","will","contain","no","features","at","all",",","which","is","the","motivation","for","the","name","of","this","class",".","-","Values","for","different","attributes","might","coincide","(","e.g",".","'greet","'","can","appear","as","user","text","as","well","as","name","of","an","intent",")",",","but","attributes","are","not","all","tokenized","and","featurized","in","the","same","way",",","which","is","why","we","use","the","combination","of","key","attribute","and","value","to","identify","a","message",".","Usage",":","-","At","the","start","of","core","'s","featurization","pipeline",",","we","use","this","container","to","de-duplicate","the","given","story","data","during","training","(","e.g",".","``","Hello","''","might","appear","very","often","but","it","will","end","up","in","the","training","data","only","once",")","and","to","de-duplicate","the","data","given","in","the","tracker","(","e.g",".","if","a","text","appears","repeatedly","in","the","dialogue",",","it","will","only","be","featurized","once","later",")",".","See",":","`","rasa.core.featurizers.precomputation.CoreFeaturizationInputConverter","`",".","-","At","the","end","of","core","'s","featurization","pipeline",",","we","wrap","all","resulting","(","training","data",")","messages","into","this","container","again",".","See",":","`","rasa.core.featurizers.precomputation.CoreFeaturizationCollector","`","."]
docstr: Collects features for all attributes in the given substate.
  
  There might be be multiple messages in the container that contain features
  relevant for the given substate, e.g. this is the case if `TEXT` and
  `INTENT` are present in the given substate. All of those messages will be
  collected and their features combined.
  
  Args:
    sub_state: substate for which we want to extract the relevent features
    attributes: if not `None`, this specifies the list of the attributes of the
      `Features` that we're interested in (i.e. all other `Features` contained
      in the relevant messages will be ignored)
  
  Returns:
    a dictionary that maps all the (requested) attributes to a list of `Features`
  
  Raises:
    `ValueError`: if there exists some key pair (i.e. key attribute and
      corresponding value) from the given substate cannot be found
    `RuntimeError`: if features for the same attribute are found in two
      different messages that are associated with the given substate
docstr_tok: ["Collects","features","for","all","attributes","in","the","given","substate",".","There","might","be","be","multiple","messages","in","the","container","that","contain","features","relevant","for","the","given","substate",",","e.g",".","this","is","the","case","if","`","TEXT","`","and","`","INTENT","`","are","present","in","the","given","substate",".","All","of","those","messages","will","be","collected","and","their","features","combined",".","Args",":","sub_state",":","substate","for","which","we","want","to","extract","the","relevent","features","attributes",":","if","not","`","None","`",",","this","specifies","the","list","of","the","attributes","of","the","`","Features","`","that","we","'re","interested","in","(","i.e",".","all","other","`","Features","`","contained","in","the","relevant","messages","will","be","ignored",")","Returns",":","a","dictionary","that","maps","all","the","(","requested",")","attributes","to","a","list","of","`","Features","`","Raises",":","`","ValueError","`",":","if","there","exists","some","key","pair","(","i.e",".","key","attribute","and","corresponding","value",")","from","the","given","substate","can","not","be","found","`","RuntimeError","`",":","if","features","for","the","same","attribute","are","found","in","two","different","messages","that","are","associated","with","the","given","substate"]
code: def collect_features(
      self,
      sub_state: SubState,
      attributes: Optional[Iterable[Text]] = None,
  ) -> Dict[Text, List[Features]]:
      """Collects features for all attributes in the given substate.
  
      There might be be multiple messages in the container that contain features
      relevant for the given substate, e.g. this is the case if `TEXT` and
      `INTENT` are present in the given substate. All of those messages will be
      collected and their features combined.
  
      Args:
        sub_state: substate for which we want to extract the relevent features
        attributes: if not `None`, this specifies the list of the attributes of the
          `Features` that we're interested in (i.e. all other `Features` contained
          in the relevant messages will be ignored)
  
      Returns:
        a dictionary that maps all the (requested) attributes to a list of `Features`
  
      Raises:
        `ValueError`: if there exists some key pair (i.e. key attribute and
          corresponding value) from the given substate cannot be found
        `RuntimeError`: if features for the same attribute are found in two
          different messages that are associated with the given substate
      """
      # If we specify a list of attributes, then we want a dict with one entry
      # for each attribute back - even if the corresponding list of features is empty.
      features: Dict[Text, List[Features]] = (
          dict()
          if attributes is None
          else {attribute: [] for attribute in attributes}
      )
      # collect all relevant key attributes
      key_attributes = set(sub_state.keys()).intersection(
          self.KEY_ATTRIBUTES
      )
      for key_attribute in key_attributes:
          key_value = str(sub_state[key_attribute])
          message = self._table[key_attribute].get(key_value)
          if not message:
              raise ValueError(
                  f"Unknown key ({key_attribute},{key_value}). Cannot retrieve "
                  f"features for substate {sub_state}"
              )
          features_from_message = Features.groupby_attribute(
              message.features, attributes=attributes
          )
          for (
              feat_attribute,
              feat_value,
          ) in features_from_message.items():
              existing_values = features.get(feat_attribute)
              # Note: the following if-s are needed because if we specify a list of
              # attributes then `features_from_message` will contain one entry per
              # attribute even if the corresponding feature list is empty.
              if feat_value and existing_values:
                  raise RuntimeError(
                      f"Feature for attribute {feat_attribute} has already been "
                      f"extracted from a different message stored under a key "
                      f"in {key_attributes} "
                      f"that is different from {key_attribute}. This means there's a "
                      f"redundancy in the message container."
                  )
              if feat_value:
                  features[feat_attribute] = feat_value
      return features
  
imports: from __future__ import annotations
  from typing import Optional, Text, Dict, List, Union, Iterable, Any
  from collections.abc import ValuesView, KeysView
  from rasa.engine.graph import GraphComponent
  from rasa.engine.storage.storage import ModelStorage
  from rasa.engine.storage.resource import Resource
  from rasa.engine.graph import ExecutionContext
  from rasa.shared.core.domain import Domain, SubState
  from rasa.shared.core.events import ActionExecuted, UserUttered, Event
  from rasa.shared.core.trackers import DialogueStateTracker
  from rasa.shared.core.training_data.structures import StoryGraph
  from rasa.shared.nlu.constants import ACTION_NAME, ACTION_TEXT, INTENT, TEXT
  from rasa.shared.nlu.training_data.message import Message
  from rasa.shared.nlu.training_data.training_data import TrainingData
  from rasa.shared.nlu.training_data.features import Features
  import rasa.shared.utils.io
label_desc: Use image node_id 11 for calling the MessageContainerForCoreFeaturization obj's underlying member method code with example usage: obj.collect_features(sub_state, attributes) and returns: features