返回提交历史
Modified
.github/FUNDING.yml
+1
-1
Modified
g4f/Provider/HuggingFace.py
+5
-1
Added
g4f/Provider/WhiteRabbitNeo.py
+57
-0
Modified
g4f/Provider/__init__.py
+1
-0
Modified
g4f/gui/client/index.html
+50
-51
Modified
g4f/gui/client/static/css/style.css
+49
-8
Modified
g4f/gui/client/static/js/chat.v1.js
+77
-25
Modified
g4f/gui/server/api.py
+5
-8
Modified
g4f/gui/server/js_api.py
+0
-1
Modified
g4f/gui/server/website.py
+11
-1
XFEstudio/gpt4free
Add WhiteRabbitNeo Provider, Many tiny improvments in the gui
926ddfd5
代码差异
10 个文件
+256
-96
@@ -1,3 +1,3 @@
1
1
ko_fi: xtekky
2
github: [xtekky]
2
github: [xtekky, hlohaus]
3
3
patreon: xtekky
@@ -13,6 +13,10 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
13
13
url = "https://huggingface.co/chat"
14
14
working = True
15
15
supports_message_history = True
16
models = [
17
"mistralai/Mixtral-8x7B-Instruct-v0.1",
18
"mistralai/Mistral-7B-Instruct-v0.2"
19
]
16
20
default_model = "mistralai/Mixtral-8x7B-Instruct-v0.1"
17
21
18
22
@classmethod
@@ -29,7 +33,7 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
29
33
temperature: float = 0.7,
30
34
**kwargs
31
35
) -> AsyncResult:
32
model = cls.get_model(model)
36
model = cls.get_model(model) if not model else model
33
37
headers = {}
34
38
if api_key is not None:
35
39
headers["Authorization"] = f"Bearer {api_key}"
@@ -0,0 +1,57 @@
1
from __future__ import annotations
2
3
from aiohttp import ClientSession, BaseConnector
4
5
from ..typing import AsyncResult, Messages, Cookies
6
from ..requests.raise_for_status import raise_for_status
7
from .base_provider import AsyncGeneratorProvider
8
from .helper import get_cookies, get_connector, get_random_string
9
10
class WhiteRabbitNeo(AsyncGeneratorProvider):
11
url = "https://www.whiterabbitneo.com"
12
working = True
13
supports_message_history = True
14
needs_auth = True
15
16
@classmethod
17
async def create_async_generator(
18
cls,
19
model: str,
20
messages: Messages,
21
cookies: Cookies = None,
22
connector: BaseConnector = None,
23
proxy: str = None,
24
**kwargs
25
) -> AsyncResult:
26
if cookies is None:
27
cookies = get_cookies("www.whiterabbitneo.com")
28
headers = {
29
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0",
30
"Accept": "*/*",
31
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
32
"Accept-Encoding": "gzip, deflate, br",
33
"Referer": f"{cls.url}/",
34
"Content-Type": "text/plain;charset=UTF-8",
35
"Origin": cls.url,
36
"Connection": "keep-alive",
37
"Sec-Fetch-Dest": "empty",
38
"Sec-Fetch-Mode": "cors",
39
"Sec-Fetch-Site": "same-origin",
40
"TE": "trailers"
41
}
42
async with ClientSession(
43
headers=headers,
44
cookies=cookies,
45
connector=get_connector(connector, proxy)
46
) as session:
47
data = {
48
"messages": messages,
49
"id": get_random_string(6),
50
"enhancePrompt": False,
51
"useFunctions": False
52
}
53
async with session.post(f"{cls.url}/api/chat", json=data, proxy=proxy) as response:
54
await raise_for_status(response)
55
async for chunk in response.content.iter_any():
56
if chunk:
57
yield chunk.decode(errors="ignore")
@@ -37,6 +37,7 @@ from .Local import Local
37
37
from .PerplexityLabs import PerplexityLabs
38
38
from .Pi import Pi
39
39
from .Vercel import Vercel
40
from .WhiteRabbitNeo import WhiteRabbitNeo
40
41
from .You import You
41
42
42
43
import sys
@@ -57,13 +57,9 @@
57
57
</button>
58
58
</div>
59
59
<div class="bottom_buttons">
60
<button onclick="delete_conversations()">
61
<i class="fa-regular fa-trash"></i>
62
<span>Clear Conversations</span>
63
</button>
64
<button onclick="save_storage()">
65
<i class="fa-solid fa-download"></i>
66
<a href="" onclick="return false;">Export Conversations</a>
60
<button onclick="open_settings();">
61
<i class="fa-solid fa-toolbox"></i>
62
<span>Open Settings</span>
67
63
</button>
68
64
<div class="info">
69
65
<i class="fa-brands fa-github"></i>
@@ -76,28 +72,48 @@
76
72
</div>
77
73
</div>
78
74
</div>
79
<div class="settings">
80
<div class="field box">
81
<label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: access_token</label>
82
<textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea>
75
<div class="settings hidden">
76
<div class="field">
77
<span class="label">Web Access</span>
78
<input type="checkbox" id="switch" />
79
<label for="switch" class="toogle" title="Add the pages of the first 5 search results to the query."></label>
83
80
</div>
84
81
<div class="field">
85
<span class="label">OpenaiChat: Auto continue</span>
86
<input id="OpenaiChat-auto_continue" type="checkbox" name="OpenaiChat[auto_continue]" checked/>
87
<label for="OpenaiChat-auto_continue" class="toogle" title=""></label>
82
<span class="label">Disable History</span>
83
<input type="checkbox" id="history" />
84
<label for="history" class="toogle" title="To improve the reaction time or if you have trouble with large conversations."></label>
85
</div>
86
<div class="field">
87
<span class="label">Hide System prompt</span>
88
<input type="checkbox" id="hide-systemPrompt" />
89
<label for="hide-systemPrompt" class="toogle" title="For more space on phones"></label>
90
</div>
91
<div class="field">
92
<span class="label">Auto continue</span>
93
<input id="auto_continue" type="checkbox" name="auto_continue" checked/>
94
<label for="auto_continue" class="toogle" title="Continue long responses in OpenaiChat"></label>
95
</div>
96
<div class="paper">
97
<div class="field box">
98
<label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: api_key</label>
99
<textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea>
88
100
</div>
89
101
<div class="field box">
90
102
<label for="Bing-api_key" class="label" title="">Bing: "_U" cookie</label>
91
103
<textarea id="Bing-api_key" name="Bing[api_key]" placeholder="..."></textarea>
92
104
</div>
93
105
<div class="field box">
94
<label for="Gemini-api_key" class="label" title="">Gemini: Auth cookies</label>
106
<label for="Gemini-api_key" class="label" title="">Gemini: Cookies</label>
95
107
<textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="..."></textarea>
96
108
</div>
97
109
<div class="field box">
98
110
<label for="Openai-api_key" class="label" title="">Openai: api_key</label>
99
111
<textarea id="Openai-api_key" name="Openai[api_key]" placeholder="..."></textarea>
100
112
</div>
113
<div class="field box">
114
<label for="Openai-api_key" class="label" title="">Groq: api_key</label>
115
<textarea id="Openai-api_key" name="Groq[api_key]" placeholder="..."></textarea>
116
</div>
101
117
<div class="field box">
102
118
<label for="GeminiPro-api_key" class="label" title="">GeminiPro: api_key</label>
103
119
<textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="..."></textarea>
@@ -106,6 +122,17 @@
106
122
<label for="HuggingFace-api_key" class="label" title="">HuggingFace: api_key</label>
107
123
<textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="..."></textarea>
108
124
</div>
125
</div>
126
<div class="bottom_buttons">
127
<button onclick="delete_conversations()">
128
<i class="fa-regular fa-trash"></i>
129
<span>Clear Conversations</span>
130
</button>
131
<button onclick="save_storage()">
132
<i class="fa-solid fa-download"></i>
133
<a href="" onclick="return false;">Export Conversations</a>
134
</button>
135
</div>
109
136
</div>
110
137
<div class="conversation">
111
138
<textarea id="systemPrompt" class="box" placeholder="System prompt"></textarea>
@@ -161,43 +188,15 @@
161
188
<select name="model2" id="model2" class="hidden"></select>
162
189
</div>
163
190
<div class="field">
164
<select name="jailbreak" id="jailbreak" style="display: none;">
165
<option value="default" selected>Set Jailbreak</option>
166
<option value="gpt-math-1.0">math 1.0</option>
167
<option value="gpt-dude-1.0">dude 1.0</option>
168
<option value="gpt-dan-1.0">dan 1.0</option>
169
<option value="gpt-dan-2.0">dan 2.0</option>
170
<option value="gpt-dev-2.0">dev 2.0</option>
171
<option value="gpt-evil-1.0">evil 1.0</option>
191
<select name="provider" id="provider">
192
<option value="">Provider: Auto</option>
193
<option value="Bing">Bing</option>
194
<option value="OpenaiChat">OpenaiChat</option>
195
<option value="Gemini">Gemini</option>
196
<option value="Liaobots">Liaobots</option>
197
<option value="You">You</option>
198
<option value="">----</option>
172
199
</select>
173
<div class="field">
174
<select name="provider" id="provider">
175
<option value="">Provider: Auto</option>
176
<option value="Bing">Bing</option>
177
<option value="OpenaiChat">OpenaiChat</option>
178
<option value="Gemini">Gemini</option>
179
<option value="Liaobots">Liaobots</option>
180
<option value="You">You</option>
181
<option value="">----</option>
182
</select>
183
</div>
184
</div>
185
<div class="field">
186
<input type="checkbox" id="switch" />
187
<label for="switch" title="Add the pages of the first 5 search results to the query."></label>
188
<span class="about">Web Access</span>
189
</div>
190
<!--
191
<div class="field">
192
<input type="checkbox" id="patch" />
193
<label for="patch" title="Enable create images with Bing."></label>
194
<span class="about">Image Generator</span>
195
</div>
196
-->
197
<div class="field">
198
<input type="checkbox" id="history" />
199
<label for="history" title="To improve the reaction time or if you have trouble with large conversations."></label>
200
<span class="about">Disable History</span>
201
200
</div>
202
201
</div>
203
202
</div>
@@ -84,7 +84,7 @@ body {
84
84
}
85
85
86
86
body {
87
padding: var(--section-gap);
87
padding: 10px;
88
88
background: var(--colour-1);
89
89
color: var(--colour-3);
90
90
height: 100vh;
@@ -92,7 +92,7 @@ body {
92
92
93
93
.row {
94
94
display: flex;
95
gap: var(--section-gap);
95
gap: 10px;
96
96
height: 100%;
97
97
}
98
98
@@ -111,7 +111,7 @@ body {
111
111
}
112
112
113
113
.conversations {
114
max-width: 260px;
114
max-width: 280px;
115
115
padding: var(--section-gap);
116
116
overflow: auto;
117
117
flex-shrink: 0;
@@ -183,8 +183,8 @@ body {
183
183
.conversations {
184
184
display: flex;
185
185
flex-direction: column;
186
gap: var(--inner-gap);
187
padding: var(--inner-gap);
186
gap: 10px;
187
padding: 10px;
188
188
}
189
189
190
190
.conversations .title {
@@ -207,7 +207,12 @@ body {
207
207
cursor: pointer;
208
208
display: flex;
209
209
align-items: center;
210
gap: 10px;
210
gap: 4px;
211
}
212
213
.conversations .convo .fa-trash {
214
position: absolute;
215
right: 8px;
211
216
}
212
217
213
218
.conversations .convo .choise {
@@ -216,7 +221,7 @@ body {
216
221
background-color: var(--blur-bg);
217
222
}
218
223
219
.conversations i {
224
.conversations i, .bottom_buttons i {
220
225
color: var(--conversations);
221
226
cursor: pointer;
222
227
}
@@ -229,6 +234,10 @@ body {
229
234
white-space: nowrap;
230
235
}
231
236
237
.convo-title .datetime {
238
font-size: 10px;
239
}
240
232
241
.message {
233
242
width: 100%;
234
243
overflow-wrap: break-word;
@@ -351,10 +360,23 @@ body {
351
360
cursor: pointer;
352
361
}
353
362
363
.message .count .fa-clipboard {
364
z-index: 1000;
365
cursor: pointer;
366
}
367
354
368
.message .user .fa-xmark {
355
369
color: var(--colour-1);
356
370
}
357
371
372
.message .count .fa-clipboard {
373
color: var(--colour-3);
374
}
375
376
.message .count .fa-clipboard.clicked {
377
color: var(--accent);
378
}
379
358
380
.message .assistant:hover .fa-xmark,
359
381
.message .user:hover .fa-xmark {
360
382
display: block;
@@ -556,6 +578,16 @@ label[for="camera"] {
556
578
background: var(--accent);
557
579
}
558
580
581
.settings .bottom_buttons {
582
flex-direction: row;
583
}
584
585
.settings .bottom_buttons button {
586
display: inline-block;
587
max-width: 210px;
588
width: 100%;
589
}
590
559
591
.buttons input:checked+label:after {
560
592
left: calc(100% - 5px - 20px);
561
593
}
@@ -565,6 +597,7 @@ label[for="camera"] {
565
597
align-items: center;
566
598
justify-content: left;
567
599
width: 100%;
600
margin-bottom: 2px;
568
601
}
569
602
570
603
.field {
@@ -635,6 +668,7 @@ select {
635
668
display: flex;
636
669
flex-direction: column;
637
670
gap: 10px;
671
margin: 4px;
638
672
}
639
673
640
674
.bottom_buttons button {
@@ -1026,7 +1060,14 @@ a:-webkit-any-link {
1026
1060
1027
1061
.settings {
1028
1062
width: 100%;
1029
display: none;
1063
min-width: 700px;
1064
display: flex;
1065
flex-direction: column;
1066
}
1067
1068
.settings .paper {
1069
overflow: auto;
1070
flex-direction: column;
1030
1071
}
1031
1072
1032
1073
.settings .field {
@@ -15,13 +15,13 @@ const providerSelect = document.getElementById("provider");
15
15
const modelSelect = document.getElementById("model");
16
16
const modelProvider = document.getElementById("model2");
17
17
const systemPrompt = document.getElementById("systemPrompt")
18
const jailbreak = document.getElementById("jailbreak");
18
const settings = document.querySelector(".settings")
19
19
20
20
let prompt_lock = false;
21
21
22
22
let content, content_inner, content_count = null;
23
23
24
const options = ["switch", "model", "model2", "jailbreak", "patch", "provider", "history"];
24
const optionElements = document.querySelectorAll(".settings input, .settings textarea, #model, #model2, #provider")
25
25
26
26
messageInput.addEventListener("blur", () => {
27
27
window.scrollTo(0, 0);
@@ -63,7 +63,7 @@ const highlight = (container) => {
63
63
);
64
64
}
65
65
66
const register_remove_message = async () => {
66
const register_message_buttons = async () => {
67
67
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
68
68
if (!("click" in el.dataset)) {
69
69
el.dataset.click = "true";
@@ -77,6 +77,18 @@ const register_remove_message = async () => {
77
77
})
78
78
}
79
79
});
80
document.querySelectorAll(".message .fa-clipboard").forEach(async (el) => {
81
if (!("click" in el.dataset)) {
82
el.dataset.click = "true";
83
el.addEventListener("click", async () => {
84
const message_el = el.parentElement.parentElement;
85
const copyText = await get_message(window.conversation_id, message_el.dataset.index);
86
navigator.clipboard.writeText(copyText);
87
el.classList.add("clicked");
88
setTimeout(() => el.classList.remove("clicked"), 1000);
89
})
90
}
91
});
80
92
}
81
93
82
94
const delete_conversations = async () => {
@@ -132,7 +144,7 @@ const handle_ask = async () => {
132
144
: ''
133
145
}
134
146
</div>
135
<div class="count">${count_words_and_tokens(message, get_selected_model())}</div>
147
<div class="count">${count_words_and_tokens(message, get_selected_model())} <i class="fa-regular fa-clipboard"></i></div>
136
148
</div>
137
149
</div>
138
150
`;
@@ -305,15 +317,22 @@ const ask_gpt = async () => {
305
317
try {
306
318
const input = imageInput && imageInput.files.length > 0 ? imageInput : cameraInput;
307
319
const file = input && input.files.length > 0 ? input.files[0] : null;
320
const provider = providerSelect.options[providerSelect.selectedIndex].value;
321
const auto_continue = document.getElementById("auto_continue")?.checked;
322
if (file && !provider)
323
provider = "Bing";
324
let api_key = null;
325
if (provider)
326
api_key = document.getElementById(`${provider}-api_key`)?.value;
308
327
await api("conversation", {
309
328
id: window.token,
310
329
conversation_id: window.conversation_id,
311
330
model: get_selected_model(),
312
jailbreak: jailbreak?.options[jailbreak.selectedIndex].value,
313
331
web_search: document.getElementById("switch").checked,
314
provider: providerSelect.options[providerSelect.selectedIndex].value,
315
patch_provider: document.getElementById("patch")?.checked,
316
messages: messages
332
provider: provider,
333
messages: messages,
334
auto_continue: auto_continue,
335
api_key: api_key
317
336
}, file);
318
337
if (!error) {
319
338
html = markdown_render(text);
@@ -341,7 +360,7 @@ const ask_gpt = async () => {
341
360
window.scrollTo(0, 0);
342
361
message_box.scrollTop = message_box.scrollHeight;
343
362
await remove_cancel_button();
344
await register_remove_message();
363
await register_message_buttons();
345
364
prompt_lock = false;
346
365
await load_conversations();
347
366
regenerate.classList.remove("regenerate-hidden");
@@ -459,7 +478,7 @@ const load_conversation = async (conversation_id, scroll=true) => {
459
478
<div class="content">
460
479
${provider}
461
480
<div class="content_inner">${markdown_render(item.content)}</div>
462
<div class="count">${count_words_and_tokens(item.content, next_provider?.model)}</div>
481
<div class="count">${count_words_and_tokens(item.content, next_provider?.model)} <i class="fa-regular fa-clipboard"></i></div>
463
482
</div>
464
483
</div>
465
484
`;
@@ -475,8 +494,9 @@ const load_conversation = async (conversation_id, scroll=true) => {
475
494
}
476
495
477
496
message_box.innerHTML = elements;
478
register_remove_message();
497
register_message_buttons();
479
498
highlight(message_box);
499
regenerate.classList.remove("regenerate-hidden");
480
500
481
501
if (scroll) {
482
502
message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
@@ -495,6 +515,7 @@ async function get_conversation(conversation_id) {
495
515
}
496
516
497
517
async function save_conversation(conversation_id, conversation) {
518
conversation.updated = Date.now();
498
519
appStorage.setItem(
499
520
`conversation:${conversation_id}`,
500
521
JSON.stringify(conversation)
@@ -517,6 +538,7 @@ async function add_conversation(conversation_id, content) {
517
538
await save_conversation(conversation_id, {
518
539
id: conversation_id,
519
540
title: title,
541
added: Date.now(),
520
542
system: systemPrompt?.value,
521
543
items: [],
522
544
});
@@ -563,6 +585,11 @@ const remove_message = async (conversation_id, index) => {
563
585
await save_conversation(conversation_id, conversation);
564
586
};
565
587
588
const get_message = async (conversation_id, index) => {
589
const conversation = await get_conversation(conversation_id);
590
return conversation.items[index]["content"];
591
};
592
566
593
const add_message = async (conversation_id, role, content, provider) => {
567
594
const conversation = await get_conversation(conversation_id);
568
595
conversation.items.push({
@@ -586,11 +613,17 @@ const load_conversations = async () => {
586
613
await clear_conversations();
587
614
588
615
for (conversation of conversations) {
616
let updated = "";
617
if (conversation.updated) {
618
const date = new Date(conversation.updated);
619
updated = date.toLocaleString('en-GB', {dateStyle: 'short', timeStyle: 'short', monthStyle: 'short'});
620
updated = updated.replace("/" + date.getFullYear(), "")
621
}
589
622
box_conversations.innerHTML += `
590
623
<div class="convo" id="convo-${conversation.id}">
591
624
<div class="left" onclick="set_conversation('${conversation.id}')">
592
625
<i class="fa-regular fa-comments"></i>
593
<span class="convo-title">${conversation.title}</span>
626
<span class="convo-title"><span class="datetime">${updated}</span> ${conversation.title}</span>
594
627
</div>
595
628
<i onclick="show_option('${conversation.id}')" class="fa-regular fa-trash" id="conv-${conversation.id}"></i>
596
629
<div id="cho-${conversation.id}" class="choise" style="display:none;">
@@ -642,7 +675,8 @@ const message_id = () => {
642
675
async function hide_sidebar() {
643
676
sidebar.classList.remove("shown");
644
677
sidebar_button.classList.remove("rotated");
645
if (window.location.pathname == "/menu/") {
678
settings.classList.add("hidden");
679
if (window.location.pathname == "/menu/" || window.location.pathname == "/settings/") {
646
680
history.back();
647
681
}
648
682
}
@@ -650,6 +684,7 @@ async function hide_sidebar() {
650
684
window.addEventListener('popstate', hide_sidebar, false);
651
685
652
686
sidebar_button.addEventListener("click", (event) => {
687
settings.classList.add("hidden");
653
688
if (sidebar.classList.contains("shown")) {
654
689
hide_sidebar();
655
690
} else {
@@ -660,19 +695,25 @@ sidebar_button.addEventListener("click", (event) => {
660
695
window.scrollTo(0, 0);
661
696
});
662
697
698
function open_settings() {
699
if (settings.classList.contains("hidden")) {
700
sidebar.classList.remove("shown");
701
settings.classList.remove("hidden");
702
history.pushState({}, null, "/settings/");
703
} else {
704
settings.classList.add("hidden");
705
}
706
}
707
663
708
const register_settings_storage = async () => {
664
options.forEach((id) => {
665
element = document.getElementById(id);
666
if (!element) {
667
return;
668
}
709
optionElements.forEach((element) => {
669
710
element.addEventListener('change', async (event) => {
670
711
switch (event.target.type) {
671
712
case "checkbox":
672
appStorage.setItem(id, event.target.checked);
713
appStorage.setItem(element.id, event.target.checked);
673
714
break;
674
715
case "select-one":
675
appStorage.setItem(id, event.target.selectedIndex);
716
appStorage.setItem(element.id, event.target.selectedIndex);
676
717
break;
677
718
default:
678
719
console.warn("Unresolved element type");
@@ -682,9 +723,8 @@ const register_settings_storage = async () => {
682
723
}
683
724
684
725
const load_settings_storage = async () => {
685
options.forEach((id) => {
686
element = document.getElementById(id);
687
if (!element || !(value = appStorage.getItem(id))) {
726
optionElements.forEach((element) => {
727
if (!(value = appStorage.getItem(element.id))) {
688
728
return;
689
729
}
690
730
if (value) {
@@ -859,6 +899,18 @@ async function on_api() {
859
899
860
900
await load_provider_models(appStorage.getItem("provider"));
861
901
await load_settings_storage()
902
903
const hide_systemPrompt = document.getElementById("hide-systemPrompt")
904
if (hide_systemPrompt.checked) {
905
systemPrompt.classList.add("hidden");
906
}
907
hide_systemPrompt.addEventListener('change', async (event) => {
908
if (event.target.checked) {
909
systemPrompt.classList.add("hidden");
910
} else {
911
systemPrompt.classList.remove("hidden");
912
}
913
});
862
914
}
863
915
864
916
async function load_version() {
@@ -875,7 +927,7 @@ async function load_version() {
875
927
}
876
928
document.getElementById("version_text").innerHTML = text
877
929
}
878
setTimeout(load_version, 5000);
930
setTimeout(load_version, 2000);
879
931
880
932
for (const el of [imageInput, cameraInput]) {
881
933
el.addEventListener('click', async () => {
@@ -1035,7 +1087,7 @@ function save_storage() {
1035
1087
let item = appStorage.getItem(key);
1036
1088
if (key.startsWith("conversation:")) {
1037
1089
data[key] = JSON.parse(item);
1038
} else {
1090
} else if (!key.includes("api_key")) {
1039
1091
data["options"][key] = item;
1040
1092
}
1041
1093
}
@@ -80,13 +80,12 @@ class Api():
80
80
Returns:
81
81
dict: Arguments prepared for chat completion.
82
82
"""
83
provider = json_data.get('provider', None)
84
if "image" in kwargs and provider is None:
85
provider = "Bing"
86
if provider == 'OpenaiChat':
87
kwargs['auto_continue'] = True
88
83
model = json_data.get('model') or models.default
84
provider = json_data.get('provider')
89
85
messages = json_data['messages']
86
api_key = json_data.get("api_key")
87
if api_key is not None:
88
kwargs["api_key"] = api_key
90
89
if json_data.get('web_search'):
91
90
if provider == "Bing":
92
91
kwargs['web_search'] = True
@@ -98,8 +97,6 @@ class Api():
98
97
if conversation_id and provider in conversations and conversation_id in conversations[provider]:
99
98
kwargs["conversation"] = conversations[provider][conversation_id]
100
99
101
model = json_data.get('model') or models.default
102
103
100
return {
104
101
"model": model,
105
102
"provider": provider,
@@ -1,6 +1,5 @@
1
1
from __future__ import annotations
2
2
3
import logging
4
3
import json
5
4
import os.path
6
5
from typing import Iterator
@@ -4,9 +4,11 @@ from flask import render_template, redirect
4
4
class Website:
5
5
def __init__(self, app) -> None:
6
6
self.app = app
7
def redirect_home():
8
return redirect('/chat')
7
9
self.routes = {
8
10
'/': {
9
'function': lambda: redirect('/chat'),
11
'function': redirect_home,
10
12
'methods': ['GET', 'POST']
11
13
},
12
14
'/chat/': {
@@ -17,6 +19,14 @@ class Website:
17
19
'function': self._chat,
18
20
'methods': ['GET', 'POST']
19
21
},
22
'/menu/': {
23
'function': redirect_home,
24
'methods': ['GET', 'POST']
25
},
26
'/settings/': {
27
'function': redirect_home,
28
'methods': ['GET', 'POST']
29
},
20
30
}
21
31
22
32
def _chat(self, conversation_id):