From 7893a0835e2c3f4e06c1ccfaec9baef1bdacea7d Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Wed, 1 Jan 2025 04:20:02 +0100 Subject: Add filessupport, scrape and refine your data Remove Webdriver usages Add continue messages for other providers --- g4f/gui/client/index.html | 7 +- g4f/gui/client/static/css/style.css | 35 ++++- g4f/gui/client/static/js/chat.v1.js | 249 ++++++++++++++++++++++++++++-------- 3 files changed, 233 insertions(+), 58 deletions(-) (limited to 'g4f/gui/client') diff --git a/g4f/gui/client/index.html b/g4f/gui/client/index.html index acd6b7e5..31ffc0b0 100644 --- a/g4f/gui/client/index.html +++ b/g4f/gui/client/index.html @@ -136,6 +136,11 @@ +
+ Refine files with spaCy + + +
@@ -258,7 +263,7 @@
${count_words_and_tokens(message, get_selected_model()?.value)} - - - - -
@@ -484,11 +498,15 @@ const prepare_messages = (messages, message_index = -1, do_continue = false) => } } - messages.forEach((new_message) => { + messages.forEach((new_message, i) => { + // Copy message first + new_message = { ...new_message }; + // Include last message, if do_continue + if (i + 1 == messages.length && do_continue) { + delete new_message.regenerate; + } // Include only not regenerated messages if (new_message && !new_message.regenerate) { - // Copy message first - new_message = { ...new_message }; // Remove generated images from history new_message.content = filter_message(new_message.content); // Remove internal fields @@ -707,8 +725,8 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi message_storage[message_id] = ""; stop_generating.classList.remove("stop_generating-hidden"); - if (message_index == -1 && !regenerate) { - await scroll_to_bottom(); + if (message_index == -1) { + await lazy_scroll_to_bottom(); } let count_total = message_box.querySelector('.count_total'); @@ -750,9 +768,10 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi inner: content_el.querySelector('.content_inner'), count: content_el.querySelector('.count'), update_timeouts: [], + message_index: message_index, } - if (message_index == -1 && !regenerate) { - await scroll_to_bottom(); + if (message_index == -1) { + await lazy_scroll_to_bottom(); } try { const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput; @@ -813,7 +832,7 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi let cursorDiv = message_el.querySelector(".cursor"); if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv); if (message_index == -1) { - await scroll_to_bottom(); + await lazy_scroll_to_bottom(); } await safe_remove_cancel_button(); await register_message_buttons(); @@ -826,6 +845,12 @@ async function scroll_to_bottom() { message_box.scrollTop = message_box.scrollHeight; } +async function lazy_scroll_to_bottom() { + if (message_box.scrollHeight - message_box.scrollTop < 2 * message_box.clientHeight) { + await scroll_to_bottom(); + } +} + const clear_conversations = async () => { const elements = box_conversations.childNodes; let index = elements.length; @@ -971,7 +996,23 @@ const load_conversation = async (conversation_id, scroll=true) => { } else { buffer = ""; } - buffer += item.content; + buffer = buffer.replace(/ \[aborted\]$/g, "").replace(/ \[error\]$/g, ""); + let lines = buffer.trim().split("\n"); + let lastLine = lines[lines.length - 1]; + let newContent = item.content; + if (newContent.startsWith("```\n")) { + newContent = item.content.substring(4); + } + if (newContent.startsWith(lastLine)) { + newContent = newContent.substring(lastLine.length); + } else { + let words = buffer.trim().split(" "); + let lastWord = words[words.length - 1]; + if (newContent.startsWith(lastWord)) { + newContent = newContent.substring(lastWord.length); + } + } + buffer += newContent; last_model = item.provider?.model; providers.push(item.provider?.name); let next_i = parseInt(i) + 1; @@ -993,28 +1034,74 @@ const load_conversation = async (conversation_id, scroll=true) => { synthesize_params = (new URLSearchParams(synthesize_params)).toString(); let synthesize_url = `/backend-api/v2/synthesize/${synthesize_provider}?${synthesize_params}`; + const file = new File([buffer], 'message.md', {type: 'text/plain'}); + const objectUrl = URL.createObjectURL(file); + let add_buttons = []; - // Always add regenerate button - add_buttons.push(``); // Add continue button if possible + actions = ["variant"] if (item.finish && item.finish.actions) { - item.finish.actions.forEach((action) => { - if (action == "continue") { - if (messages.length >= i - 1) { - add_buttons.push(``); - } + actions = item.finish.actions + } + if (!("continue" in actions)) { + let reason = "stop"; + // Read finish reason from conversation + if (item.finish && item.finish.reason) { + reason = item.finish.reason; + } + let lines = buffer.trim().split("\n"); + let lastLine = lines[lines.length - 1]; + // Has a stop or error token at the end + if (lastLine.endsWith("[aborted]") || lastLine.endsWith("[error]")) { + reason = "error"; + // Has an even number of start or end code tags + } else if (buffer.split("```").length - 1 % 2 === 1) { + reason = "error"; + // Has a end token at the end + } else if (lastLine.endsWith("```") || lastLine.endsWith(".") || lastLine.endsWith("?") || lastLine.endsWith("!") + || lastLine.endsWith('"') || lastLine.endsWith("'") || lastLine.endsWith(")") + || lastLine.endsWith(">") || lastLine.endsWith("]") || lastLine.endsWith("}") ) { + reason = "stop" + } else { + // Has an emoji at the end + const regex = /\p{Emoji}$/u; + if (regex.test(lastLine)) { + reason = "stop" } - }); + } + if (reason == "max_tokens" || reason == "error") { + actions.push("continue") + } + } + + add_buttons.push(``); + + if (actions.includes("variant")) { + add_buttons.push(``); + } + if (actions.includes("continue")) { + if (messages.length >= i - 1) { + add_buttons.push(``); + } } elements.push(` -
+
${item.role == "assistant" ? gpt_image : user_image} @@ -1028,12 +1115,6 @@ const load_conversation = async (conversation_id, scroll=true) => {
${markdown_render(buffer)}
${count_words_and_tokens(buffer, next_provider?.model)} - - - - - - ${add_buttons.join("")}
@@ -1444,11 +1525,8 @@ function update_message(content_map, message_id, content = null) { content_map.inner.innerHTML = html; content_map.count.innerText = count_words_and_tokens(message_storage[message_id], provider_storage[message_id]?.model); highlight(content_map.inner); - if (!content_map.container.classList.contains("regenerate")) { - if (message_box.scrollTop >= message_box.scrollHeight - message_box.clientHeight - 200) { - window.scrollTo(0, 0); - message_box.scrollTo({ top: message_box.scrollHeight, behavior: "auto" }); - } + if (content_map.message_index == -1) { + lazy_scroll_to_bottom(); } content_map.update_timeouts.forEach((timeoutId)=>clearTimeout(timeoutId)); content_map.update_timeouts = []; @@ -1711,19 +1789,76 @@ async function upload_cookies() { fileInput.value = ""; } +function formatFileSize(bytes) { + const units = ['B', 'KB', 'MB', 'GB']; + let unitIndex = 0; + while (bytes >= 1024 && unitIndex < units.length - 1) { + bytes /= 1024; + unitIndex++; + } + return `${bytes.toFixed(2)} ${units[unitIndex]}`; +} + +async function upload_files(fileInput) { + const paperclip = document.querySelector(".user-input .fa-paperclip"); + const bucket_id = uuid(); + + const formData = new FormData(); + Array.from(fileInput.files).forEach(file => { + formData.append('files[]', file); + }); + paperclip.classList.add("blink"); + await fetch("/backend-api/v2/files/" + bucket_id, { + method: 'POST', + body: formData + }); + let do_refine = document.getElementById("refine").checked; + function connectToSSE(url) { + const eventSource = new EventSource(url); + eventSource.onmessage = (event) => { + const data = JSON.parse(event.data); + if (data.error) { + inputCount.innerText = `Error: ${data.error.message}`; + } else if (data.action == "load") { + inputCount.innerText = `Read data: ${formatFileSize(data.size)}`; + } else if (data.action == "refine") { + inputCount.innerText = `Refine data: ${formatFileSize(data.size)}`; + } else if (data.action == "done") { + if (do_refine) { + do_refine = false; + connectToSSE(`/backend-api/v2/files/${bucket_id}?refine_chunks_with_spacy=true`); + return; + } + inputCount.innerText = "Files are loaded successfully"; + messageInput.value += (messageInput.value ? "\n" : "") + JSON.stringify({bucket_id: bucket_id}) + "\n"; + paperclip.classList.remove("blink"); + fileInput.value = ""; + delete fileInput.dataset.text; + } + }; + eventSource.onerror = (event) => { + eventSource.close(); + paperclip.classList.remove("blink"); + } + } + connectToSSE(`/backend-api/v2/files/${bucket_id}`); +} + fileInput.addEventListener('change', async (event) => { if (fileInput.files.length) { type = fileInput.files[0].name.split('.').pop() if (type == "har") { return await upload_cookies(); + } else if (type != "json") { + await upload_files(fileInput); } fileInput.dataset.type = type - const reader = new FileReader(); - reader.addEventListener('load', async (event) => { - fileInput.dataset.text = event.target.result; - if (type == "json") { + if (type == "json") { + const reader = new FileReader(); + reader.addEventListener('load', async (event) => { + fileInput.dataset.text = event.target.result; const data = JSON.parse(fileInput.dataset.text); - if ("g4f" in data.options) { + if (data.options && "g4f" in data.options) { let count = 0; Object.keys(data).forEach(key => { if (key != "options" && !localStorage.getItem(key)) { @@ -1736,11 +1871,23 @@ fileInput.addEventListener('change', async (event) => { fileInput.value = ""; inputCount.innerText = `${count} Conversations were imported successfully`; } else { - await upload_cookies(); + is_cookie_file = false; + if (Array.isArray(data)) { + data.forEach((item) => { + if (item.domain && item.name && item.value) { + is_cookie_file = true; + } + }); + } + if (is_cookie_file) { + await upload_cookies(); + } else { + await upload_files(fileInput); + } } - } - }); - reader.readAsText(fileInput.files[0]); + }); + reader.readAsText(fileInput.files[0]); + } } else { delete fileInput.dataset.text; } -- cgit v1.2.3