class_docstr: Composes models from explicit model definitions.
  
  :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 policy: Mapping of sub-step keys to models.
  :param critic: Configuration for the critic composer.
code: def __init__(
      self,
      action_spaces_dict: Dict[StepKeyType, gym.spaces.Dict],
      observation_spaces_dict: Dict[StepKeyType, gym.spaces.Dict],
      agent_counts_dict: Dict[StepKeyType, int],
      distribution_mapper_config: ConfigType,
      policy: ConfigType,
      critic: ConfigType,
  ):
      super().__init__(
          action_spaces_dict,
          observation_spaces_dict,
          agent_counts_dict,
          distribution_mapper_config,
      )
  
      # init policy composer
      self._policy_composer = Factory(BasePolicyComposer).instantiate(
          policy,
          action_spaces_dict=self.action_spaces_dict,
          observation_spaces_dict=self.observation_spaces_dict,
          agent_counts_dict=self.agent_counts_dict,
          distribution_mapper=self._distribution_mapper,
      )
  
      self.critic_input_spaces_dict = (
          self._build_critic_input_space_dict()
      )
  
      # init critic composer
      self._critics_composer = None
      if critic is not None:
          critic_type = (
              Factory(CriticComposerInterface).type_from_name(
                  critic["_target_"]
              )
              if isinstance(critic, Mapping)
              else type(critic)
          )
          if issubclass(critic_type, SharedStateCriticComposer):
              assert (
                  self.critic_input_spaces_dict
                  == self.observation_spaces_dict
              ), f"Shared embedding is not yet supported for shared state critics"
  
          if issubclass(critic_type, BaseStateCriticComposer):
              self._critics_composer = Factory(
                  BaseStateCriticComposer
              ).instantiate(
                  critic,
                  observation_spaces_dict=self.critic_input_spaces_dict,
                  agent_counts_dict=self.agent_counts_dict,
              )
          elif issubclass(critic_type, BaseStateActionCriticComposer):
              assert (
                  self.critic_input_spaces_dict
                  == self.observation_spaces_dict
              ), f"Shared embedding is not yet supported for state-action critics"
              self._critics_composer = Factory(
                  BaseStateActionCriticComposer
              ).instantiate(
                  critic,
                  observation_spaces_dict=self.critic_input_spaces_dict,
                  action_spaces_dict=self.action_spaces_dict,
              )
          else:
              raise ValueError(
                  f"Critic of type {critic_type} not supported!"
              )
  
      # save model graphs to pdf
      self.save_models()
  
imports: import copy
  from typing import Dict, Union, Optional, Mapping
  import gym
  import numpy
  from gym import spaces
  from maze.core.agent.state_critic_input_output import StateCriticStepInput
  from maze.core.agent.torch_policy import TorchPolicy
  from maze.core.agent.torch_state_action_critic import TorchStateActionCritic
  from maze.core.agent.torch_state_critic import TorchStateCritic
  from maze.core.annotations import override
  from maze.core.env.structured_env import StepKeyType, ActorID
  from maze.core.utils.factory import Factory, ConfigType
  from maze.perception.models.critics import BaseStateCriticComposer, SharedStateCriticComposer
  from maze.perception.models.critics.base_state_action_critic_composer import BaseStateActionCriticComposer
  from maze.perception.models.critics.critic_composer_interface import CriticComposerInterface
  from maze.perception.models.model_composer import BaseModelComposer
  from maze.perception.models.policies.base_policy_composer import BasePolicyComposer
  from maze.perception.perception_utils import map_nested_structure
label_desc: Use image node_id 2 to create a new CustomModelComposer object from inherited base classes: BaseModelComposer with example: obj = CustomModelComposer(action_spaces_dict, observation_spaces_dict, agent_counts_dict, distribution_mapper_config, policy, critic)