From 5a0afdb11009352a283dc0396789198fdbac26a7 Mon Sep 17 00:00:00 2001 From: hlohaus <983577+hlohaus@users.noreply.github.com> Date: Sun, 26 Jan 2025 04:25:21 +0100 Subject: Handle demo modus in Web UI --- g4f/gui/client/static/js/chat.v1.js | 290 +++++++++++++++++++++++------------- g4f/gui/server/backend_api.py | 4 +- 2 files changed, 193 insertions(+), 101 deletions(-) (limited to 'g4f') diff --git a/g4f/gui/client/static/js/chat.v1.js b/g4f/gui/client/static/js/chat.v1.js index d0116c80..dfedb2aa 100644 --- a/g4f/gui/client/static/js/chat.v1.js +++ b/g4f/gui/client/static/js/chat.v1.js @@ -36,6 +36,7 @@ let parameters_storage = {}; let finish_storage = {}; let usage_storage = {}; let reasoning_storage = {} +let is_demo = false; messageInput.addEventListener("blur", () => { window.scrollTo(0, 0); @@ -683,7 +684,7 @@ async function load_provider_parameters(provider) { } } -async function add_message_chunk(message, message_id, provider, scroll) { +async function add_message_chunk(message, message_id, provider, scroll, finish_message=null) { content_map = content_storage[message_id]; if (message.type == "conversation") { const conversation = await get_conversation(window.conversation_id); @@ -737,6 +738,9 @@ async function add_message_chunk(message, message_id, provider, scroll) { update_message(content_map, message_id, markdown_render(message.login), scroll); } else if (message.type == "finish") { finish_storage[message_id] = message.finish; + if (finish_message) { + await finish_message(); + } } else if (message.type == "usage") { usage_storage[message_id] = message.usage; } else if (message.type == "reasoning") { @@ -829,11 +833,67 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi if (scroll) { await lazy_scroll_to_bottom(); } + async function finish_message() { + content_map.update_timeouts.forEach((timeoutId)=>clearTimeout(timeoutId)); + content_map.update_timeouts = []; + if (!error_storage[message_id] && message_storage[message_id]) { + html = markdown_render(message_storage[message_id]); + content_map.inner.innerHTML = html; + highlight(content_map.inner); + if (imageInput) imageInput.value = ""; + if (cameraInput) cameraInput.value = ""; + } + if (message_storage[message_id]) { + const message_provider = message_id in provider_storage ? provider_storage[message_id] : null; + await add_message( + window.conversation_id, + "assistant", + message_storage[message_id] + (error_storage[message_id] ? " [error]" : "") + (stop_generating.classList.contains('stop_generating-hidden') ? " [aborted]" : ""), + message_provider, + message_index, + synthesize_storage[message_id], + regenerate, + title_storage[message_id], + finish_storage[message_id], + usage_storage[message_id], + reasoning_storage[message_id], + action=="continue" + ); + delete message_storage[message_id]; + } + if (controller_storage[message_id]) { + if (!controller_storage[message_id].signal.aborted) { + controller_storage[message_id].abort(); + } + delete controller_storage[message_id]; + } + if (!error_storage[message_id]) { + await safe_load_conversation(window.conversation_id, scroll); + } + let cursorDiv = message_el.querySelector(".cursor"); + if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv); + if (scroll) { + await lazy_scroll_to_bottom(); + } + await safe_remove_cancel_button(); + await register_message_buttons(); + await load_conversations(); + regenerate_button.classList.remove("regenerate-hidden"); + } try { + let api_key; + if (is_demo && provider != "Custom") { + api_key = localStorage.getItem("HuggingFace-api_key"); + if (!api_key) { + location.href = "/"; + return; + } + } else { + api_key = get_api_key_by_provider(provider); + } const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput; const files = input && input.files.length > 0 ? input.files : null; const download_images = document.getElementById("download_images")?.checked; - const api_key = get_api_key_by_provider(provider); const api_base = provider == "Custom" ? document.getElementById(`${provider}-api_base`).value : null; const ignored = Array.from(settings.querySelectorAll("input.provider:not(:checked)")).map((el)=>el.value); await api("conversation", { @@ -849,54 +909,15 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi api_key: api_key, api_base: api_base, ignored: ignored, - }, files, message_id, scroll); - content_map.update_timeouts.forEach((timeoutId)=>clearTimeout(timeoutId)); - content_map.update_timeouts = []; - if (!error_storage[message_id]) { - html = markdown_render(message_storage[message_id]); - content_map.inner.innerHTML = html; - highlight(content_map.inner); - if (imageInput) imageInput.value = ""; - if (cameraInput) cameraInput.value = ""; - } + }, files, message_id, scroll, finish_message); } catch (e) { console.error(e); if (e.name != "AbortError") { error_storage[message_id] = true; content_map.inner.innerHTML += markdown_render(`**An error occured:** ${e}`); } + await finish_message(); } - if (message_storage[message_id]) { - const message_provider = message_id in provider_storage ? provider_storage[message_id] : null; - await add_message( - window.conversation_id, - "assistant", - message_storage[message_id] + (error_storage[message_id] ? " [error]" : "") + (stop_generating.classList.contains('stop_generating-hidden') ? " [aborted]" : ""), - message_provider, - message_index, - synthesize_storage[message_id], - regenerate, - title_storage[message_id], - finish_storage[message_id], - usage_storage[message_id], - reasoning_storage[message_id], - action=="continue" - ); - delete controller_storage[message_id]; - delete message_storage[message_id]; - if (!error_storage[message_id]) { - await safe_load_conversation(window.conversation_id, scroll); - } - } - let cursorDiv = message_el.querySelector(".cursor"); - if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv); - if (scroll) { - await lazy_scroll_to_bottom(); - } - await safe_remove_cancel_button(); - await register_message_buttons(); - await load_conversations(); - regenerate_button.classList.remove("regenerate-hidden"); }; async function scroll_to_bottom() { @@ -1789,70 +1810,93 @@ async function on_api() { models.forEach((model) => { let option = document.createElement("option"); option.value = model.name; - option.text = model.name + (model.image ? " (Image Generation)" : ""); + option.text = model.name + (model.image ? " (Image Generation)" : "") + (model.vision ? " (Image Upload)" : ""); option.dataset.providers = model.providers.join(" "); modelSelect.appendChild(option); + is_demo = model.demo; }); - providers = await api("providers") - providers.sort((a, b) => a.label.localeCompare(b.label)); - let login_urls = {}; - providers.forEach((provider) => { - let option = document.createElement("option"); - option.value = provider.name; - option.dataset.label = provider.label; - option.text = provider.label - + (provider.vision ? " (Image Upload)" : "") - + (provider.image ? " (Image Generation)" : "") - + (provider.webdriver ? " (Webdriver)" : "") - + (provider.auth ? " (Auth)" : ""); - if (provider.parent) - option.dataset.parent = provider.parent; - providerSelect.appendChild(option); - - if (provider.parent) { - if (!login_urls[provider.parent]) { - login_urls[provider.parent] = [provider.label, provider.login_url, [provider.name]]; - } else { - login_urls[provider.parent][2].push(provider.name); + let login_urls; + if (is_demo) { + if (!localStorage.getItem("HuggingFace-api_key")) { + location.href = "/"; + return; + } + providerSelect.innerHTML = '' + document.getElementById("pin")?.remove(); + document.getElementById("refine")?.parentElement.remove(); + Array.from(modelSelect.querySelectorAll(':not([data-providers])')).forEach((option)=>{ + if (!option.disabled && option.value) { + option.remove(); } - } else if (provider.login_url) { - if (!login_urls[provider.name]) { - login_urls[provider.name] = [provider.label, provider.login_url, []]; - } else { - login_urls[provider.name][0] = provider.label; - login_urls[provider.name][1] = provider.login_url; + }); + login_urls = { + "Custom": ["Custom Provider", "", []], + "HuggingFace": ["HuggingFace", "", []], + }; + } else { + providers = await api("providers") + providers.sort((a, b) => a.label.localeCompare(b.label)); + login_urls = {}; + providers.forEach((provider) => { + let option = document.createElement("option"); + option.value = provider.name; + option.dataset.label = provider.label; + option.text = provider.label + + (provider.vision ? " (Image Upload)" : "") + + (provider.image ? " (Image Generation)" : "") + + (provider.webdriver ? " (Webdriver)" : "") + + (provider.auth ? " (Auth)" : ""); + if (provider.parent) + option.dataset.parent = provider.parent; + providerSelect.appendChild(option); + + if (provider.parent) { + if (!login_urls[provider.parent]) { + login_urls[provider.parent] = [provider.label, provider.login_url, [provider.name]]; + } else { + login_urls[provider.parent][2].push(provider.name); + } + } else if (provider.login_url) { + if (!login_urls[provider.name]) { + login_urls[provider.name] = [provider.label, provider.login_url, []]; + } else { + login_urls[provider.name][0] = provider.label; + login_urls[provider.name][1] = provider.login_url; + } } - } - }); + }); + providers.forEach((provider) => { + if (!provider.parent) { + option = document.createElement("div"); + option.classList.add("field"); + option.innerHTML = ` + Enable ${provider.label} + + + `; + option.querySelector("input").addEventListener("change", (event) => load_provider_option(event.target, provider.name)); + settings.querySelector(".paper").appendChild(option); + provider_options[provider.name] = option; + } + }); + await load_provider_models(appStorage.getItem("provider")) + } for (let [name, [label, login_url, childs]] of Object.entries(login_urls)) { - if (!login_url) { + if (!login_url && !is_demo) { continue; } option = document.createElement("div"); - option.classList.add("field", "box", "hidden"); + option.classList.add("field", "box"); + if (!is_demo) { + option.classList.add("hidden"); + } childs = childs.map((child)=>`${child}-api_key`).join(" "); option.innerHTML = ` - - Get API key - `; + + ` + (login_url ? `Get API key` : ""); settings.querySelector(".paper").appendChild(option); } - providers.forEach((provider) => { - if (!provider.parent) { - option = document.createElement("div"); - option.classList.add("field"); - option.innerHTML = ` - Enable ${provider.label} - - - `; - option.querySelector("input").addEventListener("change", (event) => load_provider_option(event.target, provider.name)); - settings.querySelector(".paper").appendChild(option); - provider_options[provider.name] = option; - } - }); - await load_provider_models(appStorage.getItem("provider")) register_settings_storage(); await load_settings_storage() @@ -2093,7 +2137,7 @@ function get_selected_model() { } } -async function api(ressource, args=null, files=null, message_id=null, scroll=true) { +async function api(ressource, args=null, files=null, message_id=null, scroll=true, finish_message=null) { if (window?.pywebview) { if (args !== null) { if (ressource == "conversation") { @@ -2138,16 +2182,43 @@ async function api(ressource, args=null, files=null, message_id=null, scroll=tru headers: headers, body: body, }); - return read_response(response, message_id, args.provider || null, scroll); + // On Ratelimit + if (response.status == 429) { + // They are still pending requests? + for (let key in controller_storage) { + if (!controller_storage[key].signal.aborted) { + console.error(response); + await finish_message(); + return; + } + } + setTimeout(async () => { + response = await fetch(url, { + method: 'POST', + signal: controller_storage[message_id].signal, + headers: headers, + body: body, + }); + if (response.status != 200) { + console.error(response); + } + await read_response(response, message_id, args.provider || null, scroll, finish_message); + await finish_message(); + }, 20000) // Wait 20 secounds on rate limit + } else { + await read_response(response, message_id, args.provider || null, scroll, finish_message); + await finish_message(); + return; + } } response = await fetch(url, {headers: headers}); - if (response.status == 200) { - return await response.json(); + if (response.status != 200) { + console.error(response); } - console.error(response); + return await response.json(); } -async function read_response(response, message_id, provider, scroll) { +async function read_response(response, message_id, provider, scroll, finish_message) { const reader = response.body.pipeThrough(new TextDecoderStream()).getReader(); let buffer = "" while (true) { @@ -2160,7 +2231,7 @@ async function read_response(response, message_id, provider, scroll) { continue; } try { - add_message_chunk(JSON.parse(buffer + line), message_id, provider, scroll); + add_message_chunk(JSON.parse(buffer + line), message_id, provider, scroll, finish_message); buffer = ""; } catch { buffer += line @@ -2278,6 +2349,25 @@ function save_storage() { } } +function add_memory() { + let conversations = []; + for (let i = 0; i < appStorage.length; i++) { + if (appStorage.key(i).startsWith("conversation:")) { + let conversation = appStorage.getItem(appStorage.key(i)); + conversations.push(JSON.parse(conversation)); + } + } + conversations.sort((a, b) => (b.updated||0)-(a.updated||0)); + conversations.forEach(async (conversation)=>{ + let body = JSON.stringify(conversation); + response = await fetch("/backend-api/v2/memory", { + method: 'POST', + body: body, + headers: {"content-type": "application/json"} + }); + }); +} + const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (SpeechRecognition) { const mircoIcon = microLabel.querySelector("i"); diff --git a/g4f/gui/server/backend_api.py b/g4f/gui/server/backend_api.py index a6775847..9c2d5261 100644 --- a/g4f/gui/server/backend_api.py +++ b/g4f/gui/server/backend_api.py @@ -71,7 +71,9 @@ class Backend_Api(Api): else: class Dummy(): def limit(self, value): - pass + def callback(v): + return v + return callback limiter = Dummy() @app.route('/backend-api/v2/models', methods=['GET']) -- cgit v1.2.3