def __init__(
        self,
        loaded_model: Union[RecursiveScriptModule, "ExportedProgram"],
        inputs: Optional[List[TensorType]] = None,
        outputs: Optional[List[TensorType]] = None,
        cut_at_symbols: Optional[List[str]] = None,
        opset_version: Optional[int] = None,
        use_default_fp16_io: bool = False,
        states: Optional[List[StateType]] = None,
    ) -> None:
        """
        Arguments:
            loaded_model: It could be one of the following:
                    - In-memory TorchScript model of type torch.jit.ScriptModule
                    - In-memory EXIR program of type ExportedProgram
            inputs: Input values and optional names. See kwarg in load.py for full description.
            outputs: List of outputs as ct.InputType. See kwarg in load.py for full description.
            cut_at_symbols: A list of internal symbol name strings. Graph conversion will
                terminate once these symbols have been generated. For debugging use
                only. See kwarg in load.py.
            opset_version: An int represents the Core ML opset version.
            use_default_fp16_io (optional): bool. Defaults to False.
                When minimum_deployment_target set >= ct.target.iOS16 (the same as ct.target.macOS13),
                and the compute precision set to fp16, this flag is True.
                When True, fp32 i/o defaults to fp16.
        """
        self.use_default_fp16_io = use_default_fp16_io

        # process inputs
        if inputs is None:
            inputs = []
        allow_default_shape = _HAS_TORCH_EXPORT_API and isinstance(loaded_model, ExportedProgram)
        self.inputs = _convert_to_torch_inputtype(inputs, allow_default_shape=allow_default_shape)
        for idx, inp in enumerate(self.inputs):
            if isinstance(inp, ImageType) and self.inputs[idx].channel_first is None:
                self.inputs[idx].channel_first = True

        # process states
        if states is None:
            states = []
        self.states = states

        if self.use_default_fp16_io:
            # If the input type is not specified by the user and use_default_fp16_io
            # is True. Make the default input type to fp16
            self._adjust_default_input_to_fp16()

        if outputs is not None:
            if any(map(
                    lambda o: isinstance(o, ImageType) and o.grayscale_use_uint8,
                    outputs
            )):
                raise ValueError("'grayscale_use_uint8' can not be set on image output")
        self.outputs = outputs
        self.output_names = frontend_utils.get_output_names(self.outputs)
        self.opset_version = _target(opset_version) if opset_version is not None else None
        self._prog = mil.Program()

        if isinstance(loaded_model, torch.jit.ScriptModule):
            self.context = TranscriptionContext(frontend=TorchFrontend.TORCHSCRIPT)
            self.graph = InternalTorchIRGraph.from_torchscript(
                torchscript=loaded_model, inputs=self.inputs, cut_at_symbols=cut_at_symbols
            )

            # TODO (rdar://106161395): Register Torch IR passes and unify them into the pass pipeline.
            # Apply Torch IR passes
            passes = [
                transform_inplace_ops,
                flatten_graph_input_values,
                flatten_graph_output_values,
                remove_getattr_nodes,
                generate_tensor_assignment_ops,
                populate_native_const_model_hierarchy,
            ]
            for p in passes:
                p(self.graph)

            # finalize inputs after internal graph gets settled
            self.inputs = list(self.graph.inputs.values())

        elif _HAS_TORCH_EXPORT_API and isinstance(loaded_model, ExportedProgram):
            if loaded_model.dialect == "ATEN":
                frontend = TorchFrontend.TORCHEXPORT
            elif loaded_model.dialect == "EDGE":
                frontend = TorchFrontend.EXECUTORCH
            else:
                raise NotImplementedError(
                    "Conversion for models with only ATEN or EDGE dialect is supported/tested. "
                    f"Provided Dialect: {loaded_model.dialect}"
                )
            self.context = TranscriptionContext(frontend=frontend)
            self.graph = InternalTorchIRGraph.from_exir(
                exir=loaded_model, cut_at_symbols=cut_at_symbols
            )

            # finalize inputs after internal graph gets settled
            self.inputs = self._match_user_exir_inputs(inputs)

            if states is None or len(states) == 0:
                # For torch.export, we default to create states from torch mutable buffers
                self.states = []
                for name, tensor in self.graph.buffers.items():
                    dtype = NUM_TO_NUMPY_DTYPE[TORCH_DTYPE_TO_NUM[tensor.dtype]]
                    if dtype != np.float16:
                        logger.warning(
                            "Core ML only supports fp16 states, "
                            f"so buffer {name} has been cast to fp16"
                        )
                        dtype = np.float16
                    state = StateType(
                        wrapped_type=TensorType(shape=tensor.shape, dtype=dtype), name=name
                    )
                    self.states.append(state)

        else:
            raise ValueError(
                "Model should be an instance of either torch.jit.ScriptModule or ExportedProgram"
            )

        self.context.torch_graph = self.graph
        self._validate_states()

        # Store the mapping from parameter name (such as "dense1.weight") to the compression info.
        self.param_to_compression_info: Dict[str, CompressionInfo] = dict()
        if self.opset_version is not None and self.opset_version >= _target.iOS16:
            # Notice that even the compression info in registered buffer is kept in self.graph,
            # we still want to explicitly construct it here, to make it useful for both TorchScript
            # and ExportedProgram.
            state_dict = loaded_model.state_dict
            self.param_to_compression_info = self._construct_compression_info(
                state_dict() if callable(state_dict) else state_dict
            )
            if self.context.frontend in TORCH_EXPORT_BASED_FRONTENDS:
                # For EXIR, all param names are lifted as input names (in the format of `argx_x`), so we need to
                # change names accordingly to make sure the compression info could be found later.
                for (
                    arg_name,
                    param_name,
                ) in loaded_model.graph_signature.inputs_to_parameters.items():
                    if param_name in self.param_to_compression_info:
                        self.param_to_compression_info[arg_name] = self.param_to_compression_info[
                            param_name
                        ]
                        del self.param_to_compression_info[param_name]

        Arguments:
            loaded_model: It could be one of the following:
                    - In-memory TorchScript model of type torch.jit.ScriptModule
                    - In-memory EXIR program of type ExportedProgram
            inputs: Input values and optional names. See kwarg in load.py for full description.
            outputs: List of outputs as ct.InputType. See kwarg in load.py for full description.
            cut_at_symbols: A list of internal symbol name strings. Graph conversion will
                terminate once these symbols have been generated. For debugging use
                only. See kwarg in load.py.
            opset_version: An int represents the Core ML opset version.
            use_default_fp16_io (optional): bool. Defaults to False.
                When minimum_deployment_target set >= ct.target.iOS16 (the same as ct.target.macOS13),
                and the compute precision set to fp16, this flag is True.
                When True, fp32 i/o defaults to fp16.
        
coremltools/converters/mil/frontend/torch/converter.py