summaryrefslogtreecommitdiffstats
path: root/g4f
diff options
context:
space:
mode:
authorTekky <98614666+xtekky@users.noreply.github.com>2023-12-13 15:27:55 +0100
committerGitHub <noreply@github.com>2023-12-13 15:27:55 +0100
commit99127111f525d4ed1469c3547bcb491a8cdf5963 (patch)
tree10ed7693fe0116fa91ab9c77cbc0aa0951417f75 /g4f
parent~ (diff)
parentChange default port for gui (diff)
downloadgpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar.gz
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar.bz2
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar.lz
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar.xz
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.tar.zst
gpt4free-99127111f525d4ed1469c3547bcb491a8cdf5963.zip
Diffstat (limited to 'g4f')
-rw-r--r--g4f/Provider/retry_provider.py7
-rw-r--r--g4f/__init__.py81
-rw-r--r--g4f/cli.py2
-rw-r--r--g4f/debug.py39
-rw-r--r--g4f/errors.py26
-rw-r--r--g4f/gui/client/css/style.css18
-rw-r--r--g4f/gui/client/html/index.html6
-rw-r--r--g4f/gui/client/js/chat.v1.js239
-rw-r--r--g4f/gui/run.py2
-rw-r--r--g4f/gui/server/backend.py70
10 files changed, 252 insertions, 238 deletions
diff --git a/g4f/Provider/retry_provider.py b/g4f/Provider/retry_provider.py
index 6fdefe0f..e49b6da6 100644
--- a/g4f/Provider/retry_provider.py
+++ b/g4f/Provider/retry_provider.py
@@ -6,6 +6,7 @@ from typing import List, Type, Dict
from ..typing import CreateResult, Messages
from .base_provider import BaseProvider, AsyncProvider
from .. import debug
+from ..errors import RetryProviderError, RetryNoProviderError
class RetryProvider(AsyncProvider):
@@ -84,8 +85,8 @@ class RetryProvider(AsyncProvider):
def raise_exceptions(self) -> None:
if self.exceptions:
- raise RuntimeError("\n".join(["RetryProvider failed:"] + [
- f"{p}: {self.exceptions[p].__class__.__name__}: {self.exceptions[p]}" for p in self.exceptions
+ raise RetryProviderError("RetryProvider failed:\n" + "\n".join([
+ f"{p}: {exception.__class__.__name__}: {exception}" for p, exception in self.exceptions.items()
]))
- raise RuntimeError("RetryProvider: No provider found") \ No newline at end of file
+ raise RetryNoProviderError("No provider found") \ No newline at end of file
diff --git a/g4f/__init__.py b/g4f/__init__.py
index 92bce194..3b0fcad0 100644
--- a/g4f/__init__.py
+++ b/g4f/__init__.py
@@ -1,61 +1,35 @@
from __future__ import annotations
import os
-from requests import get
-from importlib.metadata import version as get_package_version, PackageNotFoundError
-from subprocess import check_output, CalledProcessError, PIPE
+from .errors import *
from .models import Model, ModelUtils, _all_models
-from .Provider import BaseProvider, AsyncGeneratorProvider, RetryProvider
+from .Provider import BaseProvider, AsyncGeneratorProvider, RetryProvider, ProviderUtils
from .typing import Messages, CreateResult, AsyncResult, Union, List
from . import debug
-def get_version() -> str:
- # Read from package manager
- try:
- return get_package_version("g4f")
- except PackageNotFoundError:
- pass
- # Read from docker environment
- current_version = os.environ.get("G4F_VERSION")
- if current_version:
- return current_version
- # Read from git repository
- try:
- command = ["git", "describe", "--tags", "--abbrev=0"]
- return check_output(command, text=True, stderr=PIPE).strip()
- except CalledProcessError:
- pass
-
-def get_lastet_version() -> str:
- response = get("https://pypi.org/pypi/g4f/json").json()
- return response["info"]["version"]
-
-def check_pypi_version() -> None:
- try:
- version = get_version()
- latest_version = get_lastet_version()
- except Exception as e:
- print(f'Failed to check g4f pypi version: {e}')
- if version != latest_version:
- print(f'New pypi version: {latest_version} (current: {version}) | pip install -U g4f')
-
def get_model_and_provider(model : Union[Model, str],
- provider : Union[type[BaseProvider], None],
+ provider : Union[type[BaseProvider], str, None],
stream : bool,
ignored : List[str] = None,
ignore_working: bool = False,
ignore_stream: bool = False) -> tuple[Model, type[BaseProvider]]:
if debug.version_check:
- check_pypi_version()
debug.version_check = False
-
+ debug.check_pypi_version()
+
+ if isinstance(provider, str):
+ if provider in ProviderUtils.convert:
+ provider = ProviderUtils.convert[provider]
+ else:
+ raise ProviderNotFoundError(f'Provider not found: {provider}')
+
if isinstance(model, str):
if model in ModelUtils.convert:
model = ModelUtils.convert[model]
else:
- raise ValueError(f'The model: {model} does not exist')
-
+ raise ModelNotFoundError(f'The model: {model} does not exist')
+
if not provider:
provider = model.best_provider
@@ -63,14 +37,14 @@ def get_model_and_provider(model : Union[Model, str],
provider.providers = [p for p in provider.providers if p.__name__ not in ignored]
if not provider:
- raise RuntimeError(f'No provider found for model: {model}')
-
+ raise ProviderNotFoundError(f'No provider found for model: {model}')
+
if not provider.working and not ignore_working:
- raise RuntimeError(f'{provider.__name__} is not working')
-
+ raise ProviderNotWorkingError(f'{provider.__name__} is not working')
+
if not ignore_stream and not provider.supports_stream and stream:
- raise ValueError(f'{provider.__name__} does not support "stream" argument')
-
+ raise StreamNotSupportedError(f'{provider.__name__} does not support "stream" argument')
+
if debug.logging:
print(f'Using {provider.__name__} provider')
@@ -80,7 +54,7 @@ class ChatCompletion:
@staticmethod
def create(model : Union[Model, str],
messages : Messages,
- provider : Union[type[BaseProvider], None] = None,
+ provider : Union[type[BaseProvider], str, None] = None,
stream : bool = False,
auth : Union[str, None] = None,
ignored : List[str] = None,
@@ -91,11 +65,15 @@ class ChatCompletion:
model, provider = get_model_and_provider(model, provider, stream, ignored, ignore_working, ignore_stream_and_auth)
if not ignore_stream_and_auth and provider.needs_auth and not auth:
- raise ValueError(
- f'{provider.__name__} requires authentication (use auth=\'cookie or token or jwt ...\' param)')
+ raise AuthenticationRequiredError(f'{provider.__name__} requires authentication (use auth=\'cookie or token or jwt ...\' param)')
if auth:
kwargs['auth'] = auth
+
+ if "proxy" not in kwargs:
+ proxy = os.environ.get("G4F_PROXY")
+ if proxy:
+ kwargs['proxy'] = proxy
result = provider.create_completion(model.name, messages, stream, **kwargs)
return result if stream else ''.join(result)
@@ -103,7 +81,7 @@ class ChatCompletion:
@staticmethod
async def create_async(model : Union[Model, str],
messages : Messages,
- provider : Union[type[BaseProvider], None] = None,
+ provider : Union[type[BaseProvider], str, None] = None,
stream : bool = False,
ignored : List[str] = None,
**kwargs) -> Union[AsyncResult, str]:
@@ -112,7 +90,7 @@ class ChatCompletion:
if stream:
if isinstance(provider, type) and issubclass(provider, AsyncGeneratorProvider):
return await provider.create_async_generator(model.name, messages, **kwargs)
- raise ValueError(f'{provider.__name__} does not support "stream" argument')
+ raise StreamNotSupportedError(f'{provider.__name__} does not support "stream" argument in "create_async"')
return await provider.create_async(model.name, messages, **kwargs)
@@ -132,9 +110,8 @@ class Completion:
'text-davinci-002',
'text-davinci-003'
]
-
if model not in allowed_models:
- raise Exception(f'ValueError: Can\'t use {model} with Completion.create()')
+ raise ModelNotAllowed(f'Can\'t use {model} with Completion.create()')
model, provider = get_model_and_provider(model, provider, stream, ignored)
diff --git a/g4f/cli.py b/g4f/cli.py
index 20131e5d..40ddd3d7 100644
--- a/g4f/cli.py
+++ b/g4f/cli.py
@@ -15,7 +15,7 @@ def main():
parser = argparse.ArgumentParser(description="Run gpt4free")
subparsers = parser.add_subparsers(dest="mode", help="Mode to run the g4f in.")
api_parser=subparsers.add_parser("api")
- api_parser.add_argument("--bind", default="127.0.0.1:1337", help="The bind string.")
+ api_parser.add_argument("--bind", default="0.0.0.0:1337", help="The bind string.")
api_parser.add_argument("--debug", type=bool, default=False, help="Enable verbose logging")
api_parser.add_argument("--ignored-providers", nargs="+", choices=[provider.name for provider in IgnoredProviders],
default=[], help="List of providers to ignore when processing request.")
diff --git a/g4f/debug.py b/g4f/debug.py
index 984d973a..1ee1506f 100644
--- a/g4f/debug.py
+++ b/g4f/debug.py
@@ -1,2 +1,39 @@
+from os import environ
+from requests import get
+from importlib.metadata import version as get_package_version, PackageNotFoundError
+from subprocess import check_output, CalledProcessError, PIPE
+from .errors import VersionNotFoundError
+
logging = False
-version_check = True \ No newline at end of file
+version_check = True
+
+def get_version() -> str:
+ # Read from package manager
+ try:
+ return get_package_version("g4f")
+ except PackageNotFoundError:
+ pass
+ # Read from docker environment
+ current_version = environ.get("G4F_VERSION")
+ if current_version:
+ return current_version
+ # Read from git repository
+ try:
+ command = ["git", "describe", "--tags", "--abbrev=0"]
+ return check_output(command, text=True, stderr=PIPE).strip()
+ except CalledProcessError:
+ pass
+ raise VersionNotFoundError("Version not found")
+
+def get_lastet_version() -> str:
+ response = get("https://pypi.org/pypi/g4f/json").json()
+ return response["info"]["version"]
+
+def check_pypi_version() -> None:
+ try:
+ version = get_version()
+ latest_version = get_lastet_version()
+ if version != latest_version:
+ print(f'New pypi version: {latest_version} (current: {version}) | pip install -U g4f')
+ except Exception as e:
+ print(f'Failed to check g4f pypi version: {e}') \ No newline at end of file
diff --git a/g4f/errors.py b/g4f/errors.py
new file mode 100644
index 00000000..b554aead
--- /dev/null
+++ b/g4f/errors.py
@@ -0,0 +1,26 @@
+class ProviderNotFoundError(Exception):
+ pass
+
+class ProviderNotWorkingError(Exception):
+ pass
+
+class StreamNotSupportedError(Exception):
+ pass
+
+class AuthenticationRequiredError(Exception):
+ pass
+
+class ModelNotFoundError(Exception):
+ pass
+
+class ModelNotAllowed(Exception):
+ pass
+
+class RetryProviderError(Exception):
+ pass
+
+class RetryNoProviderError(Exception):
+ pass
+
+class VersionNotFoundError(Exception):
+ pass \ No newline at end of file
diff --git a/g4f/gui/client/css/style.css b/g4f/gui/client/css/style.css
index 254a4b15..b6d73650 100644
--- a/g4f/gui/client/css/style.css
+++ b/g4f/gui/client/css/style.css
@@ -301,6 +301,9 @@ body {
font-size: 15px;
line-height: 1.3;
}
+.message .content pre {
+ white-space: pre-wrap;
+}
.message .user i {
position: absolute;
@@ -338,19 +341,15 @@ body {
font-size: 14px;
}
-
-.stop_generating {
+.stop_generating, .regenerate {
position: absolute;
- bottom: 118px;
- /* left: 10px;
- bottom: 125px;
- right: 8px; */
+ bottom: 158px;
left: 50%;
transform: translateX(-50%);
z-index: 1000000;
}
-.stop_generating button {
+.stop_generating button, .regenerate button{
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
background-color: var(--blur-bg);
@@ -380,11 +379,8 @@ body {
}
}
-.stop_generating-hiding button {
+.stop_generating-hidden #cancelButton, .regenerate-hidden #regenerateButton {
animation: hide_popup 0.4s;
-}
-
-.stop_generating-hidden button {
display: none;
}
diff --git a/g4f/gui/client/html/index.html b/g4f/gui/client/html/index.html
index 53c028d7..da7aeefb 100644
--- a/g4f/gui/client/html/index.html
+++ b/g4f/gui/client/html/index.html
@@ -101,6 +101,12 @@
<i class="fa-regular fa-stop"></i>
</button>
</div>
+ <div class="regenerate regenerate-hidden">
+ <button id="regenerateButton">
+ <span>Regenerate</span>
+ <i class="fa-solid fa-rotate"></i>
+ </button>
+ </div>
<div class="box" id="messages">
</div>
<div class="user-input">
diff --git a/g4f/gui/client/js/chat.v1.js b/g4f/gui/client/js/chat.v1.js
index 2a1bdd73..644ff77a 100644
--- a/g4f/gui/client/js/chat.v1.js
+++ b/g4f/gui/client/js/chat.v1.js
@@ -5,15 +5,12 @@ const message_input = document.getElementById(`message-input`);
const box_conversations = document.querySelector(`.top`);
const spinner = box_conversations.querySelector(".spinner");
const stop_generating = document.querySelector(`.stop_generating`);
+const regenerate = document.querySelector(`.regenerate`);
const send_button = document.querySelector(`#send-button`);
let prompt_lock = false;
hljs.addPlugin(new CopyButtonPlugin());
-const format = (text) => {
- return text.replace(/(?:\r\n|\r|\n)/g, "<br>");
-};
-
message_input.addEventListener("blur", () => {
window.scrollTo(0, 0);
});
@@ -22,6 +19,10 @@ message_input.addEventListener("focus", () => {
document.documentElement.scrollTop = document.documentElement.scrollHeight;
});
+const markdown_render = (content) => {
+ return markdown.render(content).replace("<a href=", '<a target="_blank" href=').replace('<code>', '<code class="language-plaintext">')
+}
+
const delete_conversations = async () => {
localStorage.clear();
await new_conversation();
@@ -30,38 +31,25 @@ const delete_conversations = async () => {
const handle_ask = async () => {
message_input.style.height = `80px`;
message_input.focus();
-
- let txtMsgs = [];
- const divTags = document.getElementsByClassName("message");
- for(let i=0;i<divTags.length;i++){
- if(!divTags[i].children[1].classList.contains("welcome-message")){
- if(divTags[i].children[0].className == "assistant"){
- const msg = {
- role: "assistant",
- content: divTags[i].children[1].textContent+" "
- };
- txtMsgs.push(msg);
- }else{
- const msg = {
- role: "user",
- content: divTags[i].children[1].textContent+" "
- };
- txtMsgs.push(msg);
- }
- }
- }
-
window.scrollTo(0, 0);
- let message = message_input.value;
- const msg = {
- role: "user",
- content: message
- };
- txtMsgs.push(msg);
-
+ message = message_input.value
if (message.length > 0) {
- message_input.value = ``;
- await ask_gpt(txtMsgs);
+ message_input.value = '';
+ await add_conversation(window.conversation_id, message);
+ await add_message(window.conversation_id, "user", message);
+ window.token = message_id();
+ message_box.innerHTML += `
+ <div class="message">
+ <div class="user">
+ ${user_image}
+ <i class="fa-regular fa-phone-arrow-up-right"></i>
+ </div>
+ <div class="content" id="user_${token}">
+ ${markdown_render(message)}
+ </div>
+ </div>
+ `;
+ await ask_gpt();
}
};
@@ -74,58 +62,40 @@ const remove_cancel_button = async () => {
}, 300);
};
-const ask_gpt = async (txtMsgs) => {
- try {
- message_input.value = ``;
- message_input.innerHTML = ``;
- message_input.innerText = ``;
+const ask_gpt = async () => {
+ regenerate.classList.add(`regenerate-hidden`);
+ messages = await get_messages(window.conversation_id);
- add_conversation(window.conversation_id, txtMsgs[0].content);
- window.scrollTo(0, 0);
- window.controller = new AbortController();
+ window.scrollTo(0, 0);
+ window.controller = new AbortController();
- jailbreak = document.getElementById("jailbreak");
- provider = document.getElementById("provider");
- model = document.getElementById("model");
- prompt_lock = true;
- window.text = ``;
- window.token = message_id();
+ jailbreak = document.getElementById("jailbreak");
+ provider = document.getElementById("provider");
+ model = document.getElementById("model");
+ prompt_lock = true;
+ window.text = ``;
- stop_generating.classList.remove(`stop_generating-hidden`);
+ stop_generating.classList.remove(`stop_generating-hidden`);
- message_box.innerHTML += `
- <div class="message">
- <div class="user">
- ${user_image}
- <i class="fa-regular fa-phone-arrow-up-right"></i>
- </div>
- <div class="content" id="user_${token}">
- ${format(txtMsgs[txtMsgs.length-1].content)}
- </div>
- </div>
- `;
-
- message_box.scrollTop = message_box.scrollHeight;
- window.scrollTo(0, 0);
- await new Promise((r) => setTimeout(r, 500));
- window.scrollTo(0, 0);
+ message_box.scrollTop = message_box.scrollHeight;
+ window.scrollTo(0, 0);
+ await new Promise((r) => setTimeout(r, 500));
+ window.scrollTo(0, 0);
- message_box.innerHTML += `
- <div class="message">
- <div class="assistant">
- ${gpt_image} <i class="fa-regular fa-phone-arrow-down-left"></i>
- </div>
- <div class="content" id="gpt_${window.token}">
- <div id="cursor"></div>
- </div>
+ message_box.innerHTML += `
+ <div class="message">
+ <div class="assistant">
+ ${gpt_image} <i class="fa-regular fa-phone-arrow-down-left"></i>
</div>
- `;
-
- message_box.scrollTop = message_box.scrollHeight;
- window.scrollTo(0, 0);
- await new Promise((r) => setTimeout(r, 1000));
- window.scrollTo(0, 0);
+ <div class="content" id="gpt_${window.token}">
+ <div id="cursor"></div>
+ </div>
+ </div>
+ `;
+ message_box.scrollTop = message_box.scrollHeight;
+ window.scrollTo(0, 0);
+ try {
const response = await fetch(`/backend-api/v2/conversation`, {
method: `POST`,
signal: window.controller.signal,
@@ -138,21 +108,22 @@ const ask_gpt = async (txtMsgs) => {
action: `_ask`,
model: model.options[model.selectedIndex].value,
jailbreak: jailbreak.options[jailbreak.selectedIndex].value,
+ internet_access: document.getElementById(`switch`).checked,
provider: provider.options[provider.selectedIndex].value,
meta: {
id: window.token,
content: {
- conversation: await get_conversation(window.conversation_id),
- internet_access: document.getElementById(`switch`).checked,
content_type: `text`,
- parts: txtMsgs,
+ parts: messages,
},
},
}),
});
- const reader = response.body.getReader();
+ await new Promise((r) => setTimeout(r, 1000));
+ window.scrollTo(0, 0);
+ const reader = response.body.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
@@ -161,7 +132,7 @@ const ask_gpt = async (txtMsgs) => {
text += chunk;
- document.getElementById(`gpt_${window.token}`).innerHTML = markdown.render(text).replace("<a href=", '<a target="_blank" href=');
+ document.getElementById(`gpt_${window.token}`).innerHTML = markdown_render(text);
document.querySelectorAll(`code`).forEach((el) => {
hljs.highlightElement(el);
});
@@ -171,45 +142,30 @@ const ask_gpt = async (txtMsgs) => {
}
if (text.includes(`G4F_ERROR`)) {
- document.getElementById(`gpt_${window.token}`).innerHTML = "An error occured, please try again, if the problem persists, please reload / refresh cache or use a differnet browser";
+ console.log("response", text);
+ document.getElementById(`gpt_${window.token}`).innerHTML = "An error occured, please try again, if the problem persists, please use a other model or provider";
}
-
- add_message(window.conversation_id, "user", txtMsgs[txtMsgs.length-1].content);
- add_message(window.conversation_id, "assistant", text);
-
- message_box.scrollTop = message_box.scrollHeight;
- await remove_cancel_button();
- prompt_lock = false;
-
- await load_conversations(20, 0);
- window.scrollTo(0, 0);
-
} catch (e) {
- add_message(window.conversation_id, "user", txtMsgs[txtMsgs.length-1].content);
-
- message_box.scrollTop = message_box.scrollHeight;
- await remove_cancel_button();
- prompt_lock = false;
-
- await load_conversations(20, 0);
-
console.log(e);
let cursorDiv = document.getElementById(`cursor`);
if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
if (e.name != `AbortError`) {
- let error_message = `oops ! something went wrong, please try again / reload. [stacktrace in console]`;
-
- document.getElementById(`gpt_${window.token}`).innerHTML = error_message;
- add_message(window.conversation_id, "assistant", error_message);
+ text = `oops ! something went wrong, please try again / reload. [stacktrace in console]`;
+ document.getElementById(`gpt_${window.token}`).innerHTML = text;
} else {
document.getElementById(`gpt_${window.token}`).innerHTML += ` [aborted]`;
- add_message(window.conversation_id, "assistant", text + ` [aborted]`);
+ text += ` [aborted]`
}
-
- window.scrollTo(0, 0);
}
+ add_message(window.conversation_id, "assistant", text);
+ message_box.scrollTop = message_box.scrollHeight;
+ await remove_cancel_button();
+ prompt_lock = false;
+ window.scrollTo(0, 0);
+ await load_conversations(20, 0);
+ regenerate.classList.remove(`regenerate-hidden`);
};
const clear_conversations = async () => {
@@ -280,7 +236,6 @@ const set_conversation = async (conversation_id) => {
};
const new_conversation = async () => {
-
history.pushState({}, null, `/chat/`);
window.conversation_id = uuid();
@@ -291,12 +246,9 @@ const new_conversation = async () => {
};
const load_conversation = async (conversation_id) => {
- let conversation = await JSON.parse(
- localStorage.getItem(`conversation:${conversation_id}`)
- );
- console.log(conversation, conversation_id);
+ let messages = await get_messages(conversation_id);
- for (item of conversation.items) {
+ for (item of messages) {
message_box.innerHTML += `
<div class="message">
<div class=${item.role == "assistant" ? "assistant" : "user"}>
@@ -308,7 +260,7 @@ const load_conversation = async (conversation_id) => {
</div>
<div class="content">
${item.role == "assistant"
- ? markdown.render(item.content).replace("<a href=", '<a target="_blank" href=')
+ ? markdown_render(item.content)
: item.content
}
</div>
@@ -331,6 +283,11 @@ const get_conversation = async (conversation_id) => {
let conversation = await JSON.parse(
localStorage.getItem(`conversation:${conversation_id}`)
);
+ return conversation;
+};
+
+const get_messages = async (conversation_id) => {
+ let conversation = await get_conversation(conversation_id);
return conversation.items;
};
@@ -351,21 +308,32 @@ const add_conversation = async (conversation_id, content) => {
})
);
}
+
+ history.pushState({}, null, `/chat/${conversation_id}`);
};
-const add_message = async (conversation_id, role, content) => {
- before_adding = JSON.parse(
- localStorage.getItem(`conversation:${conversation_id}`)
+const remove_last_message = async (conversation_id) => {
+ const conversation = await get_conversation(conversation_id)
+
+ conversation.items.pop();
+
+ localStorage.setItem(
+ `conversation:${conversation_id}`,
+ JSON.stringify(conversation)
);
+};
- before_adding.items.push({
+const add_message = async (conversation_id, role, content) => {
+ const conversation = await get_conversation(conversation_id);
+
+ conversation.items.push({
role: role,
content: content,
});
localStorage.setItem(
`conversation:${conversation_id}`,
- JSON.stringify(before_adding)
+ JSON.stringify(conversation)
);
};
@@ -404,6 +372,12 @@ document.getElementById(`cancelButton`).addEventListener(`click`, async () => {
console.log(`aborted ${window.conversation_id}`);
});
+document.getElementById(`regenerateButton`).addEventListener(`click`, async () => {
+ await remove_last_message(window.conversation_id);
+ window.token = message_id();
+ await ask_gpt();
+});
+
const uuid = () => {
return `xxxxxxxx-xxxx-4xxx-yxxx-${Date.now().toString(16)}`.replace(
/[xy]/g,
@@ -485,17 +459,16 @@ const say_hello = async () => {
${gpt_image}
<i class="fa-regular fa-phone-arrow-down-left"></i>
</div>
- <div class="content welcome-message">
+ <div class="content">
+ <p class=" welcome-message"></p>
</div>
</div>
`;
- content = ``
to_modify = document.querySelector(`.welcome-message`);
for (token of tokens) {
await new Promise(resolve => setTimeout(resolve, (Math.random() * (100 - 200) + 100)))
- content += token;
- to_modify.innerHTML = markdown.render(content);
+ to_modify.textContent += token;
}
}
@@ -542,14 +515,12 @@ window.onload = async () => {
load_conversations(20, 0);
}, 1);
- if (!window.location.href.endsWith(`#`)) {
- if (/\/chat\/.+/.test(window.location.href)) {
- await load_conversation(window.conversation_id);
- }
+ if (/\/chat\/.+/.test(window.location.href)) {
+ await load_conversation(window.conversation_id);
+ } else {
+ await say_hello()
}
-
- await say_hello()
-
+
message_input.addEventListener(`keydown`, async (evt) => {
if (prompt_lock) return;
if (evt.keyCode === 13 && !evt.shiftKey) {
diff --git a/g4f/gui/run.py b/g4f/gui/run.py
index 0f94814c..7ff769fd 100644
--- a/g4f/gui/run.py
+++ b/g4f/gui/run.py
@@ -6,7 +6,7 @@ from g4f.gui import run_gui
def gui_parser():
parser = ArgumentParser(description="Run the GUI")
parser.add_argument("-host", type=str, default="0.0.0.0", help="hostname")
- parser.add_argument("-port", type=int, default=80, help="port")
+ parser.add_argument("-port", type=int, default=8080, help="port")
parser.add_argument("-debug", action="store_true", help="debug mode")
return parser
diff --git a/g4f/gui/server/backend.py b/g4f/gui/server/backend.py
index b0c55c8a..e4669699 100644
--- a/g4f/gui/server/backend.py
+++ b/g4f/gui/server/backend.py
@@ -1,14 +1,16 @@
import g4f
from g4f.Provider import __providers__
-from flask import request
+import json
+from flask import request, Flask
from .internet import get_search_message
+from g4f import debug
-g4f.debug.logging = True
+debug.logging = True
class Backend_Api:
- def __init__(self, app) -> None:
- self.app = app
+ def __init__(self, app: Flask) -> None:
+ self.app: Flask = app
self.routes = {
'/backend-api/v2/models': {
'function': self.models,
@@ -51,8 +53,8 @@ class Backend_Api:
def version(self):
return {
- "version": g4f.get_version(),
- "lastet_version": g4f.get_lastet_version(),
+ "version": debug.get_version(),
+ "lastet_version": debug.get_lastet_version(),
}
def _gen_title(self):
@@ -61,33 +63,31 @@ class Backend_Api:
}
def _conversation(self):
- try:
- #jailbreak = request.json['jailbreak']
- web_search = request.json['meta']['content']['internet_access']
- messages = request.json['meta']['content']['parts']
- if web_search:
- messages[-1]["content"] = get_search_message(messages[-1]["content"])
- model = request.json.get('model')
- model = model if model else g4f.models.default
- provider = request.json.get('provider').replace('g4f.Provider.', '')
- provider = provider if provider and provider != "Auto" else None
- if provider != None:
- provider = g4f.Provider.ProviderUtils.convert.get(provider)
+ #jailbreak = request.json['jailbreak']
+ messages = request.json['meta']['content']['parts']
+ if request.json['internet_access']:
+ messages[-1]["content"] = get_search_message(messages[-1]["content"])
+ model = request.json.get('model')
+ model = model if model else g4f.models.default
+ provider = request.json.get('provider', '').replace('g4f.Provider.', '')
+ provider = provider if provider and provider != "Auto" else None
+
+ def try_response():
+ try:
+ yield from g4f.ChatCompletion.create(
+ model=model,
+ provider=provider,
+ messages=messages,
+ stream=True,
+ ignore_stream_and_auth=True
+ )
+ except Exception as e:
+ print(e)
+ yield json.dumps({
+ 'code' : 'G4F_ERROR',
+ '_action': '_ask',
+ 'success': False,
+ 'error' : f'{e.__class__.__name__}: {e}'
+ })
- response = g4f.ChatCompletion.create(
- model=model,
- provider=provider,
- messages=messages,
- stream=True,
- ignore_stream_and_auth=True
- )
-
- return self.app.response_class(response, mimetype='text/event-stream')
-
- except Exception as e:
- print(e)
- return {
- 'code' : 'G4F_ERROR',
- '_action': '_ask',
- 'success': False,
- 'error' : f'an error occurred {str(e)}'}, 400
+ return self.app.response_class(try_response(), mimetype='text/event-stream') \ No newline at end of file