import os
from enum import Enum
import json
from typing import List, Union, Optional
from contextlib import contextmanager
import logging


class Mode(Enum):
    """An enumeration."""
    Display = 0,
    Normal = 1,
    Debug = 2,


class _MetaDoc(type):
    """<property object at 0x7f191c1e2cf0>"""
    _description = dict()
    _doc = ''

    @staticmethod
    def _get_description(name):
        desc = _MetaDoc._description[name]
        if not desc: raise ValueError(f'Description for {name} is not found')
        doc = (f'    Description: {desc["description"]}, type is `{desc["type"]}`, default is `{desc["default"]}`.\n')
        if (options := desc.get('options')):
            doc += f'    Options: {", ".join(options)}\n'
        if (env := desc.get('env')):
            if isinstance(env, str):
                doc += f'    Environment Variable: {("LAZYLLM_" + env).upper()}\n'
            elif isinstance(env, dict):
                doc += '    Environment Variable:\n'
                for k, v in env.items():
                    doc += f'{("      LAZYLLM_" + k).upper()}: {v}\n'
        return doc

    @property
    def __doc__(self):
        doc = f'{self._doc}\n**LazyLLM Configurations:**\n\n'
        return doc + '\n'.join([f'  **{name}**:\n{self._get_description(name)}' for name in self._description.keys()])

    @__doc__.setter
    def __doc__(self, value):
        self._doc = value


class Config(metaclass=_MetaDoc):
    """Config is a configuration class provided by LazyLLM, which loads configurations of LazyLLM framework from config files,
environment variables, or specify them explicitly. it can export all configuration items as well.
The Config module automatically generates an object named 'config' containing all configurations.

Args:
    prefix (str, optional): Environment variable prefix. Defaults to 'LAZYLLM'
    home (str, optional): Configuration file directory path. Defaults to '~/.lazyllm'

**LazyLLM Configurations:**

  **home**:
    Description: The default home directory for LazyLLM., type is `str`, default is `/home/runner/.lazyllm`.
    Environment Variable: LAZYLLM_HOME

  **mode**:
    Description: The default mode for LazyLLM., type is `Mode`, default is `Mode.Normal`.
    Environment Variable:
      LAZYLLM_DISPLAY: Mode.Display
      LAZYLLM_DEBUG: Mode.Debug

  **repr_ml**:
    Description: Whether to use Markup Language for repr., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_REPR_USE_ML

  **repr_show_child**:
    Description: Whether to show child modules in repr., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_REPR_SHOW_CHILD

  **rag_store**:
    Description: The default store for RAG., type is `str`, default is `none`.
    Environment Variable: LAZYLLM_RAG_STORE

  **gpu_type**:
    Description: The default GPU type for LazyLLM., type is `str`, default is `A100`.
    Environment Variable: LAZYLLM_GPU_TYPE

  **train_target_root**:
    Description: The default target root for training., type is `str`, default is `/home/runner/work/LazyLLM/LazyLLM/save_ckpt`.
    Environment Variable: LAZYLLM_TRAIN_TARGET_ROOT

  **infer_log_root**:
    Description: The default log root for inference., type is `str`, default is `/home/runner/work/LazyLLM/LazyLLM/infer_log`.
    Environment Variable: LAZYLLM_INFER_LOG_ROOT

  **temp_dir**:
    Description: The default temp directory for LazyLLM., type is `str`, default is `/home/runner/work/LazyLLM/LazyLLM/.temp`.
    Environment Variable: LAZYLLM_TEMP_DIR

  **thread_pool_worker_num**:
    Description: The default number of workers for thread pool., type is `int`, default is `16`.
    Environment Variable: LAZYLLM_THREAD_POOL_WORKER_NUM

  **deploy_skip_check_kw**:
    Description: Whether to skip check keywords for deployment., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_DEPLOY_SKIP_CHECK_KW

  **debug**:
    Description: Whether to enable debug mode., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_DEBUG

  **log_name**:
    Description: The name of the log file., type is `str`, default is `lazyllm`.
    Environment Variable: LAZYLLM_LOG_NAME

  **log_level**:
    Description: The level of the log., type is `str`, default is `INFO`.
    Environment Variable: LAZYLLM_LOG_LEVEL

  **log_format**:
    Description: The format of the log., type is `str`, default is `{process}: <green>{time:YYYY-MM-DD HH:mm:ss}</green> {extra[name]} <level>{level}</level>: ({name}:{line}) <cyan>{message}</cyan>`.
    Environment Variable: LAZYLLM_LOG_FORMAT

  **log_dir**:
    Description: The directory of the log file., type is `str`, default is `/home/runner/.lazyllm/logs`.
    Environment Variable: LAZYLLM_LOG_DIR

  **log_file_level**:
    Description: The level of the log file., type is `str`, default is `ERROR`.
    Environment Variable: LAZYLLM_LOG_FILE_LEVEL

  **log_file_size**:
    Description: The size of the log file., type is `str`, default is `4 MB`.
    Environment Variable: LAZYLLM_LOG_FILE_SIZE

  **log_file_retention**:
    Description: The retention of the log file., type is `str`, default is `7 days`.
    Environment Variable: LAZYLLM_LOG_FILE_RETENTION

  **log_file_mode**:
    Description: The mode of the log file., type is `str`, default is `merge`.
    Environment Variable: LAZYLLM_LOG_FILE_MODE

  **redis_url**:
    Description: The URL of the Redis server., type is `str`, default is ``.
    Environment Variable: LAZYLLM_REDIS_URL

  **redis_recheck_delay**:
    Description: The delay of the Redis server check., type is `int`, default is `5`.
    Environment Variable: LAZYLLM_REDIS_RECHECK_DELAY

  **use_builtin**:
    Description: Whether to use registry modules in python builtin., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_USE_BUILTIN

  **default_fsqueue**:
    Description: The default file system queue to use., type is `str`, default is `sqlite`.
    Environment Variable: LAZYLLM_DEFAULT_FSQUEUE

  **fsqredis_url**:
    Description: The URL of the Redis server for the file system queue., type is `str`, default is ``.
    Environment Variable: LAZYLLM_FSQREDIS_URL

  **launcher**:
    Description: The default remote launcher to use if no launcher is specified., type is `str`, default is `empty`.
    Environment Variable: LAZYLLM_DEFAULT_LAUNCHER

  **cuda_visible**:
    Description: Whether to set the CUDA_VISIBLE_DEVICES environment variable., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_CUDA_VISIBLE

  **partition**:
    Description: The default Slurm partition to use if no partition is specified., type is `str`, default is `your_part`.
    Environment Variable: LAZYLLM_SLURM_PART

  **sco.workspace**:
    Description: The default SCO workspace to use if no workspace is specified., type is `str`, default is `your_workspace`.
    Environment Variable: LAZYLLM_SCO_WORKSPACE

  **sco_env_name**:
    Description: The default SCO environment name to use if no environment name is specified., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SCO_ENV_NAME

  **sco_keep_record**:
    Description: Whether to keep the record of the Sensecore job., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_SCO_KEEP_RECORD

  **sco_resource_type**:
    Description: The default SCO resource type to use if no resource type is specified., type is `str`, default is `N3lS.Ii.I60`.
    Environment Variable: LAZYLLM_SCO_RESOURCE_TYPE

  **k8s_env_name**:
    Description: The default k8s environment name to use if no environment name is specified., type is `str`, default is ``.
    Environment Variable: LAZYLLM_K8S_ENV_NAME

  **k8s_config_path**:
    Description: The default k8s configuration path to use if no configuration path is specified., type is `str`, default is ``.
    Environment Variable: LAZYLLM_K8S_CONFIG_PATH

  **k8s_device_type**:
    Description: The default k8s device type to use if no device type is specified., type is `str`, default is `nvidia.com/gpu`.
    Environment Variable: LAZYLLM_K8S_DEVICE_TYPE

  **save_flow_result**:
    Description: Whether to save the intermediate result of the pipeline., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_SAVE_FLOW_RESULT

  **parallel_multiprocessing**:
    Description: Whether to use multiprocessing for parallel execution, if not, default to use threading., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_PARALLEL_MULTIPROCESSING

  **model_source**:
    Description: The default model source to use., type is `str`, default is `modelscope`.
    Environment Variable: LAZYLLM_MODEL_SOURCE

  **model_cache_dir**:
    Description: The default model cache directory to use(Read and Write)., type is `str`, default is `/home/runner/.lazyllm/model`.
    Environment Variable: LAZYLLM_MODEL_CACHE_DIR

  **model_path**:
    Description: The default model path to use(ReadOnly)., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MODEL_PATH

  **model_source_token**:
    Description: The default token for configed model source(hf or ms) to use., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MODEL_SOURCE_TOKEN

  **data_path**:
    Description: The default data path to use., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DATA_PATH

  **openai_api**:
    Description: Whether to use OpenAI API for vllm deployer., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_OPENAI_API

  **use_ray**:
    Description: Whether to use Ray for ServerModule(relay server)., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_USE_RAY

  **num_gpus_per_node**:
    Description: The number of GPUs per node for Ray launcher when deploy models., type is `int`, default is `8`.
    Environment Variable: LAZYLLM_NUM_GPUS_PER_NODE

  **lmdeploy_eager_mode**:
    Description: Whether to use eager mode for lmdeploy., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_LMDEPLOY_EAGER_MODE

  **default_embedding_engine**:
    Description: The default embedding engine to use., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEFAULT_EMBEDDING_ENGINE

  **mindie_home**:
    Description: The home directory of MindIE., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINDIE_HOME

  **gpu_memory**:
    Description: The memory of the GPU., type is `int`, default is `80`.
    Environment Variable: LAZYLLM_GPU_MEMORY

  **cache_dir**:
    Description: The default result cache directory for module to use(Read and Write)., type is `str`, default is `/home/runner/.lazyllm/cache`.
    Environment Variable: LAZYLLM_CACHE_DIR

  **cache_strategy**:
    Description: The default cache strategy to use(memory, file, sqlite, redis)., type is `str`, default is `memory`.
    Environment Variable: LAZYLLM_CACHE_STRATEGY

  **cache_mode**:
    Description: The default cache mode to use(Read and Write, Read Only, Write Only, None)., type is `str`, default is `RW`.
    Options: RW, RO, WO, NONE
    Environment Variable: LAZYLLM_CACHE_MODE

  **trainable_module_config_map_path**:
    Description: The default path for trainable module config map., type is `str`, default is ``.
    Environment Variable: LAZYLLM_TRAINABLE_MODULE_CONFIG_MAP_PATH

  **trainable_magic_mock**:
    Description: Whether to use magic mock for trainable module(used for unit test)., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_TRAINABLE_MAGIC_MOCK

  **cache_local_module**:
    Description: Whether to cache the local module result. Use for unit test., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_CACHE_LOCAL_MODULE

  **cache_online_module**:
    Description: Whether to cache the online module result. Use for unit test., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_CACHE_ONLINE_MODULE

  **openai_api_key**:
    Description: The API key for openai., type is `str`, default is ``.
    Environment Variable: LAZYLLM_OPENAI_API_KEY

  **openai_model_name**:
    Description: The default model name for openai., type is `str`, default is ``.
    Environment Variable: LAZYLLM_OPENAI_MODEL_NAME

  **openai_text2image_model_name**:
    Description: The default text2image model name for openai., type is `str`, default is ``.
    Environment Variable: LAZYLLM_OPENAI_TEXT2IMAGE_MODEL_NAME

  **openai_tts_model_name**:
    Description: The default tts model name for openai., type is `str`, default is ``.
    Environment Variable: LAZYLLM_OPENAI_TTS_MODEL_NAME

  **openai_stt_model_name**:
    Description: The default stt model name for openai., type is `str`, default is ``.
    Environment Variable: LAZYLLM_OPENAI_STT_MODEL_NAME

  **sensenova_api_key**:
    Description: The API key for sensenova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_API_KEY

  **sensenova_model_name**:
    Description: The default model name for sensenova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_MODEL_NAME

  **sensenova_text2image_model_name**:
    Description: The default text2image model name for sensenova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_TEXT2IMAGE_MODEL_NAME

  **sensenova_tts_model_name**:
    Description: The default tts model name for sensenova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_TTS_MODEL_NAME

  **sensenova_stt_model_name**:
    Description: The default stt model name for sensenova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_STT_MODEL_NAME

  **glm_api_key**:
    Description: The API key for glm., type is `str`, default is ``.
    Environment Variable: LAZYLLM_GLM_API_KEY

  **glm_model_name**:
    Description: The default model name for glm., type is `str`, default is ``.
    Environment Variable: LAZYLLM_GLM_MODEL_NAME

  **glm_text2image_model_name**:
    Description: The default text2image model name for glm., type is `str`, default is ``.
    Environment Variable: LAZYLLM_GLM_TEXT2IMAGE_MODEL_NAME

  **glm_tts_model_name**:
    Description: The default tts model name for glm., type is `str`, default is ``.
    Environment Variable: LAZYLLM_GLM_TTS_MODEL_NAME

  **glm_stt_model_name**:
    Description: The default stt model name for glm., type is `str`, default is ``.
    Environment Variable: LAZYLLM_GLM_STT_MODEL_NAME

  **kimi_api_key**:
    Description: The API key for kimi., type is `str`, default is ``.
    Environment Variable: LAZYLLM_KIMI_API_KEY

  **kimi_model_name**:
    Description: The default model name for kimi., type is `str`, default is ``.
    Environment Variable: LAZYLLM_KIMI_MODEL_NAME

  **kimi_text2image_model_name**:
    Description: The default text2image model name for kimi., type is `str`, default is ``.
    Environment Variable: LAZYLLM_KIMI_TEXT2IMAGE_MODEL_NAME

  **kimi_tts_model_name**:
    Description: The default tts model name for kimi., type is `str`, default is ``.
    Environment Variable: LAZYLLM_KIMI_TTS_MODEL_NAME

  **kimi_stt_model_name**:
    Description: The default stt model name for kimi., type is `str`, default is ``.
    Environment Variable: LAZYLLM_KIMI_STT_MODEL_NAME

  **qwen_api_key**:
    Description: The API key for qwen., type is `str`, default is ``.
    Environment Variable: LAZYLLM_QWEN_API_KEY

  **qwen_model_name**:
    Description: The default model name for qwen., type is `str`, default is ``.
    Environment Variable: LAZYLLM_QWEN_MODEL_NAME

  **qwen_text2image_model_name**:
    Description: The default text2image model name for qwen., type is `str`, default is ``.
    Environment Variable: LAZYLLM_QWEN_TEXT2IMAGE_MODEL_NAME

  **qwen_tts_model_name**:
    Description: The default tts model name for qwen., type is `str`, default is ``.
    Environment Variable: LAZYLLM_QWEN_TTS_MODEL_NAME

  **qwen_stt_model_name**:
    Description: The default stt model name for qwen., type is `str`, default is ``.
    Environment Variable: LAZYLLM_QWEN_STT_MODEL_NAME

  **doubao_api_key**:
    Description: The API key for doubao., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DOUBAO_API_KEY

  **doubao_model_name**:
    Description: The default model name for doubao., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DOUBAO_MODEL_NAME

  **doubao_text2image_model_name**:
    Description: The default text2image model name for doubao., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DOUBAO_TEXT2IMAGE_MODEL_NAME

  **doubao_tts_model_name**:
    Description: The default tts model name for doubao., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DOUBAO_TTS_MODEL_NAME

  **doubao_stt_model_name**:
    Description: The default stt model name for doubao., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DOUBAO_STT_MODEL_NAME

  **deepseek_api_key**:
    Description: The API key for deepseek., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEEPSEEK_API_KEY

  **deepseek_model_name**:
    Description: The default model name for deepseek., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEEPSEEK_MODEL_NAME

  **deepseek_text2image_model_name**:
    Description: The default text2image model name for deepseek., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEEPSEEK_TEXT2IMAGE_MODEL_NAME

  **deepseek_tts_model_name**:
    Description: The default tts model name for deepseek., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEEPSEEK_TTS_MODEL_NAME

  **deepseek_stt_model_name**:
    Description: The default stt model name for deepseek., type is `str`, default is ``.
    Environment Variable: LAZYLLM_DEEPSEEK_STT_MODEL_NAME

  **siliconflow_api_key**:
    Description: The API key for siliconflow., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SILICONFLOW_API_KEY

  **siliconflow_model_name**:
    Description: The default model name for siliconflow., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SILICONFLOW_MODEL_NAME

  **siliconflow_text2image_model_name**:
    Description: The default text2image model name for siliconflow., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SILICONFLOW_TEXT2IMAGE_MODEL_NAME

  **siliconflow_tts_model_name**:
    Description: The default tts model name for siliconflow., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SILICONFLOW_TTS_MODEL_NAME

  **siliconflow_stt_model_name**:
    Description: The default stt model name for siliconflow., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SILICONFLOW_STT_MODEL_NAME

  **minimax_api_key**:
    Description: The API key for minimax., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINIMAX_API_KEY

  **minimax_model_name**:
    Description: The default model name for minimax., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINIMAX_MODEL_NAME

  **minimax_text2image_model_name**:
    Description: The default text2image model name for minimax., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINIMAX_TEXT2IMAGE_MODEL_NAME

  **minimax_tts_model_name**:
    Description: The default tts model name for minimax., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINIMAX_TTS_MODEL_NAME

  **minimax_stt_model_name**:
    Description: The default stt model name for minimax., type is `str`, default is ``.
    Environment Variable: LAZYLLM_MINIMAX_STT_MODEL_NAME

  **sensenova_secret_key**:
    Description: The secret key for SenseNova., type is `str`, default is ``.
    Environment Variable: LAZYLLM_SENSENOVA_SECRET_KEY

  **max_embedding_workers**:
    Description: The default number of workers for embedding in RAG., type is `int`, default is `8`.
    Environment Variable: LAZYLLM_MAX_EMBEDDING_WORKERS

  **default_dlmanager**:
    Description: The default document list manager for RAG., type is `str`, default is `sqlite`.
    Environment Variable: LAZYLLM_DEFAULT_DOCLIST_MANAGER

  **paddleocr_api_key**:
    Description: The API key for PaddleOCR, type is `str`, default is `None`.
    Environment Variable: LAZYLLM_PADDLEOCR_API_KEY

  **rag_filename_as_id**:
    Description: Whether to use filename as id for RAG., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_RAG_FILENAME_AS_ID

  **use_fallback_reader**:
    Description: Whether to use fallback reader for RAG., type is `bool`, default is `True`.
    Environment Variable: LAZYLLM_USE_FALLBACK_READER

  **eval_result_dir**:
    Description: The default result directory for eval., type is `str`, default is `/home/runner/.lazyllm/eval_res`.
    Environment Variable: LAZYLLM_EVAL_RESULT_DIR

  **raise_on_add_doc_error**:
    Description: Whether to raise an error when adding doc failed., type is `bool`, default is `False`.
    Environment Variable: LAZYLLM_RAISE_ON_ADD_DOC_ERROR

  **language**:
    Description: The language of the documentation., type is `str`, default is `ENGLISH`.
    Environment Variable: LAZYLLM_LANGUAGE
"""
    def __init__(self, prefix='LAZYLLM', home=os.path.join(os.path.expanduser('~'), '.lazyllm')):  # noqa B008
        self._config_params = dict()
        self._env_map_name = dict()
        self.prefix = prefix
        self.impl, self.cfgs = dict(), dict()
        self.add('home', str, os.path.expanduser(home), 'HOME', description='The default home directory for LazyLLM.')
        os.makedirs(home, exist_ok=True)
        self.cgf_path = os.path.join(self['home'], 'config.json')
        if os.path.exists(self.cgf_path):
            with open(self.cgf_path, 'r+') as f:
                self.cfgs = Config.get_config(json.loads(f))

    def done(self):
        """Check if any configuration items in the config.json file that is not loaded by the add method.

Args:
    None.
"""
        assert len(self.cfgs) == 0, f'Invalid cfgs ({"".join(self.cfgs.keys())}) are given in {self.cgf_path}'
        return self

    def getenv(self, name, type, default=None):
        """Get value of LazyLLM-related environment variables.

Args:
    name (str): The name of the environment variable （without the prefix）, case-insensitive. The function obtains value
    from environment variable by concatenating the prefix and this name, with all uppercase letters.
    type (type): Specifies the type of the configuration, for example, str. For boolean types, the function will
    convert inputs ‘TRUE’, ‘True’, 1, ‘ON’, and ‘1’ to True.
    default (optional): If the value of the environment variable cannot be obtained, this value is returned.
"""
        r = os.getenv(f'{self.prefix}_{name.upper()}', default)
        if type == bool:
            return r in (True, 'TRUE', 'True', 1, 'ON', '1')
        return type(r)

    @staticmethod
    def get_config(cfg):
        """
Static method: Get configuration from config dictionary.
This is a simple configuration retrieval method mainly used to extract configuration information from already loaded configuration dictionaries.

Args:
    cfg (dict): The configuration dictionary read from the config file.
"""
        return cfg

    def get_all_configs(self):
        """Get all configurations from the config.

Args:
    None.


Examples:
    >>> import lazyllm
    >>> from lazyllm.configs import config
    >>> config['launcher']
    'empty'
    >>> config.get_all_configs()
    {'home': '~/.lazyllm/', 'mode': <Mode.Normal: (1,)>, 'repr_ml': False, 'rag_store': 'None', 'redis_url': 'None', ...}
    """
        return self.impl

    @contextmanager
    def temp(self, name, value):
        """
Context manager for temporary configuration modification.

Temporarily modifies the value of the specified configuration item within the with statement block, and automatically restores the original value when exiting the block.

Args:
    name (str): The name of the configuration item to temporarily change.
    value (Any): The temporary value to set.
"""
        old_value = self[name]
        self.impl[name] = value
        yield
        self.impl[name] = old_value

    def add(self, name: str, type: type, default: Optional[Union[int, str, bool]] = None, env: Union[str, dict] = None,
            *, options: Optional[List] = None, description: Optional[str] = None):
        """Loads value into LazyLLM configuration item. The function first attempts to find the value with the given name from the
dict loaded from config.json. If found, it removes the key from the dict and saves the value to the config.
If 'env' is a string, the function calls getenv to look for the corresponding LazyLLM environment variable, and if
it's found, writes it to the config. If 'env' is a dictionary, the function attempts to call getenv to find the
environment variables corresponding to the keys in the dict and convert them to boolean type.
If the converted boolean value is True, the value corresponding to the current key in the dict is written to the config.

Args:
    name (str): The name of the configuration item
    type (type): The type of the configuration
    default (optional): The default value of the configuration if no value can be obtained
    env (optional): The name of the environment variable without the prefix, or a dictionary where the keys are the
    names of the environment variables(without the prefix), and the values are what to be added to the configuration.
"""
        update_params = (type, default, env)
        if name not in self._config_params or self._config_params[name] != update_params:
            if name in self._config_params:
                logging.warning(f'The default configuration parameter {name}({self._config_params[name]}) '
                                f'has been added, but a new {name}({update_params}) has been added repeatedly.')
            self._config_params.update({name: update_params})
            if isinstance(env, str):
                self._env_map_name[('lazyllm_' + env).upper()] = name
            elif isinstance(env, dict):
                for k in env.keys():
                    self._env_map_name[('lazyllm_' + k).upper()] = name
        self._update_impl(name, type, default, env)
        _MetaDoc._description[name] = dict(type=type.__name__, default=default,
                                           env=env, options=options, description=description)
        return self

    def _update_impl(self, name: str, type: type, default: Optional[Union[int, str, bool]] = None,
                     env: Union[str, dict] = None):
        self.impl[name] = self.cfgs.pop(name) if name in self.cfgs else default
        if isinstance(env, dict):
            for k, v in env.items():
                if self.getenv(k, bool):
                    self.impl[name] = v
                    break
        elif env:
            self.impl[name] = self.getenv(env, type, self.impl[name])
        if not isinstance(self.impl[name], type): raise TypeError(
            f'Invalid config type for {name}, type is {type}')

    def __getitem__(self, name):
        try:
            if isinstance(name, bytes): name = name.decode('utf-8')
            return self.impl[name]
        except KeyError:
            raise RuntimeError(f'Key `{name}` is not in lazyllm global config')

    def __str__(self):
        return str(self.impl)

    def refresh(self, targets: Union[bytes, str, List[str]] = None) -> None:
        """
Refresh configuration items based on the latest environment variable values.  
If `targets` is a string, updates the single corresponding configuration item;  
if it's a list, updates multiple;  
if None, scans all environment-variable-mapped configuration items and updates them.

Args:
    targets (str | list[str] | None): Name of the config key or list of keys to refresh, or None to refresh all environment-backed keys.
"""
        names = targets
        if isinstance(targets, bytes): targets = targets.decode('utf-8')
        if isinstance(targets, str):
            names = targets.lower()
            if names.startswith('lazyllm_'):
                names = names[8:]
            names = [names]
        elif targets is None:
            curr_envs = [key for key in os.environ.keys() if key.startswith('LAZYLLM_')]
            names = list(set([self._env_map_name[key] for key in curr_envs if key in self._env_map_name]))
        assert isinstance(names, list)
        for name in names:
            if name in self.impl: self._update_impl(name, *self._config_params[name])

config = Config().add('mode', Mode, Mode.Normal, dict(DISPLAY=Mode.Display, DEBUG=Mode.Debug),
                      description='The default mode for LazyLLM.'
                ).add('repr_ml', bool, False, 'REPR_USE_ML', description='Whether to use Markup Language for repr.'
                ).add('repr_show_child', bool, False, 'REPR_SHOW_CHILD',
                      description='Whether to show child modules in repr.'
                ).add('rag_store', str, 'none', 'RAG_STORE', description='The default store for RAG.'
                ).add('gpu_type', str, 'A100', 'GPU_TYPE', description='The default GPU type for LazyLLM.'
                ).add('train_target_root', str, os.path.join(os.getcwd(), 'save_ckpt'), 'TRAIN_TARGET_ROOT',
                      description='The default target root for training.'
                ).add('infer_log_root', str, os.path.join(os.getcwd(), 'infer_log'), 'INFER_LOG_ROOT',
                      description='The default log root for inference.'
                ).add('temp_dir', str, os.path.join(os.getcwd(), '.temp'), 'TEMP_DIR',
                      description='The default temp directory for LazyLLM.'
                ).add('thread_pool_worker_num', int, 16, 'THREAD_POOL_WORKER_NUM',
                      description='The default number of workers for thread pool.'
                ).add('deploy_skip_check_kw', bool, False, 'DEPLOY_SKIP_CHECK_KW',
                      description='Whether to skip check keywords for deployment.'
                )
