mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-05 18:20:35 -08:00
Add WhiteRabbitNeo Provider, Many tiny improvments in the gui
This commit is contained in:
parent
bdc61ca273
commit
926ddfd543
10 changed files with 256 additions and 96 deletions
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
|
@ -1,3 +1,3 @@
|
||||||
ko_fi: xtekky
|
ko_fi: xtekky
|
||||||
github: [xtekky]
|
github: [xtekky, hlohaus]
|
||||||
patreon: xtekky
|
patreon: xtekky
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
url = "https://huggingface.co/chat"
|
url = "https://huggingface.co/chat"
|
||||||
working = True
|
working = True
|
||||||
supports_message_history = True
|
supports_message_history = True
|
||||||
|
models = [
|
||||||
|
"mistralai/Mixtral-8x7B-Instruct-v0.1",
|
||||||
|
"mistralai/Mistral-7B-Instruct-v0.2"
|
||||||
|
]
|
||||||
default_model = "mistralai/Mixtral-8x7B-Instruct-v0.1"
|
default_model = "mistralai/Mixtral-8x7B-Instruct-v0.1"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -29,7 +33,7 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
temperature: float = 0.7,
|
temperature: float = 0.7,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> AsyncResult:
|
) -> AsyncResult:
|
||||||
model = cls.get_model(model)
|
model = cls.get_model(model) if not model else model
|
||||||
headers = {}
|
headers = {}
|
||||||
if api_key is not None:
|
if api_key is not None:
|
||||||
headers["Authorization"] = f"Bearer {api_key}"
|
headers["Authorization"] = f"Bearer {api_key}"
|
||||||
|
|
|
||||||
57
g4f/Provider/WhiteRabbitNeo.py
Normal file
57
g4f/Provider/WhiteRabbitNeo.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from aiohttp import ClientSession, BaseConnector
|
||||||
|
|
||||||
|
from ..typing import AsyncResult, Messages, Cookies
|
||||||
|
from ..requests.raise_for_status import raise_for_status
|
||||||
|
from .base_provider import AsyncGeneratorProvider
|
||||||
|
from .helper import get_cookies, get_connector, get_random_string
|
||||||
|
|
||||||
|
class WhiteRabbitNeo(AsyncGeneratorProvider):
|
||||||
|
url = "https://www.whiterabbitneo.com"
|
||||||
|
working = True
|
||||||
|
supports_message_history = True
|
||||||
|
needs_auth = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def create_async_generator(
|
||||||
|
cls,
|
||||||
|
model: str,
|
||||||
|
messages: Messages,
|
||||||
|
cookies: Cookies = None,
|
||||||
|
connector: BaseConnector = None,
|
||||||
|
proxy: str = None,
|
||||||
|
**kwargs
|
||||||
|
) -> AsyncResult:
|
||||||
|
if cookies is None:
|
||||||
|
cookies = get_cookies("www.whiterabbitneo.com")
|
||||||
|
headers = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0",
|
||||||
|
"Accept": "*/*",
|
||||||
|
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
|
||||||
|
"Accept-Encoding": "gzip, deflate, br",
|
||||||
|
"Referer": f"{cls.url}/",
|
||||||
|
"Content-Type": "text/plain;charset=UTF-8",
|
||||||
|
"Origin": cls.url,
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Sec-Fetch-Dest": "empty",
|
||||||
|
"Sec-Fetch-Mode": "cors",
|
||||||
|
"Sec-Fetch-Site": "same-origin",
|
||||||
|
"TE": "trailers"
|
||||||
|
}
|
||||||
|
async with ClientSession(
|
||||||
|
headers=headers,
|
||||||
|
cookies=cookies,
|
||||||
|
connector=get_connector(connector, proxy)
|
||||||
|
) as session:
|
||||||
|
data = {
|
||||||
|
"messages": messages,
|
||||||
|
"id": get_random_string(6),
|
||||||
|
"enhancePrompt": False,
|
||||||
|
"useFunctions": False
|
||||||
|
}
|
||||||
|
async with session.post(f"{cls.url}/api/chat", json=data, proxy=proxy) as response:
|
||||||
|
await raise_for_status(response)
|
||||||
|
async for chunk in response.content.iter_any():
|
||||||
|
if chunk:
|
||||||
|
yield chunk.decode(errors="ignore")
|
||||||
|
|
@ -37,6 +37,7 @@ from .Local import Local
|
||||||
from .PerplexityLabs import PerplexityLabs
|
from .PerplexityLabs import PerplexityLabs
|
||||||
from .Pi import Pi
|
from .Pi import Pi
|
||||||
from .Vercel import Vercel
|
from .Vercel import Vercel
|
||||||
|
from .WhiteRabbitNeo import WhiteRabbitNeo
|
||||||
from .You import You
|
from .You import You
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,9 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom_buttons">
|
<div class="bottom_buttons">
|
||||||
<button onclick="delete_conversations()">
|
<button onclick="open_settings();">
|
||||||
<i class="fa-regular fa-trash"></i>
|
<i class="fa-solid fa-toolbox"></i>
|
||||||
<span>Clear Conversations</span>
|
<span>Open Settings</span>
|
||||||
</button>
|
|
||||||
<button onclick="save_storage()">
|
|
||||||
<i class="fa-solid fa-download"></i>
|
|
||||||
<a href="" onclick="return false;">Export Conversations</a>
|
|
||||||
</button>
|
</button>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<i class="fa-brands fa-github"></i>
|
<i class="fa-brands fa-github"></i>
|
||||||
|
|
@ -76,28 +72,48 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings">
|
<div class="settings hidden">
|
||||||
<div class="field box">
|
<div class="field">
|
||||||
<label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: access_token</label>
|
<span class="label">Web Access</span>
|
||||||
<textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea>
|
<input type="checkbox" id="switch" />
|
||||||
|
<label for="switch" class="toogle" title="Add the pages of the first 5 search results to the query."></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<span class="label">OpenaiChat: Auto continue</span>
|
<span class="label">Disable History</span>
|
||||||
<input id="OpenaiChat-auto_continue" type="checkbox" name="OpenaiChat[auto_continue]" checked/>
|
<input type="checkbox" id="history" />
|
||||||
<label for="OpenaiChat-auto_continue" class="toogle" title=""></label>
|
<label for="history" class="toogle" title="To improve the reaction time or if you have trouble with large conversations."></label>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<span class="label">Hide System prompt</span>
|
||||||
|
<input type="checkbox" id="hide-systemPrompt" />
|
||||||
|
<label for="hide-systemPrompt" class="toogle" title="For more space on phones"></label>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<span class="label">Auto continue</span>
|
||||||
|
<input id="auto_continue" type="checkbox" name="auto_continue" checked/>
|
||||||
|
<label for="auto_continue" class="toogle" title="Continue long responses in OpenaiChat"></label>
|
||||||
|
</div>
|
||||||
|
<div class="paper">
|
||||||
|
<div class="field box">
|
||||||
|
<label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: api_key</label>
|
||||||
|
<textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="field box">
|
<div class="field box">
|
||||||
<label for="Bing-api_key" class="label" title="">Bing: "_U" cookie</label>
|
<label for="Bing-api_key" class="label" title="">Bing: "_U" cookie</label>
|
||||||
<textarea id="Bing-api_key" name="Bing[api_key]" placeholder="..."></textarea>
|
<textarea id="Bing-api_key" name="Bing[api_key]" placeholder="..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="field box">
|
<div class="field box">
|
||||||
<label for="Gemini-api_key" class="label" title="">Gemini: Auth cookies</label>
|
<label for="Gemini-api_key" class="label" title="">Gemini: Cookies</label>
|
||||||
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="..."></textarea>
|
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="field box">
|
<div class="field box">
|
||||||
<label for="Openai-api_key" class="label" title="">Openai: api_key</label>
|
<label for="Openai-api_key" class="label" title="">Openai: api_key</label>
|
||||||
<textarea id="Openai-api_key" name="Openai[api_key]" placeholder="..."></textarea>
|
<textarea id="Openai-api_key" name="Openai[api_key]" placeholder="..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field box">
|
||||||
|
<label for="Openai-api_key" class="label" title="">Groq: api_key</label>
|
||||||
|
<textarea id="Openai-api_key" name="Groq[api_key]" placeholder="..."></textarea>
|
||||||
|
</div>
|
||||||
<div class="field box">
|
<div class="field box">
|
||||||
<label for="GeminiPro-api_key" class="label" title="">GeminiPro: api_key</label>
|
<label for="GeminiPro-api_key" class="label" title="">GeminiPro: api_key</label>
|
||||||
<textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="..."></textarea>
|
<textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="..."></textarea>
|
||||||
|
|
@ -106,6 +122,17 @@
|
||||||
<label for="HuggingFace-api_key" class="label" title="">HuggingFace: api_key</label>
|
<label for="HuggingFace-api_key" class="label" title="">HuggingFace: api_key</label>
|
||||||
<textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="..."></textarea>
|
<textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bottom_buttons">
|
||||||
|
<button onclick="delete_conversations()">
|
||||||
|
<i class="fa-regular fa-trash"></i>
|
||||||
|
<span>Clear Conversations</span>
|
||||||
|
</button>
|
||||||
|
<button onclick="save_storage()">
|
||||||
|
<i class="fa-solid fa-download"></i>
|
||||||
|
<a href="" onclick="return false;">Export Conversations</a>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="conversation">
|
<div class="conversation">
|
||||||
<textarea id="systemPrompt" class="box" placeholder="System prompt"></textarea>
|
<textarea id="systemPrompt" class="box" placeholder="System prompt"></textarea>
|
||||||
|
|
@ -161,43 +188,15 @@
|
||||||
<select name="model2" id="model2" class="hidden"></select>
|
<select name="model2" id="model2" class="hidden"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<select name="jailbreak" id="jailbreak" style="display: none;">
|
<select name="provider" id="provider">
|
||||||
<option value="default" selected>Set Jailbreak</option>
|
<option value="">Provider: Auto</option>
|
||||||
<option value="gpt-math-1.0">math 1.0</option>
|
<option value="Bing">Bing</option>
|
||||||
<option value="gpt-dude-1.0">dude 1.0</option>
|
<option value="OpenaiChat">OpenaiChat</option>
|
||||||
<option value="gpt-dan-1.0">dan 1.0</option>
|
<option value="Gemini">Gemini</option>
|
||||||
<option value="gpt-dan-2.0">dan 2.0</option>
|
<option value="Liaobots">Liaobots</option>
|
||||||
<option value="gpt-dev-2.0">dev 2.0</option>
|
<option value="You">You</option>
|
||||||
<option value="gpt-evil-1.0">evil 1.0</option>
|
<option value="">----</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="field">
|
|
||||||
<select name="provider" id="provider">
|
|
||||||
<option value="">Provider: Auto</option>
|
|
||||||
<option value="Bing">Bing</option>
|
|
||||||
<option value="OpenaiChat">OpenaiChat</option>
|
|
||||||
<option value="Gemini">Gemini</option>
|
|
||||||
<option value="Liaobots">Liaobots</option>
|
|
||||||
<option value="You">You</option>
|
|
||||||
<option value="">----</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<input type="checkbox" id="switch" />
|
|
||||||
<label for="switch" title="Add the pages of the first 5 search results to the query."></label>
|
|
||||||
<span class="about">Web Access</span>
|
|
||||||
</div>
|
|
||||||
<!--
|
|
||||||
<div class="field">
|
|
||||||
<input type="checkbox" id="patch" />
|
|
||||||
<label for="patch" title="Enable create images with Bing."></label>
|
|
||||||
<span class="about">Image Generator</span>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div class="field">
|
|
||||||
<input type="checkbox" id="history" />
|
|
||||||
<label for="history" title="To improve the reaction time or if you have trouble with large conversations."></label>
|
|
||||||
<span class="about">Disable History</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
padding: var(--section-gap);
|
padding: 10px;
|
||||||
background: var(--colour-1);
|
background: var(--colour-1);
|
||||||
color: var(--colour-3);
|
color: var(--colour-3);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
@ -92,7 +92,7 @@ body {
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--section-gap);
|
gap: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversations {
|
.conversations {
|
||||||
max-width: 260px;
|
max-width: 280px;
|
||||||
padding: var(--section-gap);
|
padding: var(--section-gap);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
@ -183,8 +183,8 @@ body {
|
||||||
.conversations {
|
.conversations {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--inner-gap);
|
gap: 10px;
|
||||||
padding: var(--inner-gap);
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversations .title {
|
.conversations .title {
|
||||||
|
|
@ -207,7 +207,12 @@ body {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversations .convo .fa-trash {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversations .convo .choise {
|
.conversations .convo .choise {
|
||||||
|
|
@ -216,7 +221,7 @@ body {
|
||||||
background-color: var(--blur-bg);
|
background-color: var(--blur-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversations i {
|
.conversations i, .bottom_buttons i {
|
||||||
color: var(--conversations);
|
color: var(--conversations);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
@ -229,6 +234,10 @@ body {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.convo-title .datetime {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
@ -351,10 +360,23 @@ body {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message .count .fa-clipboard {
|
||||||
|
z-index: 1000;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.message .user .fa-xmark {
|
.message .user .fa-xmark {
|
||||||
color: var(--colour-1);
|
color: var(--colour-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message .count .fa-clipboard {
|
||||||
|
color: var(--colour-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message .count .fa-clipboard.clicked {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
.message .assistant:hover .fa-xmark,
|
.message .assistant:hover .fa-xmark,
|
||||||
.message .user:hover .fa-xmark {
|
.message .user:hover .fa-xmark {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -556,6 +578,16 @@ label[for="camera"] {
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings .bottom_buttons {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings .bottom_buttons button {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 210px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.buttons input:checked+label:after {
|
.buttons input:checked+label:after {
|
||||||
left: calc(100% - 5px - 20px);
|
left: calc(100% - 5px - 20px);
|
||||||
}
|
}
|
||||||
|
|
@ -565,6 +597,7 @@ label[for="camera"] {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field {
|
.field {
|
||||||
|
|
@ -635,6 +668,7 @@ select {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom_buttons button {
|
.bottom_buttons button {
|
||||||
|
|
@ -1026,7 +1060,14 @@ a:-webkit-any-link {
|
||||||
|
|
||||||
.settings {
|
.settings {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: none;
|
min-width: 700px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings .paper {
|
||||||
|
overflow: auto;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings .field {
|
.settings .field {
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ const providerSelect = document.getElementById("provider");
|
||||||
const modelSelect = document.getElementById("model");
|
const modelSelect = document.getElementById("model");
|
||||||
const modelProvider = document.getElementById("model2");
|
const modelProvider = document.getElementById("model2");
|
||||||
const systemPrompt = document.getElementById("systemPrompt")
|
const systemPrompt = document.getElementById("systemPrompt")
|
||||||
const jailbreak = document.getElementById("jailbreak");
|
const settings = document.querySelector(".settings")
|
||||||
|
|
||||||
let prompt_lock = false;
|
let prompt_lock = false;
|
||||||
|
|
||||||
let content, content_inner, content_count = null;
|
let content, content_inner, content_count = null;
|
||||||
|
|
||||||
const options = ["switch", "model", "model2", "jailbreak", "patch", "provider", "history"];
|
const optionElements = document.querySelectorAll(".settings input, .settings textarea, #model, #model2, #provider")
|
||||||
|
|
||||||
messageInput.addEventListener("blur", () => {
|
messageInput.addEventListener("blur", () => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
|
|
@ -63,7 +63,7 @@ const highlight = (container) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const register_remove_message = async () => {
|
const register_message_buttons = async () => {
|
||||||
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
|
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
|
||||||
if (!("click" in el.dataset)) {
|
if (!("click" in el.dataset)) {
|
||||||
el.dataset.click = "true";
|
el.dataset.click = "true";
|
||||||
|
|
@ -77,6 +77,18 @@ const register_remove_message = async () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
document.querySelectorAll(".message .fa-clipboard").forEach(async (el) => {
|
||||||
|
if (!("click" in el.dataset)) {
|
||||||
|
el.dataset.click = "true";
|
||||||
|
el.addEventListener("click", async () => {
|
||||||
|
const message_el = el.parentElement.parentElement;
|
||||||
|
const copyText = await get_message(window.conversation_id, message_el.dataset.index);
|
||||||
|
navigator.clipboard.writeText(copyText);
|
||||||
|
el.classList.add("clicked");
|
||||||
|
setTimeout(() => el.classList.remove("clicked"), 1000);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const delete_conversations = async () => {
|
const delete_conversations = async () => {
|
||||||
|
|
@ -132,7 +144,7 @@ const handle_ask = async () => {
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="count">${count_words_and_tokens(message, get_selected_model())}</div>
|
<div class="count">${count_words_and_tokens(message, get_selected_model())} <i class="fa-regular fa-clipboard"></i></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
@ -305,15 +317,22 @@ const ask_gpt = async () => {
|
||||||
try {
|
try {
|
||||||
const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput;
|
const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput;
|
||||||
const file = input && input.files.length > 0 ? input.files[0] : null;
|
const file = input && input.files.length > 0 ? input.files[0] : null;
|
||||||
|
const provider = providerSelect.options[providerSelect.selectedIndex].value;
|
||||||
|
const auto_continue = document.getElementById("auto_continue")?.checked;
|
||||||
|
if (file && !provider)
|
||||||
|
provider = "Bing";
|
||||||
|
let api_key = null;
|
||||||
|
if (provider)
|
||||||
|
api_key = document.getElementById(`${provider}-api_key`)?.value;
|
||||||
await api("conversation", {
|
await api("conversation", {
|
||||||
id: window.token,
|
id: window.token,
|
||||||
conversation_id: window.conversation_id,
|
conversation_id: window.conversation_id,
|
||||||
model: get_selected_model(),
|
model: get_selected_model(),
|
||||||
jailbreak: jailbreak?.options[jailbreak.selectedIndex].value,
|
|
||||||
web_search: document.getElementById("switch").checked,
|
web_search: document.getElementById("switch").checked,
|
||||||
provider: providerSelect.options[providerSelect.selectedIndex].value,
|
provider: provider,
|
||||||
patch_provider: document.getElementById("patch")?.checked,
|
messages: messages,
|
||||||
messages: messages
|
auto_continue: auto_continue,
|
||||||
|
api_key: api_key
|
||||||
}, file);
|
}, file);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
html = markdown_render(text);
|
html = markdown_render(text);
|
||||||
|
|
@ -341,7 +360,7 @@ const ask_gpt = async () => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
message_box.scrollTop = message_box.scrollHeight;
|
message_box.scrollTop = message_box.scrollHeight;
|
||||||
await remove_cancel_button();
|
await remove_cancel_button();
|
||||||
await register_remove_message();
|
await register_message_buttons();
|
||||||
prompt_lock = false;
|
prompt_lock = false;
|
||||||
await load_conversations();
|
await load_conversations();
|
||||||
regenerate.classList.remove("regenerate-hidden");
|
regenerate.classList.remove("regenerate-hidden");
|
||||||
|
|
@ -459,7 +478,7 @@ const load_conversation = async (conversation_id, scroll=true) => {
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${provider}
|
${provider}
|
||||||
<div class="content_inner">${markdown_render(item.content)}</div>
|
<div class="content_inner">${markdown_render(item.content)}</div>
|
||||||
<div class="count">${count_words_and_tokens(item.content, next_provider?.model)}</div>
|
<div class="count">${count_words_and_tokens(item.content, next_provider?.model)} <i class="fa-regular fa-clipboard"></i></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
@ -475,8 +494,9 @@ const load_conversation = async (conversation_id, scroll=true) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
message_box.innerHTML = elements;
|
message_box.innerHTML = elements;
|
||||||
register_remove_message();
|
register_message_buttons();
|
||||||
highlight(message_box);
|
highlight(message_box);
|
||||||
|
regenerate.classList.remove("regenerate-hidden");
|
||||||
|
|
||||||
if (scroll) {
|
if (scroll) {
|
||||||
message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
|
message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
|
||||||
|
|
@ -495,6 +515,7 @@ async function get_conversation(conversation_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function save_conversation(conversation_id, conversation) {
|
async function save_conversation(conversation_id, conversation) {
|
||||||
|
conversation.updated = Date.now();
|
||||||
appStorage.setItem(
|
appStorage.setItem(
|
||||||
`conversation:${conversation_id}`,
|
`conversation:${conversation_id}`,
|
||||||
JSON.stringify(conversation)
|
JSON.stringify(conversation)
|
||||||
|
|
@ -517,6 +538,7 @@ async function add_conversation(conversation_id, content) {
|
||||||
await save_conversation(conversation_id, {
|
await save_conversation(conversation_id, {
|
||||||
id: conversation_id,
|
id: conversation_id,
|
||||||
title: title,
|
title: title,
|
||||||
|
added: Date.now(),
|
||||||
system: systemPrompt?.value,
|
system: systemPrompt?.value,
|
||||||
items: [],
|
items: [],
|
||||||
});
|
});
|
||||||
|
|
@ -563,6 +585,11 @@ const remove_message = async (conversation_id, index) => {
|
||||||
await save_conversation(conversation_id, conversation);
|
await save_conversation(conversation_id, conversation);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const get_message = async (conversation_id, index) => {
|
||||||
|
const conversation = await get_conversation(conversation_id);
|
||||||
|
return conversation.items[index]["content"];
|
||||||
|
};
|
||||||
|
|
||||||
const add_message = async (conversation_id, role, content, provider) => {
|
const add_message = async (conversation_id, role, content, provider) => {
|
||||||
const conversation = await get_conversation(conversation_id);
|
const conversation = await get_conversation(conversation_id);
|
||||||
conversation.items.push({
|
conversation.items.push({
|
||||||
|
|
@ -586,11 +613,17 @@ const load_conversations = async () => {
|
||||||
await clear_conversations();
|
await clear_conversations();
|
||||||
|
|
||||||
for (conversation of conversations) {
|
for (conversation of conversations) {
|
||||||
|
let updated = "";
|
||||||
|
if (conversation.updated) {
|
||||||
|
const date = new Date(conversation.updated);
|
||||||
|
updated = date.toLocaleString('en-GB', {dateStyle: 'short', timeStyle: 'short', monthStyle: 'short'});
|
||||||
|
updated = updated.replace("/" + date.getFullYear(), "")
|
||||||
|
}
|
||||||
box_conversations.innerHTML += `
|
box_conversations.innerHTML += `
|
||||||
<div class="convo" id="convo-${conversation.id}">
|
<div class="convo" id="convo-${conversation.id}">
|
||||||
<div class="left" onclick="set_conversation('${conversation.id}')">
|
<div class="left" onclick="set_conversation('${conversation.id}')">
|
||||||
<i class="fa-regular fa-comments"></i>
|
<i class="fa-regular fa-comments"></i>
|
||||||
<span class="convo-title">${conversation.title}</span>
|
<span class="convo-title"><span class="datetime">${updated}</span> ${conversation.title}</span>
|
||||||
</div>
|
</div>
|
||||||
<i onclick="show_option('${conversation.id}')" class="fa-regular fa-trash" id="conv-${conversation.id}"></i>
|
<i onclick="show_option('${conversation.id}')" class="fa-regular fa-trash" id="conv-${conversation.id}"></i>
|
||||||
<div id="cho-${conversation.id}" class="choise" style="display:none;">
|
<div id="cho-${conversation.id}" class="choise" style="display:none;">
|
||||||
|
|
@ -642,7 +675,8 @@ const message_id = () => {
|
||||||
async function hide_sidebar() {
|
async function hide_sidebar() {
|
||||||
sidebar.classList.remove("shown");
|
sidebar.classList.remove("shown");
|
||||||
sidebar_button.classList.remove("rotated");
|
sidebar_button.classList.remove("rotated");
|
||||||
if (window.location.pathname == "/menu/") {
|
settings.classList.add("hidden");
|
||||||
|
if (window.location.pathname == "/menu/" || window.location.pathname == "/settings/") {
|
||||||
history.back();
|
history.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -650,6 +684,7 @@ async function hide_sidebar() {
|
||||||
window.addEventListener('popstate', hide_sidebar, false);
|
window.addEventListener('popstate', hide_sidebar, false);
|
||||||
|
|
||||||
sidebar_button.addEventListener("click", (event) => {
|
sidebar_button.addEventListener("click", (event) => {
|
||||||
|
settings.classList.add("hidden");
|
||||||
if (sidebar.classList.contains("shown")) {
|
if (sidebar.classList.contains("shown")) {
|
||||||
hide_sidebar();
|
hide_sidebar();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -660,19 +695,25 @@ sidebar_button.addEventListener("click", (event) => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function open_settings() {
|
||||||
|
if (settings.classList.contains("hidden")) {
|
||||||
|
sidebar.classList.remove("shown");
|
||||||
|
settings.classList.remove("hidden");
|
||||||
|
history.pushState({}, null, "/settings/");
|
||||||
|
} else {
|
||||||
|
settings.classList.add("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const register_settings_storage = async () => {
|
const register_settings_storage = async () => {
|
||||||
options.forEach((id) => {
|
optionElements.forEach((element) => {
|
||||||
element = document.getElementById(id);
|
|
||||||
if (!element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
element.addEventListener('change', async (event) => {
|
element.addEventListener('change', async (event) => {
|
||||||
switch (event.target.type) {
|
switch (event.target.type) {
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
appStorage.setItem(id, event.target.checked);
|
appStorage.setItem(element.id, event.target.checked);
|
||||||
break;
|
break;
|
||||||
case "select-one":
|
case "select-one":
|
||||||
appStorage.setItem(id, event.target.selectedIndex);
|
appStorage.setItem(element.id, event.target.selectedIndex);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn("Unresolved element type");
|
console.warn("Unresolved element type");
|
||||||
|
|
@ -682,9 +723,8 @@ const register_settings_storage = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const load_settings_storage = async () => {
|
const load_settings_storage = async () => {
|
||||||
options.forEach((id) => {
|
optionElements.forEach((element) => {
|
||||||
element = document.getElementById(id);
|
if (!(value = appStorage.getItem(element.id))) {
|
||||||
if (!element || !(value = appStorage.getItem(id))) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
@ -859,6 +899,18 @@ async function on_api() {
|
||||||
|
|
||||||
await load_provider_models(appStorage.getItem("provider"));
|
await load_provider_models(appStorage.getItem("provider"));
|
||||||
await load_settings_storage()
|
await load_settings_storage()
|
||||||
|
|
||||||
|
const hide_systemPrompt = document.getElementById("hide-systemPrompt")
|
||||||
|
if (hide_systemPrompt.checked) {
|
||||||
|
systemPrompt.classList.add("hidden");
|
||||||
|
}
|
||||||
|
hide_systemPrompt.addEventListener('change', async (event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
systemPrompt.classList.add("hidden");
|
||||||
|
} else {
|
||||||
|
systemPrompt.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load_version() {
|
async function load_version() {
|
||||||
|
|
@ -875,7 +927,7 @@ async function load_version() {
|
||||||
}
|
}
|
||||||
document.getElementById("version_text").innerHTML = text
|
document.getElementById("version_text").innerHTML = text
|
||||||
}
|
}
|
||||||
setTimeout(load_version, 5000);
|
setTimeout(load_version, 2000);
|
||||||
|
|
||||||
for (const el of [imageInput, cameraInput]) {
|
for (const el of [imageInput, cameraInput]) {
|
||||||
el.addEventListener('click', async () => {
|
el.addEventListener('click', async () => {
|
||||||
|
|
@ -1035,7 +1087,7 @@ function save_storage() {
|
||||||
let item = appStorage.getItem(key);
|
let item = appStorage.getItem(key);
|
||||||
if (key.startsWith("conversation:")) {
|
if (key.startsWith("conversation:")) {
|
||||||
data[key] = JSON.parse(item);
|
data[key] = JSON.parse(item);
|
||||||
} else {
|
} else if (!key.includes("api_key")) {
|
||||||
data["options"][key] = item;
|
data["options"][key] = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,12 @@ class Api():
|
||||||
Returns:
|
Returns:
|
||||||
dict: Arguments prepared for chat completion.
|
dict: Arguments prepared for chat completion.
|
||||||
"""
|
"""
|
||||||
provider = json_data.get('provider', None)
|
model = json_data.get('model') or models.default
|
||||||
if "image" in kwargs and provider is None:
|
provider = json_data.get('provider')
|
||||||
provider = "Bing"
|
|
||||||
if provider == 'OpenaiChat':
|
|
||||||
kwargs['auto_continue'] = True
|
|
||||||
|
|
||||||
messages = json_data['messages']
|
messages = json_data['messages']
|
||||||
|
api_key = json_data.get("api_key")
|
||||||
|
if api_key is not None:
|
||||||
|
kwargs["api_key"] = api_key
|
||||||
if json_data.get('web_search'):
|
if json_data.get('web_search'):
|
||||||
if provider == "Bing":
|
if provider == "Bing":
|
||||||
kwargs['web_search'] = True
|
kwargs['web_search'] = True
|
||||||
|
|
@ -98,8 +97,6 @@ class Api():
|
||||||
if conversation_id and provider in conversations and conversation_id in conversations[provider]:
|
if conversation_id and provider in conversations and conversation_id in conversations[provider]:
|
||||||
kwargs["conversation"] = conversations[provider][conversation_id]
|
kwargs["conversation"] = conversations[provider][conversation_id]
|
||||||
|
|
||||||
model = json_data.get('model') or models.default
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"model": model,
|
"model": model,
|
||||||
"provider": provider,
|
"provider": provider,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ from flask import render_template, redirect
|
||||||
class Website:
|
class Website:
|
||||||
def __init__(self, app) -> None:
|
def __init__(self, app) -> None:
|
||||||
self.app = app
|
self.app = app
|
||||||
|
def redirect_home():
|
||||||
|
return redirect('/chat')
|
||||||
self.routes = {
|
self.routes = {
|
||||||
'/': {
|
'/': {
|
||||||
'function': lambda: redirect('/chat'),
|
'function': redirect_home,
|
||||||
'methods': ['GET', 'POST']
|
'methods': ['GET', 'POST']
|
||||||
},
|
},
|
||||||
'/chat/': {
|
'/chat/': {
|
||||||
|
|
@ -17,6 +19,14 @@ class Website:
|
||||||
'function': self._chat,
|
'function': self._chat,
|
||||||
'methods': ['GET', 'POST']
|
'methods': ['GET', 'POST']
|
||||||
},
|
},
|
||||||
|
'/menu/': {
|
||||||
|
'function': redirect_home,
|
||||||
|
'methods': ['GET', 'POST']
|
||||||
|
},
|
||||||
|
'/settings/': {
|
||||||
|
'function': redirect_home,
|
||||||
|
'methods': ['GET', 'POST']
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def _chat(self, conversation_id):
|
def _chat(self, conversation_id):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue