mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2025-06-07 14:17:09 -04:00
UI: Add footer buttons for editing messages (#7019)
--------- Co-authored-by: oobabooga <112222186+oobabooga@users.noreply.github.com>
This commit is contained in:
parent
355b5f6c8b
commit
5028480eba
7 changed files with 282 additions and 74 deletions
49
css/main.css
49
css/main.css
|
@ -1457,6 +1457,53 @@ strong {
|
|||
color: #ccc;
|
||||
}
|
||||
|
||||
/* Message Editing Styles */
|
||||
.editing-textarea {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: var(--light-theme-gray);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.dark .editing-textarea {
|
||||
border: 1px solid var(--border-color-dark);
|
||||
background-color: var(--darker-gray);
|
||||
}
|
||||
|
||||
.editing-textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--selected-item-color-dark);
|
||||
}
|
||||
|
||||
.edit-controls-container {
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.edit-control-button {
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dark .edit-control-button {
|
||||
border: 1px solid var(--border-color-dark);
|
||||
background-color: var(--light-gray);
|
||||
color: #efefef;
|
||||
}
|
||||
|
||||
/* --- Simple Version Navigation --- */
|
||||
.version-navigation {
|
||||
position: absolute;
|
||||
|
@ -1488,7 +1535,7 @@ strong {
|
|||
|
||||
.version-position {
|
||||
font-size: 11px;
|
||||
color: currentColor;
|
||||
color: currentcolor;
|
||||
font-family: monospace;
|
||||
min-width: 35px;
|
||||
text-align: center;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// -------------------------------------------------
|
||||
// Event handlers
|
||||
// -------------------------------------------------
|
||||
|
||||
function copyToClipboard(element) {
|
||||
if (!element) return;
|
||||
|
||||
|
@ -42,11 +46,135 @@ function branchHere(element) {
|
|||
branchIndexInput.value = index;
|
||||
|
||||
// Trigger any 'change' or 'input' events Gradio might be listening for
|
||||
const event = new Event("input", { bubbles: true }); // 'change' might also work
|
||||
const event = new Event("input", { bubbles: true });
|
||||
branchIndexInput.dispatchEvent(event);
|
||||
|
||||
branchButton.click(); // Gradio will now pick up the 'index'
|
||||
branchButton.click();
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// Message Editing Functions
|
||||
// -------------------------------------------------
|
||||
|
||||
function editHere(buttonElement) {
|
||||
if (!buttonElement) return;
|
||||
|
||||
const messageElement = buttonElement.closest(".message, .user-message, .assistant-message");
|
||||
if (!messageElement) return;
|
||||
|
||||
const messageBody = messageElement.querySelector(".message-body");
|
||||
if (!messageBody) return;
|
||||
|
||||
// If already editing, focus the textarea
|
||||
const existingTextarea = messageBody.querySelector(".editing-textarea");
|
||||
if (existingTextarea) {
|
||||
existingTextarea.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine role based on message element - handle different chat modes
|
||||
const isUserMessage = messageElement.classList.contains("user-message") ||
|
||||
messageElement.querySelector(".text-you") !== null ||
|
||||
messageElement.querySelector(".circle-you") !== null;
|
||||
|
||||
startEditing(messageElement, messageBody, isUserMessage);
|
||||
}
|
||||
|
||||
function startEditing(messageElement, messageBody, isUserMessage) {
|
||||
const rawText = messageElement.getAttribute("data-raw") || messageBody.textContent;
|
||||
const originalHTML = messageBody.innerHTML;
|
||||
|
||||
// Create editing interface
|
||||
const editingInterface = createEditingInterface(rawText);
|
||||
|
||||
// Replace message content
|
||||
messageBody.innerHTML = "";
|
||||
messageBody.appendChild(editingInterface.textarea);
|
||||
messageBody.appendChild(editingInterface.controls);
|
||||
|
||||
editingInterface.textarea.focus();
|
||||
editingInterface.textarea.setSelectionRange(rawText.length, rawText.length);
|
||||
|
||||
// Setup event handlers
|
||||
setupEditingHandlers(editingInterface.textarea, messageElement, originalHTML, messageBody, isUserMessage);
|
||||
}
|
||||
|
||||
function createEditingInterface(text) {
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.value = text;
|
||||
textarea.className = "editing-textarea";
|
||||
textarea.rows = Math.max(3, text.split("\n").length);
|
||||
|
||||
const controls = document.createElement("div");
|
||||
controls.className = "edit-controls-container";
|
||||
|
||||
const saveButton = document.createElement("button");
|
||||
saveButton.textContent = "Save";
|
||||
saveButton.className = "edit-control-button";
|
||||
saveButton.type = "button";
|
||||
|
||||
const cancelButton = document.createElement("button");
|
||||
cancelButton.textContent = "Cancel";
|
||||
cancelButton.className = "edit-control-button edit-cancel-button";
|
||||
cancelButton.type = "button";
|
||||
|
||||
controls.appendChild(saveButton);
|
||||
controls.appendChild(cancelButton);
|
||||
|
||||
return { textarea, controls, saveButton, cancelButton };
|
||||
}
|
||||
|
||||
function setupEditingHandlers(textarea, messageElement, originalHTML, messageBody, isUserMessage) {
|
||||
const saveButton = messageBody.querySelector(".edit-control-button:not(.edit-cancel-button)");
|
||||
const cancelButton = messageBody.querySelector(".edit-cancel-button");
|
||||
|
||||
const submitEdit = () => {
|
||||
const index = messageElement.getAttribute("data-index");
|
||||
if (!index || !submitMessageEdit(index, textarea.value, isUserMessage)) {
|
||||
cancelEdit();
|
||||
}
|
||||
};
|
||||
|
||||
const cancelEdit = () => {
|
||||
messageBody.innerHTML = originalHTML;
|
||||
};
|
||||
|
||||
// Event handlers
|
||||
saveButton.onclick = submitEdit;
|
||||
cancelButton.onclick = cancelEdit;
|
||||
|
||||
textarea.onkeydown = (e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
submitEdit();
|
||||
} else if (e.key === "Escape") {
|
||||
e.preventDefault();
|
||||
cancelEdit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function submitMessageEdit(index, newText, isUserMessage) {
|
||||
const editIndexInput = document.getElementById("Edit-message-index")?.querySelector("input");
|
||||
const editTextInput = document.getElementById("Edit-message-text")?.querySelector("textarea");
|
||||
const editRoleInput = document.getElementById("Edit-message-role")?.querySelector("textarea");
|
||||
const editButton = document.getElementById("Edit-message");
|
||||
|
||||
if (!editIndexInput || !editTextInput || !editRoleInput || !editButton) {
|
||||
console.error("Edit elements not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
editIndexInput.value = index;
|
||||
editTextInput.value = newText;
|
||||
editRoleInput.value = isUserMessage ? "user" : "assistant";
|
||||
|
||||
editIndexInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
editTextInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
editRoleInput.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
|
||||
editButton.click();
|
||||
return true;
|
||||
}
|
||||
|
||||
function navigateVersion(element, direction) {
|
||||
|
|
26
js/main.js
26
js/main.js
|
@ -1,3 +1,7 @@
|
|||
// ------------------------------------------------
|
||||
// Main
|
||||
// ------------------------------------------------
|
||||
|
||||
let main_parent = document.getElementById("chat-tab").parentNode;
|
||||
let extensions = document.getElementById("extensions");
|
||||
|
||||
|
@ -102,18 +106,6 @@ document.addEventListener("keydown", function(event) {
|
|||
document.getElementById("Remove-last").click();
|
||||
}
|
||||
|
||||
// Copy last on Ctrl + Shift + K
|
||||
else if (event.ctrlKey && event.shiftKey && event.key === "K") {
|
||||
event.preventDefault();
|
||||
document.getElementById("Copy-last").click();
|
||||
}
|
||||
|
||||
// Replace last on Ctrl + Shift + L
|
||||
else if (event.ctrlKey && event.shiftKey && event.key === "L") {
|
||||
event.preventDefault();
|
||||
document.getElementById("Replace-last").click();
|
||||
}
|
||||
|
||||
// Impersonate on Ctrl + Shift + M
|
||||
else if (event.ctrlKey && event.shiftKey && event.key === "M") {
|
||||
event.preventDefault();
|
||||
|
@ -388,6 +380,16 @@ document.addEventListener("click", function (event) {
|
|||
}
|
||||
});
|
||||
|
||||
document.addEventListener("dblclick", (event) => {
|
||||
const messageElement = event.target.closest(".message, .user-message, .assistant-message");
|
||||
if (!messageElement) return;
|
||||
|
||||
const editButton = messageElement.querySelector(".footer-edit-button");
|
||||
if (editButton) {
|
||||
editButton.click();
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------
|
||||
// Relocate the "Show controls" checkbox
|
||||
//------------------------------------------------
|
||||
|
|
|
@ -712,32 +712,6 @@ def remove_last_message(history):
|
|||
return html.unescape(last[0]), history
|
||||
|
||||
|
||||
def send_last_reply_to_input(history):
|
||||
if len(history['visible']) > 0:
|
||||
return html.unescape(history['visible'][-1][1])
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def replace_last_reply(textbox, state):
|
||||
history = state['history']
|
||||
text = textbox['text']
|
||||
|
||||
# Initialize metadata if not present
|
||||
if 'metadata' not in history:
|
||||
history['metadata'] = {}
|
||||
|
||||
if len(text.strip()) == 0:
|
||||
return history
|
||||
elif len(history['visible']) > 0:
|
||||
row_idx = len(history['internal']) - 1
|
||||
history['visible'][-1][1] = html.escape(text)
|
||||
history['internal'][-1][1] = apply_extensions('input', text, state, is_chat=True)
|
||||
update_message_metadata(history['metadata'], "assistant", row_idx, timestamp=get_current_timestamp())
|
||||
|
||||
return history
|
||||
|
||||
|
||||
def send_dummy_message(textbox, state):
|
||||
history = state['history']
|
||||
text = textbox['text']
|
||||
|
@ -1330,14 +1304,6 @@ def my_yaml_output(data):
|
|||
return result
|
||||
|
||||
|
||||
def handle_replace_last_reply_click(text, state):
|
||||
history = replace_last_reply(text, state)
|
||||
save_history(history, state['unique_id'], state['character_menu'], state['mode'])
|
||||
html = redraw_html(history, state['name1'], state['name2'], state['mode'], state['chat_style'], state['character_menu'])
|
||||
|
||||
return [history, html, {"text": "", "files": []}]
|
||||
|
||||
|
||||
def handle_send_dummy_message_click(text, state):
|
||||
history = send_dummy_message(text, state)
|
||||
save_history(history, state['unique_id'], state['character_menu'], state['mode'])
|
||||
|
@ -1425,6 +1391,52 @@ def handle_branch_chat_click(state):
|
|||
return [history, html, past_chats_update, -1]
|
||||
|
||||
|
||||
def handle_edit_message_click(state):
|
||||
history = state['history']
|
||||
message_index = int(state['edit_message_index'])
|
||||
new_text = state['edit_message_text']
|
||||
role = state['edit_message_role'] # "user" or "assistant"
|
||||
|
||||
if message_index >= len(history['internal']):
|
||||
html_output = redraw_html(history, state['name1'], state['name2'], state['mode'], state['chat_style'], state['character_menu'])
|
||||
return [history, html_output, gr.update()]
|
||||
|
||||
# Use the role passed from frontend
|
||||
is_user_msg = (role == "user")
|
||||
role_idx = 0 if is_user_msg else 1
|
||||
|
||||
# For assistant messages, save the original version BEFORE updating content
|
||||
if not is_user_msg:
|
||||
if not history['metadata'].get(f"assistant_{message_index}", {}).get('versions'):
|
||||
add_message_version(history, message_index, is_current=False)
|
||||
|
||||
# NOW update the message content
|
||||
history['internal'][message_index][role_idx] = apply_extensions('input', new_text, state, is_chat=True)
|
||||
history['visible'][message_index][role_idx] = html.escape(new_text)
|
||||
|
||||
# Branch if editing user message, add version if editing assistant message
|
||||
if is_user_msg:
|
||||
# Branch like branch-here
|
||||
history['visible'] = history['visible'][:message_index + 1]
|
||||
history['internal'] = history['internal'][:message_index + 1]
|
||||
new_unique_id = datetime.now().strftime('%Y%m%d-%H-%M-%S')
|
||||
save_history(history, new_unique_id, state['character_menu'], state['mode'])
|
||||
histories = find_all_histories_with_first_prompts(state)
|
||||
past_chats_update = gr.update(choices=histories, value=new_unique_id)
|
||||
state['unique_id'] = new_unique_id
|
||||
elif not is_user_msg:
|
||||
# Add the new version as current
|
||||
add_message_version(history, message_index, is_current=True)
|
||||
past_chats_update = gr.update()
|
||||
else:
|
||||
past_chats_update = gr.update()
|
||||
|
||||
save_history(history, state['unique_id'], state['character_menu'], state['mode'])
|
||||
html_output = redraw_html(history, state['name1'], state['name2'], state['mode'], state['chat_style'], state['character_menu'])
|
||||
|
||||
return [history, html_output, past_chats_update]
|
||||
|
||||
|
||||
def handle_navigate_version_click(state):
|
||||
history = state['history']
|
||||
message_index = int(state['navigate_message_index'])
|
||||
|
|
|
@ -336,12 +336,14 @@ refresh_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
|
|||
continue_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-player-play"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 4v16l13 -8z" /></svg>'''
|
||||
remove_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-trash"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 7l16 0" /><path d="M10 11l0 6" /><path d="M14 11l0 6" /><path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" /><path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" /></svg>'''
|
||||
branch_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-git-branch"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 18m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /><path d="M7 6m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /><path d="M17 6m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /><path d="M7 8l0 8" /><path d="M9 18h6a2 2 0 0 0 2 -2v-5" /><path d="M14 14l3 -3l3 3" /></svg>'''
|
||||
edit_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-pencil"><path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4"></path><path d="M13.5 6.5l4 4"></path></svg>'''
|
||||
info_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="thinking-icon tabler-icon tabler-icon-info-circle"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 2a10 10 0 0 1 0 20a10 10 0 0 1 0 -20z" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>'''
|
||||
info_svg_small = '''<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="thinking-icon tabler-icon tabler-icon-info-circle"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 2a10 10 0 0 1 0 20a10 10 0 0 1 0 -20z" /><path d="M12 16v-4" /><path d="M12 8h.01" /></svg>'''
|
||||
attachment_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.48-8.48l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>'''
|
||||
|
||||
copy_button = f'<button class="footer-button footer-copy-button" title="Copy" onclick="copyToClipboard(this)">{copy_svg}</button>'
|
||||
branch_button = f'<button class="footer-button footer-branch-button" title="Branch here" onclick="branchHere(this)">{branch_svg}</button>'
|
||||
edit_button = f'<button class="footer-button footer-edit-button" title="Edit" onclick="editHere(this)">{edit_svg}</button>'
|
||||
refresh_button = f'<button class="footer-button footer-refresh-button" title="Regenerate" onclick="regenerateClick()">{refresh_svg}</button>'
|
||||
continue_button = f'<button class="footer-button footer-continue-button" title="Continue" onclick="continueClick()">{continue_svg}</button>'
|
||||
remove_button = f'<button class="footer-button footer-remove-button" title="Remove last reply" onclick="removeLastClick()">{remove_svg}</button>'
|
||||
|
@ -404,9 +406,11 @@ def get_version_navigation_html(history, i):
|
|||
return f'<div class="version-navigation">{left_arrow}{position}{right_arrow}</div>'
|
||||
|
||||
|
||||
def actions_html(history, i, info_message=""):
|
||||
def actions_html(history, i, role, info_message=""):
|
||||
if role == "assistant":
|
||||
return (f'<div class="message-actions">'
|
||||
f'{copy_button}'
|
||||
f'{edit_button}'
|
||||
f'{refresh_button if i == len(history["visible"]) - 1 else ""}'
|
||||
f'{continue_button if i == len(history["visible"]) - 1 else ""}'
|
||||
f'{remove_button if i == len(history["visible"]) - 1 else ""}'
|
||||
|
@ -414,6 +418,11 @@ def actions_html(history, i, info_message=""):
|
|||
f'{info_message}'
|
||||
f'</div>'
|
||||
f'{get_version_navigation_html(history, i)}')
|
||||
return (f'<div class="message-actions">'
|
||||
f'{copy_button}'
|
||||
f'{edit_button}'
|
||||
f'{info_message}'
|
||||
f'</div>')
|
||||
|
||||
|
||||
def generate_instruct_html(history):
|
||||
|
@ -448,11 +457,12 @@ def generate_instruct_html(history):
|
|||
if converted_visible[0]: # Don't display empty user messages
|
||||
output += (
|
||||
f'<div class="user-message" '
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}"'
|
||||
f'data-index={i}>'
|
||||
f'<div class="text">'
|
||||
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||
f'{user_attachments}'
|
||||
f'<div class="message-actions">{copy_button}{info_message_user}</div>'
|
||||
f'{actions_html(history, i, "user", info_message_user)}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
@ -464,7 +474,7 @@ def generate_instruct_html(history):
|
|||
f'<div class="text">'
|
||||
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||
f'{assistant_attachments}'
|
||||
f'{actions_html(history, i, info_message_assistant)}'
|
||||
f'{actions_html(history, i, "assistant", info_message_assistant)}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
@ -503,13 +513,14 @@ def generate_cai_chat_html(history, name1, name2, style, character, reset_cache=
|
|||
if converted_visible[0]: # Don't display empty user messages
|
||||
output += (
|
||||
f'<div class="message" '
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}"'
|
||||
f'data-index={i}>'
|
||||
f'<div class="circle-you">{img_me}</div>'
|
||||
f'<div class="text">'
|
||||
f'<div class="username">{name1}{user_timestamp}</div>'
|
||||
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||
f'{user_attachments}'
|
||||
f'<div class="message-actions">{copy_button}</div>'
|
||||
f'{actions_html(history, i, "user")}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
@ -523,7 +534,7 @@ def generate_cai_chat_html(history, name1, name2, style, character, reset_cache=
|
|||
f'<div class="username">{name2}{assistant_timestamp}</div>'
|
||||
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||
f'{assistant_attachments}'
|
||||
f'{actions_html(history, i)}'
|
||||
f'{actions_html(history, i, "assistant")}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
@ -564,11 +575,12 @@ def generate_chat_html(history, name1, name2, reset_cache=False):
|
|||
if converted_visible[0]: # Don't display empty user messages
|
||||
output += (
|
||||
f'<div class="message" '
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||
f'data-raw="{html.escape(row_internal[0], quote=True)}"'
|
||||
f'data-index={i}>'
|
||||
f'<div class="text-you">'
|
||||
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||
f'{user_attachments}'
|
||||
f'<div class="message-actions">{copy_button}{info_message_user}</div>'
|
||||
f'{actions_html(history, i, "user", info_message_user)}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
@ -580,7 +592,7 @@ def generate_chat_html(history, name1, name2, reset_cache=False):
|
|||
f'<div class="text-bot">'
|
||||
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||
f'{assistant_attachments}'
|
||||
f'{actions_html(history, i, info_message_assistant)}'
|
||||
f'{actions_html(history, i, "assistant", info_message_assistant)}'
|
||||
f'</div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
|
|
@ -212,7 +212,12 @@ def list_interface_input_elements():
|
|||
'negative_prompt',
|
||||
'dry_sequence_breakers',
|
||||
'grammar_string',
|
||||
'branch_index'
|
||||
'navigate_message_index',
|
||||
'navigate_direction',
|
||||
'edit_message_index',
|
||||
'edit_message_text',
|
||||
'edit_message_role',
|
||||
'branch_index',
|
||||
]
|
||||
|
||||
# Chat elements
|
||||
|
|
|
@ -71,8 +71,6 @@ def create_ui():
|
|||
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():
|
||||
|
@ -97,11 +95,15 @@ def create_ui():
|
|||
with gr.Row():
|
||||
shared.gradio['chat-instruct_command'] = gr.Textbox(value=shared.settings['chat-instruct_command'], lines=12, label='Command for chat-instruct mode', info='<|character|> and <|prompt|> get replaced with the bot name and the regular chat prompt respectively.', visible=shared.settings['mode'] == 'chat-instruct', elem_classes=['add_scrollbar'])
|
||||
|
||||
# Hidden elements for version navigation (similar to branch)
|
||||
# Hidden elements for version navigation and editing
|
||||
with gr.Row(visible=False):
|
||||
shared.gradio['navigate_message_index'] = gr.Number(value=-1, precision=0, elem_id="Navigate-message-index")
|
||||
shared.gradio['navigate_direction'] = gr.Textbox(value="", elem_id="Navigate-direction")
|
||||
shared.gradio['navigate_version'] = gr.Button(elem_id="Navigate-version")
|
||||
shared.gradio['edit_message_index'] = gr.Number(value=-1, precision=0, elem_id="Edit-message-index")
|
||||
shared.gradio['edit_message_text'] = gr.Textbox(value="", elem_id="Edit-message-text")
|
||||
shared.gradio['edit_message_role'] = gr.Textbox(value="", elem_id="Edit-message-role")
|
||||
shared.gradio['edit_message'] = gr.Button(elem_id="Edit-message")
|
||||
|
||||
|
||||
def create_chat_settings_ui():
|
||||
|
@ -228,10 +230,6 @@ def create_event_handlers():
|
|||
None, None, None, js='() => document.getElementById("chat").parentNode.parentNode.parentNode.classList.remove("_generating")').then(
|
||||
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.handle_replace_last_reply_click, gradio('textbox', 'interface_state'), gradio('history', 'display', 'textbox'), show_progress=False)
|
||||
|
||||
shared.gradio['Send dummy message'].click(
|
||||
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
||||
chat.handle_send_dummy_message_click, gradio('textbox', 'interface_state'), gradio('history', 'display', 'textbox'), show_progress=False)
|
||||
|
@ -297,12 +295,16 @@ def create_event_handlers():
|
|||
None, gradio('mode'), None, js="(mode) => {mode === 'instruct' ? document.getElementById('character-menu').parentNode.parentNode.style.display = 'none' : document.getElementById('character-menu').parentNode.parentNode.style.display = ''}")
|
||||
|
||||
shared.gradio['chat_style'].change(chat.redraw_html, gradio(reload_arr), gradio('display'), show_progress=False)
|
||||
shared.gradio['Copy last reply'].click(chat.send_last_reply_to_input, gradio('history'), gradio('textbox'), show_progress=False)
|
||||
|
||||
shared.gradio['navigate_version'].click(
|
||||
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
||||
chat.handle_navigate_version_click, gradio('interface_state'), gradio('history', 'display'), show_progress=False)
|
||||
|
||||
shared.gradio['edit_message'].click(
|
||||
ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then(
|
||||
chat.handle_edit_message_click, gradio('interface_state'), gradio('history', 'display', 'unique_id'), show_progress=False).then(
|
||||
lambda: None, None, None, js='() => { const role = document.getElementById("Edit-message-role").querySelector("textarea").value; if (role === "user") document.getElementById("Regenerate").click(); }')
|
||||
|
||||
# Save/delete a character
|
||||
shared.gradio['save_character'].click(chat.handle_save_character_click, gradio('name2'), gradio('save_character_filename', 'character_saver'), show_progress=False)
|
||||
shared.gradio['delete_character'].click(lambda: gr.update(visible=True), None, gradio('character_deleter'), show_progress=False)
|
||||
|
|
Loading…
Add table
Reference in a new issue