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

XFEstudio/gpt4free

Add ReplicateImage Provider, Fix BingCreateImages Provider

009a6723
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

7 个文件 +254 -60
Modified g4f/Provider/BingCreateImages.py +20 -3
@@ -7,16 +7,33 @@ from typing import Iterator, Union
7 7 from ..cookies import get_cookies
8 8 from ..image import ImageResponse
9 9 from ..errors import MissingRequirementsError, MissingAuthError
10 from ..typing import Cookies
10 from ..typing import AsyncResult, Messages, Cookies
11 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
11 12 from .bing.create_images import create_images, create_session, get_cookies_from_browser
12 13
13 class BingCreateImages:
14 """A class for creating images using Bing."""
14 class BingCreateImages(AsyncGeneratorProvider, ProviderModelMixin):
15 url = "https://www.bing.com/images/create"
16 working = True
15 17
16 18 def __init__(self, cookies: Cookies = None, proxy: str = None) -> None:
17 19 self.cookies: Cookies = cookies
18 20 self.proxy: str = proxy
19 21
22 @classmethod
23 async def create_async_generator(
24 cls,
25 model: str,
26 messages: Messages,
27 api_key: str = None,
28 cookies: Cookies = None,
29 proxy: str = None,
30 **kwargs
31 ) -> AsyncResult:
32 if api_key is not None:
33 cookies = {"_U": api_key}
34 session = BingCreateImages(cookies, proxy)
35 yield await session.create_async(messages[-1]["content"])
36
20 37 def create(self, prompt: str) -> Iterator[Union[ImageResponse, str]]:
21 38 """
22 39 Generator for creating imagecompletion based on a prompt.
Added g4f/Provider/ReplicateImage.py +96 -0
@@ -0,0 +1,96 @@
1 from __future__ import annotations
2
3 import random
4 import asyncio
5
6 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
7 from ..typing import AsyncResult, Messages
8 from ..requests import StreamSession, raise_for_status
9 from ..image import ImageResponse
10 from ..errors import ResponseError
11
12 class ReplicateImage(AsyncGeneratorProvider, ProviderModelMixin):
13 url = "https://replicate.com"
14 working = True
15 default_model = 'stability-ai/sdxl'
16 default_versions = [
17 "39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
18 "2b017d9b67edd2ee1401238df49d75da53c523f36e363881e057f5dc3ed3c5b2"
19 ]
20
21 @classmethod
22 async def create_async_generator(
23 cls,
24 model: str,
25 messages: Messages,
26 **kwargs
27 ) -> AsyncResult:
28 yield await cls.create_async(messages[-1]["content"], model, **kwargs)
29
30 @classmethod
31 async def create_async(
32 cls,
33 prompt: str,
34 model: str,
35 api_key: str = None,
36 proxy: str = None,
37 timeout: int = 180,
38 version: str = None,
39 extra_data: dict = {},
40 **kwargs
41 ) -> ImageResponse:
42 headers = {
43 'Accept-Encoding': 'gzip, deflate, br',
44 'Accept-Language': 'en-US',
45 'Connection': 'keep-alive',
46 'Origin': cls.url,
47 'Referer': f'{cls.url}/',
48 'Sec-Fetch-Dest': 'empty',
49 'Sec-Fetch-Mode': 'cors',
50 'Sec-Fetch-Site': 'same-site',
51 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
52 'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
53 'sec-ch-ua-mobile': '?0',
54 'sec-ch-ua-platform': '"macOS"',
55 }
56 if version is None:
57 version = random.choice(cls.default_versions)
58 if api_key is not None:
59 headers["Authorization"] = f"Bearer {api_key}"
60 async with StreamSession(
61 proxies={"all": proxy},
62 headers=headers,
63 timeout=timeout
64 ) as session:
65 data = {
66 "input": {
67 "prompt": prompt,
68 **extra_data
69 },
70 "version": version
71 }
72 if api_key is None:
73 data["model"] = cls.get_model(model)
74 url = "https://homepage.replicate.com/api/prediction"
75 else:
76 url = "https://api.replicate.com/v1/predictions"
77 async with session.post(url, json=data) as response:
78 await raise_for_status(response)
79 result = await response.json()
80 if "id" not in result:
81 raise ResponseError(f"Invalid response: {result}")
82 while True:
83 if api_key is None:
84 url = f"https://homepage.replicate.com/api/poll?id={result['id']}"
85 else:
86 url = f"https://api.replicate.com/v1/predictions/{result['id']}"
87 async with session.get(url) as response:
88 await raise_for_status(response)
89 result = await response.json()
90 if "status" not in result:
91 raise ResponseError(f"Invalid response: {result}")
92 if result["status"] == "succeeded":
93 images = result['output']
94 images = images[0] if len(images) == 1 else images
95 return ImageResponse(images, prompt)
96 await asyncio.sleep(0.5)
Modified g4f/Provider/bing/create_images.py +1 -1
@@ -151,7 +151,7 @@ async def create_images(session: ClientSession, prompt: str, proxy: str = None,
151 151 if response.status != 200:
152 152 raise RuntimeError(f"Polling images faild. Code: {response.status}")
153 153 text = await response.text()
154 if not text:
154 if not text or "GenerativeImagesStatusPage" in text:
155 155 await asyncio.sleep(1)
156 156 else:
157 157 break
Added g4f/Provider/unfinished/Replicate.py +78 -0
@@ -0,0 +1,78 @@
1 from __future__ import annotations
2
3 import asyncio
4
5 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
6 from ..helper import format_prompt, filter_none
7 from ...typing import AsyncResult, Messages
8 from ...requests import StreamSession, raise_for_status
9 from ...image import ImageResponse
10 from ...errors import ResponseError, MissingAuthError
11
12 class Replicate(AsyncGeneratorProvider, ProviderModelMixin):
13 url = "https://replicate.com"
14 working = True
15 default_model = "mistralai/mixtral-8x7b-instruct-v0.1"
16 api_base = "https://api.replicate.com/v1/models/"
17
18 @classmethod
19 async def create_async_generator(
20 cls,
21 model: str,
22 messages: Messages,
23 api_key: str = None,
24 proxy: str = None,
25 timeout: int = 180,
26 system_prompt: str = None,
27 max_new_tokens: int = None,
28 temperature: float = None,
29 top_p: float = None,
30 top_k: float = None,
31 stop: list = None,
32 extra_data: dict = {},
33 headers: dict = {},
34 **kwargs
35 ) -> AsyncResult:
36 model = cls.get_model(model)
37 if api_key is None:
38 raise MissingAuthError("api_key is missing")
39 headers["Authorization"] = f"Bearer {api_key}"
40 async with StreamSession(
41 proxies={"all": proxy},
42 headers=headers,
43 timeout=timeout
44 ) as session:
45 data = {
46 "stream": True,
47 "input": {
48 "prompt": format_prompt(messages),
49 **filter_none(
50 system_prompt=system_prompt,
51 max_new_tokens=max_new_tokens,
52 temperature=temperature,
53 top_p=top_p,
54 top_k=top_k,
55 stop_sequences=",".join(stop) if stop else None
56 ),
57 **extra_data
58 },
59 }
60 url = f"{cls.api_base.rstrip('/')}/{model}/predictions"
61 async with session.post(url, json=data) as response:
62 await raise_for_status(response)
63 result = await response.json()
64 if "id" not in result:
65 raise ResponseError(f"Invalid response: {result}")
66 async with session.get(result["urls"]["stream"], headers={"Accept": "text/event-stream"}) as response:
67 await raise_for_status(response)
68 event = None
69 async for line in response.iter_lines():
70 if line.startswith(b"event: "):
71 event = line[7:]
72 elif event == b"output":
73 if line.startswith(b"data: "):
74 yield line[6:].decode()
75 elif not line.startswith(b"id: "):
76 continue#yield "+"+line.decode()
77 elif event == b"done":
78 break
Modified g4f/gui/client/index.html +28 -19
@@ -58,6 +58,12 @@
58 58 </button>
59 59 </div>
60 60 <div class="bottom_buttons">
61 <!--
62 <button onclick="open_album();">
63 <i class="fa-solid fa-toolbox"></i>
64 <span>Images Album</span>
65 </button>
66 -->
61 67 <button onclick="open_settings();">
62 68 <i class="fa-solid fa-toolbox"></i>
63 69 <span>Open Settings</span>
@@ -77,6 +83,9 @@
77 83 <span id="version_text" class="convo-title"></span>
78 84 </div>
79 85 </div>
86 </div>
87 <div class="images hidden">
88
80 89 </div>
81 90 <div class="settings hidden">
82 91 <div class="paper">
@@ -101,7 +110,7 @@
101 110 <label for="auto_continue" class="toogle" title="Continue large responses in OpenaiChat"></label>
102 111 </div>
103 112 <div class="field box">
104 <label for="message-input-height" class="label" title="">Input max. grow height</label>
113 <label for="message-input-height" class="label" title="">Input max. height</label>
105 114 <input type="number" id="message-input-height" value="200"/>
106 115 </div>
107 116 <div class="field box">
@@ -109,40 +118,40 @@
109 118 <input type="text" id="recognition-language" value="" placeholder="navigator.language"/>
110 119 </div>
111 120 <div class="field box">
112 <label for="OpenaiChat-api_key" class="label" title="">OpenaiChat: api_key</label>
113 <textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="..."></textarea>
121 <label for="Bing-api_key" class="label" title="">Bing:</label>
122 <textarea id="Bing-api_key" name="Bing[api_key]" class="BingCreateImages-api_key" placeholder="&quot;_U&quot; cookie"></textarea>
114 123 </div>
115 124 <div class="field box">
116 <label for="Bing-api_key" class="label" title="">Bing: "_U" cookie</label>
117 <textarea id="Bing-api_key" name="Bing[api_key]" placeholder="..."></textarea>
125 <label for="DeepInfra-api_key" class="label" title="">DeepInfra:</label>
126 <textarea id="DeepInfra-api_key" name="DeepInfra[api_key]" class="DeepInfraImage-api_key" placeholder="api_key"></textarea>
118 127 </div>
119 128 <div class="field box">
120 <label for="Gemini-api_key" class="label" title="">Gemini: Cookies</label>
121 <textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="..."></textarea>
129 <label for="Gemini-api_key" class="label" title="">Gemini:</label>
130 <textarea id="Gemini-api_key" name="Gemini[api_key]" placeholder="Cookies"></textarea>
122 131 </div>
123 132 <div class="field box">
124 <label for="Openai-api_key" class="label" title="">Openai: api_key</label>
125 <textarea id="Openai-api_key" name="Openai[api_key]" placeholder="..."></textarea>
133 <label for="GeminiPro-api_key" class="label" title="">GeminiPro:</label>
134 <textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="api_key"></textarea>
126 135 </div>
127 136 <div class="field box">
128 <label for="Groq-api_key" class="label" title="">Groq: api_key</label>
129 <textarea id="Groq-api_key" name="Groq[api_key]" placeholder="..."></textarea>
137 <label for="Groq-api_key" class="label" title="">Groq:</label>
138 <textarea id="Groq-api_key" name="Groq[api_key]" placeholder="api_key"></textarea>
130 139 </div>
131 140 <div class="field box">
132 <label for="GeminiPro-api_key" class="label" title="">GeminiPro: api_key</label>
133 <textarea id="GeminiPro-api_key" name="GeminiPro[api_key]" placeholder="..."></textarea>
141 <label for="HuggingFace-api_key" class="label" title="">HuggingFace:</label>
142 <textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="api_key"></textarea>
134 143 </div>
135 144 <div class="field box">
136 <label for="OpenRouter-api_key" class="label" title="">OpenRouter: api_key</label>
137 <textarea id="OpenRouter-api_key" name="OpenRouter[api_key]" placeholder="..."></textarea>
145 <label for="Openai-api_key" class="label" title="">Openai:</label>
146 <textarea id="Openai-api_key" name="Openai[api_key]" placeholder="api_key"></textarea>
138 147 </div>
139 148 <div class="field box">
140 <label for="HuggingFace-api_key" class="label" title="">HuggingFace: api_key</label>
141 <textarea id="HuggingFace-api_key" name="HuggingFace[api_key]" placeholder="..."></textarea>
149 <label for="OpenaiChat-api_key" class="label" title="">OpenaiChat:</label>
150 <textarea id="OpenaiChat-api_key" name="OpenaiChat[api_key]" placeholder="api_key"></textarea>
142 151 </div>
143 152 <div class="field box">
144 <label for="DeepInfra-api_key" class="label" title="">DeepInfra: api_key</label>
145 <textarea id="DeepInfra-api_key" name="DeepInfra[api_key]" placeholder="..."></textarea>
153 <label for="OpenRouter-api_key" class="label" title="">OpenRouter:</label>
154 <textarea id="OpenRouter-api_key" name="OpenRouter[api_key]" placeholder="api_key"></textarea>
146 155 </div>
147 156 </div>
148 157 <div class="bottom_buttons">
Modified g4f/gui/client/static/css/style.css +11 -13
@@ -653,7 +653,7 @@ select {
653 653 font-size: 15px;
654 654 width: 100%;
655 655 color: var(--colour-3);
656 min-height: 50px;
656 min-height: 49px;
657 657 height: 59px;
658 658 outline: none;
659 659 padding: var(--inner-gap) var(--section-gap);
@@ -809,7 +809,7 @@ ul {
809 809 }
810 810
811 811 .mobile-sidebar {
812 display: none !important;
812 display: none;
813 813 position: absolute;
814 814 z-index: 100000;
815 815 top: 0;
@@ -850,12 +850,8 @@ ul {
850 850 gap: 15px;
851 851 }
852 852
853 .field {
854 width: fit-content;
855 }
856
857 853 .mobile-sidebar {
858 display: flex !important;
854 display: flex;
859 855 }
860 856
861 857 #systemPrompt {
@@ -1090,7 +1086,13 @@ a:-webkit-any-link {
1090 1086 }
1091 1087
1092 1088 .settings textarea {
1093 height: 51px;
1089 height: 19px;
1090 min-height: 19px;
1091 padding: 0;
1092 }
1093
1094 .settings .field.box {
1095 padding: var(--inner-gap) var(--inner-gap) var(--inner-gap) 0;
1094 1096 }
1095 1097
1096 1098 .settings, .images {
@@ -1112,7 +1114,6 @@ a:-webkit-any-link {
1112 1114 .settings textarea {
1113 1115 background-color: transparent;
1114 1116 border: none;
1115 padding: var(--inner-gap) 0;
1116 1117 }
1117 1118
1118 1119 .settings input {
@@ -1130,10 +1131,7 @@ a:-webkit-any-link {
1130 1131
1131 1132 .settings .label {
1132 1133 font-size: 15px;
1133 padding: var(--inner-gap) 0;
1134 width: fit-content;
1135 min-width: 190px;
1136 margin-left: var(--section-gap);
1134 margin-left: var(--inner-gap);
1137 1135 white-space:nowrap;
1138 1136 }
1139 1137
Modified g4f/gui/client/static/js/chat.v1.js +20 -24
@@ -179,12 +179,14 @@ const register_message_buttons = async () => {
179 179 }
180 180
181 181 const delete_conversations = async () => {
182 const remove_keys = [];
182 183 for (let i = 0; i < appStorage.length; i++){
183 184 let key = appStorage.key(i);
184 185 if (key.startsWith("conversation:")) {
185 appStorage.removeItem(key);
186 remove_keys.push(key);
186 187 }
187 188 }
189 remove_keys.forEach((key)=>appStorage.removeItem(key));
188 190 hide_sidebar();
189 191 await new_conversation();
190 192 };
@@ -274,31 +276,21 @@ const prepare_messages = (messages, filter_last_message=true) => {
274 276 }
275 277
276 278 let new_messages = [];
277 if (messages) {
278 for (i in messages) {
279 new_message = messages[i];
280 // Remove generated images from history
281 new_message.content = new_message.content.replaceAll(
282 /<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
283 ""
284 )
285 delete new_message["provider"];
286 // Remove regenerated messages
287 if (!new_message.regenerate) {
288 new_messages.push(new_message)
289 }
290 }
291 }
292
293 // Add system message
294 system_content = systemPrompt?.value;
295 if (system_content) {
296 new_messages.unshift({
279 if (systemPrompt?.value) {
280 new_messages.push({
297 281 "role": "system",
298 "content": system_content
282 "content": systemPrompt.value
299 283 });
300 284 }
301
285 messages.forEach((new_message) => {
286 // Include only not regenerated messages
287 if (!new_message.regenerate) {
288 // Remove generated images from history
289 new_message.content = filter_message(new_message.content);
290 delete new_message.provider;
291 new_messages.push(new_message)
292 }
293 });
302 294 return new_messages;
303 295 }
304 296
@@ -413,8 +405,11 @@ const ask_gpt = async () => {
413 405 if (file && !provider)
414 406 provider = "Bing";
415 407 let api_key = null;
416 if (provider)
408 if (provider) {
417 409 api_key = document.getElementById(`${provider}-api_key`)?.value || null;
410 if (api_key == null)
411 api_key = document.querySelector(`.${provider}-api_key`)?.value || null;
412 }
418 413 await api("conversation", {
419 414 id: window.token,
420 415 conversation_id: window.conversation_id,
@@ -949,6 +944,7 @@ function count_chars(text) {
949 944 }
950 945
951 946 function count_words_and_tokens(text, model) {
947 text = filter_message(text);
952 948 return `(${count_words(text)} words, ${count_chars(text)} chars, ${count_tokens(model, text)} tokens)`;
953 949 }
954 950