mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2024-11-26 01:30:20 +01:00
Add direct download for session/chat history JSONs
This commit is contained in:
parent
32a2bbee4a
commit
0e8f9354b5
@ -17,6 +17,7 @@ main_parent.addEventListener('click', function(e) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add some scrollbars
|
||||||
const textareaElements = document.querySelectorAll('.add_scrollbar textarea');
|
const textareaElements = document.querySelectorAll('.add_scrollbar textarea');
|
||||||
for(i = 0; i < textareaElements.length; i++) {
|
for(i = 0; i < textareaElements.length; i++) {
|
||||||
textareaElements[i].classList.remove('scroll-hide');
|
textareaElements[i].classList.remove('scroll-hide');
|
||||||
|
40
css/save_files.js
Normal file
40
css/save_files.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Functions for downloading JSON files
|
||||||
|
function getCurrentTimestamp() {
|
||||||
|
const now = new Date();
|
||||||
|
const timezoneOffset = now.getTimezoneOffset() * 60000; // Convert to milliseconds
|
||||||
|
const localTime = new Date(now.getTime() - timezoneOffset);
|
||||||
|
const formattedTimestamp = localTime.toISOString().replace(/[-:]/g, '').slice(0, 15);
|
||||||
|
return formattedTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveFile(contents, filename) {
|
||||||
|
const element = document.createElement('a');
|
||||||
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents));
|
||||||
|
element.setAttribute('download', filename);
|
||||||
|
element.style.display = 'none';
|
||||||
|
document.body.appendChild(element);
|
||||||
|
element.click();
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveHistory(history, character, mode) {
|
||||||
|
let path = null;
|
||||||
|
|
||||||
|
if (['chat', 'chat-instruct'].includes(mode) && character && character.trim() !== '') {
|
||||||
|
path = `history_${character}_${getCurrentTimestamp()}.json`;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
path = `history_${mode}_${getCurrentTimestamp()}.json`;
|
||||||
|
} catch (error) {
|
||||||
|
path = `history_${getCurrentTimestamp()}.json`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveFile(history, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSession(session, mode) {
|
||||||
|
let path = null;
|
||||||
|
|
||||||
|
path = `session_${mode}_${getCurrentTimestamp()}.json`;
|
||||||
|
saveFile(session, path);
|
||||||
|
}
|
@ -412,23 +412,6 @@ def load_history(file, history):
|
|||||||
return history
|
return history
|
||||||
|
|
||||||
|
|
||||||
def save_history_at_user_request(history, character, mode):
|
|
||||||
def make_timestamp_path(character=None):
|
|
||||||
return f"logs/{character or ''}{'_' if character else ''}{datetime.now().strftime('%Y%m%d-%H%M%S')}.json"
|
|
||||||
|
|
||||||
path = None
|
|
||||||
if mode in ['chat', 'chat-instruct'] and character not in ['', 'None', None]:
|
|
||||||
path = make_timestamp_path(character)
|
|
||||||
else:
|
|
||||||
# Try to use mode as the file name, otherwise just use the timestamp
|
|
||||||
try:
|
|
||||||
path = make_timestamp_path(mode.capitalize())
|
|
||||||
except:
|
|
||||||
path = make_timestamp_path()
|
|
||||||
|
|
||||||
return save_history(history, path)
|
|
||||||
|
|
||||||
|
|
||||||
def save_persistent_history(history, character, mode):
|
def save_persistent_history(history, character, mode):
|
||||||
if mode in ['chat', 'chat-instruct'] and character not in ['', 'None', None] and not shared.args.multi_user:
|
if mode in ['chat', 'chat-instruct'] and character not in ['', 'None', None] and not shared.args.multi_user:
|
||||||
save_history(history, path=Path(f'logs/{character}_persistent.json'))
|
save_history(history, path=Path(f'logs/{character}_persistent.json'))
|
||||||
|
@ -15,6 +15,8 @@ with open(Path(__file__).resolve().parent / '../css/main.js', 'r') as f:
|
|||||||
main_js = f.read()
|
main_js = f.read()
|
||||||
with open(Path(__file__).resolve().parent / '../css/chat.js', 'r') as f:
|
with open(Path(__file__).resolve().parent / '../css/chat.js', 'r') as f:
|
||||||
chat_js = f.read()
|
chat_js = f.read()
|
||||||
|
with open(Path(__file__).resolve().parent / '../css/save_files.js', 'r') as f:
|
||||||
|
save_files_js = f.read()
|
||||||
|
|
||||||
refresh_symbol = '🔄'
|
refresh_symbol = '🔄'
|
||||||
delete_symbol = '🗑️'
|
delete_symbol = '🗑️'
|
||||||
@ -145,9 +147,6 @@ def gather_interface_values(*args):
|
|||||||
|
|
||||||
if not shared.args.multi_user:
|
if not shared.args.multi_user:
|
||||||
shared.persistent_interface_state = output
|
shared.persistent_interface_state = output
|
||||||
Path('logs').mkdir(exist_ok=True)
|
|
||||||
with open(Path(f'logs/session_{shared.get_mode()}_autosave.json'), 'w') as f:
|
|
||||||
f.write(json.dumps(output, indent=4))
|
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
66
server.py
66
server.py
@ -508,44 +508,24 @@ def create_file_saving_event_handlers():
|
|||||||
|
|
||||||
if not shared.args.multi_user:
|
if not shared.args.multi_user:
|
||||||
|
|
||||||
def load_session(session, state):
|
def load_session(file, state):
|
||||||
with open(Path(f'logs/{session}.json'), 'r') as f:
|
decoded_file = file if type(file) == str else file.decode('utf-8')
|
||||||
state.update(json.loads(f.read()))
|
data = json.loads(decoded_file)
|
||||||
|
state.update(data)
|
||||||
|
|
||||||
if shared.is_chat():
|
if shared.is_chat():
|
||||||
chat.save_persistent_history(state['history'], state['character_menu'], state['mode'])
|
chat.save_persistent_history(state['history'], state['character_menu'], state['mode'])
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
if shared.is_chat():
|
shared.gradio['save_session'].click(
|
||||||
shared.gradio['save_session'].click(
|
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
||||||
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
lambda x: json.dumps(x, indent=4), gradio('interface_state'), gradio('temporary_text')).then(
|
||||||
lambda x: json.dumps(x, indent=4), gradio('interface_state'), gradio('save_contents')).then(
|
None, gradio('temporary_text'), None, _js=f"(contents) => {{{ui.save_files_js}; saveSession(contents, \"{shared.get_mode()}\")}}")
|
||||||
lambda: 'logs/', None, gradio('save_root')).then(
|
|
||||||
lambda x: f'session_{shared.get_mode()}_{x + "_" if x not in ["None", None, ""] else ""}{utils.current_time()}.json', gradio('character_menu'), gradio('save_filename')).then(
|
|
||||||
lambda: gr.update(visible=True), None, gradio('file_saver'))
|
|
||||||
|
|
||||||
shared.gradio['session_menu'].change(
|
shared.gradio['load_session'].upload(
|
||||||
load_session, gradio('session_menu', 'interface_state'), gradio('interface_state')).then(
|
load_session, gradio('load_session', 'interface_state'), gradio('interface_state')).then(
|
||||||
ui.apply_interface_values, gradio('interface_state'), gradio(ui.list_interface_input_elements()), show_progress=False).then(
|
ui.apply_interface_values, gradio('interface_state'), gradio(ui.list_interface_input_elements()), show_progress=False)
|
||||||
chat.redraw_html, shared.reload_inputs, gradio('display'))
|
|
||||||
|
|
||||||
else:
|
|
||||||
shared.gradio['save_session'].click(
|
|
||||||
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
|
||||||
lambda x: json.dumps(x, indent=4), gradio('interface_state'), gradio('save_contents')).then(
|
|
||||||
lambda: 'logs/', None, gradio('save_root')).then(
|
|
||||||
lambda: f'session_{shared.get_mode()}_{utils.current_time()}.json', None, gradio('save_filename')).then(
|
|
||||||
lambda: gr.update(visible=True), None, gradio('file_saver'))
|
|
||||||
|
|
||||||
shared.gradio['session_menu'].change(
|
|
||||||
load_session, gradio('session_menu', 'interface_state'), gradio('interface_state')).then(
|
|
||||||
ui.apply_interface_values, gradio('interface_state'), gradio(ui.list_interface_input_elements()), show_progress=False)
|
|
||||||
|
|
||||||
shared.gradio['delete_session'].click(
|
|
||||||
lambda x: f'{x}.json', gradio('session_menu'), gradio('delete_filename')).then(
|
|
||||||
lambda: 'logs/', None, gradio('delete_root')).then(
|
|
||||||
lambda: gr.update(visible=True), None, gradio('file_deleter'))
|
|
||||||
|
|
||||||
|
|
||||||
def set_interface_arguments(interface_mode, extensions, bool_active):
|
def set_interface_arguments(interface_mode, extensions, bool_active):
|
||||||
@ -558,7 +538,6 @@ def set_interface_arguments(interface_mode, extensions, bool_active):
|
|||||||
setattr(shared.args, k, False)
|
setattr(shared.args, k, False)
|
||||||
if interface_mode != "default":
|
if interface_mode != "default":
|
||||||
setattr(shared.args, interface_mode, True)
|
setattr(shared.args, interface_mode, True)
|
||||||
|
|
||||||
for k in bool_list:
|
for k in bool_list:
|
||||||
setattr(shared.args, k, False)
|
setattr(shared.args, k, False)
|
||||||
for k in bool_active:
|
for k in bool_active:
|
||||||
@ -622,6 +601,9 @@ def create_interface():
|
|||||||
# Floating menus for saving/deleting files
|
# Floating menus for saving/deleting files
|
||||||
create_file_saving_menus()
|
create_file_saving_menus()
|
||||||
|
|
||||||
|
# Used for saving files using javascript
|
||||||
|
shared.gradio['temporary_text'] = gr.Textbox(visible=False)
|
||||||
|
|
||||||
# Create chat mode interface
|
# Create chat mode interface
|
||||||
if shared.is_chat():
|
if shared.is_chat():
|
||||||
shared.input_elements = ui.list_interface_input_elements()
|
shared.input_elements = ui.list_interface_input_elements()
|
||||||
@ -702,11 +684,10 @@ def create_interface():
|
|||||||
with gr.Tab('Chat history'):
|
with gr.Tab('Chat history'):
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
shared.gradio['download'] = gr.File(label="Download")
|
shared.gradio['save_chat_history'] = gr.Button(value='Save history')
|
||||||
shared.gradio['download_button'] = gr.Button(value='Refresh')
|
|
||||||
|
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
shared.gradio['upload_chat_history'] = gr.File(type='binary', file_types=['.json', '.txt'], label="Upload")
|
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('Upload character'):
|
||||||
with gr.Tab('YAML or JSON'):
|
with gr.Tab('YAML or JSON'):
|
||||||
@ -845,11 +826,8 @@ def create_interface():
|
|||||||
|
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
if not shared.args.multi_user:
|
if not shared.args.multi_user:
|
||||||
with gr.Row():
|
shared.gradio['save_session'] = gr.Button('Save session')
|
||||||
shared.gradio['session_menu'] = gr.Dropdown(choices=utils.get_available_sessions(), value='None', label='Session', elem_classes='slim-dropdown', info='When saving a session, make sure to keep the initial part of the filename (session_chat, session_notebook, or session_default), otherwise it will not appear on this list afterwards.')
|
shared.gradio['load_session'] = gr.File(type='binary', file_types=['.json'], label="Upload Session JSON")
|
||||||
ui.create_refresh_button(shared.gradio['session_menu'], lambda: None, lambda: {'choices': utils.get_available_sessions()}, ['refresh-button'])
|
|
||||||
shared.gradio['save_session'] = gr.Button('💾', elem_classes=['refresh-button'])
|
|
||||||
shared.gradio['delete_session'] = gr.Button('🗑️', elem_classes=['refresh-button'])
|
|
||||||
|
|
||||||
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.')
|
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.')
|
||||||
extension_status = gr.Markdown()
|
extension_status = gr.Markdown()
|
||||||
@ -967,8 +945,8 @@ def create_interface():
|
|||||||
shared.gradio['instruction_template'].change(
|
shared.gradio['instruction_template'].change(
|
||||||
partial(chat.load_character, instruct=True), gradio('instruction_template', 'name1_instruct', 'name2_instruct'), gradio('name1_instruct', 'name2_instruct', 'dummy', 'dummy', 'context_instruct', 'turn_template'))
|
partial(chat.load_character, instruct=True), gradio('instruction_template', 'name1_instruct', 'name2_instruct'), gradio('name1_instruct', 'name2_instruct', 'dummy', 'dummy', 'context_instruct', 'turn_template'))
|
||||||
|
|
||||||
shared.gradio['upload_chat_history'].upload(
|
shared.gradio['load_chat_history'].upload(
|
||||||
chat.load_history, gradio('upload_chat_history', 'history'), gradio('history')).then(
|
chat.load_history, gradio('load_chat_history', 'history'), gradio('history')).then(
|
||||||
chat.redraw_html, shared.reload_inputs, gradio('display'))
|
chat.redraw_html, shared.reload_inputs, gradio('display'))
|
||||||
|
|
||||||
shared.gradio['Copy last reply'].click(chat.send_last_reply_to_input, gradio('history'), gradio('textbox'), show_progress=False)
|
shared.gradio['Copy last reply'].click(chat.send_last_reply_to_input, gradio('history'), gradio('textbox'), show_progress=False)
|
||||||
@ -991,7 +969,9 @@ def create_interface():
|
|||||||
lambda: 'characters/instruction-following/', None, gradio('delete_root')).then(
|
lambda: 'characters/instruction-following/', None, gradio('delete_root')).then(
|
||||||
lambda: gr.update(visible=True), None, gradio('file_deleter'))
|
lambda: gr.update(visible=True), None, gradio('file_deleter'))
|
||||||
|
|
||||||
shared.gradio['download_button'].click(chat.save_history_at_user_request, gradio('history', 'character_menu', 'mode'), gradio('download'))
|
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'))
|
shared.gradio['Submit character'].click(chat.upload_character, gradio('upload_json', 'upload_img_bot'), gradio('character_menu'))
|
||||||
shared.gradio['upload_json'].upload(lambda: gr.update(interactive=True), None, gradio('Submit 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_json'].clear(lambda: gr.update(interactive=False), None, gradio('Submit character'))
|
||||||
|
Loading…
Reference in New Issue
Block a user