def attach_scale_zp_values_to_model(
    module: torch.nn.Module,
) -> None:
    """
    Calculates the scale and zero_point from each observer and attaches
    these values to the parent module. This is done to avoid recalculating
    these values at inference.
    """
    if hasattr(module, "_auto_quant_state"):
        qstate: AutoQuantizationState = module._auto_quant_state  # type: ignore[assignment]
        quantized_dtype = [torch.quint8, torch.qint8]
        for tensor_id, observer in qstate.tensor_id_to_observer.items():
            if observer.dtype in quantized_dtype:
                scale, zp = observer.calculate_qparams()
                qstate.tensor_id_to_scale_zp[int(tensor_id)] = (scale, zp)
            else:
                AssertionError(
                    False
                ), "The observer's dtype only can be torch.quint8 or torch.qint8"
        for tensor_id, observer in qstate.weight_tensor_id_to_observer.items():
            if observer.dtype in quantized_dtype:
                scale, zp = observer.calculate_qparams()
                qstate.weight_tensor_id_to_scale_zp[tensor_id] = (scale, zp)
            else:
                AssertionError(
                    False
                ), "The observer's dtype only can be torch.quint8 or torch.qint8"
        _attach_smooth_quant_scaling_factor_to_model(module)
        qstate.tensor_id_to_observer.clear()
        qstate.weight_tensor_id_to_observer.clear()

    for _, child in module.named_children():
        attach_scale_zp_values_to_model(child)

    Calculates the scale and zero_point from each observer and attaches
    these values to the parent module. This is done to avoid recalculating
    these values at inference.
    
intel_extension_for_pytorch/quantization/_utils.py