audio-webui / webui /ui /tabs /settings.py
mrtroydev's picture
Upload folder using huggingface_hub
3883c60 verified
import json
import os.path
import shlex
import shutil
import subprocess
import gradio
import huggingface_hub
import webui.modules.models as mod
import webui.extensionlib.callbacks as cb
from setup_tools.os import is_windows
class CustomSetting:
def __init__(self, value):
self.value = self.load_val(value)
def create_ui(self, name, setting):
raise NotImplementedError('UI for setting not implemented.')
def load_val(self, val):
raise NotImplementedError('Value loading not implemented.')
def save_val(self):
raise NotImplementedError('Value saving not implemented.')
class BarkMix(CustomSetting):
model_indexes = ['text', 'coarse', 'fine']
valid_models = {
'large': {
'name': 'large',
'large': True
},
'small': {
'name': 'small',
'large': False
}
}
def create_ui(self, name, setting):
gradio.Markdown('### Bark models')
with gradio.Row():
def create_model_el(model):
dd = gradio.Dropdown(self.valid_models.keys(), value=setting['value'].value[model]['name'], label=model)
def s(v):
self.value[model] = self.valid_models[v]
change_value(name)
dd.change(fn=s, inputs=dd)
for model in self.model_indexes:
create_model_el(model)
def load_val(self, val):
val = val.split(':')
if len(val) != 3:
raise ValueError('Incorrect syntax for --bark-models-mix, use 3 characters')
selected_models = []
for char in val:
if char not in self.valid_models.keys():
raise ValueError(
f'An unknown model was specified for --bark-models-mix, Available models: {list(self.valid_models.keys())}')
selected_models.append(self.valid_models[char])
return {key: value for key, value in zip(self.model_indexes, selected_models)}
def save_val(self):
return ':'.join([self.value[idx]['name'] for idx in self.model_indexes])
config = {
'bark_models_mix': {
'tab': '🐢 Bark',
'type': BarkMix,
'default': BarkMix('large:large:large')
},
'bark_half': {
'tab': '🐢 Bark',
'type': bool,
'default': False,
'readname': 'Half precision',
'description': 'Use half precision for Bark models, lower VRAM, slightly slower generations.'
},
'bark_offload_cpu': {
'tab': '🐢 Bark',
'type': bool,
'default': True,
'readname': 'Cpu offload',
'description': 'Only load the currently needed bark model into the gpu\'s VRAM, keep unused models in RAM for quick loading.'
},
'bark_use_cpu': {
'tab': '🐢 Bark',
'type': bool,
'default': False,
'readname': 'Use cpu',
'description': 'Do all processing on cpu, slow.'
},
# 'tts_use_gpu': {
# 'tab': '🐸 Coqui TTS',
# 'type': bool,
# 'default': False,
# 'readname': 'use gpu',
# 'description': 'Use the GPU for TTS',
# 'el_kwargs': {} # Example
# },
'wav_type': {
'type': str,
'default': 'gradio',
'choices': ['none', 'gradio', 'showwaves'],
'readname': 'Waveform visualizer',
'description': 'Pick a style to display the audio outputs as in a video.'
}
}
settings_add = cb.get_manager('webui.settings')()
for settings_dict in settings_add:
for k, v in zip(settings_dict.keys(), settings_dict.values()):
if k not in config.keys():
config[k] = v
config_path = os.path.join('data', 'config.json')
def get(name):
val = config[name]['value']
if isinstance(val, CustomSetting):
return val.value
return val
def auto_value(val):
if hasattr(val, 'save_val'):
return val.save_val()
return val
def save_config():
global config
output = {key: [auto_value(v) for k, v in zip(config[key].keys(), config[key].values()) if k == 'value'][0] for key, value in zip(config.keys(), config.values())}
json.dump(output, open(config_path, 'w'), indent=2)
def load_config():
global config
if os.path.isfile(config_path):
config_dict = json.load(open(config_path))
for k, v in zip(config.keys(), config.values()):
if k in config_dict.keys():
v['value'] = v['type'](config_dict[k])
for k, v in zip(config.keys(), config.values()):
v.setdefault('value', v['default'])
return config
def change_value(name, value=None):
global config
if value is not None:
config[name]['value'] = value
if 'change_call' in config[name].keys():
config[name].change_call()
save_config() # Maybe add autosave as a setting instead of always on if the amount of settings becomes too much
def ui_for_setting(name, setting):
if hasattr(setting['value'], 'create_ui'):
return setting['value'].create_ui(name, setting)
standard_kwargs = {
'value': setting.get('value', setting.get('default', None)),
'label': setting.get('readname', None)
}
for kwarg, kwarg_val in zip(setting['el_kwargs'].keys(), setting['el_kwargs'].values()) if 'el_kwargs' in setting.keys() else []:
standard_kwargs[kwarg] = kwarg_val
withinfo = standard_kwargs.copy()
withinfo['info'] = setting.get('description', None)
typename = setting['type'].__name__
match typename:
case 'bool':
return gradio.Checkbox(**withinfo)
case 'int' | 'float':
num_type = 'number'
if 'num_type' in setting.keys():
num_type = setting['num_type']
step_val = setting.get('step', 1 if typename == 'int' else None)
match num_type:
case 'number':
return gradio.Number(precision=step_val, **withinfo)
case 'slider':
return gradio.Slider(step=step_val, **withinfo)
case 'list':
list_type = 'dropdown'
if 'list_type' in setting.keys():
list_type = setting['list_type']
match list_type:
case 'dropdown':
return gradio.Dropdown(choices=setting['choices'], multiselect=True, **withinfo)
case 'checkbox':
return gradio.CheckboxGroup(choices=setting['choices'], **withinfo)
case 'str':
if 'choices' in setting.keys():
list_type = 'dropdown'
if 'list_type' in setting.keys():
list_type = setting['list_type']
match list_type:
case 'dropdown':
return gradio.Dropdown(choices=setting['choices'], **withinfo)
case 'radio':
return gradio.Radio(choices=setting['choices'], **withinfo)
return gradio.Textbox(**withinfo)
raise NotImplementedError('Setting type not implemented! Create a new setting type by extending CustomSetting.')
def login_hf(token):
try:
huggingface_hub.login(token)
except (ValueError, ImportError) as e:
return False
return True
def delete_model(model):
shutil.rmtree(f'data/models/{model}')
return mod.refresh_choices()
def settings():
load_config()
save_config() # Save newly added values
tab_config = {}
other_tab = {}
for key, setting in zip(config.keys(), config.values()):
tab = setting.get('tab', '❓ other')
if tab not in tab_config.keys():
if tab == '❓ other':
other_tab[key] = setting
else:
tab_config[tab] = {key: setting}
else:
tab_config[tab][key] = setting
tab_config['❓ other'] = other_tab # Ensure other is at end
def change_setting(setting):
def c(v):
change_value(setting, v)
return c
with gradio.Tabs():
for tab, key_dict in zip(tab_config.keys(), tab_config.values()):
with gradio.Tab(tab):
for key, setting in zip(key_dict.keys(), key_dict.values()):
elem = ui_for_setting(key, setting)
if elem is not None:
elem.change(fn=change_setting(key), inputs=elem)
def extensions_tab():
with gradio.Tabs():
with gradio.Tab('βœ… Installed'):
list_all_extensions()
with gradio.Tab('⬇️ Install new extensions'):
install_extensions_tab()
def list_all_extensions():
import webui.extensionlib.extensionmanager as em
with gradio.Row():
check_updates = gradio.Button('Check for updates', variant='primary')
update_selected = gradio.Button('Update selected', variant='primary')
shutdown = gradio.Button('Shutdown audio webui')
shutdown.click(fn=lambda: os._exit(0))
gradio.Markdown('Extension managing is still work in progress, and will require restarts of the webui.')
with gradio.Row():
gradio.Markdown('## Name')
gradio.Markdown('## Description')
gradio.Markdown('## Author')
gradio.Markdown('## Update if available')
gradio.Markdown('## Enabled')
updatelist = []
def add_or_remove(name):
def f(val):
if val:
updatelist.append(val)
else:
try:
updatelist.remove(val)
except:
pass
return f
for e in em.states.values():
with gradio.Row() as parent:
gradio.Markdown(e.info['name'])
gradio.Markdown(e.info['description'])
gradio.Markdown(e.info['author'])
with gradio.Row():
e.update_el = [gradio.Markdown('Not checked'), gradio.Checkbox(False, label='Update', visible=False)]
e.update_el[1].change(fn=add_or_remove(e.extname), inputs=e.update_el[1])
enabled = gradio.Checkbox(e.enabled, label='Enabled')
enabled.change(fn=e.set_enabled, inputs=enabled, outputs=enabled)
def quick_update_return(val, l):
if isinstance(val, str):
l.append(gradio.update(visible=True, value=val))
l.append(gradio.update(visible=False))
return
l.append(gradio.update(visible=False))
l.append(gradio.update(visible=True, value=val))
def check_for_updates():
if em.git_ready():
out_list = []
for e in em.states.values():
update_status = e.check_updates()
match update_status:
case em.UpdateStatus.no_git:
if e.extname in updatelist:
updatelist.remove(e.extname)
quick_update_return('Git not installed', out_list)
case em.UpdateStatus.updated:
if e.extname in updatelist:
updatelist.remove(e.extname)
quick_update_return('Up to date', out_list)
case em.UpdateStatus.unmanaged:
if e.extname in updatelist:
updatelist.remove(e.extname)
quick_update_return('I had an issue with git', out_list)
case em.UpdateStatus.outdated:
if e.extname not in updatelist:
updatelist.append(e.extname)
quick_update_return(True, out_list)
return out_list
return quick_update_return('Git not installed') * len(em.states)
all_els = []
for e in em.states.values():
all_els.append(e.update_el[0])
all_els.append(e.update_el[1])
check_updates.click(fn=check_for_updates, outputs=all_els)
def update_exts():
for e in updatelist:
ext = em.states[e]
ext.update()
update_selected.click(fn=update_exts())
def install_extensions_tab():
import webui.extensionlib.extensionmanager as em
def install_extension(url):
command = f'git clone {url}'
command = command if is_windows() else shlex.split(command)
out = subprocess.run(command, cwd=os.path.abspath(em.ext_folder))
if out.returncode != 0:
return '', f'Something went wrong with installing! Check output in console for details.'
return '', f'Installed {url} (Not checked if successful, check console for status)'
with gradio.Row():
repo_url = gradio.Textbox(placeholder='https://www.github.com/user/repo', label='Git repo url', max_lines=1)
download_button = gradio.Button('Install from url', variant='primary')
markdown = gradio.Markdown()
download_button.click(fn=install_extension, inputs=repo_url, outputs=[repo_url, markdown])
def extra_tab():
with gradio.Tabs():
with gradio.Tab('βœ… Main'):
settings()
with gradio.Tab('πŸš€ Extensions'):
extensions_tab()
with gradio.Tab('βž• Extra'):
gradio.Markdown('# πŸ€— Huggingface')
with gradio.Row():
with gradio.Column():
textbox = gradio.Textbox(placeholder='Huggingface token from https://huggingface.co/settings/tokens goes here',
label='Huggingface token for private/gated models', lines=1, info='Put your key here if you\'re trying to load private or gated models.')
login = gradio.Button('Log in with this token', variant='primary')
login.click(fn=login_hf, inputs=textbox, api_name='login_hf', show_progress=True)
with gradio.Column():
installed_models = gradio.Dropdown(mod.choices(), label='Installed models')
with gradio.Row():
delete = gradio.Button('Delete model', variant='stop')
refresh = gradio.Button('Refresh models', variant='primary')
delete.click(fn=delete_model, inputs=installed_models, outputs=installed_models, show_progress=True, api_name='models/delete')
refresh.click(fn=mod.refresh_choices, outputs=installed_models, show_progress=True)