Merge pull request #1622 from hlohaus/gem

Add remove messages from history
This commit is contained in:
H Lohaus 2024-02-24 14:57:40 +01:00 committed by GitHub
commit 6d3ad27eed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 96 additions and 24 deletions

View File

@ -316,13 +316,33 @@ body {
z-index: 1000; z-index: 1000;
} }
.message .assistant i { .message .assistant .fa-phone-arrow-up-right,
.message .assistant .fa-phone-arrow-down-left {
position: absolute; position: absolute;
bottom: -6px; bottom: -6px;
right: -6px; right: -6px;
z-index: 1000; z-index: 1000;
} }
.message .assistant .fa-xmark,
.message .user .fa-xmark {
position: absolute;
top: -2px;
left: 0px;
z-index: 1000;
display: none;
cursor: pointer;
}
.message .user .fa-xmark {
color: var(--colour-1);
}
.message .assistant:hover .fa-xmark,
.message .user:hover .fa-xmark {
display: block;
}
.new_convo { .new_convo {
padding: 8px 12px; padding: 8px 12px;
display: flex; display: flex;

View File

@ -46,6 +46,22 @@ const highlight = (container) => {
); );
} }
const register_remove_message = async () => {
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
if (!("click" in el.dataset)) {
el.dataset.click = "true";
el.addEventListener("click", async () => {
if (prompt_lock) {
return;
}
const message_el = el.parentElement.parentElement;
await remove_message(window.conversation_id, message_el.dataset.index);
await load_conversation(window.conversation_id);
})
}
});
}
const delete_conversations = async () => { const delete_conversations = async () => {
localStorage.clear(); localStorage.clear();
await new_conversation(); await new_conversation();
@ -58,13 +74,14 @@ const handle_ask = async () => {
message = message_input.value message = message_input.value
if (message.length > 0) { if (message.length > 0) {
message_input.value = ''; message_input.value = '';
prompt_lock = true;
await add_conversation(window.conversation_id, message); await add_conversation(window.conversation_id, message);
if ("text" in fileInput.dataset) { if ("text" in fileInput.dataset) {
message += '\n```' + fileInput.dataset.type + '\n'; message += '\n```' + fileInput.dataset.type + '\n';
message += fileInput.dataset.text; message += fileInput.dataset.text;
message += '\n```' message += '\n```'
} }
await add_message(window.conversation_id, "user", message); let message_index = await add_message(window.conversation_id, "user", message);
window.token = message_id(); window.token = message_id();
if (imageInput.dataset.src) URL.revokeObjectURL(imageInput.dataset.src); if (imageInput.dataset.src) URL.revokeObjectURL(imageInput.dataset.src);
@ -73,9 +90,10 @@ const handle_ask = async () => {
else delete imageInput.dataset.src else delete imageInput.dataset.src
message_box.innerHTML += ` message_box.innerHTML += `
<div class="message"> <div class="message" data-index="${message_index}">
<div class="user"> <div class="user">
${user_image} ${user_image}
<i class="fa-solid fa-xmark"></i>
<i class="fa-regular fa-phone-arrow-up-right"></i> <i class="fa-regular fa-phone-arrow-up-right"></i>
</div> </div>
<div class="content" id="user_${token}"> <div class="content" id="user_${token}">
@ -87,6 +105,7 @@ const handle_ask = async () => {
</div> </div>
</div> </div>
`; `;
await register_remove_message();
highlight(message_box); highlight(message_box);
await ask_gpt(); await ask_gpt();
} }
@ -105,27 +124,32 @@ const ask_gpt = async () => {
regenerate.classList.add(`regenerate-hidden`); regenerate.classList.add(`regenerate-hidden`);
messages = await get_messages(window.conversation_id); messages = await get_messages(window.conversation_id);
// Remove generated images from history
for (i in messages) {
messages[i]["content"] = messages[i]["content"].replaceAll(
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
""
)
delete messages[i]["provider"];
}
// Remove history, if it is selected // Remove history, if it is selected
if (document.getElementById('history')?.checked) { if (document.getElementById('history')?.checked) {
messages = [messages[messages.length-1]] messages = [messages[messages.length-1]]
} }
new_messages = [];
for (i in messages) {
new_message = messages[i];
// Remove generated images from history
new_message["content"] = new_message["content"].replaceAll(
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
""
)
delete new_message["provider"];
// Remove regenerated messages
if (!new_message.regenerate) {
new_messages.push(new_message)
}
}
window.scrollTo(0, 0); window.scrollTo(0, 0);
window.controller = new AbortController(); window.controller = new AbortController();
jailbreak = document.getElementById("jailbreak"); jailbreak = document.getElementById("jailbreak");
provider = document.getElementById("provider"); provider = document.getElementById("provider");
model = document.getElementById("model"); model = document.getElementById("model");
prompt_lock = true;
window.text = ''; window.text = '';
stop_generating.classList.remove(`stop_generating-hidden`); stop_generating.classList.remove(`stop_generating-hidden`);
@ -136,9 +160,11 @@ const ask_gpt = async () => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
message_box.innerHTML += ` message_box.innerHTML += `
<div class="message"> <div class="message" data-index="${new_messages.length}">
<div class="assistant"> <div class="assistant">
${gpt_image} <i class="fa-regular fa-phone-arrow-down-left"></i> ${gpt_image}
<i class="fa-solid fa-xmark"></i>
<i class="fa-regular fa-phone-arrow-down-left"></i>
</div> </div>
<div class="content" id="gpt_${window.token}"> <div class="content" id="gpt_${window.token}">
<div class="provider"></div> <div class="provider"></div>
@ -160,7 +186,7 @@ const ask_gpt = async () => {
web_search: document.getElementById(`switch`).checked, web_search: document.getElementById(`switch`).checked,
provider: provider.options[provider.selectedIndex].value, provider: provider.options[provider.selectedIndex].value,
patch_provider: document.getElementById('patch').checked, patch_provider: document.getElementById('patch').checked,
messages: messages messages: new_messages
}); });
const headers = { const headers = {
accept: 'text/event-stream' accept: 'text/event-stream'
@ -185,7 +211,6 @@ const ask_gpt = async () => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader(); const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
error = provider = null; error = provider = null;
while (true) { while (true) {
const { value, done } = await reader.read(); const { value, done } = await reader.read();
@ -252,9 +277,12 @@ const ask_gpt = async () => {
} }
let cursorDiv = document.getElementById(`cursor`); let cursorDiv = document.getElementById(`cursor`);
if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv); if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
add_message(window.conversation_id, "assistant", text, provider); if (text) {
add_message(window.conversation_id, "assistant", text, provider);
}
message_box.scrollTop = message_box.scrollHeight; message_box.scrollTop = message_box.scrollHeight;
await remove_cancel_button(); await remove_cancel_button();
await register_remove_message();
prompt_lock = false; prompt_lock = false;
window.scrollTo(0, 0); window.scrollTo(0, 0);
await load_conversations(20, 0); await load_conversations(20, 0);
@ -342,7 +370,8 @@ const load_conversation = async (conversation_id) => {
let messages = await get_messages(conversation_id); let messages = await get_messages(conversation_id);
let elements = ""; let elements = "";
for (item of messages) { for (i in messages) {
let item = messages[i];
let provider = item.provider ? ` let provider = item.provider ? `
<div class="provider"> <div class="provider">
<a href="${item.provider.url}" target="_blank">${item.provider.name}</a> <a href="${item.provider.url}" target="_blank">${item.provider.name}</a>
@ -350,9 +379,10 @@ const load_conversation = async (conversation_id) => {
</div> </div>
` : ""; ` : "";
elements += ` elements += `
<div class="message"> <div class="message" data-index="${i}">
<div class=${item.role == "assistant" ? "assistant" : "user"}> <div class=${item.role == "assistant" ? "assistant" : "user"}>
${item.role == "assistant" ? gpt_image : user_image} ${item.role == "assistant" ? gpt_image : user_image}
<i class="fa-solid fa-xmark"></i>
${item.role == "assistant" ${item.role == "assistant"
? `<i class="fa-regular fa-phone-arrow-down-left"></i>` ? `<i class="fa-regular fa-phone-arrow-down-left"></i>`
: `<i class="fa-regular fa-phone-arrow-up-right"></i>` : `<i class="fa-regular fa-phone-arrow-up-right"></i>`
@ -367,6 +397,7 @@ const load_conversation = async (conversation_id) => {
} }
message_box.innerHTML = elements; message_box.innerHTML = elements;
await register_remove_message();
highlight(message_box); highlight(message_box);
message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" }); message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
@ -409,11 +440,30 @@ const add_conversation = async (conversation_id, content) => {
history.pushState({}, null, `/chat/${conversation_id}`); history.pushState({}, null, `/chat/${conversation_id}`);
}; };
const remove_last_message = async (conversation_id) => { const hide_last_message = async (conversation_id) => {
const conversation = await get_conversation(conversation_id) const conversation = await get_conversation(conversation_id)
const last_message = conversation.items.pop();
last_message["regenerate"] = true;
conversation.items.push(last_message);
conversation.items.pop(); localStorage.setItem(
`conversation:${conversation_id}`,
JSON.stringify(conversation)
);
};
const remove_message = async (conversation_id, index) => {
const conversation = await get_conversation(conversation_id);
let new_items = [];
for (i in conversation.items) {
if (i == index - 1) {
delete conversation.items[i]["regenerate"];
}
if (i != index) {
new_items.push(conversation.items[i])
}
}
conversation.items = new_items;
localStorage.setItem( localStorage.setItem(
`conversation:${conversation_id}`, `conversation:${conversation_id}`,
JSON.stringify(conversation) JSON.stringify(conversation)
@ -433,6 +483,8 @@ const add_message = async (conversation_id, role, content, provider) => {
`conversation:${conversation_id}`, `conversation:${conversation_id}`,
JSON.stringify(conversation) JSON.stringify(conversation)
); );
return conversation.items.length - 1;
}; };
const load_conversations = async (limit, offset, loader) => { const load_conversations = async (limit, offset, loader) => {
@ -468,7 +520,8 @@ document.getElementById(`cancelButton`).addEventListener(`click`, async () => {
}); });
document.getElementById(`regenerateButton`).addEventListener(`click`, async () => { document.getElementById(`regenerateButton`).addEventListener(`click`, async () => {
await remove_last_message(window.conversation_id); prompt_lock = true;
await hide_last_message(window.conversation_id);
window.token = message_id(); window.token = message_id();
await ask_gpt(); await ask_gpt();
}); });
@ -591,7 +644,6 @@ colorThemes.forEach((themeOption) => {
}); });
}); });
window.onload = async () => { window.onload = async () => {
setTheme(); setTheme();