Spaces:
No application file
No application file
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) | |