def _run_for_config(
        self, model: ONNXModelHandler, config: type[BasePassConfig], output_model_path: str
    ) -> ONNXModelHandler:
        """Convert model to mixed precision.

        It detects whether original model has fp16 precision weights,
        and set parameters for float16 conversion automatically.
        """
        from onnxruntime.transformers.float16 import float_to_float16_max_diff
        from onnxruntime.transformers.onnx_model import OnnxModel

        onnx_model = OnnxModel(model.load_model())

        op_block_list = config.op_block_list
        op_full_set = {node.op_type for node in onnx_model.nodes()}
        fp32_op_set = set(op_block_list)
        fp16_op_set = op_full_set.difference(fp32_op_set)
        logger.info("fp32 op: %s fp16 op: %s", fp32_op_set, fp16_op_set)

        # logits is the first output
        logits_output_name = onnx_model.graph().output[0].name

        # We use the weight in last MatMul node to detect
        # whether the model is stored with float16 weights from training.
        is_weight_fp16_precision = False
        output_name_to_node = onnx_model.output_name_to_node()
        assert logits_output_name in output_name_to_node
        node = output_name_to_node[logits_output_name]
        last_matmul_node = None
        if node.op_type == "MatMul":
            last_matmul_node = node
            logger.info("Found last MatMul node for logits: %s", node.name)
            initializer = None
            for node_input in node.input:
                initializer = onnx_model.get_initializer(node_input)
                if initializer is not None:
                    break

            # when the max difference of value after converting float to float16 is lower than a threshold (1e-6),
            # we can deduce that the weights are stored in float16 precision.
            max_diff = float_to_float16_max_diff(initializer)
            logger.debug("max diff of converting weights in last MatMul node %s: %s", node.name, max_diff)
            is_weight_fp16_precision = max_diff < config.atol
        else:
            logger.warning("Failed to find MatMul node for logits. Found %s of node %s", node.op_type, node.name)

        keep_io_types = []
        node_block_list = []
        if (not is_weight_fp16_precision) and (last_matmul_node is not None):
            # When original weight is float32 precision,
            # keep logits and last MatMul in float32 could get better precision.
            keep_io_types = [logits_output_name]
            node_block_list = [last_matmul_node.name]

        parameters = {
            "keep_io_types": keep_io_types,
            "op_block_list": list(op_block_list),
            "node_block_list": node_block_list,
            "force_fp16_initializers": is_weight_fp16_precision,
        }

        logger.info("auto_mixed_precision parameters: %s", parameters)
        fp16_model = self._convert_float_to_float16(model=onnx_model.model, use_symbolic_shape_infer=True, **parameters)
        output_model_path = resolve_onnx_path(output_model_path, Path(model.model_path).name)
        return model_proto_to_olive_model(fp16_model, output_model_path, config)
Convert model to mixed precision.

        It detects whether original model has fp16 precision weights,
        and set parameters for float16 conversion automatically.
        
olive/passes/onnx/mixed_precision.py