返回提交历史
Modified
g4f/Provider/Blackbox.py
+1
-1
Modified
g4f/Provider/CablyAI.py
+0
-1
Modified
g4f/Provider/hf/HuggingFaceInference.py
+1
-1
Modified
g4f/Provider/hf_space/G4F.py
+20
-6
Modified
g4f/Provider/hf_space/Janus_Pro_7B.py
+2
-3
Modified
g4f/Provider/hf_space/__init__.py
+9
-5
Modified
g4f/gui/client/index.html
+7
-2
Modified
g4f/gui/client/static/css/style.css
+4
-0
Modified
g4f/gui/client/static/js/chat.v1.js
+4
-6
Modified
g4f/gui/server/backend_api.py
+7
-4
XFEstudio/gpt4free
Remove login url from error message Remove print in CablyAI Fix Vision Support in HuggingSpace provider Support images in BackendApi provider Add missing import in Blackbox provider
88918cb8
代码差异
10 个文件
+55
-29
@@ -15,7 +15,7 @@ from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
15
15
from ..image import to_data_uri
16
16
from ..cookies import get_cookies_dir
17
17
from .helper import format_prompt, format_image_prompt
18
from ..providers.response import JsonConversation, ImageResponse
18
from ..providers.response import JsonConversation, ImageResponse, Reasoning
19
19
20
20
class Conversation(JsonConversation):
21
21
validated_value: str = None
@@ -87,7 +87,6 @@ class CablyAI(AsyncGeneratorProvider, ProviderModelMixin):
87
87
continue
88
88
89
89
line = line.decode('utf-8').strip()
90
print(line)
91
90
92
91
if not line.startswith("data: "):
93
92
continue
@@ -148,7 +148,7 @@ class HuggingFaceInference(AsyncGeneratorProvider, ProviderModelMixin):
148
148
if response.headers["content-type"].startswith("image/"):
149
149
base64_data = base64.b64encode(b"".join([chunk async for chunk in response.iter_content()]))
150
150
url = f"data:{response.headers['content-type']};base64,{base64_data.decode()}"
151
yield ImageResponse(url, prompt)
151
yield ImageResponse(url, inputs)
152
152
else:
153
153
yield (await response.json())[0]["generated_text"].strip()
154
154
@@ -2,14 +2,16 @@ from __future__ import annotations
2
2
3
3
from aiohttp import ClientSession
4
4
import time
5
import asyncio
5
6
6
7
from ...typing import AsyncResult, Messages
7
from ...providers.response import ImageResponse
8
from ...providers.response import ImageResponse, Reasoning
8
9
from ...requests.raise_for_status import raise_for_status
9
10
from ..helper import format_image_prompt, get_random_string
10
11
from .Janus_Pro_7B import Janus_Pro_7B, JsonConversation, get_zerogpu_token
11
12
12
13
class G4F(Janus_Pro_7B):
14
label = "G4F framework"
13
15
space = "roxky/Janus-Pro-7B"
14
16
url = f"https://huggingface.co/spaces/roxky/g4f-space"
15
17
api_url = "https://roxky-janus-pro-7b.hf.space"
@@ -62,13 +64,25 @@ class G4F(Janus_Pro_7B):
62
64
"trigger_id": 10
63
65
}
64
66
async with ClientSession() as session:
67
yield Reasoning(status="Acquiring GPU Token")
65
68
zerogpu_uuid, zerogpu_token = await get_zerogpu_token(cls.space, session, JsonConversation(), cookies)
66
69
headers = {
67
70
"x-zerogpu-token": zerogpu_token,
68
71
"x-zerogpu-uuid": zerogpu_uuid,
69
72
}
70
async with session.post(cls.url_flux, json=payload, proxy=proxy, headers=headers) as response:
71
await raise_for_status(response)
72
response_data = await response.json()
73
image_url = response_data["data"][0]['url']
74
yield ImageResponse(images=[image_url], alt=prompt)
73
async def generate():
74
async with session.post(cls.url_flux, json=payload, proxy=proxy, headers=headers) as response:
75
await raise_for_status(response)
76
response_data = await response.json()
77
image_url = response_data["data"][0]['url']
78
return ImageResponse(images=[image_url], alt=prompt)
79
background_tasks = set()
80
started = time.time()
81
task = asyncio.create_task(generate())
82
background_tasks.add(task)
83
task.add_done_callback(background_tasks.discard)
84
while background_tasks:
85
yield Reasoning(status=f"Generating {time.time() - started:.2f}s")
86
await asyncio.sleep(0.2)
87
yield await task
88
yield Reasoning(status=f"Finished {time.time() - started:.2f}s")
@@ -82,10 +82,8 @@ class Janus_Pro_7B(AsyncGeneratorProvider, ProviderModelMixin):
82
82
method = "post"
83
83
if model == cls.default_image_model or prompt is not None:
84
84
method = "image"
85
86
85
prompt = format_prompt(messages) if prompt is None and conversation is None else prompt
87
86
prompt = format_image_prompt(messages, prompt)
88
89
87
if seed is None:
90
88
seed = int(time.time())
91
89
@@ -139,7 +137,8 @@ class Janus_Pro_7B(AsyncGeneratorProvider, ProviderModelMixin):
139
137
140
138
if json_data.get('msg') == 'process_completed':
141
139
if 'output' in json_data and 'error' in json_data['output']:
142
raise ResponseError("Missing image input" if json_data['output']['error'] and "AttributeError" in json_data['output']['error'] else json_data['output']['error'])
140
json_data['output']['error'] = json_data['output']['error'].split(" <a ")[0]
141
raise ResponseError("Missing images input" if json_data['output']['error'] and "AttributeError" in json_data['output']['error'] else json_data['output']['error'])
143
142
if 'output' in json_data and 'data' in json_data['output']:
144
143
yield Reasoning(status="Finished")
145
144
if "image" in json_data['output']['data'][0][0]:
@@ -27,10 +27,14 @@ class HuggingSpace(AsyncGeneratorProvider, ProviderModelMixin):
27
27
default_image_model = BlackForestLabsFlux1Dev.default_model
28
28
default_vision_model = Qwen_QVQ_72B.default_model
29
29
providers = [
30
BlackForestLabsFlux1Dev, BlackForestLabsFlux1Schnell,
30
BlackForestLabsFlux1Dev,
31
BlackForestLabsFlux1Schnell,
31
32
VoodoohopFlux1Schnell,
32
CohereForAI, Janus_Pro_7B,
33
Qwen_QVQ_72B, Qwen_Qwen_2_5M_Demo, Qwen_Qwen_2_72B_Instruct,
33
CohereForAI,
34
Janus_Pro_7B,
35
Qwen_QVQ_72B,
36
Qwen_Qwen_2_5M_Demo,
37
Qwen_Qwen_2_72B_Instruct,
34
38
StableDiffusion35Large,
35
39
G4F
36
40
]
@@ -70,7 +74,7 @@ class HuggingSpace(AsyncGeneratorProvider, ProviderModelMixin):
70
74
random.shuffle(cls.providers)
71
75
for provider in cls.providers:
72
76
if model in provider.model_aliases:
73
async for chunk in provider.create_async_generator(provider.model_aliases[model], messages, **kwargs):
77
async for chunk in provider.create_async_generator(provider.model_aliases[model], messages, images=images, **kwargs):
74
78
is_started = True
75
79
yield chunk
76
80
if is_started:
@@ -79,7 +83,7 @@ class HuggingSpace(AsyncGeneratorProvider, ProviderModelMixin):
79
83
for provider in cls.providers:
80
84
if model in provider.get_models():
81
85
try:
82
async for chunk in provider.create_async_generator(model, messages, **kwargs):
86
async for chunk in provider.create_async_generator(model, messages, images=images, **kwargs):
83
87
is_started = True
84
88
yield chunk
85
89
if is_started:
@@ -68,12 +68,17 @@
68
68
const currSlideElement = lightbox.pswp.currSlide.data.element;
69
69
if (currSlideElement) {
70
70
const img = currSlideElement.querySelector('img');
71
el.innerText = img.getAttribute('alt');
72
71
const download = document.createElement("a");
73
72
download.setAttribute("href", img.getAttribute('src'));
74
download.setAttribute("download", `${img.getAttribute('alt')}${lightbox.pswp.currSlide.index}.jpg`);
73
let extension = img.getAttribute('src').includes(".webp") ? ".webp" : ".jpg";
74
download.setAttribute("download", `${img.getAttribute('alt')} ${lightbox.pswp.currSlide.index}${extension}`);
75
download.style.float = "right";
75
76
download.innerHTML = '<i class="fa-solid fa-download"></i>';
77
let span = document.createElement("span");
78
span.innerText = img.getAttribute('alt');
79
el.innerHTML = '';
76
80
el.appendChild(download);
81
el.appendChild(span);
77
82
}
78
83
});
79
84
}
@@ -1165,6 +1165,10 @@ ul {
1165
1165
.settings h3 {
1166
1166
text-align: center;
1167
1167
}
1168
1169
.field.collapsible {
1170
flex-direction: column;
1171
}
1168
1172
}
1169
1173
1170
1174
.shown {
@@ -1023,14 +1023,11 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi
1023
1023
let api_key;
1024
1024
if (is_demo && provider == "Feature") {
1025
1025
api_key = localStorage.getItem("user");
1026
} else if (is_demo && provider != "Custom") {
1026
} else if (is_demo) {
1027
1027
api_key = localStorage.getItem("HuggingFace-api_key");
1028
1028
} else {
1029
1029
api_key = get_api_key_by_provider(provider);
1030
1030
}
1031
if (is_demo && !api_key) {
1032
api_key = localStorage.getItem("HuggingFace-api_key");
1033
}
1034
1031
if (is_demo && !api_key) {
1035
1032
location.href = "/";
1036
1033
return;
@@ -2005,7 +2002,9 @@ async function on_api() {
2005
2002
providerSelect.innerHTML = `
2006
2003
<option value="">Demo Mode</option>
2007
2004
<option value="Feature">Feature Provider</option>
2008
<option value="Custom">Custom Provider</option>`;
2005
<option value="G4F">G4F framework</option>
2006
<option value="HuggingFace">HuggingFace</option>
2007
<option value="HuggingSpace">HuggingSpace</option>`;
2009
2008
providerSelect.selectedIndex = 0;
2010
2009
document.getElementById("pin").disabled = true;
2011
2010
document.getElementById("refine")?.parentElement.classList.add("hidden")
@@ -2018,7 +2017,6 @@ async function on_api() {
2018
2017
}
2019
2018
});
2020
2019
login_urls = {
2021
"Custom": ["Custom Provider", "", []],
2022
2020
"HuggingFace": ["HuggingFace", "", []],
2023
2021
};
2024
2022
} else {
@@ -116,7 +116,7 @@ class Backend_Api(Api):
116
116
}
117
117
for model, providers in models.demo_models.values()]
118
118
119
def handle_conversation():
119
def handle_conversation(limiter_check: callable = None):
120
120
"""
121
121
Handles conversation requests and streams responses back.
122
122
@@ -135,7 +135,7 @@ class Backend_Api(Api):
135
135
else:
136
136
json_data = request.json
137
137
138
if app.demo and json_data.get("provider") not in ["Custom", "Feature"]:
138
if app.demo and json_data.get("provider") not in ["Custom", "Feature", "HuggingFace", "HuggingSpace", "G4F"]:
139
139
model = json_data.get("model")
140
140
if model != "default" and model in models.demo_models:
141
141
json_data["provider"] = random.choice(models.demo_models[model][1])
@@ -143,6 +143,10 @@ class Backend_Api(Api):
143
143
if not model or model == "default":
144
144
json_data["model"] = models.demo_models["default"][0].name
145
145
json_data["provider"] = random.choice(models.demo_models["default"][1])
146
if limiter_check is not None and json_data.get("provider") in ["Feature"]:
147
limiter_check()
148
if "images" in json_data:
149
kwargs["images"] = json_data["images"]
146
150
kwargs = self._prepare_conversation_kwargs(json_data, kwargs)
147
151
return self.app.response_class(
148
152
self._create_response_stream(
@@ -158,8 +162,7 @@ class Backend_Api(Api):
158
162
@app.route('/backend-api/v2/conversation', methods=['POST'])
159
163
@limiter.limit("2 per minute")
160
164
def _handle_conversation():
161
limiter.check()
162
return handle_conversation()
165
return handle_conversation(limiter.check)
163
166
else:
164
167
@app.route('/backend-api/v2/conversation', methods=['POST'])
165
168
def _handle_conversation():