def op_weight_convert_before_hook(
        self,
        op: Callable,
    ) -> Tuple[Callable, Tuple[Any, ...], Dict[str, Any]]:
        """
        This function is called before an op call in a converted model.
        For each arg in `args`, quantizes it if necessary.
        Returns potentially modified `op`, potentially modified `args`,
        potentially modified `kwargs`.
        """
        (
            arg_quant_infos,
            any_arg_quant_or_dequant_needed,
        ) = self.get_op_weight_convert_info(op)
        new_args = []
        if type(op) in [
            torch.nn.Conv2d,
            torch.nn.Conv3d,
            torch.nn.ConvTranspose2d,
            torch.nn.ConvTranspose3d,
            torch.nn.Linear,
        ]:
            tensor_arg_idx = 0
            quant_info = arg_quant_infos[tensor_arg_idx]
            if (
                quant_info is not None
                and any_arg_quant_or_dequant_needed[tensor_arg_idx]
            ):
                scale, zp, dtype = quant_info
                weight = op.weight
                ch_axis = 0
                if type(op) in [torch.nn.ConvTranspose2d, torch.nn.ConvTranspose3d]:
                    ch_axis = 1
                # Update weight of nn.Linear for SmoothQuant
                wei_key = str(self.idx) + "_0"
                if wei_key in self.idx_to_smooth_quant_scaling_factor:
                    wei_scaling_factors = self.idx_to_smooth_quant_scaling_factor[
                        wei_key
                    ]
                    if wei_scaling_factors is not None:
                        w_dtype = weight.dtype
                        if w_dtype != torch.float32:
                            weight = weight.to(torch.float32)
                        weight = torch.mul(weight, wei_scaling_factors)
                        if w_dtype != torch.float32:
                            weight = weight.to(w_dtype)
                if (
                    torch.is_autocast_enabled("cpu")
                    and torch.get_autocast_dtype("cpu") == torch.bfloat16
                ):
                    if weight.dtype == torch.bfloat16:
                        weight = weight.to(dtype=torch.float32)
                    if scale.numel() > 1:
                        arg = torch.quantize_per_channel(
                            weight, scale, zp, ch_axis, dtype
                        )
                    else:
                        arg = torch.quantize_per_tensor(
                            weight, scale.item(), zp.item(), dtype
                        )
                    arg = arg.dequantize()
                    arg = arg.to(dtype=torch.bfloat16)
                else:
                    if scale.numel() > 1:
                        arg = torch.quantize_per_channel(
                            weight, scale, zp, ch_axis, dtype
                        )
                    else:
                        arg = torch.quantize_per_tensor(
                            weight, scale.item(), zp.item(), dtype
                        )
                    arg = arg.dequantize()
                new_args.append(arg)
            else:
                new_args.append(op.weight)
        elif isinstance(op, torch.nn.EmbeddingBag):
            tensor_arg_idx = 0
            quant_info = arg_quant_infos[tensor_arg_idx]
            if (
                quant_info is not None
                and any_arg_quant_or_dequant_needed[tensor_arg_idx]
            ):
                scale, zp, dtype = quant_info
                weight = op.weight
                if (
                    torch.torch.is_autocast_enabled("cpu")
                    and torch.get_autocast_dtype("cpu") == torch.bfloat16
                ):
                    if weight.dtype == torch.bfloat16:
                        weight = weight.to(dtype=torch.float32)
                    arg = torch.quantize_per_tensor(
                        weight, scale.item(), zp.item(), dtype
                    )
                    arg = arg.dequantize()
                    arg = arg.to(dtype=torch.bfloat16)
                else:
                    arg = torch.quantize_per_tensor(
                        op.weight, scale.item(), zp.item(), dtype
                    )
                    arg = arg.dequantize()
                new_args.append(arg)
            else:
                new_args.append(op.weight)
        elif isinstance(op, MergedEmbeddingBagWithCat):
            weights = op.weights
            for tensor_arg_idx in range(0, len(arg_quant_infos)):
                quant_info = arg_quant_infos[tensor_arg_idx]
                if (
                    quant_info is not None
                    and any_arg_quant_or_dequant_needed[tensor_arg_idx]
                ):
                    scale, zp, dtype = quant_info
                    if (
                        torch.torch.is_autocast_enabled("cpu")
                        and torch.get_autocast_dtype("cpu") == torch.bfloat16
                    ):
                        if weights[tensor_arg_idx].dtype == torch.bfloat16:
                            weights[tensor_arg_idx] = weights[tensor_arg_idx].to(
                                dtype=torch.float32
                            )
                        arg = torch.quantize_per_tensor(
                            weights[tensor_arg_idx], scale.item(), zp.item(), dtype
                        )
                        arg = arg.dequantize()
                        arg = arg.to(dtype=torch.bfloat16)
                    else:
                        arg = torch.quantize_per_tensor(
                            op.weights[tensor_arg_idx], scale.item(), zp.item(), dtype
                        )
                        arg = arg.dequantize()
                    new_args.append(arg)
                else:
                    new_args.append(op.weights[tensor_arg_idx])
        elif isinstance(op, torch.nn.LSTM):
            step = 4 if op.bias else 2
            weights = op._flat_weights
            for tensor_arg_idx in range(0, len(arg_quant_infos), step):
                quant_info = arg_quant_infos[tensor_arg_idx]
                if (
                    quant_info is not None
                    and any_arg_quant_or_dequant_needed[tensor_arg_idx]
                ):
                    w_ih = weights[tensor_arg_idx]
                    w_hh = weights[tensor_arg_idx + 1]
                    w_ih_scale, w_ih_zp, w_ih_dtype = quant_info
                    w_hh_scale, w_hh_zp, w_hh_dtype = arg_quant_infos[
                        tensor_arg_idx + 1
                    ]
                    if (
                        torch.torch.is_autocast_enabled("cpu")
                        and torch.get_autocast_dtype("cpu") == torch.bfloat16
                    ):
                        weight_if_bf16 = w_ih.dtype == torch.bfloat16
                        if weight_if_bf16:
                            w_ih = w_ih.to(dtype=torch.float32)
                            w_hh = w_hh.to(dtype=torch.float32)
                        if w_ih_scale.numel() > 1:
                            w_ih = torch.quantize_per_channel(
                                w_ih, w_ih_scale, w_ih_zp, 0, w_ih_dtype
                            )
                            w_hh = torch.quantize_per_channel(
                                w_hh, w_hh_scale, w_hh_zp, 0, w_hh_dtype
                            )
                        else:
                            w_ih = torch.quantize_per_tensor(
                                w_ih, w_ih_scale.item(), w_ih_zp.item(), w_ih_dtype
                            )
                            w_hh = torch.quantize_per_tensor(
                                w_hh, w_hh_scale.item(), w_hh_zp.item(), w_hh_dtype
                            )
                        w_ih = w_ih.dequantize()
                        w_hh = w_hh.dequantize()
                        if weight_if_bf16:
                            w_ih = w_ih.to(dtype=torch.bfloat16)
                            w_hh = w_hh.to(dtype=torch.bfloat16)
                    else:
                        if w_ih_scale.numel() > 1:
                            w_ih = torch.quantize_per_channel(
                                w_ih, w_ih_scale, w_ih_zp, 0, w_ih_dtype
                            )
                            w_hh = torch.quantize_per_channel(
                                w_hh, w_hh_scale, w_hh_zp, 0, w_hh_dtype
                            )
                        else:
                            w_ih = torch.quantize_per_tensor(
                                w_ih, w_ih_scale, w_ih_zp, w_ih_dtype
                            )
                            w_hh = torch.quantize_per_tensor(
                                w_hh, w_hh_scale, w_hh_zp, w_hh_dtype
                            )
                        w_ih = w_ih.dequantize()
                        w_hh = w_hh.dequantize()
                    new_args.append(w_ih)
                    new_args.append(w_hh)
                    if op.bias:
                        new_args.append(weights[tensor_arg_idx + 2])
                        new_args.append(weights[tensor_arg_idx + 3])
                else:
                    for s in range(step):
                        new_args.append(weights[tensor_arg_idx + s])

        return new_args

        This function is called before an op call in a converted model.
        For each arg in `args`, quantizes it if necessary.
        Returns potentially modified `op`, potentially modified `args`,
        potentially modified `kwargs`.
        
intel_extension_for_pytorch/quantization/_quantization_state.py