code: def _maybe_insert_observers_before_graph_output(
      graph_output_node: Node,
      model: torch.nn.Module,
      named_modules: Dict[str, torch.nn.Module],
      graph: Graph,
      obs_or_fq_map: Dict[EdgeOrNode, ObserverOrFakeQuantize],
      is_qat: bool,
  ) -> None:
      """
      If the output needs to be quantized and there are any nodes
      in the output which are not already observed, inserts observers
      for those nodes.
      """
  
      def _recursive_maybe_replace_node_with_obs(
          maybe_node: Argument,
          model: torch.nn.Module,
          named_modules: Dict[str, torch.nn.Module],
          graph: Graph,
      ) -> Argument:
          """
          Navigate an arbitrary data structure of lists, tuples, dicts.
          For each container type, recurse on all inputs. Once any Node
          is found, insert an observer if needed and do not recurse further.
  
          For example, given a structure of
  
            {'foo1': [[bar1]], 'foo2': {'foo3': [[[bar3]]]}}
  
          we recurse down to bar1 and bar3, observe them if necessary,
          and if we inserted an observer then replace the original node
          with its observer.
  
          Returns the data structure with all nodes needing observation being
          replaced by their observers.
          """
          if isinstance(maybe_node, Node):
              # check dtype of this node
              arg_as_output_target_dtype = (
                  _get_arg_target_dtype_as_output(
                      maybe_node, named_modules, obs_or_fq_map, is_qat
                  )
              )
              observer_mod = None
              arg_as_input_target_dtype = torch.float
              if "target_dtype_info" in maybe_node.meta:
                  observer_cls = maybe_node.meta[
                      "target_dtype_info"
                  ].get("input_act_obs_or_fq_ctr", None)
                  if observer_cls is not None:
                      observer_mod = observer_cls()
                      arg_as_input_target_dtype = observer_mod.dtype
              # TODO: this does not handle dynamic quantization yet
              need_obs = (
                  arg_as_output_target_dtype
                  != arg_as_input_target_dtype
                  and arg_as_input_target_dtype != torch.float
              )
              if need_obs:
                  assert observer_mod is not None
                  # insert observer
                  observer_node = _insert_obs_or_fq(
                      maybe_node,
                      observer_mod,
                      model,
                      named_modules,
                      graph,
                  )
                  return observer_node
              else:
                  return maybe_node
          elif isinstance(maybe_node, (list, tuple)):
              results = []
              for inner_node in maybe_node:
                  results.append(
                      _recursive_maybe_replace_node_with_obs(
                          inner_node, model, named_modules, graph
                      )
                  )
              if isinstance(maybe_node, list):
                  return results
              else:
                  return tuple(results)
          elif isinstance(maybe_node, dict):
              results_dict = {}
              for k, inner_v in maybe_node.items():
                  results_dict[
                      k
                  ] = _recursive_maybe_replace_node_with_obs(
                      inner_v, model, named_modules, graph
                  )
              return results_dict
          elif maybe_node is None:
              return None
          else:
              raise Exception(
                  "Unhandled type for returned node:", maybe_node
              )
  
      new_args = []
      for old_arg in graph_output_node.args:
          new_args.append(
              _recursive_maybe_replace_node_with_obs(
                  old_arg, model, named_modules, graph
              )
          )
  
      graph_output_node.args = tuple(new_args)
  
imports: import copy
  import torch
  import warnings
  from torch.fx import GraphModule
  from torch.fx.graph import Graph, Node
  from torch.fx.node import Argument
  from ..quantize import propagate_qconfig_
  from ..observer import _is_activation_post_process, _PartialWrapper
  from ..qconfig import _is_reuse_input_qconfig, QConfigAny
  from ..qconfig_mapping import QConfigMapping
  from .qconfig_mapping_utils import _generate_node_name_to_qconfig, _update_qconfig_for_fusion, _get_flattened_qconfig_dict, _update_qconfig_for_qat
  from .quantize_handler import _default_root_node_getter, _get_pattern_to_quantize_handlers, QuantizeHandler
  from torch.ao.quantization import ObserverBase, FixedQParamsObserver, FixedQParamsFakeQuantize, _DerivedObserverOrFakeQuantize
  from torch.ao.quantization.utils import Pattern, NodePattern
  from ._equalize import is_equalization_observer, node_supports_equalization
  from .pattern_utils import _sorted_patterns_dict
  from .match_utils import _MatchResultWithQConfig, _find_matches
  from .utils import _insert_dequant_stubs_for_custom_module_lstm_output, _is_custom_module_lstm, _maybe_get_custom_module_lstm_from_node_arg, _qconfig_satisfies_dtype_config_constraints, get_custom_module_class_keys, all_node_args_have_no_tensors, assert_and_get_unique_device, get_non_observable_arg_indexes_and_types, get_new_attr_name_with_prefix, node_arg_is_weight, node_arg_is_bias, NON_QUANTIZABLE_WEIGHT_OPS, ObservedGraphModuleAttrs
  from torch.ao.quantization import PlaceholderObserver
  from torch.ao.quantization.quantize import convert
  from ..utils import _parent_name, get_qconfig_dtypes, get_swapped_custom_module_class
  from ..backend_config.utils import get_pattern_to_dtype_configs, get_module_to_qat_module, get_fusion_pattern_to_root_node_getter
  from ..backend_config import BackendConfig, DTypeConfig, get_native_backend_config
  from .custom_config import PrepareCustomConfig, StandaloneModuleConfigEntry
  from torch.ao.quantization.quantizer import EdgeOrNode, QuantizationSpec, QuantizationSpecBase, FixedQParamsQuantizationSpec, SharedQuantizationSpec, DerivedQuantizationSpec
  from torch.ao.quantization import ObserverOrFakeQuantize
  from torch._subclasses import FakeTensor
  from typing import Any, Dict, List, Optional, Set, Tuple, Type, Union
  from dataclasses import asdict
label_desc: Use image node_id 24 for calling a global function with example usage: _maybe_insert_observers_before_graph_output(graph_output_node, model, named_modules, graph, obs_or_fq_map, is_qat) and returns: observer_node, maybe_node, results, tuple, results_dict, None