VTuberAI / src /utils /config.py
Saidie000's picture
Upload 90 files
1905805 verified
import os
import yaml
from typing import get_type_hints, List, Dict
from .helpers.singleton import Singleton
from .helpers.path import portable_path
from .args import args
class UnknownField(Exception):
def __init__(self, field: str):
super().__init__("Config field {} does not exist".format(field))
class UnknownFile(Exception):
def __init__(self, filepath: str):
super().__init__("Config file {} does not exist".format(filepath))
class Config(metaclass=Singleton):
# Every attribute must be typed for validation
CONFIG_DIR: str = portable_path(os.path.join(os.getcwd(), "configs"))
WORKING_DIR: str = portable_path(os.path.join(os.getcwd(),"output","temp"))
current_config: str = "Unsaved"
# Defaults
operations: list = list()
# Prompter
PROMPT_DIR: str = portable_path(os.path.join(os.getcwd(), "prompts"))
PROMPT_INSTRUCTION_SUBDIR: str = "instructions"
PROMPT_CHARACTER_SUBDIR: str = "characters"
PROMPT_SCENE_SUBDIR: str = "scenes"
prompter: dict = dict()
history_filepath: str = portable_path(os.path.join(os.getcwd(), "output", "history.txt")) # debug
# MCP
MCP_DIR: str = portable_path(os.path.join(os.getcwd(), "models", "mcp"))
mcp: list = list()
# Kobold
kobold_filepath: str = None
kcpps_filepath: str = None
# Melo
MELO_DIR: str = portable_path(os.path.join(os.getcwd(), "models", "melotts"))
# Shared
stt_working_src: str = portable_path(os.path.join(WORKING_DIR,'stt_src.wav'))
ffmpeg_working_src: str = portable_path(os.path.join(WORKING_DIR,'ffmpeg_src.wav'))
ffmpeg_working_dest: str = portable_path(os.path.join(WORKING_DIR,'ffmpeg_dest.wav'))
spacy_model: str = None
def __init__(self):
# Every attribute must be typed for validation
if args.config is not None: self.load_from_name(args.config)
# Can raise: FileNotFoundError,
def load_from_name(self, config_name: str):
filepath = os.path.join(self.CONFIG_DIR, config_name+".yaml")
if not os.path.isfile(filepath):
filepath = os.path.join(self.CONFIG_DIR, config_name)
if not os.path.isfile(filepath): raise UnknownFile(filepath)
with open(filepath) as f:
conf_d = yaml.safe_load(f)
self.load_from_dict(**conf_d)
self.current_config = config_name
def load_from_dict(self, **conf_d):
uncommitted = dict(conf_d)
config_typings = get_type_hints(Config)
# Pre-check fields before committing changes
for field in conf_d:
if field not in config_typings:
raise UnknownField(field)
uncommitted[field] = config_typings[field](conf_d[field]) if conf_d[field] is not None else None # attempt cast to correct typing
# Commit config change request
for field in uncommitted:
setattr(self, field, uncommitted[field])
self.current_config = "Unsaved"
def save(self, config_name: str):
with open(portable_path(os.path.join(self.CONFIG_DIR, config_name))) as f:
yaml.dump(self.get_config_dict(),f)
def get_config_dict(self):
return vars(self)