From 486e9a9122d901aa8eba57a9a83c4c41d13e1de4 Mon Sep 17 00:00:00 2001 From: Heiner Lohaus Date: Fri, 3 Jan 2025 02:40:21 +0100 Subject: Add login_url to authed providers Create a home page for the GUI Fix CopyButton in Code Highlight --- g4f/gui/client/home.html | 230 +++++++++++++++++++++++ g4f/gui/client/static/js/chat.v1.js | 17 +- g4f/gui/client/static/js/highlightjs-copy.min.js | 2 +- g4f/gui/server/app.py | 4 +- g4f/gui/server/backend_api.py | 41 ++++ g4f/gui/server/website.py | 7 +- 6 files changed, 288 insertions(+), 13 deletions(-) create mode 100644 g4f/gui/client/home.html (limited to 'g4f/gui') diff --git a/g4f/gui/client/home.html b/g4f/gui/client/home.html new file mode 100644 index 00000000..43cd3cc0 --- /dev/null +++ b/g4f/gui/client/home.html @@ -0,0 +1,230 @@ + + + + + + + G4F GUI + + + + + + +
+ + +
+
+ G4F GUI +
+
+ Welcome to the G4F GUI!
+ Your AI assistant is ready to assist you. +
+ + +
+ + +
+ + + + + +
+ + + \ No newline at end of file diff --git a/g4f/gui/client/static/js/chat.v1.js b/g4f/gui/client/static/js/chat.v1.js index 8ecc74ca..5466c578 100644 --- a/g4f/gui/client/static/js/chat.v1.js +++ b/g4f/gui/client/static/js/chat.v1.js @@ -137,14 +137,13 @@ class HtmlRenderPlugin { } } } - +if (window.hljs) { + hljs.addPlugin(new HtmlRenderPlugin()) + hljs.addPlugin(new CopyButtonPlugin()); +} let typesetPromise = Promise.resolve(); const highlight = (container) => { if (window.hljs) { - hljs.addPlugin(new HtmlRenderPlugin()) - if (window.CopyButtonPlugin) { - hljs.addPlugin(new CopyButtonPlugin()); - } container.querySelectorAll('code:not(.hljs').forEach((el) => { if (el.className != "hljs") { hljs.highlightElement(el); @@ -542,7 +541,6 @@ async function load_provider_parameters(provider) { if (old_form) { provider_forms.removeChild(old_form); } - console.log(provider, parameters_storage[provider]); Object.entries(parameters_storage[provider]).forEach(([key, value]) => { let el_id = `${provider}-${key}`; let saved_value = appStorage.getItem(el_id); @@ -1012,8 +1010,9 @@ const load_conversation = async (conversation_id, scroll=true) => { 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("```")) { + const index = str.indexOf("\n"); + newContent = newContent.substring(index); } if (newContent.startsWith(lastLine)) { newContent = newContent.substring(lastLine.length); @@ -1763,7 +1762,7 @@ async function load_version() { new_version = document.createElement("div"); new_version.classList.add("new_version"); const link = `v${versions["latest_version"]}`; - new_version.innerHTML = `g4f ${link}  ðŸ†•`; + new_version.innerHTML = `G4F ${link}  ðŸ†•`; new_version.addEventListener("click", ()=>new_version.parentElement.removeChild(new_version)); document.body.appendChild(new_version); } else { diff --git a/g4f/gui/client/static/js/highlightjs-copy.min.js b/g4f/gui/client/static/js/highlightjs-copy.min.js index 0dca7a29..3cf14366 100644 --- a/g4f/gui/client/static/js/highlightjs-copy.min.js +++ b/g4f/gui/client/static/js/highlightjs-copy.min.js @@ -7,7 +7,7 @@ class CopyButtonPlugin { el, text }) { - if (el.classList.contains("language-plaintext")) { + if (el.parentElement.tagName != "PRE") { return; } let button = Object.assign(document.createElement("button"), { diff --git a/g4f/gui/server/app.py b/g4f/gui/server/app.py index 86ea40a3..211eb2a9 100644 --- a/g4f/gui/server/app.py +++ b/g4f/gui/server/app.py @@ -6,4 +6,6 @@ def create_app() -> Flask: template_folder = os.path.join(sys._MEIPASS, "client") else: template_folder = "../client" - return Flask(__name__, template_folder=template_folder, static_folder=f"{template_folder}/static") \ No newline at end of file + app = Flask(__name__, template_folder=template_folder, static_folder=f"{template_folder}/static") + app.config["TEMPLATES_AUTO_RELOAD"] = True # Enable auto reload in debug mode + return app \ No newline at end of file diff --git a/g4f/gui/server/backend_api.py b/g4f/gui/server/backend_api.py index 07505424..9858b4a3 100644 --- a/g4f/gui/server/backend_api.py +++ b/g4f/gui/server/backend_api.py @@ -14,9 +14,12 @@ from werkzeug.utils import secure_filename from ...image import is_allowed_extension, to_image from ...client.service import convert_to_provider from ...providers.asyncio import to_sync_generator +from ...client.helper import filter_markdown from ...tools.files import supports_filename, get_streaming, get_bucket_dir, get_buckets +from ...tools.run_tools import iter_run_tools from ...errors import ProviderNotFoundError from ...cookies import get_cookies_dir +from ... import ChatCompletion from .api import Api logger = logging.getLogger(__name__) @@ -101,6 +104,44 @@ class Backend_Api(Api): } } + @app.route('/backend-api/v2/create', methods=['GET', 'POST']) + def create(): + try: + tool_calls = [{ + "function": { + "name": "bucket_tool" + }, + "type": "function" + }] + web_search = request.args.get("web_search") + if web_search: + tool_calls.append({ + "function": { + "name": "search_tool", + "arguments": {"query": web_search, "instructions": ""} if web_search != "true" else {} + }, + "type": "function" + }) + do_filter_markdown = request.args.get("filter_markdown") + response = iter_run_tools( + ChatCompletion.create, + model=request.args.get("model"), + messages=[{"role": "user", "content": request.args.get("prompt")}], + provider=request.args.get("provider", None), + stream=not do_filter_markdown, + ignore_stream=not request.args.get("stream"), + tool_calls=tool_calls, + ) + if do_filter_markdown: + return Response(filter_markdown(response, do_filter_markdown), mimetype='text/plain') + def cast_str(): + for chunk in response: + yield str(chunk) + return Response(cast_str(), mimetype='text/plain') + except Exception as e: + logger.exception(e) + return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500 + @app.route('/backend-api/v2/buckets', methods=['GET']) def list_buckets(): try: diff --git a/g4f/gui/server/website.py b/g4f/gui/server/website.py index a3d6edd5..1af8aa08 100644 --- a/g4f/gui/server/website.py +++ b/g4f/gui/server/website.py @@ -9,7 +9,7 @@ class Website: self.app = app self.routes = { '/': { - 'function': redirect_home, + 'function': self._home, 'methods': ['GET', 'POST'] }, '/chat/': { @@ -40,4 +40,7 @@ class Website: return render_template('index.html', chat_id=conversation_id) def _index(self): - return render_template('index.html', chat_id=str(uuid.uuid4())) \ No newline at end of file + return render_template('index.html', chat_id=str(uuid.uuid4())) + + def _home(self): + return render_template('home.html') \ No newline at end of file -- cgit v1.2.3