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

XFEstudio/gpt4free

Some small fixes

65bcc8ae
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

9 个文件 +138 -82
Modified .gitignore +4 -1
@@ -54,4 +54,7 @@ local.py
54 54 *.gguf
55 55 image.py
56 56 .buildozer
57 hardir
57 hardir
58 node_modules
59 models
60 projects/windows/g4f
Modified g4f/Provider/You.py +0 -2
@@ -10,8 +10,6 @@ from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
10 10 from .helper import format_prompt
11 11 from ..image import ImageResponse, to_bytes, is_accepted_format
12 12 from ..requests import StreamSession, FormData, raise_for_status
13 from ..errors import MissingRequirementsError
14
15 13 from .you.har_file import get_dfp_telemetry_id
16 14
17 15 class You(AsyncGeneratorProvider, ProviderModelMixin):
Modified g4f/gui/client/static/css/style.css +20 -12
@@ -646,6 +646,21 @@ select {
646 646 width: 160px;
647 647 }
648 648
649 #systemPrompt, .settings textarea {
650 font-size: 15px;
651 width: 100%;
652 color: var(--colour-3);
653 min-height: 50px;
654 height: 59px;
655 outline: none;
656 padding: var(--inner-gap) var(--section-gap);
657 resize: vertical;
658 }
659
660 #systemPrompt {
661 padding-left: 35px;
662 }
663
649 664 @media only screen and (min-width: 40em) {
650 665 select {
651 666 width: 200px;
@@ -836,6 +851,10 @@ ul {
836 851 .mobile-sidebar {
837 852 display: flex !important;
838 853 }
854
855 #systemPrompt {
856 padding-left: 48px;
857 }
839 858 }
840 859
841 860 .shown {
@@ -1064,22 +1083,11 @@ a:-webkit-any-link {
1064 1083 border: 1px solid #e4d4ffc9;
1065 1084 }
1066 1085
1067 #systemPrompt, .settings textarea {
1068 font-size: 15px;
1069 width: 100%;
1070 color: var(--colour-3);
1071 min-height: 50px;
1072 height: 59px;
1073 outline: none;
1074 padding: var(--inner-gap) var(--section-gap);
1075 resize: vertical;
1076 }
1077
1078 1086 .settings textarea {
1079 1087 height: 51px;
1080 1088 }
1081 1089
1082 .settings {
1090 .settings, .images {
1083 1091 width: 100%;
1084 1092 display: flex;
1085 1093 flex-direction: column;
Modified g4f/gui/client/static/js/chat.v1.js +86 -57
@@ -10,13 +10,14 @@ const sendButton = document.getElementById("send-button");
10 10 const imageInput = document.getElementById("image");
11 11 const cameraInput = document.getElementById("camera");
12 12 const fileInput = document.getElementById("file");
13 const microLabel = document.querySelector(".micro-label")
14 const inputCount = document.getElementById("input-count")
13 const microLabel = document.querySelector(".micro-label");
14 const inputCount = document.getElementById("input-count");
15 15 const providerSelect = document.getElementById("provider");
16 16 const modelSelect = document.getElementById("model");
17 17 const modelProvider = document.getElementById("model2");
18 const systemPrompt = document.getElementById("systemPrompt")
19 const settings = document.querySelector(".settings")
18 const systemPrompt = document.getElementById("systemPrompt");
19 const settings = document.querySelector(".settings");
20 const album = document.querySelector(".images");
20 21
21 22 let prompt_lock = false;
22 23
@@ -49,6 +50,12 @@ const markdown_render = (content) => {
49 50 .replaceAll('<code>', '<code class="language-plaintext">')
50 51 }
51 52
53 function filter_message(text) {
54 return text.replaceAll(
55 /<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm, ""
56 )
57 }
58
52 59 hljs.addPlugin(new CopyButtonPlugin());
53 60 let typesetPromise = Promise.resolve();
54 61 const highlight = (container) => {
@@ -64,7 +71,6 @@ const highlight = (container) => {
64 71 );
65 72 }
66 73
67 let stopped = false;
68 74 const register_message_buttons = async () => {
69 75 document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
70 76 if (!("click" in el.dataset)) {
@@ -95,69 +101,76 @@ const register_message_buttons = async () => {
95 101 if (!("click" in el.dataset)) {
96 102 el.dataset.click = "true";
97 103 el.addEventListener("click", async () => {
98 if ("active" in el.classList || window.doSpeech) {
99 el.classList.add("blink")
100 stopped = true;
101 return;
104 let playlist = [];
105 function play_next() {
106 const next = playlist.shift();
107 if (next)
108 next.play();
102 109 }
103 if (stopped) {
110 if (el.dataset.stopped) {
104 111 el.classList.remove("blink")
105 stopped = false;
112 delete el.dataset.stopped;
113 return;
114 }
115 if (el.dataset.running) {
116 el.dataset.stopped = true;
117 el.classList.add("blink")
118 playlist = [];
106 119 return;
107 120 }
121 el.dataset.running = true;
108 122 el.classList.add("blink")
109 123 el.classList.add("active")
110 const message_el = el.parentElement.parentElement.parentElement;
111 124 const content_el = el.parentElement.parentElement;
125 const message_el = content_el.parentElement;
112 126 let speechText = await get_message(window.conversation_id, message_el.dataset.index);
113 127
128 speechText = speechText.replaceAll(/([^0-9])\./gm, "$1.;");
129 speechText = speechText.replaceAll("?", "?;");
114 130 speechText = speechText.replaceAll(/\[(.+)\]\(.+\)/gm, "($1)");
115 speechText = speechText.replaceAll("`", "").replaceAll("#", "")
116 speechText = speechText.replaceAll(
117 /<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
118 ""
119 )
120
121 const lines = speechText.trim().split(/\n|\.|;/);
122 let ended = true;
131 speechText = speechText.replaceAll(/```[a-z]+/gm, "");
132 speechText = filter_message(speechText.replaceAll("`", "").replaceAll("#", ""))
133 const lines = speechText.trim().split(/\n|;/).filter(v => v.trim());
134
123 135 window.onSpeechResponse = (url) => {
124 el.classList.remove("blink")
136 if (!el.dataset.stopped) {
137 el.classList.remove("blink")
138 }
125 139 if (url) {
126 140 var sound = document.createElement('audio');
127 141 sound.controls = 'controls';
128 142 sound.src = url;
129 143 sound.type = 'audio/wav';
130 144 sound.onended = function() {
131 ended = true;
145 el.dataset.do_play = true;
146 setTimeout(play_next, 1000);
132 147 };
133 148 sound.onplay = function() {
134 ended = false;
149 delete el.dataset.do_play;
135 150 };
136 151 var container = document.createElement('div');
137 152 container.classList.add("audio");
138 153 container.appendChild(sound);
139 154 content_el.appendChild(container);
140 if (ended && !stopped) {
141 sound.play();
155 if (!el.dataset.stopped) {
156 playlist.push(sound);
157 if (el.dataset.do_play) {
158 play_next();
159 }
142 160 }
143 161 }
144 if (lines.length < 1 || stopped) {
162 let line = lines.length > 0 ? lines.shift() : null;
163 if (line && !el.dataset.stopped) {
164 handleGenerateSpeech(line);
165 } else {
145 166 el.classList.remove("active");
146 return;
147 }
148 while (lines.length > 0) {
149 let line = lines.shift();
150 var reg = new RegExp('^[0-9]$');
151 if (line && !reg.test(line)) {
152 return handleGenerateSpeech(line);
153 }
154 }
155 if (!line) {
156 el.classList.remove("active")
167 el.classList.remove("blink");
168 delete el.dataset.running;
157 169 }
158 170 }
171 el.dataset.do_play = true;
159 172 let line = lines.shift();
160 return handleGenerateSpeech(line);
173 handleGenerateSpeech(line);
161 174 });
162 175 }
163 176 });
@@ -399,7 +412,7 @@ const ask_gpt = async () => {
399 412 provider = "Bing";
400 413 let api_key = null;
401 414 if (provider)
402 api_key = document.getElementById(`${provider}-api_key`)?.value;
415 api_key = document.getElementById(`${provider}-api_key`)?.value || null;
403 416 await api("conversation", {
404 417 id: window.token,
405 418 conversation_id: window.conversation_id,
@@ -717,7 +730,7 @@ const load_conversations = async () => {
717 730 </div>
718 731 `;
719 732 });
720 box_conversations.innerHTML = html;
733 box_conversations.innerHTML += html;
721 734 };
722 735
723 736 document.getElementById("cancelButton").addEventListener("click", async () => {
@@ -790,6 +803,17 @@ function open_settings() {
790 803 }
791 804 }
792 805
806 function open_album() {
807 if (album.classList.contains("hidden")) {
808 sidebar.classList.remove("shown");
809 settings.classList.add("hidden");
810 album.classList.remove("hidden");
811 history.pushState({}, null, "/images/");
812 } else {
813 album.classList.add("hidden");
814 }
815 }
816
793 817 const register_settings_storage = async () => {
794 818 optionElements.forEach((element) => {
795 819 if (element.type == "textarea") {
@@ -1232,12 +1256,12 @@ if (SpeechRecognition) {
1232 1256 }
1233 1257
1234 1258 let startValue;
1235 let lastValue;
1236 1259 let timeoutHandle;
1260 let lastDebounceTranscript;
1237 1261 recognition.onstart = function() {
1238 1262 microLabel.classList.add("recognition");
1239 1263 startValue = messageInput.value;
1240 lastValue = "";
1264 lastDebounceTranscript = "";
1241 1265 timeoutHandle = window.setTimeout(may_stop, 8000);
1242 1266 };
1243 1267 recognition.onend = function() {
@@ -1248,22 +1272,27 @@ if (SpeechRecognition) {
1248 1272 return;
1249 1273 }
1250 1274 window.clearTimeout(timeoutHandle);
1251 let newText;
1252 Array.from(event.results).forEach((result) => {
1253 newText = result[0].transcript;
1254 if (newText && newText != lastValue) {
1255 messageInput.value = `${startValue ? startValue+"\n" : ""}${newText.trim()}`;
1256 if (result.isFinal) {
1257 lastValue = newText;
1258 startValue = messageInput.value;
1259 messageInput.focus();
1260 }
1261 messageInput.style.height = messageInput.scrollHeight + "px";
1262 messageInput.scrollTop = messageInput.scrollHeight;
1275
1276 let result = event.results[event.resultIndex];
1277 let isFinal = result.isFinal && (result[0].confidence > 0);
1278 let transcript = result[0].transcript;
1279 if (isFinal) {
1280 if(transcript == lastDebounceTranscript) {
1281 return;
1263 1282 }
1264 });
1265 window.clearTimeout(timeoutHandle);
1266 timeoutHandle = window.setTimeout(may_stop, newText ? 8000 : 5000);
1283 lastDebounceTranscript = transcript;
1284 }
1285 if (transcript) {
1286 messageInput.value = `${startValue ? startValue+"\n" : ""}${transcript.trim()}`;
1287 if (isFinal) {
1288 startValue = messageInput.value;
1289 messageInput.focus();
1290 }
1291 messageInput.style.height = messageInput.scrollHeight + "px";
1292 messageInput.scrollTop = messageInput.scrollHeight;
1293 }
1294
1295 timeoutHandle = window.setTimeout(may_stop, transcript ? 8000 : 5000);
1267 1296 };
1268 1297
1269 1298 microLabel.addEventListener("click", () => {
Modified g4f/providers/base_provider.py +4 -1
@@ -78,6 +78,7 @@ class AbstractProvider(BaseProvider):
78 78 timeout=kwargs.get("timeout")
79 79 )
80 80
81 @classmethod
81 82 def get_parameters(cls) -> dict:
82 83 return signature(
83 84 cls.create_async_generator if issubclass(cls, AsyncGeneratorProvider) else
@@ -107,7 +108,9 @@ class AbstractProvider(BaseProvider):
107 108 continue
108 109 args += f"\n {name}"
109 110 args += f": {get_type_name(param.annotation)}" if param.annotation is not Parameter.empty else ""
110 args += f' = "{param.default}"' if param.default == "" else f" = {param.default}" if param.default is not Parameter.empty else ""
111 default_value = f'"{param.default}"' if isinstance(param.default, str) else param.default
112 args += f" = {default_value}" if param.default is not Parameter.empty else ""
113 args += ","
111 114
112 115 return f"g4f.Provider.{cls.__name__} supports: ({args}\n)"
113 116
Modified g4f/requests/aiohttp.py +6 -1
@@ -33,9 +33,14 @@ class StreamSession(ClientSession):
33 33 **DEFAULT_HEADERS,
34 34 **headers
35 35 }
36 connect = None
37 if isinstance(timeout, tuple):
38 connect, timeout = timeout;
39 if timeout is not None:
40 timeout = ClientTimeout(timeout, connect)
36 41 super().__init__(
37 42 **kwargs,
38 timeout=ClientTimeout(timeout) if timeout else None,
43 timeout=timeout,
39 44 response_class=StreamResponse,
40 45 connector=get_connector(connector, proxies.get("all", proxies.get("https"))),
41 46 headers=headers
Modified g4f/requests/curl_cffi.py +14 -4
@@ -1,6 +1,11 @@
1 1 from __future__ import annotations
2 2
3 from curl_cffi.requests import AsyncSession, Response, CurlMime
3 from curl_cffi.requests import AsyncSession, Response
4 try:
5 from curl_cffi.requests import CurlMime
6 has_curl_mime = True
7 except ImportError:
8 has_curl_mime = False
4 9 from typing import AsyncGenerator, Any
5 10 from functools import partialmethod
6 11 import json
@@ -78,6 +83,11 @@ class StreamSession(AsyncSession):
78 83 patch = partialmethod(request, "PATCH")
79 84 delete = partialmethod(request, "DELETE")
80 85
81 class FormData(CurlMime):
82 def add_field(self, name, data=None, content_type: str = None, filename: str = None) -> None:
83 self.addpart(name, content_type=content_type, filename=filename, data=data)
86 if has_curl_mime:
87 class FormData(CurlMime):
88 def add_field(self, name, data=None, content_type: str = None, filename: str = None) -> None:
89 self.addpart(name, content_type=content_type, filename=filename, data=data)
90 else:
91 class FormData():
92 def __init__(self) -> None:
93 raise RuntimeError("CurlMimi in curl_cffi is missing | pip install -U g4f[curl_cffi]")
Modified projects/text_to_speech/package.json +1 -4
@@ -12,8 +12,5 @@
12 12 "pack": "^2.2.0",
13 13 "web": "^0.0.2",
14 14 "webpack-cli": "^5.1.4"
15 },
16 "bundleDependencies": [
17 "@xenova/transformers"
18 ]
15 }
19 16 }
Modified setup.py +3 -0
@@ -74,6 +74,9 @@ EXTRA_REQUIRE = {
74 74 ],
75 75 "local": [
76 76 "gpt4all"
77 ],
78 "curl_cffi": [
79 "curl_cffi>=0.6.2",
77 80 ]
78 81 }
79 82