class_docstr: Composes template models from configs.
  
  :param action_spaces_dict: Dict of sub-step id to action space.
  :param observation_spaces_dict: Dict of sub-step id to observation space.
  :param distribution_mapper_config: Distribution mapper configuration.
  :param model_builder: The model builder (template) to create the model from.
  :param policy: Specifies the policy type as a configType.
      E.g. {'type': maze.perception.models.policies.ProbabilisticPolicyComposer} specifies a probabilistic policy.
  :param critic: Specifies the critic type as a configType.
      E.g. {'type': maze.perception.models.critics.StateCriticComposer} specifies the single step state critic.
class_docstr_tok: ["Composes","template","models","from","configs",".",":","param","action_spaces_dict",":","Dict","of","sub-step","id","to","action","space",".",":","param","observation_spaces_dict",":","Dict","of","sub-step","id","to","observation","space",".",":","param","distribution_mapper_config",":","Distribution","mapper","configuration",".",":","param","model_builder",":","The","model","builder","(","template",")","to","create","the","model","from",".",":","param","policy",":","Specifies","the","policy","type","as","a","configType",".","E.g",".","{","'type","'",":","maze.perception.models.policies.ProbabilisticPolicyComposer","}","specifies","a","probabilistic","policy",".",":","param","critic",":","Specifies","the","critic","type","as","a","configType",".","E.g",".","{","'type","'",":","maze.perception.models.critics.StateCriticComposer","}","specifies","the","single","step","state","critic","."]
docstr: Compiles a template state action (Q) value network.
  
  :param observation_space: The input observations for the perception network.
  :param action_space: The action space that defines the network action heads.
  :param perception_net: A initial network to continue from.
                         (e.g. useful for shared weights. Model building continues from the key 'latent'.)
  :param only_discrete_spaces: A dict specifying if the action spaces w.r.t. the step only hold discrete action
                               spaces.
  :return: A q value network (critic) InferenceBlock.
docstr_tok: ["Compiles","a","template","state","action","(","Q",")","value","network",".",":","param","observation_space",":","The","input","observations","for","the","perception","network",".",":","param","action_space",":","The","action","space","that","defines","the","network","action","heads",".",":","param","perception_net",":","A","initial","network","to","continue","from",".","(","e.g",".","useful","for","shared","weights",".","Model","building","continues","from","the","key","'latent","'",".",")",":","param","only_discrete_spaces",":","A","dict","specifying","if","the","action","spaces","w.r.t",".","the","step","only","hold","discrete","action","spaces",".",":","return",":","A","q","value","network","(","critic",")","InferenceBlock","."]
code: def template_q_value_net(
      self,
      observation_space: Optional[spaces.Dict],
      action_space: spaces.Dict,
      only_discrete_spaces: bool,
      perception_net: Optional[InferenceBlock] = None,
  ) -> InferenceBlock:
      """Compiles a template state action (Q) value network.
  
      :param observation_space: The input observations for the perception network.
      :param action_space: The action space that defines the network action heads.
      :param perception_net: A initial network to continue from.
                             (e.g. useful for shared weights. Model building continues from the key 'latent'.)
      :param only_discrete_spaces: A dict specifying if the action spaces w.r.t. the step only hold discrete action
                                   spaces.
      :return: A q value network (critic) InferenceBlock.
      """
      assert all(
          map(
              lambda space: isinstance(
                  space, (spaces.Discrete, spaces.Box)
              ),
              action_space.spaces.values(),
          )
      ), (
          "Only discrete and box spaces supported thus far for q values "
          "critic."
      )
  
      if not only_discrete_spaces:
          discrete_space = list(
              filter(
                  lambda kk: isinstance(
                      action_space.spaces[kk], spaces.Discrete
                  ),
                  action_space.spaces,
              )
          )
          if len(discrete_space) > 0:
              new_action_space = {}
              for key in action_space.spaces.keys():
                  if key in discrete_space:
                      new_action_space[key] = OneHotPreProcessor(
                          action_space.spaces[key]
                      ).processed_space()
                  else:
                      new_action_space[key] = action_space.spaces[key]
              action_space = spaces.Dict(new_action_space)
          observation_space = spaces.Dict(
              {**observation_space.spaces, **action_space.spaces}
          )
          value_heads = {"q_value": 1}
      else:
          value_heads = {
              f"{act_key}_q_values": act_space.n
              for act_key, act_space in action_space.spaces.items()
          }
  
      # check if actions are considered as observations for the state-action critic
      for action_head in action_space.spaces.keys():
          if (
              action_head
              not in self.model_builder.observation_modality_mapping
          ):
              BColors.print_colored(
                  f"TemplateModelComposer: The action '{action_head}' could not be found in the "
                  f"model_builder.observation_modality_mapping and wont be considered "
                  f"as an input to the state-action critic!",
                  BColors.FAIL,
              )
  
      # build perception net
      if perception_net is None:
          perception_net = self.template_perception_net(
              observation_space
          )
  
      perception_dict = perception_net.perception_dict
      for value_head, output_units in value_heads.items():
          # initialize action head
          value_net = LinearOutputBlock(
              in_keys="latent",
              out_keys=value_head,
              in_shapes=perception_dict["latent"].out_shapes(),
              output_units=output_units,
          )
  
          module_init = make_module_init_normc(std=0.01)
          value_net.apply(module_init)
  
          # extent perception dictionary
          perception_dict[value_head] = value_net
  
      # compile inference model
      net = InferenceBlock(
          in_keys=perception_net.in_keys,
          out_keys=list(value_heads.keys()),
          in_shapes=perception_net.in_shapes,
          perception_blocks=perception_dict,
      )
  
      return net
  
imports: import functools
  from typing import Optional, Dict, Union, Type, Tuple, List
  from gym import spaces
  from maze.core.agent.torch_policy import TorchPolicy
  from maze.core.agent.torch_state_action_critic import TorchSharedStateActionCritic, TorchStateActionCritic, TorchStepStateActionCritic
  from maze.core.agent.torch_state_critic import TorchStateCritic, TorchSharedStateCritic, TorchStepStateCritic, TorchDeltaStateCritic
  from maze.core.annotations import override
  from maze.core.env.structured_env import StepKeyType
  from maze.core.utils.factory import ConfigType, Factory
  from maze.core.utils.structured_env_utils import flat_structured_space
  from maze.core.wrappers.observation_preprocessing.preprocessors.one_hot import OneHotPreProcessor
  from maze.perception.blocks.inference import InferenceBlock
  from maze.perception.blocks.output.linear import LinearOutputBlock
  from maze.perception.builders.base import BaseModelBuilder
  from maze.perception.models.critics import SharedStateCriticComposer, DeltaStateCriticComposer, StepStateCriticComposer
  from maze.perception.models.critics.critic_composer_interface import CriticComposerInterface
  from maze.perception.models.critics.shared_state_action_critics_composer import SharedStateActionCriticComposer
  from maze.perception.models.critics.step_state_action_critic_composer import StepStateActionCriticComposer
  from maze.perception.models.model_composer import BaseModelComposer
  from maze.perception.models.policies.base_policy_composer import BasePolicyComposer
  from maze.perception.models.policies.probabilistic_policy_composer import ProbabilisticPolicyComposer
  from maze.perception.weight_init import make_module_init_normc
  from maze.utils.bcolors import BColors
label_desc: Use image node_id 6 for calling the TemplateModelComposer obj's underlying member method code with example usage: obj.template_q_value_net(observation_space, action_space, only_discrete_spaces, perception_net) and returns: net