☰', elem_id='gr-hover')
+
+ with gr.Column(scale=10, elem_id='chat-input-container'):
+ shared.gradio['textbox'] = gr.Textbox(label='', placeholder='Send a message', elem_id='chat-input', elem_classes=['add_scrollbar'])
+ shared.gradio['show_controls'] = gr.Checkbox(value=shared.settings['show_controls'], label='Show controls (Ctrl+S)', elem_id='show-controls')
+ shared.gradio['typing-dots'] = gr.HTML(value='
', label='typing', elem_id='typing-container')
+
+ with gr.Column(scale=1, elem_id='generate-stop-container'):
+ with gr.Row():
+ shared.gradio['Stop'] = gr.Button('Stop', elem_id='stop', visible=False)
+ shared.gradio['Generate'] = gr.Button('Generate', elem_id='Generate', variant='primary')
+
+ # Hover menu buttons
+ with gr.Column(elem_id='chat-buttons'):
+ with gr.Row():
+ shared.gradio['Regenerate'] = gr.Button('Regenerate (Ctrl + Enter)', elem_id='Regenerate')
+ shared.gradio['Continue'] = gr.Button('Continue (Alt + Enter)', elem_id='Continue')
+ shared.gradio['Remove last'] = gr.Button('Remove last reply (Ctrl + Shift + Backspace)', elem_id='Remove-last')
+
+ with gr.Row():
+ shared.gradio['Replace last reply'] = gr.Button('Replace last reply (Ctrl + Shift + L)', elem_id='Replace-last')
+ shared.gradio['Copy last reply'] = gr.Button('Copy last reply (Ctrl + Shift + K)', elem_id='Copy-last')
+ shared.gradio['Impersonate'] = gr.Button('Impersonate (Ctrl + Shift + M)', elem_id='Impersonate')
+
+ with gr.Row():
+ shared.gradio['Send dummy message'] = gr.Button('Send dummy message')
+ shared.gradio['Send dummy reply'] = gr.Button('Send dummy reply')
+
+ with gr.Row():
+ shared.gradio['send-chat-to-default'] = gr.Button('Send to default')
+ shared.gradio['send-chat-to-notebook'] = gr.Button('Send to notebook')
+
+ with gr.Row(elem_id='past-chats-row', elem_classes=['pretty_scrollbar']):
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['unique_id'] = gr.Dropdown(label='Past chats', elem_classes=['slim-dropdown'], interactive=not mu)
+
+ with gr.Row():
+ shared.gradio['rename_chat'] = gr.Button('Rename', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_chat'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_chat-confirm'] = gr.Button('Confirm', variant='stop', visible=False, elem_classes='refresh-button')
+ shared.gradio['delete_chat-cancel'] = gr.Button('Cancel', visible=False, elem_classes='refresh-button')
+ shared.gradio['Start new chat'] = gr.Button('New chat', elem_classes='refresh-button')
+
+ with gr.Row(elem_id='rename-row'):
+ shared.gradio['rename_to'] = gr.Textbox(label='Rename to:', placeholder='New name', visible=False, elem_classes=['no-background'])
+ shared.gradio['rename_to-confirm'] = gr.Button('Confirm', visible=False, elem_classes='refresh-button')
+ shared.gradio['rename_to-cancel'] = gr.Button('Cancel', visible=False, elem_classes='refresh-button')
+
+ with gr.Row():
+ shared.gradio['start_with'] = gr.Textbox(label='Start reply with', placeholder='Sure thing!', value=shared.settings['start_with'])
+
+ with gr.Row():
+ shared.gradio['mode'] = gr.Radio(choices=['chat', 'chat-instruct', 'instruct'], value='chat', label='Mode', info='Defines how the chat prompt is generated. In instruct and chat-instruct modes, the instruction template selected under Parameters > Instruction template must match the current model.', elem_id='chat-mode')
+ shared.gradio['chat_style'] = gr.Dropdown(choices=utils.get_available_chat_styles(), label='Chat style', value=shared.settings['chat_style'], visible=shared.settings['mode'] != 'instruct')
+
+
+def create_chat_settings_ui():
+ mu = shared.args.multi_user
+ with gr.Tab('Character'):
+ with gr.Row():
+ with gr.Column(scale=8):
+ with gr.Row():
+ shared.gradio['character_menu'] = gr.Dropdown(value=None, choices=utils.get_available_characters(), label='Character', elem_id='character-menu', info='Used in chat and chat-instruct modes.', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['character_menu'], lambda: None, lambda: {'choices': utils.get_available_characters()}, 'refresh-button', interactive=not mu)
+ shared.gradio['save_character'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_character'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
+
+ shared.gradio['name1'] = gr.Textbox(value=shared.settings['name1'], lines=1, label='Your name')
+ shared.gradio['name2'] = gr.Textbox(value='', lines=1, label='Character\'s name')
+ shared.gradio['context'] = gr.Textbox(value='', lines=10, label='Context', elem_classes=['add_scrollbar'])
+ shared.gradio['greeting'] = gr.Textbox(value='', lines=5, label='Greeting', elem_classes=['add_scrollbar'])
+
+ with gr.Column(scale=1):
+ shared.gradio['character_picture'] = gr.Image(label='Character picture', type='pil', interactive=not mu)
+ shared.gradio['your_picture'] = gr.Image(label='Your picture', type='pil', value=Image.open(Path('cache/pfp_me.png')) if Path('cache/pfp_me.png').exists() else None, interactive=not mu)
+
+ with gr.Tab('Instruction template'):
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['instruction_template'] = gr.Dropdown(choices=utils.get_available_instruction_templates(), label='Saved instruction templates', value='Select template to load...', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['instruction_template'], lambda: None, lambda: {'choices': utils.get_available_instruction_templates()}, 'refresh-button', interactive=not mu)
+ shared.gradio['load_template'] = gr.Button("Load", elem_classes='refresh-button')
+ shared.gradio['save_template'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_template'] = gr.Button('🗑️ ', elem_classes='refresh-button', interactive=not mu)
+
+ with gr.Column():
+ pass
+
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['custom_system_message'] = gr.Textbox(value=shared.settings['custom_system_message'], lines=2, label='Custom system message', info='If not empty, will be used instead of the default one.', elem_classes=['add_scrollbar'])
+ shared.gradio['instruction_template_str'] = gr.Textbox(value='', label='Instruction template', lines=24, info='Change this according to the model/LoRA that you are using. Used in instruct and chat-instruct modes.', elem_classes=['add_scrollbar', 'monospace'])
+ with gr.Row():
+ shared.gradio['send_instruction_to_default'] = gr.Button('Send to default', elem_classes=['small-button'])
+ shared.gradio['send_instruction_to_notebook'] = gr.Button('Send to notebook', elem_classes=['small-button'])
+ shared.gradio['send_instruction_to_negative_prompt'] = gr.Button('Send to negative prompt', elem_classes=['small-button'])
+
+ with gr.Column():
+ shared.gradio['chat_template_str'] = gr.Textbox(value=shared.settings['chat_template_str'], label='Chat template', lines=22, elem_classes=['add_scrollbar', 'monospace'])
+ shared.gradio['chat-instruct_command'] = gr.Textbox(value=shared.settings['chat-instruct_command'], lines=4, label='Command for chat-instruct mode', info='<|character|> gets replaced by the bot name, and <|prompt|> gets replaced by the regular chat prompt.', elem_classes=['add_scrollbar'])
+
+ with gr.Tab('Chat history'):
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['save_chat_history'] = gr.Button(value='Save history')
+
+ with gr.Column():
+ shared.gradio['load_chat_history'] = gr.File(type='binary', file_types=['.json', '.txt'], label='Upload History JSON')
+
+ with gr.Tab('Upload character'):
+ with gr.Tab('YAML or JSON'):
+ with gr.Row():
+ shared.gradio['upload_json'] = gr.File(type='binary', file_types=['.json', '.yaml'], label='JSON or YAML File', interactive=not mu)
+ shared.gradio['upload_img_bot'] = gr.Image(type='pil', label='Profile Picture (optional)', interactive=not mu)
+
+ shared.gradio['Submit character'] = gr.Button(value='Submit', interactive=False)
+
+ with gr.Tab('TavernAI PNG'):
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['upload_img_tavern'] = gr.Image(type='pil', label='TavernAI PNG File', elem_id='upload_img_tavern', interactive=not mu)
+ shared.gradio['tavern_json'] = gr.State()
+ with gr.Column():
+ shared.gradio['tavern_name'] = gr.Textbox(value='', lines=1, label='Name', interactive=False)
+ shared.gradio['tavern_desc'] = gr.Textbox(value='', lines=4, max_lines=4, label='Description', interactive=False)
+
+ shared.gradio['Submit tavern character'] = gr.Button(value='Submit', interactive=False)
+
+
+def create_event_handlers():
+
+ # Obsolete variables, kept for compatibility with old extensions
+ shared.input_params = gradio(inputs)
+ shared.reload_inputs = gradio(reload_arr)
+
+ shared.gradio['Generate'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: (x, ''), gradio('textbox'), gradio('Chat input', 'textbox'), show_progress=False).then(
+ chat.generate_chat_reply_wrapper, gradio(inputs), gradio('display', 'history'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['textbox'].submit(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: (x, ''), gradio('textbox'), gradio('Chat input', 'textbox'), show_progress=False).then(
+ chat.generate_chat_reply_wrapper, gradio(inputs), gradio('display', 'history'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Regenerate'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ partial(chat.generate_chat_reply_wrapper, regenerate=True), gradio(inputs), gradio('display', 'history'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Continue'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ partial(chat.generate_chat_reply_wrapper, _continue=True), gradio(inputs), gradio('display', 'history'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Impersonate'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: x, gradio('textbox'), gradio('Chat input'), show_progress=False).then(
+ chat.impersonate_wrapper, gradio(inputs), gradio('textbox', 'display'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Replace last reply'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.replace_last_reply, gradio('textbox', 'interface_state'), gradio('history')).then(
+ lambda: '', None, gradio('textbox'), show_progress=False).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None)
+
+ shared.gradio['Send dummy message'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.send_dummy_message, gradio('textbox', 'interface_state'), gradio('history')).then(
+ lambda: '', None, gradio('textbox'), show_progress=False).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None)
+
+ shared.gradio['Send dummy reply'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.send_dummy_reply, gradio('textbox', 'interface_state'), gradio('history')).then(
+ lambda: '', None, gradio('textbox'), show_progress=False).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None)
+
+ shared.gradio['Remove last'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.remove_last_message, gradio('history'), gradio('textbox', 'history'), show_progress=False).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None)
+
+ shared.gradio['Stop'].click(
+ stop_everything_event, None, None, queue=False).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display'))
+
+ if not shared.args.multi_user:
+ shared.gradio['unique_id'].select(
+ chat.load_history, gradio('unique_id', 'character_menu', 'mode'), gradio('history')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display'))
+
+ shared.gradio['Start new chat'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.start_new_chat, gradio('interface_state'), gradio('history')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id'))
+
+ shared.gradio['delete_chat'].click(lambda: [gr.update(visible=True), gr.update(visible=False), gr.update(visible=True)], None, gradio(clear_arr))
+ shared.gradio['delete_chat-cancel'].click(lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)], None, gradio(clear_arr))
+ shared.gradio['delete_chat-confirm'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x, y: str(chat.find_all_histories(x).index(y)), gradio('interface_state', 'unique_id'), gradio('temporary_text')).then(
+ chat.delete_history, gradio('unique_id', 'character_menu', 'mode'), None).then(
+ chat.load_history_after_deletion, gradio('interface_state', 'temporary_text'), gradio('history', 'unique_id')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)], None, gradio(clear_arr))
+
+ shared.gradio['rename_chat'].click(
+ lambda x: x, gradio('unique_id'), gradio('rename_to')).then(
+ lambda: [gr.update(visible=True)] * 3, None, gradio('rename_to', 'rename_to-confirm', 'rename_to-cancel'), show_progress=False)
+
+ shared.gradio['rename_to-cancel'].click(
+ lambda: [gr.update(visible=False)] * 3, None, gradio('rename_to', 'rename_to-confirm', 'rename_to-cancel'), show_progress=False)
+
+ shared.gradio['rename_to-confirm'].click(
+ chat.rename_history, gradio('unique_id', 'rename_to', 'character_menu', 'mode'), None).then(
+ lambda: [gr.update(visible=False)] * 3, None, gradio('rename_to', 'rename_to-confirm', 'rename_to-cancel'), show_progress=False).then(
+ lambda x, y: gr.update(choices=chat.find_all_histories(x), value=y), gradio('interface_state', 'rename_to'), gradio('unique_id'))
+
+ shared.gradio['rename_to'].submit(
+ chat.rename_history, gradio('unique_id', 'rename_to', 'character_menu', 'mode'), None).then(
+ lambda: [gr.update(visible=False)] * 3, None, gradio('rename_to', 'rename_to-confirm', 'rename_to-cancel'), show_progress=False).then(
+ lambda x, y: gr.update(choices=chat.find_all_histories(x), value=y), gradio('interface_state', 'rename_to'), gradio('unique_id'))
+
+ shared.gradio['load_chat_history'].upload(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.start_new_chat, gradio('interface_state'), gradio('history')).then(
+ chat.load_history_json, gradio('load_chat_history', 'history'), gradio('history')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id')).then(
+ chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_chat()}}')
+
+ shared.gradio['character_menu'].change(
+ chat.load_character, gradio('character_menu', 'name1', 'name2'), gradio('name1', 'name2', 'character_picture', 'greeting', 'context')).success(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.load_latest_history, gradio('interface_state'), gradio('history')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.update_big_picture_js}; updateBigPicture()}}')
+
+ shared.gradio['mode'].change(
+ lambda x: gr.update(visible=x != 'instruct'), gradio('mode'), gradio('chat_style'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ chat.load_latest_history, gradio('interface_state'), gradio('history')).then(
+ chat.redraw_html, gradio(reload_arr), gradio('display')).then(
+ lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id'))
+
+ shared.gradio['chat_style'].change(chat.redraw_html, gradio(reload_arr), gradio('display'))
+ shared.gradio['Copy last reply'].click(chat.send_last_reply_to_input, gradio('history'), gradio('textbox'), show_progress=False)
+
+ # Save/delete a character
+ shared.gradio['save_character'].click(
+ lambda x: x, gradio('name2'), gradio('save_character_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('character_saver'))
+
+ shared.gradio['delete_character'].click(lambda: gr.update(visible=True), None, gradio('character_deleter'))
+
+ shared.gradio['load_template'].click(
+ chat.load_instruction_template, gradio('instruction_template'), gradio('instruction_template_str')).then(
+ lambda: "Select template to load...", None, gradio('instruction_template'))
+
+ shared.gradio['save_template'].click(
+ lambda: 'My Template.yaml', None, gradio('save_filename')).then(
+ lambda: 'instruction-templates/', None, gradio('save_root')).then(
+ chat.generate_instruction_template_yaml, gradio('instruction_template_str'), gradio('save_contents')).then(
+ lambda: gr.update(visible=True), None, gradio('file_saver'))
+
+ shared.gradio['delete_template'].click(
+ lambda x: f'{x}.yaml', gradio('instruction_template'), gradio('delete_filename')).then(
+ lambda: 'instruction-templates/', None, gradio('delete_root')).then(
+ lambda: gr.update(visible=True), None, gradio('file_deleter'))
+
+ shared.gradio['save_chat_history'].click(
+ lambda x: json.dumps(x, indent=4), gradio('history'), gradio('temporary_text')).then(
+ None, gradio('temporary_text', 'character_menu', 'mode'), None, _js=f'(hist, char, mode) => {{{ui.save_files_js}; saveHistory(hist, char, mode)}}')
+
+ shared.gradio['Submit character'].click(
+ chat.upload_character, gradio('upload_json', 'upload_img_bot'), gradio('character_menu')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_character()}}')
+
+ shared.gradio['Submit tavern character'].click(
+ chat.upload_tavern_character, gradio('upload_img_tavern', 'tavern_json'), gradio('character_menu')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_character()}}')
+
+ shared.gradio['upload_json'].upload(lambda: gr.update(interactive=True), None, gradio('Submit character'))
+ shared.gradio['upload_json'].clear(lambda: gr.update(interactive=False), None, gradio('Submit character'))
+ shared.gradio['upload_img_tavern'].upload(chat.check_tavern_character, gradio('upload_img_tavern'), gradio('tavern_name', 'tavern_desc', 'tavern_json', 'Submit tavern character'), show_progress=False)
+ shared.gradio['upload_img_tavern'].clear(lambda: (None, None, None, gr.update(interactive=False)), None, gradio('tavern_name', 'tavern_desc', 'tavern_json', 'Submit tavern character'), show_progress=False)
+ shared.gradio['your_picture'].change(
+ chat.upload_your_profile_picture, gradio('your_picture'), None).then(
+ partial(chat.redraw_html, reset_cache=True), gradio(reload_arr), gradio('display'))
+
+ shared.gradio['send_instruction_to_default'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: x.update({'mode': 'instruct', 'history': {'internal': [], 'visible': []}}), gradio('interface_state'), None).then(
+ partial(chat.generate_chat_prompt, 'Input'), gradio('interface_state'), gradio('textbox-default')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_default()}}')
+
+ shared.gradio['send_instruction_to_notebook'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: x.update({'mode': 'instruct', 'history': {'internal': [], 'visible': []}}), gradio('interface_state'), None).then(
+ partial(chat.generate_chat_prompt, 'Input'), gradio('interface_state'), gradio('textbox-notebook')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_notebook()}}')
+
+ shared.gradio['send_instruction_to_negative_prompt'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: x.update({'mode': 'instruct', 'history': {'internal': [], 'visible': []}}), gradio('interface_state'), None).then(
+ partial(chat.generate_chat_prompt, 'Input'), gradio('interface_state'), gradio('negative_prompt')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_generation_parameters()}}')
+
+ shared.gradio['send-chat-to-default'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ partial(chat.generate_chat_prompt, '', _continue=True), gradio('interface_state'), gradio('textbox-default')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_default()}}')
+
+ shared.gradio['send-chat-to-notebook'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ partial(chat.generate_chat_prompt, '', _continue=True), gradio('interface_state'), gradio('textbox-notebook')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.switch_tabs_js}; switch_to_notebook()}}')
+
+ shared.gradio['show_controls'].change(None, gradio('show_controls'), None, _js=f'(x) => {{{ui.show_controls_js}; toggle_controls(x)}}')
diff --git a/modules/ui_default.py b/modules/ui_default.py
new file mode 100644
index 0000000000000000000000000000000000000000..7db6f0d93abcc36354b0d687d83c865b8f5dd406
--- /dev/null
+++ b/modules/ui_default.py
@@ -0,0 +1,104 @@
+import gradio as gr
+
+from modules import logits, shared, ui, utils
+from modules.prompts import count_tokens, load_prompt
+from modules.text_generation import (
+ generate_reply_wrapper,
+ get_token_ids,
+ stop_everything_event
+)
+from modules.utils import gradio
+
+inputs = ('textbox-default', 'interface_state')
+outputs = ('output_textbox', 'html-default')
+
+
+def create_ui():
+ mu = shared.args.multi_user
+ with gr.Tab('Default', elem_id='default-tab'):
+ shared.gradio['last_input-default'] = gr.State('')
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['textbox-default'] = gr.Textbox(value='', lines=27, label='Input', elem_classes=['textbox_default', 'add_scrollbar'])
+ shared.gradio['token-counter-default'] = gr.HTML(value="
0", elem_classes=["token-counter", "default-token-counter"])
+
+ with gr.Row():
+ shared.gradio['Generate-default'] = gr.Button('Generate', variant='primary')
+ shared.gradio['Stop-default'] = gr.Button('Stop', elem_id='stop')
+ shared.gradio['Continue-default'] = gr.Button('Continue')
+
+ with gr.Row():
+ shared.gradio['prompt_menu-default'] = gr.Dropdown(choices=utils.get_available_prompts(), value='None', label='Prompt', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['prompt_menu-default'], lambda: None, lambda: {'choices': utils.get_available_prompts()}, 'refresh-button', interactive=not mu)
+ shared.gradio['save_prompt-default'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_prompt-default'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
+
+ with gr.Column():
+ with gr.Tab('Raw'):
+ shared.gradio['output_textbox'] = gr.Textbox(lines=27, label='Output', elem_id='textbox-default', elem_classes=['textbox_default_output', 'add_scrollbar'])
+
+ with gr.Tab('Markdown'):
+ shared.gradio['markdown_render-default'] = gr.Button('Render')
+ shared.gradio['markdown-default'] = gr.Markdown()
+
+ with gr.Tab('HTML'):
+ shared.gradio['html-default'] = gr.HTML()
+
+ with gr.Tab('Logits'):
+ with gr.Row():
+ with gr.Column(scale=10):
+ shared.gradio['get_logits-default'] = gr.Button('Get next token probabilities')
+ with gr.Column(scale=1):
+ shared.gradio['use_samplers-default'] = gr.Checkbox(label='Use samplers', value=True, elem_classes=['no-background'])
+
+ with gr.Row():
+ shared.gradio['logits-default'] = gr.Textbox(lines=23, label='Output', elem_classes=['textbox_logits', 'add_scrollbar'])
+ shared.gradio['logits-default-previous'] = gr.Textbox(lines=23, label='Previous output', elem_classes=['textbox_logits', 'add_scrollbar'])
+
+ with gr.Tab('Tokens'):
+ shared.gradio['get_tokens-default'] = gr.Button('Get token IDs for the input')
+ shared.gradio['tokens-default'] = gr.Textbox(lines=23, label='Tokens', elem_classes=['textbox_logits', 'add_scrollbar', 'monospace'])
+
+
+def create_event_handlers():
+ shared.gradio['Generate-default'].click(
+ lambda x: x, gradio('textbox-default'), gradio('last_input-default')).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, gradio(inputs), gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['textbox-default'].submit(
+ lambda x: x, gradio('textbox-default'), gradio('last_input-default')).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, gradio(inputs), gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['markdown_render-default'].click(lambda x: x, gradio('output_textbox'), gradio('markdown-default'), queue=False)
+ shared.gradio['Continue-default'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, [shared.gradio['output_textbox']] + gradio(inputs)[1:], gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Stop-default'].click(stop_everything_event, None, None, queue=False)
+ shared.gradio['prompt_menu-default'].change(load_prompt, gradio('prompt_menu-default'), gradio('textbox-default'), show_progress=False)
+ shared.gradio['save_prompt-default'].click(
+ lambda x: x, gradio('textbox-default'), gradio('save_contents')).then(
+ lambda: 'prompts/', None, gradio('save_root')).then(
+ lambda: utils.current_time() + '.txt', None, gradio('save_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_saver'))
+
+ shared.gradio['delete_prompt-default'].click(
+ lambda: 'prompts/', None, gradio('delete_root')).then(
+ lambda x: x + '.txt', gradio('prompt_menu-default'), gradio('delete_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_deleter'))
+
+ shared.gradio['textbox-default'].change(lambda x: f"
{count_tokens(x)}", gradio('textbox-default'), gradio('token-counter-default'), show_progress=False)
+ shared.gradio['get_logits-default'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ logits.get_next_logits, gradio('textbox-default', 'interface_state', 'use_samplers-default', 'logits-default'), gradio('logits-default', 'logits-default-previous'), show_progress=False)
+
+ shared.gradio['get_tokens-default'].click(get_token_ids, gradio('textbox-default'), gradio('tokens-default'), show_progress=False)
diff --git a/modules/ui_file_saving.py b/modules/ui_file_saving.py
new file mode 100644
index 0000000000000000000000000000000000000000..7147121773eb091a3c0bf6ebe14905783cf67405
--- /dev/null
+++ b/modules/ui_file_saving.py
@@ -0,0 +1,103 @@
+import gradio as gr
+
+from modules import chat, presets, shared, ui, utils
+from modules.utils import gradio
+
+
+def create_ui():
+ mu = shared.args.multi_user
+
+ # Text file saver
+ with gr.Group(visible=False, elem_classes='file-saver') as shared.gradio['file_saver']:
+ shared.gradio['save_filename'] = gr.Textbox(lines=1, label='File name')
+ shared.gradio['save_root'] = gr.Textbox(lines=1, label='File folder', info='For reference. Unchangeable.', interactive=False)
+ shared.gradio['save_contents'] = gr.Textbox(lines=10, label='File contents')
+ with gr.Row():
+ shared.gradio['save_cancel'] = gr.Button('Cancel', elem_classes="small-button")
+ shared.gradio['save_confirm'] = gr.Button('Save', elem_classes="small-button", variant='primary', interactive=not mu)
+
+ # Text file deleter
+ with gr.Group(visible=False, elem_classes='file-saver') as shared.gradio['file_deleter']:
+ shared.gradio['delete_filename'] = gr.Textbox(lines=1, label='File name')
+ shared.gradio['delete_root'] = gr.Textbox(lines=1, label='File folder', info='For reference. Unchangeable.', interactive=False)
+ with gr.Row():
+ shared.gradio['delete_cancel'] = gr.Button('Cancel', elem_classes="small-button")
+ shared.gradio['delete_confirm'] = gr.Button('Delete', elem_classes="small-button", variant='stop', interactive=not mu)
+
+ # Character saver/deleter
+ with gr.Group(visible=False, elem_classes='file-saver') as shared.gradio['character_saver']:
+ shared.gradio['save_character_filename'] = gr.Textbox(lines=1, label='File name', info='The character will be saved to your characters/ folder with this base filename.')
+ with gr.Row():
+ shared.gradio['save_character_cancel'] = gr.Button('Cancel', elem_classes="small-button")
+ shared.gradio['save_character_confirm'] = gr.Button('Save', elem_classes="small-button", variant='primary', interactive=not mu)
+
+ with gr.Group(visible=False, elem_classes='file-saver') as shared.gradio['character_deleter']:
+ gr.Markdown('Confirm the character deletion?')
+ with gr.Row():
+ shared.gradio['delete_character_cancel'] = gr.Button('Cancel', elem_classes="small-button")
+ shared.gradio['delete_character_confirm'] = gr.Button('Delete', elem_classes="small-button", variant='stop', interactive=not mu)
+
+ # Preset saver
+ with gr.Group(visible=False, elem_classes='file-saver') as shared.gradio['preset_saver']:
+ shared.gradio['save_preset_filename'] = gr.Textbox(lines=1, label='File name', info='The preset will be saved to your presets/ folder with this base filename.')
+ shared.gradio['save_preset_contents'] = gr.Textbox(lines=10, label='File contents')
+ with gr.Row():
+ shared.gradio['save_preset_cancel'] = gr.Button('Cancel', elem_classes="small-button")
+ shared.gradio['save_preset_confirm'] = gr.Button('Save', elem_classes="small-button", variant='primary', interactive=not mu)
+
+
+def create_event_handlers():
+ shared.gradio['save_confirm'].click(
+ lambda x, y, z: utils.save_file(x + y, z), gradio('save_root', 'save_filename', 'save_contents'), None).then(
+ lambda: gr.update(visible=False), None, gradio('file_saver'))
+
+ shared.gradio['delete_confirm'].click(
+ lambda x, y: utils.delete_file(x + y), gradio('delete_root', 'delete_filename'), None).then(
+ lambda: gr.update(visible=False), None, gradio('file_deleter'))
+
+ shared.gradio['delete_cancel'].click(lambda: gr.update(visible=False), None, gradio('file_deleter'))
+ shared.gradio['save_cancel'].click(lambda: gr.update(visible=False), None, gradio('file_saver'))
+
+ shared.gradio['save_character_confirm'].click(
+ chat.save_character, gradio('name2', 'greeting', 'context', 'character_picture', 'save_character_filename'), None).then(
+ lambda: gr.update(visible=False), None, gradio('character_saver')).then(
+ lambda x: gr.update(choices=utils.get_available_characters(), value=x), gradio('save_character_filename'), gradio('character_menu'))
+
+ shared.gradio['delete_character_confirm'].click(
+ lambda x: str(utils.get_available_characters().index(x)), gradio('character_menu'), gradio('temporary_text')).then(
+ chat.delete_character, gradio('character_menu'), None).then(
+ chat.update_character_menu_after_deletion, gradio('temporary_text'), gradio('character_menu')).then(
+ lambda: gr.update(visible=False), None, gradio('character_deleter'))
+
+ shared.gradio['save_character_cancel'].click(lambda: gr.update(visible=False), None, gradio('character_saver'))
+ shared.gradio['delete_character_cancel'].click(lambda: gr.update(visible=False), None, gradio('character_deleter'))
+
+ shared.gradio['save_preset'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ presets.generate_preset_yaml, gradio('interface_state'), gradio('save_preset_contents')).then(
+ lambda: 'My Preset', None, gradio('save_preset_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('preset_saver'))
+
+ shared.gradio['save_preset_confirm'].click(
+ lambda x, y: utils.save_file(f'presets/{x}.yaml', y), gradio('save_preset_filename', 'save_preset_contents'), None).then(
+ lambda: gr.update(visible=False), None, gradio('preset_saver')).then(
+ lambda x: gr.update(choices=utils.get_available_presets(), value=x), gradio('save_preset_filename'), gradio('preset_menu'))
+
+ shared.gradio['save_preset_cancel'].click(lambda: gr.update(visible=False), None, gradio('preset_saver'))
+
+ shared.gradio['delete_preset'].click(
+ lambda x: f'{x}.yaml', gradio('preset_menu'), gradio('delete_filename')).then(
+ lambda: 'presets/', None, gradio('delete_root')).then(
+ lambda: gr.update(visible=True), None, gradio('file_deleter'))
+
+ shared.gradio['save_grammar'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda x: x, gradio('grammar_string'), gradio('save_contents')).then(
+ lambda: 'grammars/', None, gradio('save_root')).then(
+ lambda: 'My Fancy Grammar.gbnf', None, gradio('save_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_saver'))
+
+ shared.gradio['delete_grammar'].click(
+ lambda x: x, gradio('grammar_file'), gradio('delete_filename')).then(
+ lambda: 'grammars/', None, gradio('delete_root')).then(
+ lambda: gr.update(visible=True), None, gradio('file_deleter'))
diff --git a/modules/ui_model_menu.py b/modules/ui_model_menu.py
new file mode 100644
index 0000000000000000000000000000000000000000..23679097730df1b6cb9f3b694213c3679bd42f36
--- /dev/null
+++ b/modules/ui_model_menu.py
@@ -0,0 +1,280 @@
+import importlib
+import math
+import re
+import traceback
+from functools import partial
+from pathlib import Path
+
+import gradio as gr
+import psutil
+import torch
+from transformers import is_torch_xpu_available
+
+from modules import loaders, shared, ui, utils
+from modules.logging_colors import logger
+from modules.LoRA import add_lora_to_model
+from modules.models import load_model, unload_model
+from modules.models_settings import (
+ apply_model_settings_to_state,
+ get_model_metadata,
+ save_model_settings,
+ update_model_parameters
+)
+from modules.utils import gradio
+
+
+def create_ui():
+ mu = shared.args.multi_user
+
+ # Finding the default values for the GPU and CPU memories
+ total_mem = []
+ if is_torch_xpu_available():
+ for i in range(torch.xpu.device_count()):
+ total_mem.append(math.floor(torch.xpu.get_device_properties(i).total_memory / (1024 * 1024)))
+ else:
+ for i in range(torch.cuda.device_count()):
+ total_mem.append(math.floor(torch.cuda.get_device_properties(i).total_memory / (1024 * 1024)))
+
+ default_gpu_mem = []
+ if shared.args.gpu_memory is not None and len(shared.args.gpu_memory) > 0:
+ for i in shared.args.gpu_memory:
+ if 'mib' in i.lower():
+ default_gpu_mem.append(int(re.sub('[a-zA-Z ]', '', i)))
+ else:
+ default_gpu_mem.append(int(re.sub('[a-zA-Z ]', '', i)) * 1000)
+
+ while len(default_gpu_mem) < len(total_mem):
+ default_gpu_mem.append(0)
+
+ total_cpu_mem = math.floor(psutil.virtual_memory().total / (1024 * 1024))
+ if shared.args.cpu_memory is not None:
+ default_cpu_mem = re.sub('[a-zA-Z ]', '', shared.args.cpu_memory)
+ else:
+ default_cpu_mem = 0
+
+ with gr.Tab("Model", elem_id="model-tab"):
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['model_menu'] = gr.Dropdown(choices=utils.get_available_models(), value=lambda: shared.model_name, label='Model', elem_classes='slim-dropdown', interactive=not mu)
+ ui.create_refresh_button(shared.gradio['model_menu'], lambda: None, lambda: {'choices': utils.get_available_models()}, 'refresh-button', interactive=not mu)
+ shared.gradio['load_model'] = gr.Button("Load", visible=not shared.settings['autoload_model'], elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['unload_model'] = gr.Button("Unload", elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['reload_model'] = gr.Button("Reload", elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['save_model_settings'] = gr.Button("Save settings", elem_classes='refresh-button', interactive=not mu)
+
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['lora_menu'] = gr.Dropdown(multiselect=True, choices=utils.get_available_loras(), value=shared.lora_names, label='LoRA(s)', elem_classes='slim-dropdown', interactive=not mu)
+ ui.create_refresh_button(shared.gradio['lora_menu'], lambda: None, lambda: {'choices': utils.get_available_loras(), 'value': shared.lora_names}, 'refresh-button', interactive=not mu)
+ shared.gradio['lora_menu_apply'] = gr.Button(value='Apply LoRAs', elem_classes='refresh-button', interactive=not mu)
+
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['loader'] = gr.Dropdown(label="Model loader", choices=loaders.loaders_and_params.keys(), value=None)
+ with gr.Box():
+ with gr.Row():
+ with gr.Column():
+ with gr.Blocks():
+ for i in range(len(total_mem)):
+ shared.gradio[f'gpu_memory_{i}'] = gr.Slider(label=f"gpu-memory in MiB for device :{i}", maximum=total_mem[i], value=default_gpu_mem[i])
+
+ shared.gradio['cpu_memory'] = gr.Slider(label="cpu-memory in MiB", maximum=total_cpu_mem, value=default_cpu_mem)
+
+ with gr.Blocks():
+ shared.gradio['transformers_info'] = gr.Markdown('load-in-4bit params:')
+ shared.gradio['compute_dtype'] = gr.Dropdown(label="compute_dtype", choices=["bfloat16", "float16", "float32"], value=shared.args.compute_dtype)
+ shared.gradio['quant_type'] = gr.Dropdown(label="quant_type", choices=["nf4", "fp4"], value=shared.args.quant_type)
+
+ shared.gradio['hqq_backend'] = gr.Dropdown(label="hqq_backend", choices=["PYTORCH", "PYTORCH_COMPILE", "ATEN"], value=shared.args.hqq_backend)
+ shared.gradio['n_gpu_layers'] = gr.Slider(label="n-gpu-layers", minimum=0, maximum=256, value=shared.args.n_gpu_layers)
+ shared.gradio['n_ctx'] = gr.Slider(minimum=0, maximum=shared.settings['truncation_length_max'], step=256, label="n_ctx", value=shared.args.n_ctx, info='Context length. Try lowering this if you run out of memory while loading the model.')
+ shared.gradio['tensor_split'] = gr.Textbox(label='tensor_split', info='List of proportions to split the model across multiple GPUs. Example: 18,17')
+ shared.gradio['n_batch'] = gr.Slider(label="n_batch", minimum=1, maximum=2048, step=1, value=shared.args.n_batch)
+ shared.gradio['threads'] = gr.Slider(label="threads", minimum=0, step=1, maximum=32, value=shared.args.threads)
+ shared.gradio['threads_batch'] = gr.Slider(label="threads_batch", minimum=0, step=1, maximum=32, value=shared.args.threads_batch)
+ shared.gradio['wbits'] = gr.Dropdown(label="wbits", choices=["None", 1, 2, 3, 4, 8], value=shared.args.wbits if shared.args.wbits > 0 else "None")
+ shared.gradio['groupsize'] = gr.Dropdown(label="groupsize", choices=["None", 32, 64, 128, 1024], value=shared.args.groupsize if shared.args.groupsize > 0 else "None")
+ shared.gradio['model_type'] = gr.Dropdown(label="model_type", choices=["None"], value=shared.args.model_type or "None")
+ shared.gradio['pre_layer'] = gr.Slider(label="pre_layer", minimum=0, maximum=100, value=shared.args.pre_layer[0] if shared.args.pre_layer is not None else 0)
+ shared.gradio['gpu_split'] = gr.Textbox(label='gpu-split', info='Comma-separated list of VRAM (in GB) to use per GPU. Example: 20,7,7')
+ shared.gradio['max_seq_len'] = gr.Slider(label='max_seq_len', minimum=0, maximum=shared.settings['truncation_length_max'], step=256, info='Context length. Try lowering this if you run out of memory while loading the model.', value=shared.args.max_seq_len)
+ with gr.Blocks():
+ shared.gradio['alpha_value'] = gr.Slider(label='alpha_value', minimum=1, maximum=8, step=0.05, info='Positional embeddings alpha factor for NTK RoPE scaling. Recommended values (NTKv1): 1.75 for 1.5x context, 2.5 for 2x context. Use either this or compress_pos_emb, not both.', value=shared.args.alpha_value)
+ shared.gradio['rope_freq_base'] = gr.Slider(label='rope_freq_base', minimum=0, maximum=1000000, step=1000, info='If greater than 0, will be used instead of alpha_value. Those two are related by rope_freq_base = 10000 * alpha_value ^ (64 / 63)', value=shared.args.rope_freq_base)
+ shared.gradio['compress_pos_emb'] = gr.Slider(label='compress_pos_emb', minimum=1, maximum=8, step=1, info='Positional embeddings compression factor. Should be set to (context length) / (model\'s original context length). Equal to 1/rope_freq_scale.', value=shared.args.compress_pos_emb)
+
+ shared.gradio['autogptq_info'] = gr.Markdown('ExLlamav2_HF is recommended over AutoGPTQ for models derived from Llama.')
+ shared.gradio['quipsharp_info'] = gr.Markdown('QuIP# has to be installed manually at the moment.')
+
+ with gr.Column():
+ shared.gradio['load_in_8bit'] = gr.Checkbox(label="load-in-8bit", value=shared.args.load_in_8bit)
+ shared.gradio['load_in_4bit'] = gr.Checkbox(label="load-in-4bit", value=shared.args.load_in_4bit)
+ shared.gradio['use_double_quant'] = gr.Checkbox(label="use_double_quant", value=shared.args.use_double_quant)
+ shared.gradio['use_flash_attention_2'] = gr.Checkbox(label="use_flash_attention_2", value=shared.args.use_flash_attention_2, info='Set use_flash_attention_2=True while loading the model.')
+ shared.gradio['auto_devices'] = gr.Checkbox(label="auto-devices", value=shared.args.auto_devices)
+ shared.gradio['tensorcores'] = gr.Checkbox(label="tensorcores", value=shared.args.tensorcores, info='NVIDIA only: use llama-cpp-python compiled with tensor cores support. This increases performance on RTX cards.')
+ shared.gradio['cpu'] = gr.Checkbox(label="cpu", value=shared.args.cpu, info='llama.cpp: Use llama-cpp-python compiled without GPU acceleration. Transformers: use PyTorch in CPU mode.')
+ shared.gradio['row_split'] = gr.Checkbox(label="row_split", value=shared.args.row_split, info='Split the model by rows across GPUs. This may improve multi-gpu performance.')
+ shared.gradio['no_offload_kqv'] = gr.Checkbox(label="no_offload_kqv", value=shared.args.no_offload_kqv, info='Do not offload the K, Q, V to the GPU. This saves VRAM but reduces the performance.')
+ shared.gradio['no_mul_mat_q'] = gr.Checkbox(label="no_mul_mat_q", value=shared.args.no_mul_mat_q, info='Disable the mulmat kernels.')
+ shared.gradio['triton'] = gr.Checkbox(label="triton", value=shared.args.triton)
+ shared.gradio['no_inject_fused_attention'] = gr.Checkbox(label="no_inject_fused_attention", value=shared.args.no_inject_fused_attention, info='Disable fused attention. Fused attention improves inference performance but uses more VRAM. Fuses layers for AutoAWQ. Disable if running low on VRAM.')
+ shared.gradio['no_inject_fused_mlp'] = gr.Checkbox(label="no_inject_fused_mlp", value=shared.args.no_inject_fused_mlp, info='Affects Triton only. Disable fused MLP. Fused MLP improves performance but uses more VRAM. Disable if running low on VRAM.')
+ shared.gradio['no_use_cuda_fp16'] = gr.Checkbox(label="no_use_cuda_fp16", value=shared.args.no_use_cuda_fp16, info='This can make models faster on some systems.')
+ shared.gradio['desc_act'] = gr.Checkbox(label="desc_act", value=shared.args.desc_act, info='\'desc_act\', \'wbits\', and \'groupsize\' are used for old models without a quantize_config.json.')
+ shared.gradio['no_mmap'] = gr.Checkbox(label="no-mmap", value=shared.args.no_mmap)
+ shared.gradio['mlock'] = gr.Checkbox(label="mlock", value=shared.args.mlock)
+ shared.gradio['numa'] = gr.Checkbox(label="numa", value=shared.args.numa, info='NUMA support can help on some systems with non-uniform memory access.')
+ shared.gradio['disk'] = gr.Checkbox(label="disk", value=shared.args.disk)
+ shared.gradio['bf16'] = gr.Checkbox(label="bf16", value=shared.args.bf16)
+ shared.gradio['cache_8bit'] = gr.Checkbox(label="cache_8bit", value=shared.args.cache_8bit, info='Use 8-bit cache to save VRAM.')
+ shared.gradio['no_flash_attn'] = gr.Checkbox(label="no_flash_attn", value=shared.args.no_flash_attn, info='Force flash-attention to not be used.')
+ shared.gradio['cfg_cache'] = gr.Checkbox(label="cfg-cache", value=shared.args.cfg_cache, info='Necessary to use CFG with this loader.')
+ shared.gradio['num_experts_per_token'] = gr.Number(label="Number of experts per token", value=shared.args.num_experts_per_token, info='Only applies to MoE models like Mixtral.')
+ with gr.Blocks():
+ shared.gradio['trust_remote_code'] = gr.Checkbox(label="trust-remote-code", value=shared.args.trust_remote_code, info='Set trust_remote_code=True while loading the tokenizer/model. To enable this option, start the web UI with the --trust-remote-code flag.', interactive=shared.args.trust_remote_code)
+ shared.gradio['no_use_fast'] = gr.Checkbox(label="no_use_fast", value=shared.args.no_use_fast, info='Set use_fast=False while loading the tokenizer.')
+ shared.gradio['logits_all'] = gr.Checkbox(label="logits_all", value=shared.args.logits_all, info='Needs to be set for perplexity evaluation to work with this loader. Otherwise, ignore it, as it makes prompt processing slower.')
+
+ shared.gradio['disable_exllama'] = gr.Checkbox(label="disable_exllama", value=shared.args.disable_exllama, info='Disable ExLlama kernel for GPTQ models.')
+ shared.gradio['disable_exllamav2'] = gr.Checkbox(label="disable_exllamav2", value=shared.args.disable_exllamav2, info='Disable ExLlamav2 kernel for GPTQ models.')
+ shared.gradio['gptq_for_llama_info'] = gr.Markdown('Legacy loader for compatibility with older GPUs. ExLlamav2_HF or AutoGPTQ are preferred for GPTQ models when supported.')
+ shared.gradio['exllamav2_info'] = gr.Markdown("ExLlamav2_HF is recommended over ExLlamav2 for better integration with extensions and more consistent sampling behavior across loaders.")
+ shared.gradio['llamacpp_HF_info'] = gr.Markdown('llamacpp_HF loads llama.cpp as a Transformers model. To use it, you need to download a tokenizer.\n\nOption 1 (recommended): place your .gguf in a subfolder of models/ along with these 4 files: special_tokens_map.json, tokenizer_config.json, tokenizer.json, tokenizer.model.\n\nOption 2: download `oobabooga/llama-tokenizer` under "Download model or LoRA". That\'s a default Llama tokenizer that will work for some (but not all) models.')
+
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['autoload_model'] = gr.Checkbox(value=shared.settings['autoload_model'], label='Autoload the model', info='Whether to load the model as soon as it is selected in the Model dropdown.', interactive=not mu)
+
+ shared.gradio['custom_model_menu'] = gr.Textbox(label="Download model or LoRA", info="Enter the Hugging Face username/model path, for instance: facebook/galactica-125m. To specify a branch, add it at the end after a \":\" character like this: facebook/galactica-125m:main. To download a single file, enter its name in the second box.", interactive=not mu)
+ shared.gradio['download_specific_file'] = gr.Textbox(placeholder="File name (for GGUF models)", show_label=False, max_lines=1, interactive=not mu)
+ with gr.Row():
+ shared.gradio['download_model_button'] = gr.Button("Download", variant='primary', interactive=not mu)
+ shared.gradio['get_file_list'] = gr.Button("Get file list", interactive=not mu)
+
+ with gr.Row():
+ shared.gradio['model_status'] = gr.Markdown('No model is loaded' if shared.model_name == 'None' else 'Ready')
+
+
+def create_event_handlers():
+ shared.gradio['loader'].change(
+ loaders.make_loader_params_visible, gradio('loader'), gradio(loaders.get_all_params())).then(
+ lambda value: gr.update(choices=loaders.get_model_types(value)), gradio('loader'), gradio('model_type'))
+
+ # In this event handler, the interface state is read and updated
+ # with the model defaults (if any), and then the model is loaded
+ # unless "autoload_model" is unchecked
+ shared.gradio['model_menu'].change(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ apply_model_settings_to_state, gradio('model_menu', 'interface_state'), gradio('interface_state')).then(
+ ui.apply_interface_values, gradio('interface_state'), gradio(ui.list_interface_input_elements()), show_progress=False).then(
+ update_model_parameters, gradio('interface_state'), None).then(
+ load_model_wrapper, gradio('model_menu', 'loader', 'autoload_model'), gradio('model_status'), show_progress=False).success(
+ update_truncation_length, gradio('truncation_length', 'interface_state'), gradio('truncation_length')).then(
+ lambda x: x, gradio('loader'), gradio('filter_by_loader'))
+
+ shared.gradio['load_model'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ update_model_parameters, gradio('interface_state'), None).then(
+ partial(load_model_wrapper, autoload=True), gradio('model_menu', 'loader'), gradio('model_status'), show_progress=False).success(
+ update_truncation_length, gradio('truncation_length', 'interface_state'), gradio('truncation_length')).then(
+ lambda x: x, gradio('loader'), gradio('filter_by_loader'))
+
+ shared.gradio['reload_model'].click(
+ unload_model, None, None).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ update_model_parameters, gradio('interface_state'), None).then(
+ partial(load_model_wrapper, autoload=True), gradio('model_menu', 'loader'), gradio('model_status'), show_progress=False).success(
+ update_truncation_length, gradio('truncation_length', 'interface_state'), gradio('truncation_length')).then(
+ lambda x: x, gradio('loader'), gradio('filter_by_loader'))
+
+ shared.gradio['unload_model'].click(
+ unload_model, None, None).then(
+ lambda: "Model unloaded", None, gradio('model_status'))
+
+ shared.gradio['save_model_settings'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ save_model_settings, gradio('model_menu', 'interface_state'), gradio('model_status'), show_progress=False)
+
+ shared.gradio['lora_menu_apply'].click(load_lora_wrapper, gradio('lora_menu'), gradio('model_status'), show_progress=False)
+ shared.gradio['download_model_button'].click(download_model_wrapper, gradio('custom_model_menu', 'download_specific_file'), gradio('model_status'), show_progress=True)
+ shared.gradio['get_file_list'].click(partial(download_model_wrapper, return_links=True), gradio('custom_model_menu', 'download_specific_file'), gradio('model_status'), show_progress=True)
+ shared.gradio['autoload_model'].change(lambda x: gr.update(visible=not x), gradio('autoload_model'), gradio('load_model'))
+
+
+def load_model_wrapper(selected_model, loader, autoload=False):
+ if not autoload:
+ yield f"The settings for `{selected_model}` have been updated.\n\nClick on \"Load\" to load it."
+ return
+
+ if selected_model == 'None':
+ yield "No model selected"
+ else:
+ try:
+ yield f"Loading `{selected_model}`..."
+ unload_model()
+ if selected_model != '':
+ shared.model, shared.tokenizer = load_model(selected_model, loader)
+
+ if shared.model is not None:
+ output = f"Successfully loaded `{selected_model}`."
+
+ settings = get_model_metadata(selected_model)
+ if 'instruction_template' in settings:
+ output += '\n\nIt seems to be an instruction-following model with template "{}". In the chat tab, instruct or chat-instruct modes should be used.'.format(settings['instruction_template'])
+
+ yield output
+ else:
+ yield f"Failed to load `{selected_model}`."
+ except:
+ exc = traceback.format_exc()
+ logger.error('Failed to load the model.')
+ print(exc)
+ yield exc.replace('\n', '\n\n')
+
+
+def load_lora_wrapper(selected_loras):
+ yield ("Applying the following LoRAs to {}:\n\n{}".format(shared.model_name, '\n'.join(selected_loras)))
+ add_lora_to_model(selected_loras)
+ yield ("Successfuly applied the LoRAs")
+
+
+def download_model_wrapper(repo_id, specific_file, progress=gr.Progress(), return_links=False, check=False):
+ try:
+ progress(0.0)
+ downloader = importlib.import_module("download-model").ModelDownloader()
+ model, branch = downloader.sanitize_model_and_branch_names(repo_id, None)
+ yield ("Getting the download links from Hugging Face")
+ links, sha256, is_lora, is_llamacpp = downloader.get_download_links_from_huggingface(model, branch, text_only=False, specific_file=specific_file)
+ if return_links:
+ yield '\n\n'.join([f"`{Path(link).name}`" for link in links])
+ return
+
+ yield ("Getting the output folder")
+ base_folder = shared.args.lora_dir if is_lora else shared.args.model_dir
+ output_folder = downloader.get_output_folder(model, branch, is_lora, is_llamacpp=is_llamacpp, base_folder=base_folder)
+ if check:
+ progress(0.5)
+ yield ("Checking previously downloaded files")
+ downloader.check_model_files(model, branch, links, sha256, output_folder)
+ progress(1.0)
+ else:
+ yield (f"Downloading file{'s' if len(links) > 1 else ''} to `{output_folder}/`")
+ downloader.download_model_files(model, branch, links, sha256, output_folder, progress_bar=progress, threads=4, is_llamacpp=is_llamacpp)
+ yield ("Done!")
+ except:
+ progress(1.0)
+ yield traceback.format_exc().replace('\n', '\n\n')
+
+
+def update_truncation_length(current_length, state):
+ if 'loader' in state:
+ if state['loader'].lower().startswith('exllama'):
+ return state['max_seq_len']
+ elif state['loader'] in ['llama.cpp', 'llamacpp_HF', 'ctransformers']:
+ return state['n_ctx']
+
+ return current_length
diff --git a/modules/ui_notebook.py b/modules/ui_notebook.py
new file mode 100644
index 0000000000000000000000000000000000000000..6bd5c919f797a30003f291ed40ca82a924f760e7
--- /dev/null
+++ b/modules/ui_notebook.py
@@ -0,0 +1,106 @@
+import gradio as gr
+
+from modules import logits, shared, ui, utils
+from modules.prompts import count_tokens, load_prompt
+from modules.text_generation import (
+ generate_reply_wrapper,
+ get_token_ids,
+ stop_everything_event
+)
+from modules.utils import gradio
+
+inputs = ('textbox-notebook', 'interface_state')
+outputs = ('textbox-notebook', 'html-notebook')
+
+
+def create_ui():
+ mu = shared.args.multi_user
+ with gr.Tab('Notebook', elem_id='notebook-tab'):
+ shared.gradio['last_input-notebook'] = gr.State('')
+ with gr.Row():
+ with gr.Column(scale=4):
+ with gr.Tab('Raw'):
+ with gr.Row():
+ shared.gradio['textbox-notebook'] = gr.Textbox(value='', lines=27, elem_id='textbox-notebook', elem_classes=['textbox', 'add_scrollbar'])
+ shared.gradio['token-counter-notebook'] = gr.HTML(value="
0", elem_classes=["token-counter"])
+
+ with gr.Tab('Markdown'):
+ shared.gradio['markdown_render-notebook'] = gr.Button('Render')
+ shared.gradio['markdown-notebook'] = gr.Markdown()
+
+ with gr.Tab('HTML'):
+ shared.gradio['html-notebook'] = gr.HTML()
+
+ with gr.Tab('Logits'):
+ with gr.Row():
+ with gr.Column(scale=10):
+ shared.gradio['get_logits-notebook'] = gr.Button('Get next token probabilities')
+ with gr.Column(scale=1):
+ shared.gradio['use_samplers-notebook'] = gr.Checkbox(label='Use samplers', value=True, elem_classes=['no-background'])
+
+ with gr.Row():
+ shared.gradio['logits-notebook'] = gr.Textbox(lines=23, label='Output', elem_classes=['textbox_logits_notebook', 'add_scrollbar'])
+ shared.gradio['logits-notebook-previous'] = gr.Textbox(lines=23, label='Previous output', elem_classes=['textbox_logits_notebook', 'add_scrollbar'])
+
+ with gr.Tab('Tokens'):
+ shared.gradio['get_tokens-notebook'] = gr.Button('Get token IDs for the input')
+ shared.gradio['tokens-notebook'] = gr.Textbox(lines=23, label='Tokens', elem_classes=['textbox_logits_notebook', 'add_scrollbar', 'monospace'])
+
+ with gr.Row():
+ shared.gradio['Generate-notebook'] = gr.Button('Generate', variant='primary', elem_classes='small-button')
+ shared.gradio['Stop-notebook'] = gr.Button('Stop', elem_classes='small-button', elem_id='stop')
+ shared.gradio['Undo'] = gr.Button('Undo', elem_classes='small-button')
+ shared.gradio['Regenerate-notebook'] = gr.Button('Regenerate', elem_classes='small-button')
+
+ with gr.Column(scale=1):
+ gr.HTML('
')
+ with gr.Row():
+ shared.gradio['prompt_menu-notebook'] = gr.Dropdown(choices=utils.get_available_prompts(), value='None', label='Prompt', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['prompt_menu-notebook'], lambda: None, lambda: {'choices': utils.get_available_prompts()}, ['refresh-button', 'refresh-button-small'], interactive=not mu)
+ shared.gradio['save_prompt-notebook'] = gr.Button('💾', elem_classes=['refresh-button', 'refresh-button-small'], interactive=not mu)
+ shared.gradio['delete_prompt-notebook'] = gr.Button('🗑️', elem_classes=['refresh-button', 'refresh-button-small'], interactive=not mu)
+
+
+def create_event_handlers():
+ shared.gradio['Generate-notebook'].click(
+ lambda x: x, gradio('textbox-notebook'), gradio('last_input-notebook')).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, gradio(inputs), gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['textbox-notebook'].submit(
+ lambda x: x, gradio('textbox-notebook'), gradio('last_input-notebook')).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, gradio(inputs), gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Undo'].click(lambda x: x, gradio('last_input-notebook'), gradio('textbox-notebook'), show_progress=False)
+ shared.gradio['markdown_render-notebook'].click(lambda x: x, gradio('textbox-notebook'), gradio('markdown-notebook'), queue=False)
+ shared.gradio['Regenerate-notebook'].click(
+ lambda x: x, gradio('last_input-notebook'), gradio('textbox-notebook'), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ generate_reply_wrapper, gradio(inputs), gradio(outputs), show_progress=False).then(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ lambda: None, None, None, _js=f'() => {{{ui.audio_notification_js}}}')
+
+ shared.gradio['Stop-notebook'].click(stop_everything_event, None, None, queue=False)
+ shared.gradio['prompt_menu-notebook'].change(load_prompt, gradio('prompt_menu-notebook'), gradio('textbox-notebook'), show_progress=False)
+ shared.gradio['save_prompt-notebook'].click(
+ lambda x: x, gradio('textbox-notebook'), gradio('save_contents')).then(
+ lambda: 'prompts/', None, gradio('save_root')).then(
+ lambda: utils.current_time() + '.txt', None, gradio('save_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_saver'))
+
+ shared.gradio['delete_prompt-notebook'].click(
+ lambda: 'prompts/', None, gradio('delete_root')).then(
+ lambda x: x + '.txt', gradio('prompt_menu-notebook'), gradio('delete_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_deleter'))
+
+ shared.gradio['textbox-notebook'].input(lambda x: f"
{count_tokens(x)}", gradio('textbox-notebook'), gradio('token-counter-notebook'), show_progress=False)
+ shared.gradio['get_logits-notebook'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ logits.get_next_logits, gradio('textbox-notebook', 'interface_state', 'use_samplers-notebook', 'logits-notebook'), gradio('logits-notebook', 'logits-notebook-previous'), show_progress=False)
+
+ shared.gradio['get_tokens-notebook'].click(get_token_ids, gradio('textbox-notebook'), gradio('tokens-notebook'), show_progress=False)
diff --git a/modules/ui_parameters.py b/modules/ui_parameters.py
new file mode 100644
index 0000000000000000000000000000000000000000..078590dc119340064b081108da58d031d405a88e
--- /dev/null
+++ b/modules/ui_parameters.py
@@ -0,0 +1,124 @@
+from pathlib import Path
+
+import gradio as gr
+
+from modules import loaders, presets, shared, ui, ui_chat, utils
+from modules.utils import gradio
+
+
+def create_ui(default_preset):
+ mu = shared.args.multi_user
+ generate_params = presets.load_preset(default_preset)
+ with gr.Tab("Parameters", elem_id="parameters"):
+ with gr.Tab("Generation"):
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ shared.gradio['preset_menu'] = gr.Dropdown(choices=utils.get_available_presets(), value=default_preset, label='Preset', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['preset_menu'], lambda: None, lambda: {'choices': utils.get_available_presets()}, 'refresh-button', interactive=not mu)
+ shared.gradio['save_preset'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_preset'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['random_preset'] = gr.Button('🎲', elem_classes='refresh-button')
+
+ with gr.Column():
+ shared.gradio['filter_by_loader'] = gr.Dropdown(label="Filter by loader", choices=["All"] + list(loaders.loaders_and_params.keys()), value="All", elem_classes='slim-dropdown')
+
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['max_new_tokens'] = gr.Slider(minimum=shared.settings['max_new_tokens_min'], maximum=shared.settings['max_new_tokens_max'], step=1, label='max_new_tokens', value=shared.settings['max_new_tokens'])
+ shared.gradio['temperature'] = gr.Slider(0.01, 5, value=generate_params['temperature'], step=0.01, label='temperature')
+ shared.gradio['top_p'] = gr.Slider(0.0, 1.0, value=generate_params['top_p'], step=0.01, label='top_p')
+ shared.gradio['min_p'] = gr.Slider(0.0, 1.0, value=generate_params['min_p'], step=0.01, label='min_p')
+ shared.gradio['top_k'] = gr.Slider(0, 200, value=generate_params['top_k'], step=1, label='top_k')
+ shared.gradio['repetition_penalty'] = gr.Slider(1.0, 1.5, value=generate_params['repetition_penalty'], step=0.01, label='repetition_penalty')
+ shared.gradio['presence_penalty'] = gr.Slider(0, 2, value=generate_params['presence_penalty'], step=0.05, label='presence_penalty')
+ shared.gradio['frequency_penalty'] = gr.Slider(0, 2, value=generate_params['frequency_penalty'], step=0.05, label='frequency_penalty')
+ shared.gradio['repetition_penalty_range'] = gr.Slider(0, 4096, step=64, value=generate_params['repetition_penalty_range'], label='repetition_penalty_range')
+ shared.gradio['typical_p'] = gr.Slider(0.0, 1.0, value=generate_params['typical_p'], step=0.01, label='typical_p')
+ shared.gradio['tfs'] = gr.Slider(0.0, 1.0, value=generate_params['tfs'], step=0.01, label='tfs')
+ shared.gradio['top_a'] = gr.Slider(0.0, 1.0, value=generate_params['top_a'], step=0.01, label='top_a')
+ shared.gradio['epsilon_cutoff'] = gr.Slider(0, 9, value=generate_params['epsilon_cutoff'], step=0.01, label='epsilon_cutoff')
+ shared.gradio['eta_cutoff'] = gr.Slider(0, 20, value=generate_params['eta_cutoff'], step=0.01, label='eta_cutoff')
+
+ with gr.Column():
+ shared.gradio['guidance_scale'] = gr.Slider(-0.5, 2.5, step=0.05, value=generate_params['guidance_scale'], label='guidance_scale', info='For CFG. 1.5 is a good value.')
+ shared.gradio['negative_prompt'] = gr.Textbox(value=shared.settings['negative_prompt'], label='Negative prompt', lines=3, elem_classes=['add_scrollbar'])
+ shared.gradio['penalty_alpha'] = gr.Slider(0, 5, value=generate_params['penalty_alpha'], label='penalty_alpha', info='For Contrastive Search. do_sample must be unchecked.')
+ shared.gradio['mirostat_mode'] = gr.Slider(0, 2, step=1, value=generate_params['mirostat_mode'], label='mirostat_mode', info='mode=1 is for llama.cpp only.')
+ shared.gradio['mirostat_tau'] = gr.Slider(0, 10, step=0.01, value=generate_params['mirostat_tau'], label='mirostat_tau')
+ shared.gradio['mirostat_eta'] = gr.Slider(0, 1, step=0.01, value=generate_params['mirostat_eta'], label='mirostat_eta')
+ shared.gradio['smoothing_factor'] = gr.Slider(0.0, 10.0, value=generate_params['smoothing_factor'], step=0.01, label='smoothing_factor', info='Activates Quadratic Sampling.')
+ shared.gradio['dynamic_temperature'] = gr.Checkbox(value=generate_params['dynamic_temperature'], label='dynamic_temperature')
+ shared.gradio['dynatemp_low'] = gr.Slider(0.01, 5, value=generate_params['dynatemp_low'], step=0.01, label='dynatemp_low', visible=generate_params['dynamic_temperature'])
+ shared.gradio['dynatemp_high'] = gr.Slider(0.01, 5, value=generate_params['dynatemp_high'], step=0.01, label='dynatemp_high', visible=generate_params['dynamic_temperature'])
+ shared.gradio['dynatemp_exponent'] = gr.Slider(0.01, 5, value=generate_params['dynatemp_exponent'], step=0.01, label='dynatemp_exponent', visible=generate_params['dynamic_temperature'])
+ shared.gradio['temperature_last'] = gr.Checkbox(value=generate_params['temperature_last'], label='temperature_last', info='Moves temperature/dynamic temperature/quadratic sampling to the end of the sampler stack, ignoring their positions in "Sampler priority".')
+ shared.gradio['do_sample'] = gr.Checkbox(value=generate_params['do_sample'], label='do_sample')
+ shared.gradio['seed'] = gr.Number(value=shared.settings['seed'], label='Seed (-1 for random)')
+ with gr.Accordion('Other parameters', open=False):
+ shared.gradio['encoder_repetition_penalty'] = gr.Slider(0.8, 1.5, value=generate_params['encoder_repetition_penalty'], step=0.01, label='encoder_repetition_penalty')
+ shared.gradio['no_repeat_ngram_size'] = gr.Slider(0, 20, step=1, value=generate_params['no_repeat_ngram_size'], label='no_repeat_ngram_size')
+ shared.gradio['min_length'] = gr.Slider(0, 2000, step=1, value=generate_params['min_length'], label='min_length')
+ shared.gradio['num_beams'] = gr.Slider(1, 20, step=1, value=generate_params['num_beams'], label='num_beams', info='For Beam Search, along with length_penalty and early_stopping.')
+ shared.gradio['length_penalty'] = gr.Slider(-5, 5, value=generate_params['length_penalty'], label='length_penalty')
+ shared.gradio['early_stopping'] = gr.Checkbox(value=generate_params['early_stopping'], label='early_stopping')
+
+ gr.Markdown("[Learn more](https://github.com/oobabooga/text-generation-webui/wiki/03-%E2%80%90-Parameters-Tab)")
+
+ with gr.Column():
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['truncation_length'] = gr.Slider(value=get_truncation_length(), minimum=shared.settings['truncation_length_min'], maximum=shared.settings['truncation_length_max'], step=256, label='Truncate the prompt up to this length', info='The leftmost tokens are removed if the prompt exceeds this length. Most models require this to be at most 2048.')
+ shared.gradio['max_tokens_second'] = gr.Slider(value=shared.settings['max_tokens_second'], minimum=0, maximum=20, step=1, label='Maximum tokens/second', info='To make text readable in real time.')
+ shared.gradio['max_updates_second'] = gr.Slider(value=shared.settings['max_updates_second'], minimum=0, maximum=24, step=1, label='Maximum UI updates/second', info='Set this if you experience lag in the UI during streaming.')
+ shared.gradio['prompt_lookup_num_tokens'] = gr.Slider(value=shared.settings['prompt_lookup_num_tokens'], minimum=0, maximum=10, step=1, label='prompt_lookup_num_tokens', info='Activates Prompt Lookup Decoding.')
+
+ shared.gradio['custom_stopping_strings'] = gr.Textbox(lines=1, value=shared.settings["custom_stopping_strings"] or None, label='Custom stopping strings', info='In addition to the defaults. Written between "" and separated by commas.', placeholder='"\\n", "\\nYou:"')
+ shared.gradio['custom_token_bans'] = gr.Textbox(value=shared.settings['custom_token_bans'] or None, label='Custom token bans', info='Specific token IDs to ban from generating, comma-separated. The IDs can be found in the Default or Notebook tab.')
+
+ with gr.Column():
+ shared.gradio['auto_max_new_tokens'] = gr.Checkbox(value=shared.settings['auto_max_new_tokens'], label='auto_max_new_tokens', info='Expand max_new_tokens to the available context length.')
+ shared.gradio['ban_eos_token'] = gr.Checkbox(value=shared.settings['ban_eos_token'], label='Ban the eos_token', info='Forces the model to never end the generation prematurely.')
+ shared.gradio['add_bos_token'] = gr.Checkbox(value=shared.settings['add_bos_token'], label='Add the bos_token to the beginning of prompts', info='Disabling this can make the replies more creative.')
+ shared.gradio['skip_special_tokens'] = gr.Checkbox(value=shared.settings['skip_special_tokens'], label='Skip special tokens', info='Some specific models need this unset.')
+ shared.gradio['stream'] = gr.Checkbox(value=shared.settings['stream'], label='Activate text streaming')
+
+ with gr.Blocks():
+ shared.gradio['sampler_priority'] = gr.Textbox(value=generate_params['sampler_priority'], lines=12, label='Sampler priority', info='Parameter names separated by new lines or commas.')
+
+ with gr.Row() as shared.gradio['grammar_file_row']:
+ shared.gradio['grammar_file'] = gr.Dropdown(value='None', choices=utils.get_available_grammars(), label='Load grammar from file (.gbnf)', elem_classes='slim-dropdown')
+ ui.create_refresh_button(shared.gradio['grammar_file'], lambda: None, lambda: {'choices': utils.get_available_grammars()}, 'refresh-button', interactive=not mu)
+ shared.gradio['save_grammar'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
+ shared.gradio['delete_grammar'] = gr.Button('🗑️ ', elem_classes='refresh-button', interactive=not mu)
+
+ shared.gradio['grammar_string'] = gr.Textbox(value='', label='Grammar', lines=16, elem_classes=['add_scrollbar', 'monospace'])
+
+ ui_chat.create_chat_settings_ui()
+
+
+def create_event_handlers():
+ shared.gradio['filter_by_loader'].change(loaders.blacklist_samplers, gradio('filter_by_loader', 'dynamic_temperature'), gradio(loaders.list_all_samplers()), show_progress=False)
+ shared.gradio['preset_menu'].change(presets.load_preset_for_ui, gradio('preset_menu', 'interface_state'), gradio('interface_state') + gradio(presets.presets_params()))
+ shared.gradio['random_preset'].click(presets.random_preset, gradio('interface_state'), gradio('interface_state') + gradio(presets.presets_params()))
+ shared.gradio['grammar_file'].change(load_grammar, gradio('grammar_file'), gradio('grammar_string'))
+ shared.gradio['dynamic_temperature'].change(lambda x: [gr.update(visible=x)] * 3, gradio('dynamic_temperature'), gradio('dynatemp_low', 'dynatemp_high', 'dynatemp_exponent'))
+
+
+def get_truncation_length():
+ if 'max_seq_len' in shared.provided_arguments or shared.args.max_seq_len != shared.args_defaults.max_seq_len:
+ return shared.args.max_seq_len
+ elif 'n_ctx' in shared.provided_arguments or shared.args.n_ctx != shared.args_defaults.n_ctx:
+ return shared.args.n_ctx
+ else:
+ return shared.settings['truncation_length']
+
+
+def load_grammar(name):
+ p = Path(f'grammars/{name}')
+ if p.exists():
+ return open(p, 'r', encoding='utf-8').read()
+ else:
+ return ''
diff --git a/modules/ui_session.py b/modules/ui_session.py
new file mode 100644
index 0000000000000000000000000000000000000000..989046eae8d8192610508ac731f9320996d03eda
--- /dev/null
+++ b/modules/ui_session.py
@@ -0,0 +1,74 @@
+import gradio as gr
+
+from modules import shared, ui, utils
+from modules.github import clone_or_pull_repository
+from modules.utils import gradio
+
+
+def create_ui():
+ mu = shared.args.multi_user
+ with gr.Tab("Session", elem_id="session-tab"):
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['reset_interface'] = gr.Button("Apply flags/extensions and restart", interactive=not mu)
+ with gr.Row():
+ shared.gradio['toggle_dark_mode'] = gr.Button('Toggle 💡')
+ shared.gradio['save_settings'] = gr.Button('Save UI defaults to settings.yaml', interactive=not mu)
+
+ with gr.Row():
+ with gr.Column():
+ shared.gradio['extensions_menu'] = gr.CheckboxGroup(choices=utils.get_available_extensions(), value=shared.args.extensions, label="Available extensions", info='Note that some of these extensions may require manually installing Python requirements through the command: pip install -r extensions/extension_name/requirements.txt', elem_classes='checkboxgroup-table')
+
+ with gr.Column():
+ shared.gradio['bool_menu'] = gr.CheckboxGroup(choices=get_boolean_arguments(), value=get_boolean_arguments(active=True), label="Boolean command-line flags", elem_classes='checkboxgroup-table')
+
+ with gr.Column():
+ extension_name = gr.Textbox(lines=1, label='Install or update an extension', info='Enter the GitHub URL below and press Enter. For a list of extensions, see: https://github.com/oobabooga/text-generation-webui-extensions ⚠️ WARNING ⚠️ : extensions can execute arbitrary code. Make sure to inspect their source code before activating them.', interactive=not mu)
+ extension_status = gr.Markdown()
+
+ shared.gradio['theme_state'] = gr.Textbox(visible=False, value='dark' if shared.settings['dark_theme'] else 'light')
+ extension_name.submit(clone_or_pull_repository, extension_name, extension_status, show_progress=False)
+
+ # Reset interface event
+ shared.gradio['reset_interface'].click(
+ set_interface_arguments, gradio('extensions_menu', 'bool_menu'), None).then(
+ lambda: None, None, None, _js='() => {document.body.innerHTML=\'
Reloading...
\'; setTimeout(function(){location.reload()},2500); return []}')
+
+ shared.gradio['toggle_dark_mode'].click(
+ lambda: None, None, None, _js='() => {document.getElementsByTagName("body")[0].classList.toggle("dark")}').then(
+ lambda x: 'dark' if x == 'light' else 'light', gradio('theme_state'), gradio('theme_state'))
+
+ shared.gradio['save_settings'].click(
+ ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
+ ui.save_settings, gradio('interface_state', 'preset_menu', 'extensions_menu', 'show_controls', 'theme_state'), gradio('save_contents')).then(
+ lambda: './', None, gradio('save_root')).then(
+ lambda: 'settings.yaml', None, gradio('save_filename')).then(
+ lambda: gr.update(visible=True), None, gradio('file_saver'))
+
+
+def set_interface_arguments(extensions, bool_active):
+ shared.args.extensions = extensions
+
+ bool_list = get_boolean_arguments()
+
+ for k in bool_list:
+ setattr(shared.args, k, False)
+ for k in bool_active:
+ setattr(shared.args, k, True)
+ if k == 'api':
+ shared.add_extension('openai', last=True)
+
+ shared.need_restart = True
+
+
+def get_boolean_arguments(active=False):
+ exclude = shared.deprecated_args
+
+ cmd_list = vars(shared.args)
+ bool_list = sorted([k for k in cmd_list if type(cmd_list[k]) is bool and k not in exclude + ui.list_model_elements()])
+ bool_active = [k for k in bool_list if vars(shared.args)[k]]
+
+ if active:
+ return bool_active
+ else:
+ return bool_list
diff --git a/modules/utils.py b/modules/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6d32dca61c0ebc76395d8360a55b084bb56280
--- /dev/null
+++ b/modules/utils.py
@@ -0,0 +1,134 @@
+import os
+import re
+from datetime import datetime
+from pathlib import Path
+
+from modules import github, shared
+from modules.logging_colors import logger
+
+
+# Helper function to get multiple values from shared.gradio
+def gradio(*keys):
+ if len(keys) == 1 and type(keys[0]) in [list, tuple]:
+ keys = keys[0]
+
+ return [shared.gradio[k] for k in keys]
+
+
+def save_file(fname, contents):
+ if fname == '':
+ logger.error('File name is empty!')
+ return
+
+ root_folder = Path(__file__).resolve().parent.parent
+ abs_path_str = os.path.abspath(fname)
+ rel_path_str = os.path.relpath(abs_path_str, root_folder)
+ rel_path = Path(rel_path_str)
+ if rel_path.parts[0] == '..':
+ logger.error(f'Invalid file path: \"{fname}\"')
+ return
+
+ with open(abs_path_str, 'w', encoding='utf-8') as f:
+ f.write(contents)
+
+ logger.info(f'Saved \"{abs_path_str}\".')
+
+
+def delete_file(fname):
+ if fname == '':
+ logger.error('File name is empty!')
+ return
+
+ root_folder = Path(__file__).resolve().parent.parent
+ abs_path_str = os.path.abspath(fname)
+ rel_path_str = os.path.relpath(abs_path_str, root_folder)
+ rel_path = Path(rel_path_str)
+ if rel_path.parts[0] == '..':
+ logger.error(f'Invalid file path: \"{fname}\"')
+ return
+
+ if rel_path.exists():
+ rel_path.unlink()
+ logger.info(f'Deleted \"{fname}\".')
+
+
+def current_time():
+ return f"{datetime.now().strftime('%Y-%m-%d-%H%M%S')}"
+
+
+def atoi(text):
+ return int(text) if text.isdigit() else text.lower()
+
+
+# Replace multiple string pairs in a string
+def replace_all(text, dic):
+ for i, j in dic.items():
+ text = text.replace(i, j)
+
+ return text
+
+
+def natural_keys(text):
+ return [atoi(c) for c in re.split(r'(\d+)', text)]
+
+
+def get_available_models():
+ model_list = []
+ for item in list(Path(f'{shared.args.model_dir}/').glob('*')):
+ if not item.name.endswith(('.txt', '-np', '.pt', '.json', '.yaml', '.py')) and 'llama-tokenizer' not in item.name:
+ model_list.append(re.sub('.pth$', '', item.name))
+
+ return ['None'] + sorted(model_list, key=natural_keys)
+
+
+def get_available_presets():
+ return sorted(set((k.stem for k in Path('presets').glob('*.yaml'))), key=natural_keys)
+
+
+def get_available_prompts():
+ prompts = []
+ files = set((k.stem for k in Path('prompts').glob('*.txt')))
+ prompts += sorted([k for k in files if re.match('^[0-9]', k)], key=natural_keys, reverse=True)
+ prompts += sorted([k for k in files if re.match('^[^0-9]', k)], key=natural_keys)
+ prompts += ['None']
+ return prompts
+
+
+def get_available_characters():
+ paths = (x for x in Path('characters').iterdir() if x.suffix in ('.json', '.yaml', '.yml'))
+ return sorted(set((k.stem for k in paths)), key=natural_keys)
+
+
+def get_available_instruction_templates():
+ path = "instruction-templates"
+ paths = []
+ if os.path.exists(path):
+ paths = (x for x in Path(path).iterdir() if x.suffix in ('.json', '.yaml', '.yml'))
+
+ return ['Select template to load...'] + sorted(set((k.stem for k in paths)), key=natural_keys)
+
+
+def get_available_extensions():
+ extensions = sorted(set(map(lambda x: x.parts[1], Path('extensions').glob('*/script.py'))), key=natural_keys)
+ extensions = [v for v in extensions if v not in github.new_extensions]
+ return extensions
+
+
+def get_available_loras():
+ return ['None'] + sorted([item.name for item in list(Path(shared.args.lora_dir).glob('*')) if not item.name.endswith(('.txt', '-np', '.pt', '.json'))], key=natural_keys)
+
+
+def get_datasets(path: str, ext: str):
+ # include subdirectories for raw txt files to allow training from a subdirectory of txt files
+ if ext == "txt":
+ return ['None'] + sorted(set([k.stem for k in list(Path(path).glob('*.txt')) + list(Path(path).glob('*/')) if k.stem != 'put-trainer-datasets-here']), key=natural_keys)
+
+ return ['None'] + sorted(set([k.stem for k in Path(path).glob(f'*.{ext}') if k.stem != 'put-trainer-datasets-here']), key=natural_keys)
+
+
+def get_available_chat_styles():
+ return sorted(set(('-'.join(k.stem.split('-')[1:]) for k in Path('css').glob('chat_style*.css'))), key=natural_keys)
+
+
+def get_available_grammars():
+ return ['None'] + sorted([item.name for item in list(Path('grammars').glob('*.gbnf'))], key=natural_keys)
diff --git a/presets/Big O.yaml b/presets/Big O.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2ab182687647aaa04868d08024eefaacd0b48b06
--- /dev/null
+++ b/presets/Big O.yaml
@@ -0,0 +1,6 @@
+temperature: 0.87
+top_p: 0.99
+typical_p: 0.68
+tfs: 0.68
+repetition_penalty: 1.01
+top_k: 85
diff --git a/presets/Contrastive Search.yaml b/presets/Contrastive Search.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d9a47a9f5b75ae5d2db9da0ace7a51d962fdef94
--- /dev/null
+++ b/presets/Contrastive Search.yaml
@@ -0,0 +1,3 @@
+do_sample: false
+top_k: 4
+penalty_alpha: 0.3
diff --git a/presets/Debug-deterministic.yaml b/presets/Debug-deterministic.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..45d5953f46ef1c67c72ea13cd180f2a5a606db39
--- /dev/null
+++ b/presets/Debug-deterministic.yaml
@@ -0,0 +1,2 @@
+do_sample: false
+top_k: 1
diff --git a/presets/Devia Preset Gen.yaml b/presets/Devia Preset Gen.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c3ed84f4102fde352d9cafc070be784792f19f95
--- /dev/null
+++ b/presets/Devia Preset Gen.yaml
@@ -0,0 +1,17 @@
+temperature: 0.3
+top_p: 0.5
+top_k: 100
+repetition_penalty: 1.18
+sampler_priority: |-
+ temperature
+ dynamic_temperature
+ quadratic_sampling
+ top_k
+ top_p
+ typical_p
+ epsilon_cutoff
+ eta_cutoff
+ tfs
+ top_a
+ min_p
+ mirostat
diff --git a/presets/Divine Intellect.yaml b/presets/Divine Intellect.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ac750e40dc94a7a622a21e692bc399b4e8d9e2df
--- /dev/null
+++ b/presets/Divine Intellect.yaml
@@ -0,0 +1,4 @@
+temperature: 1.31
+top_p: 0.14
+repetition_penalty: 1.17
+top_k: 49
diff --git a/presets/LLaMA-Precise.yaml b/presets/LLaMA-Precise.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c5f9cae25636cafb52a8d99c9d610c1a33a7ef3b
--- /dev/null
+++ b/presets/LLaMA-Precise.yaml
@@ -0,0 +1,4 @@
+temperature: 0.7
+top_p: 0.1
+repetition_penalty: 1.18
+top_k: 40
diff --git a/presets/Midnight Enigma.yaml b/presets/Midnight Enigma.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0bd1763c6d5aab39dd7a25ac69c453a846e93fb1
--- /dev/null
+++ b/presets/Midnight Enigma.yaml
@@ -0,0 +1,4 @@
+temperature: 0.98
+top_p: 0.37
+repetition_penalty: 1.18
+top_k: 100
diff --git a/presets/My Preset.yaml b/presets/My Preset.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2d1449a1d59bd93db69fe82833615542c2d8fd0
--- /dev/null
+++ b/presets/My Preset.yaml
@@ -0,0 +1,17 @@
+temperature: 0.7
+top_p: 0.1
+top_k: 40
+repetition_penalty: 1.18
+sampler_priority: |-
+ temperature
+ dynamic_temperature
+ quadratic_sampling
+ top_k
+ top_p
+ typical_p
+ epsilon_cutoff
+ eta_cutoff
+ tfs
+ top_a
+ min_p
+ mirostat
diff --git a/presets/Null preset.yaml b/presets/Null preset.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..714aa9a3ed57177426e4ab415107838066e21fb5
--- /dev/null
+++ b/presets/Null preset.yaml
@@ -0,0 +1 @@
+temperature: 1
diff --git a/presets/Shortwave.yaml b/presets/Shortwave.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2528abdb4b950defd50c42ef6cbe0f884560e79
--- /dev/null
+++ b/presets/Shortwave.yaml
@@ -0,0 +1,4 @@
+temperature: 1.53
+top_p: 0.64
+repetition_penalty: 1.07
+top_k: 33
diff --git a/presets/Yara.yaml b/presets/Yara.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..87bb019ec62bb7afc395d3212b7560c25c3d36ed
--- /dev/null
+++ b/presets/Yara.yaml
@@ -0,0 +1,4 @@
+temperature: 0.82
+top_p: 0.21
+repetition_penalty: 1.19
+top_k: 72
diff --git a/presets/simple-1.yaml b/presets/simple-1.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..30a106590b6d70d9c537a8b2b6c26f2a832bd8b9
--- /dev/null
+++ b/presets/simple-1.yaml
@@ -0,0 +1,4 @@
+temperature: 0.7
+top_p: 0.9
+repetition_penalty: 1.15
+top_k: 20
diff --git a/prompts/Alpaca-with-Input.txt b/prompts/Alpaca-with-Input.txt
new file mode 100644
index 0000000000000000000000000000000000000000..56df0e285be9689ab1f8ea698ce748e6d1b02af2
--- /dev/null
+++ b/prompts/Alpaca-with-Input.txt
@@ -0,0 +1,10 @@
+Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
+
+### Instruction:
+Instruction
+
+### Input:
+Input
+
+### Response:
+
diff --git a/prompts/GPT-4chan.txt b/prompts/GPT-4chan.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1bc8c7f4613f982e3dfa367562a764cf5bd4c73b
--- /dev/null
+++ b/prompts/GPT-4chan.txt
@@ -0,0 +1,6 @@
+-----
+--- 865467536
+Hello, AI frens!
+How are you doing on this fine day?
+--- 865467537
+
diff --git a/prompts/QA.txt b/prompts/QA.txt
new file mode 100644
index 0000000000000000000000000000000000000000..32b0e2350f3c0a7f447dcd1aba11d6ae2247e5a8
--- /dev/null
+++ b/prompts/QA.txt
@@ -0,0 +1,4 @@
+Common sense questions and answers
+
+Question:
+Factual answer: