chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
A common base class for configuration. A configuration could be initialized from its constructor,
|
||||
a JSON string or a JSON file, and irrelevant fields during initialization are automatically moved
|
||||
to the `kwargs` field.
|
||||
|
||||
Take model configuration as an example: it is usually a JSON file in HuggingFace that contains
|
||||
the model's hyperparameters. For instance, Vicuna-13b-v1.5-16k contains the following
|
||||
[JSON file](https://huggingface.co/lmsys/vicuna-13b-v1.5-16k/blob/main/config.json).
|
||||
The base class allows us to load the configuration from this JSON file, moving irrelevant fields
|
||||
into `kwargs`, such as `transformers_version` and `use_cache`.
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Type, TypeVar # noqa: UP035
|
||||
|
||||
from . import logging
|
||||
from .style import bold, red
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ConfigClass = TypeVar("ConfigClass", bound="ConfigBase")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ConfigBase:
|
||||
"""Base class for configurations, providing a common interface for loading configs from a
|
||||
JSON file or a dict. It requires the subclasses to be dataclasses, and has an `kwargs` field
|
||||
that stores the extra fields that are not defined in the dataclass.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type[ConfigClass], source: Dict[str, Any]) -> ConfigClass: # noqa: UP006
|
||||
"""Create a config object from a dictionary.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
source : Dict[str, Any]
|
||||
Source to create config from, usually loaded from `config.json` in HuggingFace style.
|
||||
|
||||
Returns
|
||||
-------
|
||||
cfg : ConfigClass
|
||||
An instance of the config object.
|
||||
"""
|
||||
field_names = [field.name for field in dataclasses.fields(cls)]
|
||||
fields = {k: v for k, v in source.items() if k in field_names}
|
||||
kwargs = {k: v for k, v in source.items() if k not in field_names}
|
||||
return cls(**fields, kwargs=kwargs)
|
||||
|
||||
@classmethod
|
||||
def from_file(cls: Type[ConfigClass], source: Path) -> ConfigClass: # noqa: UP006
|
||||
"""Create a config object from a file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cfg_cls : Type[ConfigClass]
|
||||
The config class to create, for example, LlamaConfig.
|
||||
|
||||
source : pathlib.Path
|
||||
Path to the source file, usually `config.json` in HuggingFace repo.
|
||||
|
||||
Returns
|
||||
-------
|
||||
cfg : ConfigClass
|
||||
An instance of the config object.
|
||||
"""
|
||||
with source.open("r", encoding="utf-8") as in_file:
|
||||
return cls.from_dict(json.load(in_file))
|
||||
|
||||
def asdict(self):
|
||||
"""Convert the config object to a dictionary.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Dict[str, Any]
|
||||
A dictionary representation of the config object.
|
||||
"""
|
||||
result = dataclasses.asdict(self)
|
||||
result.pop("kwargs")
|
||||
return result
|
||||
|
||||
|
||||
class ConfigOverrideBase:
|
||||
"""Base class for ConfigOverride, providing a common interface for overriding configs.
|
||||
It requires the subclasses to be dataclasses.
|
||||
"""
|
||||
|
||||
def apply(self, config):
|
||||
"""Apply the overrides to the given config."""
|
||||
updated = config.asdict()
|
||||
for field in dataclasses.fields(self):
|
||||
key = field.name
|
||||
value = getattr(self, key)
|
||||
if value is None:
|
||||
continue
|
||||
if key not in updated:
|
||||
logger.warning(
|
||||
"%s: Cannot override %s, because %s does not have this field",
|
||||
red("Warning"),
|
||||
bold(key),
|
||||
bold(type(config).__name__),
|
||||
)
|
||||
else:
|
||||
logger.info(f"Overriding {bold(key)} from {updated[key]} to {value}")
|
||||
updated[key] = value
|
||||
return type(config).from_dict(updated)
|
||||
|
||||
|
||||
__all__ = ["ConfigBase", "ConfigOverrideBase"]
|
||||
Reference in New Issue
Block a user