Some small fixes

This commit is contained in:
Heiner Lohaus 2024-04-10 14:23:30 +02:00
parent 00951eb791
commit 65bcc8ae8b
9 changed files with 137 additions and 81 deletions

3
.gitignore vendored
View File

@ -55,3 +55,6 @@ local.py
image.py
.buildozer
hardir
node_modules
models
projects/windows/g4f

View File

@ -10,8 +10,6 @@ from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .helper import format_prompt
from ..image import ImageResponse, to_bytes, is_accepted_format
from ..requests import StreamSession, FormData, raise_for_status
from ..errors import MissingRequirementsError
from .you.har_file import get_dfp_telemetry_id
class You(AsyncGeneratorProvider, ProviderModelMixin):

View File

@ -646,6 +646,21 @@ select {
width: 160px;
}
#systemPrompt, .settings textarea {
font-size: 15px;
width: 100%;
color: var(--colour-3);
min-height: 50px;
height: 59px;
outline: none;
padding: var(--inner-gap) var(--section-gap);
resize: vertical;
}
#systemPrompt {
padding-left: 35px;
}
@media only screen and (min-width: 40em) {
select {
width: 200px;
@ -836,6 +851,10 @@ ul {
.mobile-sidebar {
display: flex !important;
}
#systemPrompt {
padding-left: 48px;
}
}
.shown {
@ -1064,22 +1083,11 @@ a:-webkit-any-link {
border: 1px solid #e4d4ffc9;
}
#systemPrompt, .settings textarea {
font-size: 15px;
width: 100%;
color: var(--colour-3);
min-height: 50px;
height: 59px;
outline: none;
padding: var(--inner-gap) var(--section-gap);
resize: vertical;
}
.settings textarea {
height: 51px;
}
.settings {
.settings, .images {
width: 100%;
display: flex;
flex-direction: column;

View File

@ -10,13 +10,14 @@ const sendButton = document.getElementById("send-button");
const imageInput = document.getElementById("image");
const cameraInput = document.getElementById("camera");
const fileInput = document.getElementById("file");
const microLabel = document.querySelector(".micro-label")
const inputCount = document.getElementById("input-count")
const microLabel = document.querySelector(".micro-label");
const inputCount = document.getElementById("input-count");
const providerSelect = document.getElementById("provider");
const modelSelect = document.getElementById("model");
const modelProvider = document.getElementById("model2");
const systemPrompt = document.getElementById("systemPrompt")
const settings = document.querySelector(".settings")
const systemPrompt = document.getElementById("systemPrompt");
const settings = document.querySelector(".settings");
const album = document.querySelector(".images");
let prompt_lock = false;
@ -49,6 +50,12 @@ const markdown_render = (content) => {
.replaceAll('<code>', '<code class="language-plaintext">')
}
function filter_message(text) {
return text.replaceAll(
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm, ""
)
}
hljs.addPlugin(new CopyButtonPlugin());
let typesetPromise = Promise.resolve();
const highlight = (container) => {
@ -64,7 +71,6 @@ const highlight = (container) => {
);
}
let stopped = false;
const register_message_buttons = async () => {
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
if (!("click" in el.dataset)) {
@ -95,69 +101,76 @@ const register_message_buttons = async () => {
if (!("click" in el.dataset)) {
el.dataset.click = "true";
el.addEventListener("click", async () => {
if ("active" in el.classList || window.doSpeech) {
el.classList.add("blink")
stopped = true;
return;
let playlist = [];
function play_next() {
const next = playlist.shift();
if (next)
next.play();
}
if (stopped) {
if (el.dataset.stopped) {
el.classList.remove("blink")
stopped = false;
delete el.dataset.stopped;
return;
}
if (el.dataset.running) {
el.dataset.stopped = true;
el.classList.add("blink")
playlist = [];
return;
}
el.dataset.running = true;
el.classList.add("blink")
el.classList.add("active")
const message_el = el.parentElement.parentElement.parentElement;
const content_el = el.parentElement.parentElement;
const message_el = content_el.parentElement;
let speechText = await get_message(window.conversation_id, message_el.dataset.index);
speechText = speechText.replaceAll(/([^0-9])\./gm, "$1.;");
speechText = speechText.replaceAll("?", "?;");
speechText = speechText.replaceAll(/\[(.+)\]\(.+\)/gm, "($1)");
speechText = speechText.replaceAll("`", "").replaceAll("#", "")
speechText = speechText.replaceAll(
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
""
)
speechText = speechText.replaceAll(/```[a-z]+/gm, "");
speechText = filter_message(speechText.replaceAll("`", "").replaceAll("#", ""))
const lines = speechText.trim().split(/\n|;/).filter(v => v.trim());
const lines = speechText.trim().split(/\n|\.|;/);
let ended = true;
window.onSpeechResponse = (url) => {
if (!el.dataset.stopped) {
el.classList.remove("blink")
}
if (url) {
var sound = document.createElement('audio');
sound.controls = 'controls';
sound.src = url;
sound.type = 'audio/wav';
sound.onended = function() {
ended = true;
el.dataset.do_play = true;
setTimeout(play_next, 1000);
};
sound.onplay = function() {
ended = false;
delete el.dataset.do_play;
};
var container = document.createElement('div');
container.classList.add("audio");
container.appendChild(sound);
content_el.appendChild(container);
if (ended && !stopped) {
sound.play();
if (!el.dataset.stopped) {
playlist.push(sound);
if (el.dataset.do_play) {
play_next();
}
}
if (lines.length < 1 || stopped) {
}
let line = lines.length > 0 ? lines.shift() : null;
if (line && !el.dataset.stopped) {
handleGenerateSpeech(line);
} else {
el.classList.remove("active");
return;
el.classList.remove("blink");
delete el.dataset.running;
}
while (lines.length > 0) {
}
el.dataset.do_play = true;
let line = lines.shift();
var reg = new RegExp('^[0-9]$');
if (line && !reg.test(line)) {
return handleGenerateSpeech(line);
}
}
if (!line) {
el.classList.remove("active")
}
}
let line = lines.shift();
return handleGenerateSpeech(line);
handleGenerateSpeech(line);
});
}
});
@ -399,7 +412,7 @@ const ask_gpt = async () => {
provider = "Bing";
let api_key = null;
if (provider)
api_key = document.getElementById(`${provider}-api_key`)?.value;
api_key = document.getElementById(`${provider}-api_key`)?.value || null;
await api("conversation", {
id: window.token,
conversation_id: window.conversation_id,
@ -717,7 +730,7 @@ const load_conversations = async () => {
</div>
`;
});
box_conversations.innerHTML = html;
box_conversations.innerHTML += html;
};
document.getElementById("cancelButton").addEventListener("click", async () => {
@ -790,6 +803,17 @@ function open_settings() {
}
}
function open_album() {
if (album.classList.contains("hidden")) {
sidebar.classList.remove("shown");
settings.classList.add("hidden");
album.classList.remove("hidden");
history.pushState({}, null, "/images/");
} else {
album.classList.add("hidden");
}
}
const register_settings_storage = async () => {
optionElements.forEach((element) => {
if (element.type == "textarea") {
@ -1232,12 +1256,12 @@ if (SpeechRecognition) {
}
let startValue;
let lastValue;
let timeoutHandle;
let lastDebounceTranscript;
recognition.onstart = function() {
microLabel.classList.add("recognition");
startValue = messageInput.value;
lastValue = "";
lastDebounceTranscript = "";
timeoutHandle = window.setTimeout(may_stop, 8000);
};
recognition.onend = function() {
@ -1248,22 +1272,27 @@ if (SpeechRecognition) {
return;
}
window.clearTimeout(timeoutHandle);
let newText;
Array.from(event.results).forEach((result) => {
newText = result[0].transcript;
if (newText && newText != lastValue) {
messageInput.value = `${startValue ? startValue+"\n" : ""}${newText.trim()}`;
if (result.isFinal) {
lastValue = newText;
let result = event.results[event.resultIndex];
let isFinal = result.isFinal && (result[0].confidence > 0);
let transcript = result[0].transcript;
if (isFinal) {
if(transcript == lastDebounceTranscript) {
return;
}
lastDebounceTranscript = transcript;
}
if (transcript) {
messageInput.value = `${startValue ? startValue+"\n" : ""}${transcript.trim()}`;
if (isFinal) {
startValue = messageInput.value;
messageInput.focus();
}
messageInput.style.height = messageInput.scrollHeight + "px";
messageInput.scrollTop = messageInput.scrollHeight;
}
});
window.clearTimeout(timeoutHandle);
timeoutHandle = window.setTimeout(may_stop, newText ? 8000 : 5000);
timeoutHandle = window.setTimeout(may_stop, transcript ? 8000 : 5000);
};
microLabel.addEventListener("click", () => {

View File

@ -78,6 +78,7 @@ class AbstractProvider(BaseProvider):
timeout=kwargs.get("timeout")
)
@classmethod
def get_parameters(cls) -> dict:
return signature(
cls.create_async_generator if issubclass(cls, AsyncGeneratorProvider) else
@ -107,7 +108,9 @@ class AbstractProvider(BaseProvider):
continue
args += f"\n {name}"
args += f": {get_type_name(param.annotation)}" if param.annotation is not Parameter.empty else ""
args += f' = "{param.default}"' if param.default == "" else f" = {param.default}" if param.default is not Parameter.empty else ""
default_value = f'"{param.default}"' if isinstance(param.default, str) else param.default
args += f" = {default_value}" if param.default is not Parameter.empty else ""
args += ","
return f"g4f.Provider.{cls.__name__} supports: ({args}\n)"

View File

@ -33,9 +33,14 @@ class StreamSession(ClientSession):
**DEFAULT_HEADERS,
**headers
}
connect = None
if isinstance(timeout, tuple):
connect, timeout = timeout;
if timeout is not None:
timeout = ClientTimeout(timeout, connect)
super().__init__(
**kwargs,
timeout=ClientTimeout(timeout) if timeout else None,
timeout=timeout,
response_class=StreamResponse,
connector=get_connector(connector, proxies.get("all", proxies.get("https"))),
headers=headers

View File

@ -1,6 +1,11 @@
from __future__ import annotations
from curl_cffi.requests import AsyncSession, Response, CurlMime
from curl_cffi.requests import AsyncSession, Response
try:
from curl_cffi.requests import CurlMime
has_curl_mime = True
except ImportError:
has_curl_mime = False
from typing import AsyncGenerator, Any
from functools import partialmethod
import json
@ -78,6 +83,11 @@ class StreamSession(AsyncSession):
patch = partialmethod(request, "PATCH")
delete = partialmethod(request, "DELETE")
if has_curl_mime:
class FormData(CurlMime):
def add_field(self, name, data=None, content_type: str = None, filename: str = None) -> None:
self.addpart(name, content_type=content_type, filename=filename, data=data)
else:
class FormData():
def __init__(self) -> None:
raise RuntimeError("CurlMimi in curl_cffi is missing | pip install -U g4f[curl_cffi]")

View File

@ -12,8 +12,5 @@
"pack": "^2.2.0",
"web": "^0.0.2",
"webpack-cli": "^5.1.4"
},
"bundleDependencies": [
"@xenova/transformers"
]
}
}

View File

@ -74,6 +74,9 @@ EXTRA_REQUIRE = {
],
"local": [
"gpt4all"
],
"curl_cffi": [
"curl_cffi>=0.6.2",
]
}