From b748aa40df8cdbde5737e2b1b371594d829dc74c Mon Sep 17 00:00:00 2001 From: Hem Agnihotri Date: Wed, 4 Jun 2025 09:50:52 +0000 Subject: [PATCH 1/3] Adding QEFF logger Signed-off-by: Hem Agnihotri --- QEfficient/__init__.py | 8 +- QEfficient/base/modeling_qeff.py | 9 +- QEfficient/cloud/export.py | 4 +- QEfficient/cloud/infer.py | 4 +- QEfficient/compile/compile_helper.py | 4 +- QEfficient/compile/qnn_compiler.py | 4 +- .../exporter/export_hf_to_cloud_ai_100.py | 4 +- .../generation/text_generation_inference.py | 4 +- QEfficient/peft/auto.py | 4 +- QEfficient/peft/lora/auto.py | 4 +- .../models/granitemoe/modeling_granitemoe.py | 10 +- .../models/internvl/modeling_internvl.py | 4 +- .../llama_swiftkv/modeling_llama_swiftkv.py | 7 +- .../models/llava/modeling_llava.py | 4 +- .../models/llava_next/modeling_llava_next.py | 6 +- .../models/mistral/modeling_mistral.py | 4 +- .../models/mllama/modeling_mllama.py | 4 +- .../transformers/models/modeling_auto.py | 4 +- .../models/whisper/modeling_whisper.py | 4 +- .../transformers/quantizers/quantizer_awq.py | 4 +- .../quantizer_compressed_tensors.py | 4 +- .../transformers/quantizers/quantizer_gptq.py | 4 +- QEfficient/transformers/transform.py | 4 +- QEfficient/utils/_utils.py | 4 +- QEfficient/utils/device_utils.py | 4 +- QEfficient/utils/logging_utils.py | 115 ++++++++++-------- .../cpp_execution/text_inference_using_cpp.py | 7 +- examples/intern_example/internvl_inference.py | 4 +- tests/cloud/conftest.py | 4 +- .../test_transformer_pytorch_transforms.py | 4 +- 30 files changed, 167 insertions(+), 87 deletions(-) diff --git a/QEfficient/__init__.py b/QEfficient/__init__.py index be4b86321..4bf9b1e78 100644 --- a/QEfficient/__init__.py +++ b/QEfficient/__init__.py @@ -5,6 +5,7 @@ # # ----------------------------------------------------------------------------- +import atexit import os import warnings @@ -16,7 +17,12 @@ os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1" # Placeholder for all non-transformer models registered in QEfficient import QEfficient.utils.model_registery # noqa: F401 -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() + +# Register the cleanup function +atexit.register(QEFFLogger.close_logger) # custom warning for the better logging experience warnings.formatwarning = custom_format_warning diff --git a/QEfficient/base/modeling_qeff.py b/QEfficient/base/modeling_qeff.py index d9d6823ae..d2bf1ee9c 100644 --- a/QEfficient/base/modeling_qeff.py +++ b/QEfficient/base/modeling_qeff.py @@ -7,7 +7,6 @@ import hashlib import inspect -import logging import shutil import subprocess import warnings @@ -24,8 +23,9 @@ from QEfficient.generation.cloud_infer import QAICInferenceSession from QEfficient.utils import constants, create_json, dump_qconfig, generate_mdp_partition_config, load_json from QEfficient.utils.cache import QEFF_HOME, to_hashable +from QEfficient.utils.logging_utils import QEFFLogger -logger = logging.getLogger(__name__) +logger = QEFFLogger.get_logger() class QEFFBaseModel(ABC): @@ -63,6 +63,11 @@ def __init__(self, model: torch.nn.Module) -> None: else: logger.info(f"Pytorch transforms applied to model: {self.model_name}") + def set_loglevel(loglevel: Optional[str] = "INFO"): + QEFFLogger.set_loglevel(loglevel) + logger.info(f"log level to be set is: {loglevel}") + logger.debug(f"log level set to: {loglevel}") + @property @abstractmethod def model_name(self) -> str: ... diff --git a/QEfficient/cloud/export.py b/QEfficient/cloud/export.py index 849325c9d..93985ef07 100644 --- a/QEfficient/cloud/export.py +++ b/QEfficient/cloud/export.py @@ -11,7 +11,9 @@ from QEfficient.base.common import QEFFCommonLoader from QEfficient.utils import check_and_assign_cache_dir -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() # Specifically for Docker images. ROOT_DIR = os.path.dirname(os.path.abspath("")) diff --git a/QEfficient/cloud/infer.py b/QEfficient/cloud/infer.py index 1c620ad7d..887f51d60 100644 --- a/QEfficient/cloud/infer.py +++ b/QEfficient/cloud/infer.py @@ -17,7 +17,9 @@ from QEfficient.base.common import QEFFCommonLoader from QEfficient.utils import check_and_assign_cache_dir, load_hf_processor, load_hf_tokenizer -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() # TODO: Remove after adding support for VLM's compile and execute diff --git a/QEfficient/compile/compile_helper.py b/QEfficient/compile/compile_helper.py index 56177cce9..c50aabc01 100644 --- a/QEfficient/compile/compile_helper.py +++ b/QEfficient/compile/compile_helper.py @@ -14,7 +14,9 @@ from QEfficient.compile.qnn_compiler import compile as qnn_compile from QEfficient.utils._utils import load_json, load_yaml -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() def create_and_dump_specializations( diff --git a/QEfficient/compile/qnn_compiler.py b/QEfficient/compile/qnn_compiler.py index 0f862b972..9d1644d3b 100644 --- a/QEfficient/compile/qnn_compiler.py +++ b/QEfficient/compile/qnn_compiler.py @@ -18,7 +18,9 @@ generate_data_format_config, generate_qnn_specialization, ) -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QNN: diff --git a/QEfficient/exporter/export_hf_to_cloud_ai_100.py b/QEfficient/exporter/export_hf_to_cloud_ai_100.py index b769680ef..9538ae351 100644 --- a/QEfficient/exporter/export_hf_to_cloud_ai_100.py +++ b/QEfficient/exporter/export_hf_to_cloud_ai_100.py @@ -20,7 +20,9 @@ from QEfficient.utils import load_hf_tokenizer from QEfficient.utils.constants import QEFF_MODELS_DIR, Constants from QEfficient.utils.generate_inputs import InputHandler -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() def convert_to_cloud_bertstyle( diff --git a/QEfficient/generation/text_generation_inference.py b/QEfficient/generation/text_generation_inference.py index fd7ef03ff..7fa274d80 100755 --- a/QEfficient/generation/text_generation_inference.py +++ b/QEfficient/generation/text_generation_inference.py @@ -18,7 +18,9 @@ from QEfficient.generation.cloud_infer import QAICInferenceSession from QEfficient.utils import padding_check_and_fix -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() @dataclass diff --git a/QEfficient/peft/auto.py b/QEfficient/peft/auto.py index f475ad4ad..1488c8093 100644 --- a/QEfficient/peft/auto.py +++ b/QEfficient/peft/auto.py @@ -6,7 +6,6 @@ # ---------------------------------------------------------------------------- import hashlib -import logging import warnings from typing import List, Optional, Union @@ -28,8 +27,9 @@ from QEfficient.utils import constants from QEfficient.utils._utils import get_padding_shape_from_config from QEfficient.utils.cache import to_hashable +from QEfficient.utils.logging_utils import QEFFLogger -logger = logging.getLogger(__name__) +logger = QEFFLogger.get_logger() class QEffAutoPeftModelForCausalLM(QEFFBaseModel): diff --git a/QEfficient/peft/lora/auto.py b/QEfficient/peft/lora/auto.py index 1e83c18c9..5daf76832 100644 --- a/QEfficient/peft/lora/auto.py +++ b/QEfficient/peft/lora/auto.py @@ -19,7 +19,9 @@ from QEfficient.peft.lora.pytorch_transforms import LoraModelInputsTransform, TargetModulesTransform from QEfficient.utils import constants, get_padding_shape_from_config from QEfficient.utils.cache import to_hashable -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffAutoLoraModelForCausalLM(QEFFAutoModelForCausalLM): diff --git a/QEfficient/transformers/models/granitemoe/modeling_granitemoe.py b/QEfficient/transformers/models/granitemoe/modeling_granitemoe.py index 6e99e2ffa..053a031f1 100644 --- a/QEfficient/transformers/models/granitemoe/modeling_granitemoe.py +++ b/QEfficient/transformers/models/granitemoe/modeling_granitemoe.py @@ -22,13 +22,15 @@ GraniteMoeRotaryEmbedding, GraniteMoeTopKGating, load_balancing_loss_func, - logger, repeat_kv, rotate_half, ) from QEfficient.transformers.cache_utils import QEffDynamicCache from QEfficient.transformers.modeling_attn_mask_utils import _create_causal_mask +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffGraniteMoeRotaryEmbedding(GraniteMoeRotaryEmbedding): @@ -199,9 +201,7 @@ def forward( raise ValueError("You must specify exactly one of input_ids or inputs_embeds") if self.gradient_checkpointing and self.training and use_cache: - logger.warning_once( - "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`." - ) + logger.warning("`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`.") use_cache = False if inputs_embeds is None: @@ -216,7 +216,7 @@ def forward( past_key_values = QEffDynamicCache() else: past_key_values = QEffDynamicCache.from_legacy_cache(past_key_values) - logger.warning_once( + logger.warning( "We detected that you are passing `past_key_values` as a tuple of tuples. This is deprecated and " "will be removed in v4.47. Please convert your cache or use an appropriate `Cache` class " "(https://huggingface.co/docs/transformers/kv_cache#legacy-cache-format)" diff --git a/QEfficient/transformers/models/internvl/modeling_internvl.py b/QEfficient/transformers/models/internvl/modeling_internvl.py index b6fb9fd38..62794c113 100644 --- a/QEfficient/transformers/models/internvl/modeling_internvl.py +++ b/QEfficient/transformers/models/internvl/modeling_internvl.py @@ -11,7 +11,9 @@ from QEfficient.utils import constants from QEfficient.utils._utils import IOInfo, get_padding_shape_from_config -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffInternEncoderWrapper(nn.Module): diff --git a/QEfficient/transformers/models/llama_swiftkv/modeling_llama_swiftkv.py b/QEfficient/transformers/models/llama_swiftkv/modeling_llama_swiftkv.py index 7b96aefcc..3b4451e3d 100644 --- a/QEfficient/transformers/models/llama_swiftkv/modeling_llama_swiftkv.py +++ b/QEfficient/transformers/models/llama_swiftkv/modeling_llama_swiftkv.py @@ -20,7 +20,7 @@ from transformers.modeling_attn_mask_utils import AttentionMaskConverter from transformers.modeling_outputs import CausalLMOutputWithPast from transformers.modeling_utils import PreTrainedModel -from transformers.models.llama.modeling_llama import LlamaMLP, LlamaRMSNorm, logger, repeat_kv +from transformers.models.llama.modeling_llama import LlamaMLP, LlamaRMSNorm, repeat_kv from QEfficient.transformers.cache_utils import QEffDynamicCache from QEfficient.transformers.modeling_attn_mask_utils import _create_causal_mask @@ -29,6 +29,9 @@ QEffLlamaRotaryEmbedding, qeff_apply_rotary_pos_emb, ) +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffLlamaSwiftKVConfig(LlamaConfig): @@ -302,7 +305,7 @@ def forward( past_key_values = QEffDynamicCache() else: past_key_values = QEffDynamicCache.from_legacy_cache(past_key_values) - logger.warning_once( + logger.warning( "We detected that you are passing `past_key_values` as a tuple of tuples. This is deprecated and " "will be removed in v4.47. Please convert your cache or use an appropriate `Cache` class " "(https://huggingface.co/docs/transformers/kv_cache#legacy-cache-format)" diff --git a/QEfficient/transformers/models/llava/modeling_llava.py b/QEfficient/transformers/models/llava/modeling_llava.py index 99384cb55..65bc86989 100644 --- a/QEfficient/transformers/models/llava/modeling_llava.py +++ b/QEfficient/transformers/models/llava/modeling_llava.py @@ -13,7 +13,9 @@ ) from QEfficient.utils._utils import IOInfo -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() BS = 1 NUM_CHANNEL = 3 diff --git a/QEfficient/transformers/models/llava_next/modeling_llava_next.py b/QEfficient/transformers/models/llava_next/modeling_llava_next.py index 23434fc18..f969b5045 100755 --- a/QEfficient/transformers/models/llava_next/modeling_llava_next.py +++ b/QEfficient/transformers/models/llava_next/modeling_llava_next.py @@ -16,7 +16,9 @@ from QEfficient.utils import constants from QEfficient.utils._utils import IOInfo -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffLlavaNextEncoderWrapper(nn.Module): @@ -65,7 +67,7 @@ def forward(self, pixel_values, image_sizes): np.prod(image_feature.shape) % (num_patch_height * num_patch_width * height * width) != 0 and vision_feature_select_strategy == "default" ): - logger.warning_once( + logger.warning( "Image feature shape does not line up with the provided patch size. " "You may be using the `default` vision_feature_select_strategy with a" " visual encoder that does not have CLS." diff --git a/QEfficient/transformers/models/mistral/modeling_mistral.py b/QEfficient/transformers/models/mistral/modeling_mistral.py index 59c19baa2..6c0e9cc46 100644 --- a/QEfficient/transformers/models/mistral/modeling_mistral.py +++ b/QEfficient/transformers/models/mistral/modeling_mistral.py @@ -24,13 +24,15 @@ MistralForCausalLM, MistralModel, MistralRotaryEmbedding, - logger, repeat_kv, rotate_half, ) from QEfficient.transformers.cache_utils import QEffDynamicCache from QEfficient.transformers.modeling_attn_mask_utils import _create_causal_mask +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffMistralRotaryEmbedding(MistralRotaryEmbedding): diff --git a/QEfficient/transformers/models/mllama/modeling_mllama.py b/QEfficient/transformers/models/mllama/modeling_mllama.py index 1cfafae58..2fdcc9d62 100644 --- a/QEfficient/transformers/models/mllama/modeling_mllama.py +++ b/QEfficient/transformers/models/mllama/modeling_mllama.py @@ -30,7 +30,6 @@ MllamaTextModel, MllamaTextSelfAttention, MllamaVisionModel, - logger, repeat_kv, rotate_half, ) @@ -43,6 +42,9 @@ ) from QEfficient.utils import constants from QEfficient.utils._utils import IOInfo +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() MAX_NUM_IMG = 1 NUM_CHANNEL = 3 diff --git a/QEfficient/transformers/models/modeling_auto.py b/QEfficient/transformers/models/modeling_auto.py index 2f3ee3dc0..64c196bbb 100644 --- a/QEfficient/transformers/models/modeling_auto.py +++ b/QEfficient/transformers/models/modeling_auto.py @@ -57,7 +57,9 @@ get_padding_shape_from_config, ) from QEfficient.utils.cache import to_hashable -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEFFTransformersBase(QEFFBaseModel): diff --git a/QEfficient/transformers/models/whisper/modeling_whisper.py b/QEfficient/transformers/models/whisper/modeling_whisper.py index 2dda9ed96..82651cfb5 100644 --- a/QEfficient/transformers/models/whisper/modeling_whisper.py +++ b/QEfficient/transformers/models/whisper/modeling_whisper.py @@ -24,12 +24,14 @@ WhisperForConditionalGeneration, WhisperModel, WhisperPositionalEmbedding, - logger, ) from QEfficient.transformers.cache_utils import QEffEncoderDecoderCache from QEfficient.transformers.modeling_attn_mask_utils import _create_causal_mask from QEfficient.utils._utils import IOInfo +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffWhisperPositionalEmbedding(WhisperPositionalEmbedding): diff --git a/QEfficient/transformers/quantizers/quantizer_awq.py b/QEfficient/transformers/quantizers/quantizer_awq.py index ef8a03521..c026ea881 100644 --- a/QEfficient/transformers/quantizers/quantizer_awq.py +++ b/QEfficient/transformers/quantizers/quantizer_awq.py @@ -15,7 +15,9 @@ replace_linear_layer_with_target_layer, replace_quantization_scales, ) -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffAwqConfig(AwqConfig): diff --git a/QEfficient/transformers/quantizers/quantizer_compressed_tensors.py b/QEfficient/transformers/quantizers/quantizer_compressed_tensors.py index e7e14166d..f0a524ece 100644 --- a/QEfficient/transformers/quantizers/quantizer_compressed_tensors.py +++ b/QEfficient/transformers/quantizers/quantizer_compressed_tensors.py @@ -14,7 +14,9 @@ from transformers.utils.quantization_config import CompressedTensorsConfig, QuantizationConfigMixin, QuantizationMethod from QEfficient.transformers.quantizers.quantizer_utils import get_keys_to_not_convert -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() FP8_DTYPE = torch.float8_e4m3fn diff --git a/QEfficient/transformers/quantizers/quantizer_gptq.py b/QEfficient/transformers/quantizers/quantizer_gptq.py index 8a0bea1a2..b4bdb0564 100644 --- a/QEfficient/transformers/quantizers/quantizer_gptq.py +++ b/QEfficient/transformers/quantizers/quantizer_gptq.py @@ -15,7 +15,9 @@ repack_zeros, replace_linear_layer_with_target_layer, ) -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class QEffGPTQConfig(GPTQConfig): diff --git a/QEfficient/transformers/transform.py b/QEfficient/transformers/transform.py index 11d7c1dfd..18c0387de 100644 --- a/QEfficient/transformers/transform.py +++ b/QEfficient/transformers/transform.py @@ -13,7 +13,9 @@ from QEfficient.base.modeling_qeff import QEFFBaseModel from QEfficient.transformers.cache_utils import QEffDynamicCache from QEfficient.transformers.modeling_utils import TransformersToQEffModulesDict -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() def replace_module_with_qeff_layers(model: nn.Module) -> None: diff --git a/QEfficient/utils/_utils.py b/QEfficient/utils/_utils.py index b2a35c005..a1c0b2dd1 100644 --- a/QEfficient/utils/_utils.py +++ b/QEfficient/utils/_utils.py @@ -26,7 +26,9 @@ ) from QEfficient.utils.constants import QEFF_MODELS_DIR, Constants, QnnConstants -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() class DownloadRetryLimitExceeded(Exception): diff --git a/QEfficient/utils/device_utils.py b/QEfficient/utils/device_utils.py index a76dfae8a..9d5f9c55b 100644 --- a/QEfficient/utils/device_utils.py +++ b/QEfficient/utils/device_utils.py @@ -10,7 +10,9 @@ import subprocess from QEfficient.utils.constants import Constants -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() def is_networks_loaded(stdout): diff --git a/QEfficient/utils/logging_utils.py b/QEfficient/utils/logging_utils.py index d2086d830..42e329673 100644 --- a/QEfficient/utils/logging_utils.py +++ b/QEfficient/utils/logging_utils.py @@ -6,53 +6,72 @@ # ----------------------------------------------------------------------------- import logging +import os +from datetime import datetime +from typing import Optional +from concurrent_log_handler import ConcurrentRotatingFileHandler -class QEffFormatter(logging.Formatter): - """ - Formatter class used to set colors for printing different logging levels of messages on console. - """ - - cyan: str = "\x1b[38;5;14m" - yellow: str = "\x1b[33;20m" - red: str = "\x1b[31;20m" - bold_red: str = "\x1b[31;1m" - reset: str = "\x1b[0m" - common_format: str = "%(levelname)s - %(name)s - %(message)s" # type: ignore - format_with_line_info = "%(levelname)s - %(name)s - %(message)s (%(filename)s:%(lineno)d)" # type: ignore - - FORMATS = { - logging.DEBUG: cyan + format_with_line_info + reset, - logging.INFO: cyan + common_format + reset, - logging.WARNING: yellow + common_format + reset, - logging.ERROR: red + format_with_line_info + reset, - logging.CRITICAL: bold_red + format_with_line_info + reset, - } - - def format(self, record): - """ - Overriding the base class method to Choose format based on log level. - """ - log_fmt = self.FORMATS.get(record.levelno) - formatter = logging.Formatter(log_fmt) - return formatter.format(record) - - -def create_logger() -> logging.Logger: - """ - Creates a logger object with Colored QEffFormatter. - """ - logger = logging.getLogger("QEfficient") - - # create console handler and set level to debug - ch = logging.StreamHandler() - ch.setLevel(logging.INFO) - # define formatter - ch.setFormatter(QEffFormatter()) - - logger.addHandler(ch) - return logger - - -# Define the logger object that can be used for logging purposes throughout the module. -logger = create_logger() + +class QEFFLogger: + _instance: Optional[logging.Logger] = None + + def __init__(self, loglevel: Optional[str] = "INFO"): + if QEFFLogger._instance is None: + self.loglevel = loglevel + self.logger = self._initialize_logger() + QEFFLogger._instance = self.logger + + def _get_formatter(self) -> logging.Formatter: + return logging.Formatter( + "[%(asctime)s:%(levelname)s:%(threadName)s:%(filename)s:%(lineno)d:%(funcName)s()]:%(message)s" + ) + + def _initialize_logger(self) -> logging.Logger: + # Define the hidden log directory path + log_dir = os.path.expanduser("~/.cache/.log") + os.makedirs(log_dir, exist_ok=True) # Create the directory if it doesn't exist + + # Create a timestamped log file in the hidden directory + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + logfile = os.path.join(log_dir, f"QEFF_{timestamp}.log") + + numeric_level = getattr(logging, self.loglevel.upper(), None) + if not isinstance(numeric_level, int): + raise ValueError(f"Invalid log level: {self.loglevel}") + + logger = logging.getLogger("QEFF_LOGGER") + logger.setLevel(numeric_level) + + if not logger.handlers: + handler = ConcurrentRotatingFileHandler(logfile, maxBytes=5 * 1024 * 1024, backupCount=15) + handler.setFormatter(self._get_formatter()) + logger.addHandler(handler) + + return logger + + @classmethod + def get_logger(cls, loglevel: Optional[str] = "INFO") -> logging.Logger: + if cls._instance is None: + cls(loglevel) + return cls._instance + + @classmethod + def set_loglevel(cls, loglevel: Optional[str] = "INFO"): + if cls._instance is None: + raise RuntimeError("Logger has not been initialized yet. Call get_logger() first.") + + numeric_level = getattr(logging, loglevel.upper(), None) + if not isinstance(numeric_level, int): + raise ValueError(f"Invalid log level: {loglevel}") + + cls._instance.setLevel(numeric_level) + + @classmethod + def close_logger(cls): + if cls._instance: + handlers = cls._instance.handlers[:] + for handler in handlers: + handler.close() + cls._instance.removeHandler(handler) + cls._instance = None diff --git a/examples/cpp_execution/text_inference_using_cpp.py b/examples/cpp_execution/text_inference_using_cpp.py index 9b0d59c73..96d125c88 100644 --- a/examples/cpp_execution/text_inference_using_cpp.py +++ b/examples/cpp_execution/text_inference_using_cpp.py @@ -5,7 +5,6 @@ # # ----------------------------------------------------------------------------- import argparse -import logging import os import sys from pathlib import Path @@ -17,7 +16,9 @@ from QEfficient.cloud.export import get_onnx_model_path from QEfficient.generation.text_generation_inference import fix_prompts, get_compilation_dims, get_input_prompts from QEfficient.utils import check_and_assign_cache_dir, get_qpc_dir_path, load_hf_tokenizer, qpc_exists -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() script_dir = Path(__file__).resolve().parent so_folder_path = script_dir / "build" @@ -254,6 +255,6 @@ def tokenize_decode_output(tokenizer, generated_ids, prompt): args = parser.parse_args() if args.verbose: - logger.setLevel(logging.INFO) + QEFFLogger.set_loglevel("INFO") del args.verbose # type: ignore main(**args.__dict__) diff --git a/examples/intern_example/internvl_inference.py b/examples/intern_example/internvl_inference.py index eba8c10d5..b49b2d320 100644 --- a/examples/intern_example/internvl_inference.py +++ b/examples/intern_example/internvl_inference.py @@ -17,7 +17,9 @@ from transformers import AutoTokenizer, TextStreamer from QEfficient import QEFFAutoModelForCausalLM -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() IMAGENET_MEAN = (0.485, 0.456, 0.406) IMAGENET_STD = (0.229, 0.224, 0.225) diff --git a/tests/cloud/conftest.py b/tests/cloud/conftest.py index 8b17297ac..324c7967f 100644 --- a/tests/cloud/conftest.py +++ b/tests/cloud/conftest.py @@ -13,7 +13,9 @@ from QEfficient.utils import get_onnx_dir_name from QEfficient.utils.constants import QEFF_MODELS_DIR -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() def pytest_addoption(parser): diff --git a/tests/transformers/test_transformer_pytorch_transforms.py b/tests/transformers/test_transformer_pytorch_transforms.py index eb05b3f95..f898965e4 100644 --- a/tests/transformers/test_transformer_pytorch_transforms.py +++ b/tests/transformers/test_transformer_pytorch_transforms.py @@ -20,7 +20,9 @@ from QEfficient.transformers.quantizers.quant_transforms import AwqToMatmulNbitsTransform, GPTQToMatmulNbitsTransform from QEfficient.transformers.spd.turbo import ResBlock from QEfficient.utils._utils import get_padding_shape_from_config -from QEfficient.utils.logging_utils import logger +from QEfficient.utils.logging_utils import QEFFLogger + +logger = QEFFLogger.get_logger() KVCacheTransformTestConfigs = [ ("llama", 3, 32, 128, {"num_key_value_heads": 8, "intermediate_size": 512}, 0.8), From aa5aec0854766ee48771f77d8a611680346530bd Mon Sep 17 00:00:00 2001 From: Hem Agnihotri Date: Fri, 11 Jul 2025 05:21:51 +0000 Subject: [PATCH 2/3] Logging changes --- QEfficient/base/modeling_qeff.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/QEfficient/base/modeling_qeff.py b/QEfficient/base/modeling_qeff.py index d2bf1ee9c..01187d02b 100644 --- a/QEfficient/base/modeling_qeff.py +++ b/QEfficient/base/modeling_qeff.py @@ -7,6 +7,8 @@ import hashlib import inspect +import logging +import json import shutil import subprocess import warnings From f602a4880fa1d6fb67361917e40aefa6388ee1bb Mon Sep 17 00:00:00 2001 From: Hem Agnihotri Date: Fri, 11 Jul 2025 05:32:06 +0000 Subject: [PATCH 3/3] ruff check fix Signed-off-by: Hem Agnihotri --- QEfficient/base/modeling_qeff.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/QEfficient/base/modeling_qeff.py b/QEfficient/base/modeling_qeff.py index 01187d02b..d2bf1ee9c 100644 --- a/QEfficient/base/modeling_qeff.py +++ b/QEfficient/base/modeling_qeff.py @@ -7,8 +7,6 @@ import hashlib import inspect -import logging -import json import shutil import subprocess import warnings