diff --git a/modules/shared.py b/modules/shared.py index b8ab2426..83920df8 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -225,17 +225,6 @@ settings = { 'dark_theme': True, 'paste_to_attachment': False, - # Character settings - 'character': 'Assistant', - 'name1': 'You', - 'name2': 'AI', - 'user_bio': '', - 'context': 'The following is a conversation with an AI Large Language Model. The AI has been trained to answer questions, provide recommendations, and help with decision making. The AI follows user requests. The AI thinks outside the box.', - 'greeting': 'How can I help you today?', - 'custom_system_message': '', - 'instruction_template_str': "{%- set ns = namespace(found=false) -%}\n{%- for message in messages -%}\n {%- if message['role'] == 'system' -%}\n {%- set ns.found = true -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if not ns.found -%}\n {{- '' + 'Below is an instruction that describes a task. Write a response that appropriately completes the request.' + '\\n\\n' -}}\n{%- endif %}\n{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {{- '' + message['content'] + '\\n\\n' -}}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{-'### Instruction:\\n' + message['content'] + '\\n\\n'-}}\n {%- else -%}\n {{-'### Response:\\n' + message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if add_generation_prompt -%}\n {{-'### Response:\\n'-}}\n{%- endif -%}", - 'chat_template_str': "{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {%- if message['content'] -%}\n {{- message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- if user_bio -%}\n {{- user_bio + '\\n\\n' -}}\n {%- endif -%}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{- name1 + ': ' + message['content'] + '\\n'-}}\n {%- else -%}\n {{- name2 + ': ' + message['content'] + '\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}", - # Generation parameters - Curve shape 'temperature': 0.6, 'dynatemp_low': neutral_samplers['dynatemp_low'], @@ -282,6 +271,20 @@ settings = { 'sampler_priority': neutral_samplers['sampler_priority'], 'dry_sequence_breakers': neutral_samplers['dry_sequence_breakers'], 'grammar_string': '', + + # Character settings + 'character': 'Assistant', + 'name1': 'You', + 'name2': 'AI', + 'user_bio': '', + 'context': 'The following is a conversation with an AI Large Language Model. The AI has been trained to answer questions, provide recommendations, and help with decision making. The AI follows user requests. The AI thinks outside the box.', + 'greeting': 'How can I help you today?', + 'custom_system_message': '', + 'instruction_template_str': "{%- set ns = namespace(found=false) -%}\n{%- for message in messages -%}\n {%- if message['role'] == 'system' -%}\n {%- set ns.found = true -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if not ns.found -%}\n {{- '' + 'Below is an instruction that describes a task. Write a response that appropriately completes the request.' + '\\n\\n' -}}\n{%- endif %}\n{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {{- '' + message['content'] + '\\n\\n' -}}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{-'### Instruction:\\n' + message['content'] + '\\n\\n'-}}\n {%- else -%}\n {{-'### Response:\\n' + message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if add_generation_prompt -%}\n {{-'### Response:\\n'-}}\n{%- endif -%}", + 'chat_template_str': "{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {%- if message['content'] -%}\n {{- message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- if user_bio -%}\n {{- user_bio + '\\n\\n' -}}\n {%- endif -%}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{- name1 + ': ' + message['content'] + '\\n'-}}\n {%- else -%}\n {{- name2 + ': ' + message['content'] + '\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}", + + # Extensions + 'default_extensions': [], } default_settings = copy.deepcopy(settings) diff --git a/modules/ui.py b/modules/ui.py index 59da5118..2925faa5 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -316,7 +316,7 @@ def apply_interface_values(state, use_persistent=False): return [state[k] if k in state else gr.update() for k in elements] -def save_settings(state, preset, extensions_list, show_controls, theme_state): +def save_settings(state, preset, extensions_list, show_controls, theme_state, manual_save=False): output = copy.deepcopy(shared.settings) exclude = [] for k in state: @@ -333,6 +333,22 @@ def save_settings(state, preset, extensions_list, show_controls, theme_state): output.pop('instruction_template_str') output.pop('truncation_length') + # Only save extensions on manual save + if manual_save: + output['default_extensions'] = extensions_list + else: + # Preserve existing extensions from settings file during autosave + settings_path = Path('user_data') / 'settings.yaml' + if settings_path.exists(): + try: + with open(settings_path, 'r', encoding='utf-8') as f: + existing_settings = yaml.safe_load(f.read()) or {} + + if 'default_extensions' in existing_settings: + output['default_extensions'] = existing_settings['default_extensions'] + except Exception: + pass # If we can't read the file, just don't modify extensions + # Save extension values in the UI for extension_name in extensions_list: extension = getattr(extensions, extension_name, None) @@ -383,7 +399,7 @@ def _perform_debounced_save(): try: if _last_interface_state is not None: - contents = save_settings(_last_interface_state, _last_preset, _last_extensions, _last_show_controls, _last_theme_state) + contents = save_settings(_last_interface_state, _last_preset, _last_extensions, _last_show_controls, _last_theme_state, manual_save=False) settings_path = Path('user_data') / 'settings.yaml' settings_path.parent.mkdir(exist_ok=True) with open(settings_path, 'w', encoding='utf-8') as f: diff --git a/modules/ui_session.py b/modules/ui_session.py index 33d7dcb7..0673828e 100644 --- a/modules/ui_session.py +++ b/modules/ui_session.py @@ -10,12 +10,12 @@ def create_ui(): with gr.Row(): with gr.Column(): gr.Markdown("## Settings") - shared.gradio['save_settings'] = gr.Button('Save settings to user_data/settings.yaml', elem_classes='refresh-button', interactive=not mu) shared.gradio['toggle_dark_mode'] = gr.Button('Toggle light/dark theme 💡', elem_classes='refresh-button') shared.gradio['paste_to_attachment'] = gr.Checkbox(label='Turn long pasted text into attachments in the Chat tab', value=shared.settings['paste_to_attachment'], elem_id='paste_to_attachment') with gr.Column(): gr.Markdown("## Extensions & flags") + shared.gradio['save_settings'] = gr.Button('Save settings to user_data/settings.yaml', elem_classes='refresh-button', interactive=not mu) shared.gradio['reset_interface'] = gr.Button("Apply flags/extensions and restart", interactive=not mu) with gr.Row(): with gr.Column(): @@ -40,7 +40,7 @@ def create_ui(): def handle_save_settings(state, preset, extensions, show_controls, theme): - contents = ui.save_settings(state, preset, extensions, show_controls, theme) + contents = ui.save_settings(state, preset, extensions, show_controls, theme, manual_save=True) return [ contents, "settings.yaml", diff --git a/server.py b/server.py index e0e3fbe5..cfb21a6e 100644 --- a/server.py +++ b/server.py @@ -236,20 +236,26 @@ if __name__ == "__main__": settings_file = Path(shared.args.settings) elif Path('user_data/settings.yaml').exists(): settings_file = Path('user_data/settings.yaml') - elif Path('user_data/settings.json').exists(): - settings_file = Path('user_data/settings.json') if settings_file is not None: logger.info(f"Loading settings from \"{settings_file}\"") - file_contents = open(settings_file, 'r', encoding='utf-8').read() - new_settings = json.loads(file_contents) if settings_file.suffix == "json" else yaml.safe_load(file_contents) - shared.settings.update(new_settings) + with open(settings_file, 'r', encoding='utf-8') as f: + new_settings = yaml.safe_load(f.read()) + + if new_settings: + shared.settings.update(new_settings) # Fallback settings for models shared.model_config['.*'] = get_fallback_settings() shared.model_config.move_to_end('.*', last=False) # Move to the beginning + # Activate the extensions listed on settings.yaml extensions_module.available_extensions = utils.get_available_extensions() + for extension in shared.settings['default_extensions']: + shared.args.extensions = shared.args.extensions or [] + if extension not in shared.args.extensions: + shared.args.extensions.append(extension) + available_models = utils.get_available_models() # Model defined through --model