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) | |