返回提交历史
Modified
g4f/Provider/Blackbox.py
+113
-337
XFEstudio/gpt4free
Update (g4f/Provider/Blackbox.py)
36aecbd6
代码差异
1 个文件
+113
-337
@@ -1,21 +1,15 @@
1
1
from __future__ import annotations
2
2
3
import asyncio
4
import aiohttp
3
from aiohttp import ClientSession
5
4
import random
6
5
import string
7
6
import json
8
import uuid
9
7
import re
10
from typing import Optional, AsyncGenerator, Union
11
12
from aiohttp import ClientSession, ClientResponseError
13
8
14
9
from ..typing import AsyncResult, Messages, ImageType
15
10
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
16
11
from ..image import ImageResponse, to_data_uri
17
12
18
19
13
class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
20
14
label = "Blackbox AI"
21
15
url = "https://www.blackbox.ai"
@@ -24,154 +18,89 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
24
18
supports_stream = True
25
19
supports_system_message = True
26
20
supports_message_history = True
27
21
28
22
default_model = 'blackboxai'
29
image_models = ['ImageGeneration']
30
models = [
31
default_model,
32
'blackboxai-pro',
33
*image_models,
34
"llama-3.1-8b",
35
'llama-3.1-70b',
36
'llama-3.1-405b',
37
'gpt-4o',
38
'gemini-pro',
39
'gemini-1.5-flash',
40
'claude-sonnet-3.5',
41
'PythonAgent',
42
'JavaAgent',
43
'JavaScriptAgent',
44
'HTMLAgent',
45
'GoogleCloudAgent',
46
'AndroidDeveloper',
47
'SwiftDeveloper',
48
'Next.jsAgent',
49
'MongoDBAgent',
50
'PyTorchAgent',
51
'ReactAgent',
52
'XcodeAgent',
53
'AngularJSAgent',
54
'HerokuAgent',
55
'GodotAgent',
56
'GoAgent',
57
'GitlabAgent',
58
'GitAgent',
59
'RepoMap',
60
'FlaskAgent',
61
'FirebaseAgent',
62
'FastAPIAgent',
63
'ErlangAgent',
64
'ElectronAgent',
65
'DockerAgent',
66
'DigitalOceanAgent',
67
'BitbucketAgent',
68
'AzureAgent',
69
'FlutterAgent',
70
'YoutubeAgent',
71
'builderAgent',
72
]
73
23
24
image_models = ['Image Generation', 'repomap']
25
26
userSelectedModel = ['gpt-4o', 'gemini-pro', 'claude-sonnet-3.5', 'blackboxai-pro']
27
74
28
agentMode = {
75
'ImageGeneration': {'mode': True, 'id': "ImageGenerationLV45LJp", 'name': "Image Generation"},
29
'Image Generation': {'mode': True, 'id': "ImageGenerationLV45LJp", 'name': "Image Generation"},
76
30
}
77
31
78
32
trendingAgentMode = {
79
"blackboxai": {},
80
"blackboxai": {},
81
33
"gemini-1.5-flash": {'mode': True, 'id': 'Gemini'},
82
34
"llama-3.1-8b": {'mode': True, 'id': "llama-3.1-8b"},
83
35
'llama-3.1-70b': {'mode': True, 'id': "llama-3.1-70b"},
84
'llama-3.1-405b': {'mode': True, 'id': "llama-3.1-405b"},
36
#
37
'Python Agent': {'mode': True, 'id': "Python Agent"},
38
'Java Agent': {'mode': True, 'id': "Java Agent"},
39
'JavaScript Agent': {'mode': True, 'id': "JavaScript Agent"},
40
'HTML Agent': {'mode': True, 'id': "HTML Agent"},
41
'Google Cloud Agent': {'mode': True, 'id': "Google Cloud Agent"},
42
'Android Developer': {'mode': True, 'id': "Android Developer"},
43
'Swift Developer': {'mode': True, 'id': "Swift Developer"},
44
'Next.js Agent': {'mode': True, 'id': "Next.js Agent"},
45
'MongoDB Agent': {'mode': True, 'id': "MongoDB Agent"},
46
'PyTorch Agent': {'mode': True, 'id': "PyTorch Agent"},
47
'React Agent': {'mode': True, 'id': "React Agent"},
48
'Xcode Agent': {'mode': True, 'id': "Xcode Agent"},
49
'AngularJS Agent': {'mode': True, 'id': "AngularJS Agent"},
85
50
'blackboxai-pro': {'mode': True, 'id': "BLACKBOXAI-PRO"},
86
'PythonAgent': {'mode': True, 'id': "Python Agent"},
87
'JavaAgent': {'mode': True, 'id': "Java Agent"},
88
'JavaScriptAgent': {'mode': True, 'id': "JavaScript Agent"},
89
'HTMLAgent': {'mode': True, 'id': "HTML Agent"},
90
'GoogleCloudAgent': {'mode': True, 'id': "Google Cloud Agent"},
91
'AndroidDeveloper': {'mode': True, 'id': "Android Developer"},
92
'SwiftDeveloper': {'mode': True, 'id': "Swift Developer"},
93
'Next.jsAgent': {'mode': True, 'id': "Next.js Agent"},
94
'MongoDBAgent': {'mode': True, 'id': "MongoDB Agent"},
95
'PyTorchAgent': {'mode': True, 'id': "PyTorch Agent"},
96
'ReactAgent': {'mode': True, 'id': "React Agent"},
97
'XcodeAgent': {'mode': True, 'id': "Xcode Agent"},
98
'AngularJSAgent': {'mode': True, 'id': "AngularJS Agent"},
99
'HerokuAgent': {'mode': True, 'id': "Heroku Agent"},
100
'GodotAgent': {'mode': True, 'id': "Godot Agent"},
101
'GoAgent': {'mode': True, 'id': "Go Agent"},
102
'GitlabAgent': {'mode': True, 'id': "Gitlab Agent"},
103
'GitAgent': {'mode': True, 'id': "Git Agent"},
104
'RepoMap': {'mode': True, 'id': "RepoMap"},
105
'FlaskAgent': {'mode': True, 'id': "Flask Agent"},
106
'FirebaseAgent': {'mode': True, 'id': "Firebase Agent"},
107
'FastAPIAgent': {'mode': True, 'id': "FastAPI Agent"},
108
'ErlangAgent': {'mode': True, 'id': "Erlang Agent"},
109
'ElectronAgent': {'mode': True, 'id': "Electron Agent"},
110
'DockerAgent': {'mode': True, 'id': "Docker Agent"},
111
'DigitalOceanAgent': {'mode': True, 'id': "DigitalOcean Agent"},
112
'BitbucketAgent': {'mode': True, 'id': "Bitbucket Agent"},
113
'AzureAgent': {'mode': True, 'id': "Azure Agent"},
114
'FlutterAgent': {'mode': True, 'id': "Flutter Agent"},
115
'YoutubeAgent': {'mode': True, 'id': "Youtube Agent"},
116
'builderAgent': {'mode': True, 'id': "builder Agent"},
117
}
118
119
userSelectedModel = {
120
"gpt-4o": "gpt-4o",
121
"gemini-pro": "gemini-pro",
122
'claude-sonnet-3.5': "claude-sonnet-3.5",
123
}
124
125
model_prefixes = {
126
'gpt-4o': '@GPT-4o',
127
'gemini-pro': '@Gemini-PRO',
128
'PythonAgent': '@Python Agent',
129
'JavaAgent': '@Java Agent',
130
'JavaScriptAgent': '@JavaScript Agent',
131
'HTMLAgent': '@HTML Agent',
132
'GoogleCloudAgent': '@Google Cloud Agent',
133
'AndroidDeveloper': '@Android Developer',
134
'SwiftDeveloper': '@Swift Developer',
135
'Next.jsAgent': '@Next.js Agent',
136
'MongoDBAgent': '@MongoDB Agent',
137
'PyTorchAgent': '@PyTorch Agent',
138
'ReactAgent': '@React Agent',
139
'XcodeAgent': '@Xcode Agent',
140
'AngularJSAgent': '@AngularJS Agent',
141
'HerokuAgent': '@Heroku Agent',
142
'GodotAgent': '@Godot Agent',
143
'GoAgent': '@Go Agent',
144
'GitlabAgent': '@Gitlab Agent',
145
'GitAgent': '@Git Agent',
146
'blackboxai-pro': '@BLACKBOXAI-PRO',
147
'ImageGeneration': '@Image Generation',
148
'FlaskAgent': '@Flask Agent',
149
'FirebaseAgent': '@Firebase Agent',
150
'FastAPIAgent': '@FastAPI Agent',
151
'ErlangAgent': '@Erlang Agent',
152
'ElectronAgent': '@Electron Agent',
153
'DockerAgent': '@Docker Agent',
154
'DigitalOceanAgent': '@DigitalOcean Agent',
155
'BitbucketAgent': '@Bitbucket Agent',
156
'AzureAgent': '@Azure Agent',
157
'FlutterAgent': '@Flutter Agent',
158
'YoutubeAgent': '@Youtube Agent',
159
'builderAgent': '@builder Agent',
160
}
161
162
model_referers = {
163
"blackboxai": "/?model=blackboxai",
164
"gpt-4o": "/?model=gpt-4o",
165
"gemini-pro": "/?model=gemini-pro",
166
"claude-sonnet-3.5": "/?model=claude-sonnet-3.5"
51
#
52
'repomap': {'mode': True, 'id': "repomap"},
53
#
54
'Heroku Agent': {'mode': True, 'id': "Heroku Agent"},
55
'Godot Agent': {'mode': True, 'id': "Godot Agent"},
56
'Go Agent': {'mode': True, 'id': "Go Agent"},
57
'Gitlab Agent': {'mode': True, 'id': "Gitlab Agent"},
58
'Git Agent': {'mode': True, 'id': "Git Agent"},
59
'Flask Agent': {'mode': True, 'id': "Flask Agent"},
60
'Firebase Agent': {'mode': True, 'id': "Firebase Agent"},
61
'FastAPI Agent': {'mode': True, 'id': "FastAPI Agent"},
62
'Erlang Agent': {'mode': True, 'id': "Erlang Agent"},
63
'Electron Agent': {'mode': True, 'id': "Electron Agent"},
64
'Docker Agent': {'mode': True, 'id': "Docker Agent"},
65
'DigitalOcean Agent': {'mode': True, 'id': "DigitalOcean Agent"},
66
'Bitbucket Agent': {'mode': True, 'id': "Bitbucket Agent"},
67
'Azure Agent': {'mode': True, 'id': "Azure Agent"},
68
'Flutter Agent': {'mode': True, 'id': "Flutter Agent"},
69
'Youtube Agent': {'mode': True, 'id': "Youtube Agent"},
70
'builder Agent': {'mode': True, 'id': "builder Agent"},
167
71
}
72
73
model_prefixes = {mode: f"@{value['id']}" for mode, value in trendingAgentMode.items() if mode not in ["gemini-1.5-flash", "llama-3.1-8b", "llama-3.1-70b", "repomap"]}
168
74
75
76
models = [default_model, *userSelectedModel, *list(agentMode.keys()), *list(trendingAgentMode.keys())]
77
169
78
model_aliases = {
170
79
"gemini-flash": "gemini-1.5-flash",
171
80
"claude-3.5-sonnet": "claude-sonnet-3.5",
172
"flux": "ImageGeneration",
81
"flux": "Image Generation",
173
82
}
174
83
84
@staticmethod
85
def generate_id(length=7):
86
characters = string.ascii_letters + string.digits
87
return ''.join(random.choice(characters) for _ in range(length))
88
89
@classmethod
90
def add_prefix_to_messages(cls, messages: Messages, model: str) -> Messages:
91
prefix = cls.model_prefixes.get(model, "")
92
if not prefix:
93
return messages
94
95
new_messages = []
96
for message in messages:
97
new_message = message.copy()
98
if message['role'] == 'user':
99
new_message['content'] = (prefix + " " + message['content']).strip()
100
new_messages.append(new_message)
101
102
return new_messages
103
175
104
@classmethod
176
105
def get_model(cls, model: str) -> str:
177
106
if model in cls.models:
@@ -181,140 +110,54 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
181
110
else:
182
111
return cls.default_model
183
112
184
@staticmethod
185
def generate_random_string(length: int = 7) -> str:
186
characters = string.ascii_letters + string.digits
187
return ''.join(random.choices(characters, k=length))
188
189
@staticmethod
190
def generate_next_action() -> str:
191
return uuid.uuid4().hex
192
193
@staticmethod
194
def generate_next_router_state_tree() -> str:
195
router_state = [
196
"",
197
{
198
"children": [
199
"(chat)",
200
{
201
"children": [
202
"__PAGE__",
203
{}
204
]
205
}
206
]
207
},
208
None,
209
None,
210
True
211
]
212
return json.dumps(router_state)
213
214
@staticmethod
215
def clean_response(text: str) -> str:
216
pattern = r'^\$\@\$v=undefined-rv1\$\@\$'
217
cleaned_text = re.sub(pattern, '', text)
218
return cleaned_text
219
220
113
@classmethod
221
114
async def create_async_generator(
222
115
cls,
223
116
model: str,
224
117
messages: Messages,
225
proxy: Optional[str] = None,
118
proxy: str = None,
119
web_search: bool = False,
226
120
image: ImageType = None,
227
121
image_name: str = None,
228
web_search: bool = False,
229
122
**kwargs
230
) -> AsyncGenerator[Union[str, ImageResponse], None]:
231
"""
232
Creates an asynchronous generator for streaming responses from Blackbox AI.
233
234
Parameters:
235
model (str): Model to use for generating responses.
236
messages (Messages): Message history.
237
proxy (Optional[str]): Proxy URL, if needed.
238
image (ImageType): Image data to be processed, if any.
239
image_name (str): Name of the image file, if an image is provided.
240
web_search (bool): Enables or disables web search mode.
241
**kwargs: Additional keyword arguments.
123
) -> AsyncResult:
124
model = cls.get_model(model)
125
message_id = cls.generate_id()
126
messages_with_prefix = cls.add_prefix_to_messages(messages, model)
242
127
243
Yields:
244
Union[str, ImageResponse]: Segments of the generated response or ImageResponse objects.
245
"""
246
247
128
if image is not None:
248
messages[-1]['data'] = {
129
messages_with_prefix[-1]['data'] = {
249
130
'fileText': '',
250
131
'imageBase64': to_data_uri(image),
251
132
'title': image_name
252
133
}
253
messages[-1]['content'] = 'FILE:BB\n$#$\n\n$#$\n' + messages[-1]['content']
254
255
model = cls.get_model(model)
256
257
chat_id = cls.generate_random_string()
258
next_action = cls.generate_next_action()
259
next_router_state_tree = cls.generate_next_router_state_tree()
260
134
261
agent_mode = cls.agentMode.get(model, {})
262
trending_agent_mode = cls.trendingAgentMode.get(model, {})
263
264
prefix = cls.model_prefixes.get(model, "")
265
266
formatted_prompt = ""
267
for message in messages:
268
role = message.get('role', '').capitalize()
269
content = message.get('content', '')
270
if role and content:
271
formatted_prompt += f"{role}: {content}\n"
272
273
if prefix:
274
formatted_prompt = f"{prefix} {formatted_prompt}".strip()
275
276
referer_path = cls.model_referers.get(model, f"/?model={model}")
277
referer_url = f"{cls.url}{referer_path}"
278
279
common_headers = {
135
headers = {
280
136
'accept': '*/*',
281
137
'accept-language': 'en-US,en;q=0.9',
282
138
'cache-control': 'no-cache',
139
'content-type': 'application/json',
283
140
'origin': cls.url,
284
141
'pragma': 'no-cache',
285
142
'priority': 'u=1, i',
286
'sec-ch-ua': '"Chromium";v="129", "Not=A?Brand";v="8"',
143
'referer': f'{cls.url}/',
144
'sec-ch-ua': '"Not?A_Brand";v="99", "Chromium";v="130"',
287
145
'sec-ch-ua-mobile': '?0',
288
146
'sec-ch-ua-platform': '"Linux"',
289
147
'sec-fetch-dest': 'empty',
290
148
'sec-fetch-mode': 'cors',
291
149
'sec-fetch-site': 'same-origin',
292
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) '
293
'AppleWebKit/537.36 (KHTML, like Gecko) '
294
'Chrome/129.0.0.0 Safari/537.36'
295
}
296
297
headers_api_chat = {
298
'Content-Type': 'application/json',
299
'Referer': referer_url
150
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
300
151
}
301
headers_api_chat_combined = {**common_headers, **headers_api_chat}
302
303
payload_api_chat = {
304
"messages": [
305
{
306
"id": chat_id,
307
"content": formatted_prompt,
308
"role": "user",
309
"data": messages[-1].get('data')
310
}
311
],
312
"id": chat_id,
152
153
data = {
154
"messages": messages_with_prefix,
155
"id": message_id,
313
156
"previewToken": None,
314
157
"userId": None,
315
158
"codeModelMode": True,
316
"agentMode": agent_mode,
317
"trendingAgentMode": trending_agent_mode,
159
"agentMode": cls.agentMode.get(model, {}) if model in cls.agentMode else {},
160
"trendingAgentMode": cls.trendingAgentMode.get(model, {}) if model in cls.trendingAgentMode else {},
318
161
"isMicMode": False,
319
162
"userSystemPrompt": None,
320
163
"maxTokens": 1024,
@@ -327,100 +170,33 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
327
170
"clickedForceWebSearch": False,
328
171
"visitFromDelta": False,
329
172
"mobileClient": False,
173
"userSelectedModel": model if model in cls.userSelectedModel else None,
330
174
"webSearchMode": web_search,
331
"userSelectedModel": cls.userSelectedModel.get(model, model),
332
175
"validated": "69783381-2ce4-4dbd-ac78-35e9063feabc"
333
176
}
334
177
335
headers_chat = {
336
'Accept': 'text/x-component',
337
'Content-Type': 'text/plain;charset=UTF-8',
338
'Referer': f'{cls.url}/chat/{chat_id}?model={model}',
339
'next-action': next_action,
340
'next-router-state-tree': next_router_state_tree,
341
'next-url': '/'
342
}
343
headers_chat_combined = {**common_headers, **headers_chat}
344
345
data_chat = '[]'
346
347
async with ClientSession(headers=common_headers) as session:
348
try:
349
async with session.post(
350
cls.api_endpoint,
351
headers=headers_api_chat_combined,
352
json=payload_api_chat,
353
proxy=proxy
354
) as response_api_chat:
355
response_api_chat.raise_for_status()
356
text = await response_api_chat.text()
357
cleaned_response = cls.clean_response(text)
358
359
if model in cls.image_models:
360
match = re.search(r'!\[.*?\]\((https?://[^\)]+)\)', cleaned_response)
361
if match:
362
image_url = match.group(1)
363
image_response = ImageResponse(images=image_url, alt="Generated Image")
364
yield image_response
365
else:
366
yield cleaned_response
367
else:
368
if web_search:
369
match = re.search(r'\$~~~\$(.*?)\$~~~\$', cleaned_response, re.DOTALL)
370
if match:
371
source_part = match.group(1).strip()
372
answer_part = cleaned_response[match.end():].strip()
373
try:
374
sources = json.loads(source_part)
375
source_formatted = "**Source:**\n"
376
for item in sources:
377
title = item.get('title', 'No Title')
378
link = item.get('link', '#')
379
position = item.get('position', '')
380
source_formatted += f"{position}. [{title}]({link})\n"
381
final_response = f"{answer_part}\n\n{source_formatted}"
382
except json.JSONDecodeError:
383
final_response = f"{answer_part}\n\nSource information is unavailable."
384
else:
385
final_response = cleaned_response
386
else:
387
if '$~~~$' in cleaned_response:
388
final_response = cleaned_response.split('$~~~$')[0].strip()
389
else:
390
final_response = cleaned_response
391
392
yield final_response
393
except ClientResponseError as e:
394
error_text = f"Error {e.status}: {e.message}"
395
try:
396
error_response = await e.response.text()
397
cleaned_error = cls.clean_response(error_response)
398
error_text += f" - {cleaned_error}"
399
except Exception:
400
pass
401
yield error_text
402
except Exception as e:
403
yield f"Unexpected error during /api/chat request: {str(e)}"
404
405
chat_url = f'{cls.url}/chat/{chat_id}?model={model}'
406
407
try:
408
async with session.post(
409
chat_url,
410
headers=headers_chat_combined,
411
data=data_chat,
412
proxy=proxy
413
) as response_chat:
414
response_chat.raise_for_status()
415
pass
416
except ClientResponseError as e:
417
error_text = f"Error {e.status}: {e.message}"
418
try:
419
error_response = await e.response.text()
420
cleaned_error = cls.clean_response(error_response)
421
error_text += f" - {cleaned_error}"
422
except Exception:
423
pass
424
yield error_text
425
except Exception as e:
426
yield f"Unexpected error during /chat/{chat_id} request: {str(e)}"
178
async with ClientSession(headers=headers) as session:
179
async with session.post(cls.api_endpoint, json=data, proxy=proxy) as response:
180
response.raise_for_status()
181
response_text = await response.text()
182
183
if model in cls.image_models:
184
image_matches = re.findall(r'!\[.*?\]\((https?://[^\)]+)\)', response_text)
185
if image_matches:
186
image_url = image_matches[0]
187
image_response = ImageResponse(images=[image_url], alt="Generated Image")
188
yield image_response
189
return
190
191
json_match = re.search(r'\$~~~\$(.*?)\$~~~\$', response_text, re.DOTALL)
192
if json_match:
193
search_results = json.loads(json_match.group(1))
194
answer = response_text.split('$~~~$')[-1].strip()
195
196
formatted_response = f"{answer}\n\n**Source:**"
197
for i, result in enumerate(search_results, 1):
198
formatted_response += f"\n{i}. {result['title']}: {result['link']}"
199
200
yield formatted_response
201
else:
202
yield response_text.strip()