XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Handle demo modus in Web UI

5a0afdb1
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

2 个文件 +193 -101
Modified g4f/gui/client/static/js/chat.v1.js +190 -100
@@ -36,6 +36,7 @@ let parameters_storage = {};
36 36 let finish_storage = {};
37 37 let usage_storage = {};
38 38 let reasoning_storage = {}
39 let is_demo = false;
39 40
40 41 messageInput.addEventListener("blur", () => {
41 42 window.scrollTo(0, 0);
@@ -683,7 +684,7 @@ async function load_provider_parameters(provider) {
683 684 }
684 685 }
685 686
686 async function add_message_chunk(message, message_id, provider, scroll) {
687 async function add_message_chunk(message, message_id, provider, scroll, finish_message=null) {
687 688 content_map = content_storage[message_id];
688 689 if (message.type == "conversation") {
689 690 const conversation = await get_conversation(window.conversation_id);
@@ -737,6 +738,9 @@ async function add_message_chunk(message, message_id, provider, scroll) {
737 738 update_message(content_map, message_id, markdown_render(message.login), scroll);
738 739 } else if (message.type == "finish") {
739 740 finish_storage[message_id] = message.finish;
741 if (finish_message) {
742 await finish_message();
743 }
740 744 } else if (message.type == "usage") {
741 745 usage_storage[message_id] = message.usage;
742 746 } else if (message.type == "reasoning") {
@@ -829,11 +833,67 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi
829 833 if (scroll) {
830 834 await lazy_scroll_to_bottom();
831 835 }
836 async function finish_message() {
837 content_map.update_timeouts.forEach((timeoutId)=>clearTimeout(timeoutId));
838 content_map.update_timeouts = [];
839 if (!error_storage[message_id] && message_storage[message_id]) {
840 html = markdown_render(message_storage[message_id]);
841 content_map.inner.innerHTML = html;
842 highlight(content_map.inner);
843 if (imageInput) imageInput.value = "";
844 if (cameraInput) cameraInput.value = "";
845 }
846 if (message_storage[message_id]) {
847 const message_provider = message_id in provider_storage ? provider_storage[message_id] : null;
848 await add_message(
849 window.conversation_id,
850 "assistant",
851 message_storage[message_id] + (error_storage[message_id] ? " [error]" : "") + (stop_generating.classList.contains('stop_generating-hidden') ? " [aborted]" : ""),
852 message_provider,
853 message_index,
854 synthesize_storage[message_id],
855 regenerate,
856 title_storage[message_id],
857 finish_storage[message_id],
858 usage_storage[message_id],
859 reasoning_storage[message_id],
860 action=="continue"
861 );
862 delete message_storage[message_id];
863 }
864 if (controller_storage[message_id]) {
865 if (!controller_storage[message_id].signal.aborted) {
866 controller_storage[message_id].abort();
867 }
868 delete controller_storage[message_id];
869 }
870 if (!error_storage[message_id]) {
871 await safe_load_conversation(window.conversation_id, scroll);
872 }
873 let cursorDiv = message_el.querySelector(".cursor");
874 if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
875 if (scroll) {
876 await lazy_scroll_to_bottom();
877 }
878 await safe_remove_cancel_button();
879 await register_message_buttons();
880 await load_conversations();
881 regenerate_button.classList.remove("regenerate-hidden");
882 }
832 883 try {
884 let api_key;
885 if (is_demo && provider != "Custom") {
886 api_key = localStorage.getItem("HuggingFace-api_key");
887 if (!api_key) {
888 location.href = "/";
889 return;
890 }
891 } else {
892 api_key = get_api_key_by_provider(provider);
893 }
833 894 const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput;
834 895 const files = input && input.files.length > 0 ? input.files : null;
835 896 const download_images = document.getElementById("download_images")?.checked;
836 const api_key = get_api_key_by_provider(provider);
837 897 const api_base = provider == "Custom" ? document.getElementById(`${provider}-api_base`).value : null;
838 898 const ignored = Array.from(settings.querySelectorAll("input.provider:not(:checked)")).map((el)=>el.value);
839 899 await api("conversation", {
@@ -849,54 +909,15 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi
849 909 api_key: api_key,
850 910 api_base: api_base,
851 911 ignored: ignored,
852 }, files, message_id, scroll);
853 content_map.update_timeouts.forEach((timeoutId)=>clearTimeout(timeoutId));
854 content_map.update_timeouts = [];
855 if (!error_storage[message_id]) {
856 html = markdown_render(message_storage[message_id]);
857 content_map.inner.innerHTML = html;
858 highlight(content_map.inner);
859 if (imageInput) imageInput.value = "";
860 if (cameraInput) cameraInput.value = "";
861 }
912 }, files, message_id, scroll, finish_message);
862 913 } catch (e) {
863 914 console.error(e);
864 915 if (e.name != "AbortError") {
865 916 error_storage[message_id] = true;
866 917 content_map.inner.innerHTML += markdown_render(`**An error occured:** ${e}`);
867 918 }
919 await finish_message();
868 920 }
869 if (message_storage[message_id]) {
870 const message_provider = message_id in provider_storage ? provider_storage[message_id] : null;
871 await add_message(
872 window.conversation_id,
873 "assistant",
874 message_storage[message_id] + (error_storage[message_id] ? " [error]" : "") + (stop_generating.classList.contains('stop_generating-hidden') ? " [aborted]" : ""),
875 message_provider,
876 message_index,
877 synthesize_storage[message_id],
878 regenerate,
879 title_storage[message_id],
880 finish_storage[message_id],
881 usage_storage[message_id],
882 reasoning_storage[message_id],
883 action=="continue"
884 );
885 delete controller_storage[message_id];
886 delete message_storage[message_id];
887 if (!error_storage[message_id]) {
888 await safe_load_conversation(window.conversation_id, scroll);
889 }
890 }
891 let cursorDiv = message_el.querySelector(".cursor");
892 if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
893 if (scroll) {
894 await lazy_scroll_to_bottom();
895 }
896 await safe_remove_cancel_button();
897 await register_message_buttons();
898 await load_conversations();
899 regenerate_button.classList.remove("regenerate-hidden");
900 921 };
901 922
902 923 async function scroll_to_bottom() {
@@ -1789,70 +1810,93 @@ async function on_api() {
1789 1810 models.forEach((model) => {
1790 1811 let option = document.createElement("option");
1791 1812 option.value = model.name;
1792 option.text = model.name + (model.image ? " (Image Generation)" : "");
1813 option.text = model.name + (model.image ? " (Image Generation)" : "") + (model.vision ? " (Image Upload)" : "");
1793 1814 option.dataset.providers = model.providers.join(" ");
1794 1815 modelSelect.appendChild(option);
1816 is_demo = model.demo;
1795 1817 });
1796 providers = await api("providers")
1797 providers.sort((a, b) => a.label.localeCompare(b.label));
1798 let login_urls = {};
1799 providers.forEach((provider) => {
1800 let option = document.createElement("option");
1801 option.value = provider.name;
1802 option.dataset.label = provider.label;
1803 option.text = provider.label
1804 + (provider.vision ? " (Image Upload)" : "")
1805 + (provider.image ? " (Image Generation)" : "")
1806 + (provider.webdriver ? " (Webdriver)" : "")
1807 + (provider.auth ? " (Auth)" : "");
1808 if (provider.parent)
1809 option.dataset.parent = provider.parent;
1810 providerSelect.appendChild(option);
1811
1812 if (provider.parent) {
1813 if (!login_urls[provider.parent]) {
1814 login_urls[provider.parent] = [provider.label, provider.login_url, [provider.name]];
1815 } else {
1816 login_urls[provider.parent][2].push(provider.name);
1818 let login_urls;
1819 if (is_demo) {
1820 if (!localStorage.getItem("HuggingFace-api_key")) {
1821 location.href = "/";
1822 return;
1823 }
1824 providerSelect.innerHTML = '<option value="" selected>Demo Modus</option>'
1825 document.getElementById("pin")?.remove();
1826 document.getElementById("refine")?.parentElement.remove();
1827 Array.from(modelSelect.querySelectorAll(':not([data-providers])')).forEach((option)=>{
1828 if (!option.disabled && option.value) {
1829 option.remove();
1817 1830 }
1818 } else if (provider.login_url) {
1819 if (!login_urls[provider.name]) {
1820 login_urls[provider.name] = [provider.label, provider.login_url, []];
1821 } else {
1822 login_urls[provider.name][0] = provider.label;
1823 login_urls[provider.name][1] = provider.login_url;
1831 });
1832 login_urls = {
1833 "Custom": ["Custom Provider", "", []],
1834 "HuggingFace": ["HuggingFace", "", []],
1835 };
1836 } else {
1837 providers = await api("providers")
1838 providers.sort((a, b) => a.label.localeCompare(b.label));
1839 login_urls = {};
1840 providers.forEach((provider) => {
1841 let option = document.createElement("option");
1842 option.value = provider.name;
1843 option.dataset.label = provider.label;
1844 option.text = provider.label
1845 + (provider.vision ? " (Image Upload)" : "")
1846 + (provider.image ? " (Image Generation)" : "")
1847 + (provider.webdriver ? " (Webdriver)" : "")
1848 + (provider.auth ? " (Auth)" : "");
1849 if (provider.parent)
1850 option.dataset.parent = provider.parent;
1851 providerSelect.appendChild(option);
1852
1853 if (provider.parent) {
1854 if (!login_urls[provider.parent]) {
1855 login_urls[provider.parent] = [provider.label, provider.login_url, [provider.name]];
1856 } else {
1857 login_urls[provider.parent][2].push(provider.name);
1858 }
1859 } else if (provider.login_url) {
1860 if (!login_urls[provider.name]) {
1861 login_urls[provider.name] = [provider.label, provider.login_url, []];
1862 } else {
1863 login_urls[provider.name][0] = provider.label;
1864 login_urls[provider.name][1] = provider.login_url;
1865 }
1824 1866 }
1825 }
1826 });
1867 });
1868 providers.forEach((provider) => {
1869 if (!provider.parent) {
1870 option = document.createElement("div");
1871 option.classList.add("field");
1872 option.innerHTML = `
1873 <span class="label">Enable ${provider.label}</span>
1874 <input id="Provider${provider.name}" type="checkbox" name="Provider${provider.name}" value="${provider.name}" class="provider" checked="">
1875 <label for="Provider${provider.name}" class="toogle" title="Remove provider from dropdown"></label>
1876 `;
1877 option.querySelector("input").addEventListener("change", (event) => load_provider_option(event.target, provider.name));
1878 settings.querySelector(".paper").appendChild(option);
1879 provider_options[provider.name] = option;
1880 }
1881 });
1882 await load_provider_models(appStorage.getItem("provider"))
1883 }
1827 1884 for (let [name, [label, login_url, childs]] of Object.entries(login_urls)) {
1828 if (!login_url) {
1885 if (!login_url && !is_demo) {
1829 1886 continue;
1830 1887 }
1831 1888 option = document.createElement("div");
1832 option.classList.add("field", "box", "hidden");
1889 option.classList.add("field", "box");
1890 if (!is_demo) {
1891 option.classList.add("hidden");
1892 }
1833 1893 childs = childs.map((child)=>`${child}-api_key`).join(" ");
1834 1894 option.innerHTML = `
1835 1895 <label for="${name}-api_key" class="label" title="">${label}:</label>
1836 <input type="text" id="${name}-api_key" name="${name}[api_key]" class="${childs}" placeholder="api_key"/>
1837 <a href="${login_url}" target="_blank" title="Login to ${label}">Get API key</a>
1838 `;
1896 <input type="text" id="${name}-api_key" name="${name}[api_key]" class="${childs}" placeholder="api_key" autocomplete="off"/>
1897 ` + (login_url ? `<a href="${login_url}" target="_blank" title="Login to ${label}">Get API key</a>` : "");
1839 1898 settings.querySelector(".paper").appendChild(option);
1840 1899 }
1841 providers.forEach((provider) => {
1842 if (!provider.parent) {
1843 option = document.createElement("div");
1844 option.classList.add("field");
1845 option.innerHTML = `
1846 <span class="label">Enable ${provider.label}</span>
1847 <input id="Provider${provider.name}" type="checkbox" name="Provider${provider.name}" value="${provider.name}" class="provider" checked="">
1848 <label for="Provider${provider.name}" class="toogle" title="Remove provider from dropdown"></label>
1849 `;
1850 option.querySelector("input").addEventListener("change", (event) => load_provider_option(event.target, provider.name));
1851 settings.querySelector(".paper").appendChild(option);
1852 provider_options[provider.name] = option;
1853 }
1854 });
1855 await load_provider_models(appStorage.getItem("provider"))
1856 1900
1857 1901 register_settings_storage();
1858 1902 await load_settings_storage()
@@ -2093,7 +2137,7 @@ function get_selected_model() {
2093 2137 }
2094 2138 }
2095 2139
2096 async function api(ressource, args=null, files=null, message_id=null, scroll=true) {
2140 async function api(ressource, args=null, files=null, message_id=null, scroll=true, finish_message=null) {
2097 2141 if (window?.pywebview) {
2098 2142 if (args !== null) {
2099 2143 if (ressource == "conversation") {
@@ -2138,16 +2182,43 @@ async function api(ressource, args=null, files=null, message_id=null, scroll=tru
2138 2182 headers: headers,
2139 2183 body: body,
2140 2184 });
2141 return read_response(response, message_id, args.provider || null, scroll);
2185 // On Ratelimit
2186 if (response.status == 429) {
2187 // They are still pending requests?
2188 for (let key in controller_storage) {
2189 if (!controller_storage[key].signal.aborted) {
2190 console.error(response);
2191 await finish_message();
2192 return;
2193 }
2194 }
2195 setTimeout(async () => {
2196 response = await fetch(url, {
2197 method: 'POST',
2198 signal: controller_storage[message_id].signal,
2199 headers: headers,
2200 body: body,
2201 });
2202 if (response.status != 200) {
2203 console.error(response);
2204 }
2205 await read_response(response, message_id, args.provider || null, scroll, finish_message);
2206 await finish_message();
2207 }, 20000) // Wait 20 secounds on rate limit
2208 } else {
2209 await read_response(response, message_id, args.provider || null, scroll, finish_message);
2210 await finish_message();
2211 return;
2212 }
2142 2213 }
2143 2214 response = await fetch(url, {headers: headers});
2144 if (response.status == 200) {
2145 return await response.json();
2215 if (response.status != 200) {
2216 console.error(response);
2146 2217 }
2147 console.error(response);
2218 return await response.json();
2148 2219 }
2149 2220
2150 async function read_response(response, message_id, provider, scroll) {
2221 async function read_response(response, message_id, provider, scroll, finish_message) {
2151 2222 const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
2152 2223 let buffer = ""
2153 2224 while (true) {
@@ -2160,7 +2231,7 @@ async function read_response(response, message_id, provider, scroll) {
2160 2231 continue;
2161 2232 }
2162 2233 try {
2163 add_message_chunk(JSON.parse(buffer + line), message_id, provider, scroll);
2234 add_message_chunk(JSON.parse(buffer + line), message_id, provider, scroll, finish_message);
2164 2235 buffer = "";
2165 2236 } catch {
2166 2237 buffer += line
@@ -2278,6 +2349,25 @@ function save_storage() {
2278 2349 }
2279 2350 }
2280 2351
2352 function add_memory() {
2353 let conversations = [];
2354 for (let i = 0; i < appStorage.length; i++) {
2355 if (appStorage.key(i).startsWith("conversation:")) {
2356 let conversation = appStorage.getItem(appStorage.key(i));
2357 conversations.push(JSON.parse(conversation));
2358 }
2359 }
2360 conversations.sort((a, b) => (b.updated||0)-(a.updated||0));
2361 conversations.forEach(async (conversation)=>{
2362 let body = JSON.stringify(conversation);
2363 response = await fetch("/backend-api/v2/memory", {
2364 method: 'POST',
2365 body: body,
2366 headers: {"content-type": "application/json"}
2367 });
2368 });
2369 }
2370
2281 2371 const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
2282 2372 if (SpeechRecognition) {
2283 2373 const mircoIcon = microLabel.querySelector("i");
Modified g4f/gui/server/backend_api.py +3 -1
@@ -71,7 +71,9 @@ class Backend_Api(Api):
71 71 else:
72 72 class Dummy():
73 73 def limit(self, value):
74 pass
74 def callback(v):
75 return v
76 return callback
75 77 limiter = Dummy()
76 78
77 79 @app.route('/backend-api/v2/models', methods=['GET'])