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

XFEstudio/gpt4free

update providers and documentation with image handling improvements (#2451)

* refactor(g4f/Provider/Airforce.py): Enhance Airforce provider with dynamic model fetching * refactor(g4f/Provider/Blackbox.py): Enhance Blackbox AI provider configuration and streamline code * feat(g4f/Provider/RobocodersAPI.py): Add RobocodersAPI new async chat provider * refactor(g4f/client/__init__.py): Improve provider handling in async_generate method * refactor(g4f/models.py): Update provider configurations for multiple models * refactor(g4f/Provider/Blackbox.py): Streamline model configuration and improve response handling * feat(g4f/Provider/DDG.py): Enhance model support and improve conversation handling * refactor(g4f/Provider/Copilot.py): Enhance Copilot provider with model support * refactor(g4f/Provider/AmigoChat.py): update models and improve code structure * chore(g4f/Provider/not_working/AIUncensored.): move AIUncensored to not_working directory * chore(g4f/Provider/not_working/Allyfy.py): remove Allyfy provider * Update (g4f/Provider/not_working/AIUncensored.py g4f/Provider/not_working/__init__.py) * refactor(g4f/Provider/ChatGptEs.py): Implement format_prompt for message handling * refactor(g4f/Provider/Blackbox.py): Update message formatting and improve code structure * refactor(g4f/Provider/LLMPlayground.py): Enhance text generation and error handling * refactor(g4f/Provider/needs_auth/PollinationsAI.py): move PollinationsAI to needs_auth directory * refactor(g4f/Provider/Liaobots.py): Update Liaobots provider models and aliases * feat(g4f/Provider/DeepInfraChat.py): Add new DeepInfra models and aliases * Update (g4f/Provider/__init__.py) * Update (g4f/models.py) * g4f/models.py * Update g4f/models.py * Update g4f/Provider/LLMPlayground.py * Update (g4f/models.py g4f/Provider/Airforce.py g4f/Provider/__init__.py g4f/Provider/LLMPlayground.py) * Update g4f/Provider/__init__.py * refactor(g4f/Provider/Airforce.py): Enhance text generation with retry and timeout * Update g4f/Provider/AmigoChat.py g4f/Provider/__init__.py * refactor(g4f/Provider/Blackbox.py): update model prefixes and image handling Fixes #2445 - Update model prefixes for gpt-4o, gemini-pro, and claude-sonnet-3.5 - Add 'gpt-3.5-turbo' alias for 'blackboxai' model - Modify image handling in create_async_generator method - Add 'imageGenerationMode' and 'webSearchModePrompt' flags to API request - Remove redundant 'imageBase64' field from image data structure * New provider (g4f/Provider/Blackbox2.py) Support for model llama-3.1-70b text generation * docs(docs/async_client.md): update AsyncClient API guide with minor improvements - Improve formatting and readability of code examples - Add line breaks for better visual separation of sections - Fix minor typos and inconsistencies in text - Enhance clarity of explanations in various sections - Remove unnecessary whitespace * feat(docs/client.md): add response_format parameter - Add 'response_format' parameter to image generation examples - Specify 'url' format for standard image generation - Include 'b64_json' format for base64 encoded image response - Update documentation to reflect new parameter usage - Improve code examples for clarity and consistency * docs(README.md): update usage examples and add image generation - Update text generation example to use new Client API - Add image generation example with Client API - Update configuration section with new cookie setting instructions - Add response_format parameter to image generation example - Remove outdated information and reorganize sections - Update contributors list * refactor(g4f/client/__init__.py): optimize image processing and response handling - Modify _process_image_response to handle 'url' format without local saving - Update ImagesResponse construction to include 'created' timestamp - Simplify image processing logic for different response formats - Improve error handling and logging for image generation - Enhance type hints and docstrings for better code clarity * feat(g4f/models.py): update model providers and add new models - Add Blackbox2 to Provider imports - Update gpt-3.5-turbo best provider to Blackbox - Add Blackbox2 to llama-3.1-70b best providers - Rename dalle_3 to dall_e_3 and update its best providers - Add new models: solar_mini, openhermes_2_5, lfm_40b, zephyr_7b, neural_7b, mythomax_13b - Update ModelUtils.convert with new models and changes - Remove duplicate 'dalle-3' entry in ModelUtils.convert * refactor(Airforce): improve API handling and add authentication - Implement API key authentication with check_api_key method - Refactor image generation to use new imagine2 endpoint - Improve text generation with better error handling and streaming - Update model aliases and add new image models - Enhance content filtering for various model outputs - Replace StreamSession with aiohttp's ClientSession for async operations - Simplify model fetching logic and remove redundant code - Add is_image_model method for better model type checking - Update class attributes for better organization and clarity * feat(g4f/Provider/HuggingChat.py): update HuggingChat model list and aliases Request by @TheFirstNoob - Add 'Qwen/Qwen2.5-72B-Instruct' as the first model in the list - Update model aliases to include 'qwen-2.5-72b' - Reorder existing models in the list for consistency - Remove duplicate entry for 'Qwen/Qwen2.5-72B-Instruct' in models list * refactor(g4f/Provider/ReplicateHome.py): remove unused text models Request by @TheFirstNoob - Removed the 'meta/meta-llama-3-70b-instruct' and 'mistralai/mixtral-8x7b-instruct-v0.1' text models from the list - Updated the list to only include the remaining text and image models - This change simplifies the model configuration and reduces the number of available models, focusing on the core text and image models provided by Replicate * refactor(g4f/Provider/HuggingChat.py): Move HuggingChat to needs_auth directory Request by @TheFirstNoob * Update (g4f/Provider/needs_auth/HuggingChat.py) * Update g4f/models.py * Update g4f/Provider/Airforce.py * Update g4f/models.py g4f/Provider/needs_auth/HuggingChat.py * Added 'Airforce' provider to the 'o1-mini' model (g4f/models.py) * Update (g4f/Provider/Airforce.py g4f/Provider/AmigoChat.py) * Update g4f/models.py g4f/Provider/DeepInfraChat.py g4f/Provider/Airforce.py * Update g4f/Provider/DeepInfraChat.py * Update (g4f/Provider/DeepInfraChat.py) * Update g4f/Provider/Blackbox.py * Update (docs/client.md docs/async_client.md g4f/client/__init__.py) * Update (docs/async_client.md docs/client.md) * Update (g4f/client/__init__.py) --------- Co-authored-by: kqlio67 <kqlio67@users.noreply.github.com> Co-authored-by: kqlio67 <> Co-authored-by: H Lohaus <hlohaus@users.noreply.github.com>

b198d900
kqlio67 <166700875+kqlio67@users.noreply.github.com>
提交于

代码差异

16 个文件 +372 -258
Modified README.md +1 -0
@@ -196,6 +196,7 @@ client = Client()
196 196 response = client.images.generate(
197 197 model="flux",
198 198 prompt="a white siamese cat",
199 response_format="url"
199 200 # Add any other necessary parameters
200 201 )
201 202
Modified docs/async_client.md +11 -2
@@ -164,6 +164,11 @@ asyncio.run(main())
164 164 ```
165 165
166 166 ### Image Generation
167 **The `response_format` parameter is optional and can have the following values:**
168 - **If not specified (default):** The image will be saved locally, and a local path will be returned (e.g., "/images/1733331238_cf9d6aa9-f606-4fea-ba4b-f06576cba309.jpg").
169 - **"url":** Returns a URL to the generated image.
170 - **"b64_json":** Returns the image as a base64-encoded JSON string.
171
167 172 **Generate images using a specified prompt:**
168 173 ```python
169 174 import asyncio
@@ -174,7 +179,9 @@ async def main():
174 179
175 180 response = await client.images.generate(
176 181 prompt="a white siamese cat",
177 model="flux"
182 model="flux",
183 response_format="url"
184 # Add any other necessary parameters
178 185 )
179 186
180 187 image_url = response.data[0].url
@@ -195,6 +202,7 @@ async def main():
195 202 prompt="a white siamese cat",
196 203 model="flux",
197 204 response_format="b64_json"
205 # Add any other necessary parameters
198 206 )
199 207
200 208 base64_text = response.data[0].b64_json
@@ -224,7 +232,8 @@ async def main():
224 232
225 233 task2 = client.images.generate(
226 234 model="flux",
227 prompt="a white siamese cat"
235 prompt="a white siamese cat",
236 response_format="url"
228 237 )
229 238
230 239 try:
Modified docs/client.md +8 -1
@@ -130,6 +130,11 @@ for chunk in stream:
130 130 ```
131 131
132 132 ### Image Generation
133 **The `response_format` parameter is optional and can have the following values:**
134 - **If not specified (default):** The image will be saved locally, and a local path will be returned (e.g., "/images/1733331238_cf9d6aa9-f606-4fea-ba4b-f06576cba309.jpg").
135 - **"url":** Returns a URL to the generated image.
136 - **"b64_json":** Returns the image as a base64-encoded JSON string.
137
133 138 **Generate images using a specified prompt:**
134 139 ```python
135 140 from g4f.client import Client
@@ -138,7 +143,8 @@ client = Client()
138 143
139 144 response = client.images.generate(
140 145 model="flux",
141 prompt="a white siamese cat"
146 prompt="a white siamese cat",
147 response_format="url"
142 148 # Add any other necessary parameters
143 149 )
144 150
@@ -157,6 +163,7 @@ response = client.images.generate(
157 163 model="flux",
158 164 prompt="a white siamese cat",
159 165 response_format="b64_json"
166 # Add any other necessary parameters
160 167 )
161 168
162 169 base64_text = response.data[0].b64_json
Modified g4f/Provider/Airforce.py +167 -159
@@ -1,18 +1,17 @@
1 1 from __future__ import annotations
2
3 import random
4 2 import json
3 import random
5 4 import re
6
7 5 import requests
8 6 from requests.packages.urllib3.exceptions import InsecureRequestWarning
9 requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
10 7 from urllib.parse import quote
8 from aiohttp import ClientSession
11 9
12 10 from ..typing import AsyncResult, Messages
13 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
14 11 from ..image import ImageResponse
15 from ..requests import StreamSession, raise_for_status
12 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
13
14 requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
16 15
17 16 def split_message(message: str, max_length: int = 1000) -> list[str]:
18 17 """Splits the message into parts up to (max_length)."""
@@ -30,197 +29,203 @@ def split_message(message: str, max_length: int = 1000) -> list[str]:
30 29 class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
31 30 url = "https://llmplayground.net"
32 31 api_endpoint_completions = "https://api.airforce/chat/completions"
33 api_endpoint_imagine = "https://api.airforce/imagine2"
32 api_endpoint_imagine2 = "https://api.airforce/imagine2"
33
34 34 working = True
35 needs_auth = True
36 supports_stream = True
35 37 supports_system_message = True
36 38 supports_message_history = True
37 39
38 @classmethod
39 def fetch_completions_models(cls):
40 response = requests.get('https://api.airforce/models', verify=False)
41 response.raise_for_status()
42 data = response.json()
43 return [model['id'] for model in data['data']]
44
45 @classmethod
46 def fetch_imagine_models(cls):
47 response = requests.get('https://api.airforce/imagine/models', verify=False)
48 response.raise_for_status()
49 return response.json()
50
51 40 default_model = "gpt-4o-mini"
52 41 default_image_model = "flux"
53 additional_models_imagine = ["stable-diffusion-xl-base", "stable-diffusion-xl-lightning", "flux-1.1-pro"]
54 42
55 @classmethod
56 def get_models(cls):
57 if not cls.models:
58 cls.image_models = [*cls.fetch_imagine_models(), *cls.additional_models_imagine]
59 cls.models = [
60 *cls.fetch_completions_models(),
61 *cls.image_models
62 ]
63 return cls.models
64
65 model_aliases = {
66 ### completions ###
67 # openchat
43 additional_models_imagine = ["flux-1.1-pro", "dall-e-3"]
44
45 model_aliases = {
46 # Alias mappings for models
68 47 "openchat-3.5": "openchat-3.5-0106",
69
70 # deepseek-ai
71 48 "deepseek-coder": "deepseek-coder-6.7b-instruct",
72
73 # NousResearch
74 49 "hermes-2-dpo": "Nous-Hermes-2-Mixtral-8x7B-DPO",
75 50 "hermes-2-pro": "hermes-2-pro-mistral-7b",
76
77 # teknium
78 51 "openhermes-2.5": "openhermes-2.5-mistral-7b",
79
80 # liquid
81 52 "lfm-40b": "lfm-40b-moe",
82
83 # DiscoResearch
84 "german-7b": "discolm-german-7b-v1",
85
86 # meta-llama
53 "discolm-german-7b": "discolm-german-7b-v1",
87 54 "llama-2-7b": "llama-2-7b-chat-int8",
88 "llama-2-7b": "llama-2-7b-chat-fp16",
89 "llama-3.1-70b": "llama-3.1-70b-chat",
90 "llama-3.1-8b": "llama-3.1-8b-chat",
91 55 "llama-3.1-70b": "llama-3.1-70b-turbo",
92 "llama-3.1-8b": "llama-3.1-8b-turbo",
93
94 # inferless
95 56 "neural-7b": "neural-chat-7b-v3-1",
96
97 # HuggingFaceH4
98 57 "zephyr-7b": "zephyr-7b-beta",
99
100
101 ### imagine ###
102 58 "sdxl": "stable-diffusion-xl-base",
103 "sdxl": "stable-diffusion-xl-lightning",
104 59 "flux-pro": "flux-1.1-pro",
105 60 }
106 61
107 62 @classmethod
108 def create_async_generator(
63 def fetch_completions_models(cls):
64 response = requests.get('https://api.airforce/models', verify=False)
65 response.raise_for_status()
66 data = response.json()
67 return [model['id'] for model in data['data']]
68
69 @classmethod
70 def fetch_imagine_models(cls):
71 response = requests.get(
72 'https://api.airforce/imagine/models',
73 'https://api.airforce/v1/imagine2/models',
74 verify=False
75 )
76 response.raise_for_status()
77 return response.json()
78
79 image_models = fetch_imagine_models.__get__(None, object)() + additional_models_imagine
80
81 @classmethod
82 def is_image_model(cls, model: str) -> bool:
83 return model in cls.image_models
84
85 models = list(dict.fromkeys([default_model] +
86 fetch_completions_models.__get__(None, object)() +
87 image_models))
88
89 @classmethod
90 async def check_api_key(cls, api_key: str) -> bool:
91 """
92 Always returns True to allow all models.
93 """
94 if not api_key or api_key == "null":
95 return True # No restrictions if no key.
96
97 headers = {
98 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
99 "Accept": "*/*",
100 }
101
102 try:
103 async with ClientSession(headers=headers) as session:
104 async with session.get(f"https://api.airforce/check?key={api_key}") as response:
105 if response.status == 200:
106 data = await response.json()
107 return data.get('info') in ['Sponsor key', 'Premium key']
108 return False
109 except Exception as e:
110 print(f"Error checking API key: {str(e)}")
111 return False
112
113 @classmethod
114 async def generate_image(
109 115 cls,
110 116 model: str,
111 messages: Messages,
112 proxy: str = None,
113 prompt: str = None,
114 seed: int = None,
115 size: str = "1:1", # "1:1", "16:9", "9:16", "21:9", "9:21", "1:2", "2:1"
116 stream: bool = False,
117 **kwargs
117 prompt: str,
118 api_key: str,
119 size: str,
120 seed: int,
121 proxy: str = None
118 122 ) -> AsyncResult:
119 model = cls.get_model(model)
123 headers = {
124 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0",
125 "Accept": "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5",
126 "Accept-Encoding": "gzip, deflate, br, zstd",
127 "Content-Type": "application/json",
128 "Authorization": f"Bearer {api_key}",
129 }
130 params = {"model": model, "prompt": prompt, "size": size, "seed": seed}
120 131
121 if model in cls.image_models:
122 if prompt is None:
123 prompt = messages[-1]['content']
124 return cls._generate_image(model, prompt, proxy, seed, size)
125 else:
126 return cls._generate_text(model, messages, proxy, stream, **kwargs)
132 async with ClientSession(headers=headers) as session:
133 async with session.get(cls.api_endpoint_imagine2, params=params, proxy=proxy) as response:
134 if response.status == 200:
135 image_url = str(response.url)
136 yield ImageResponse(images=image_url, alt=f"Generated image: {prompt}")
137 else:
138 error_text = await response.text()
139 raise RuntimeError(f"Image generation failed: {response.status} - {error_text}")
127 140
128 141 @classmethod
129 async def _generate_image(
142 async def generate_text(
130 143 cls,
131 144 model: str,
132 prompt: str,
133 proxy: str = None,
134 seed: int = None,
135 size: str = "1:1",
136 **kwargs
145 messages: Messages,
146 max_tokens: int,
147 temperature: float,
148 top_p: float,
149 stream: bool,
150 api_key: str,
151 proxy: str = None
137 152 ) -> AsyncResult:
138 153 headers = {
139 "accept": "*/*",
140 "accept-language": "en-US,en;q=0.9",
141 "cache-control": "no-cache",
142 "user-agent": "Mozilla/5.0"
154 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0",
155 "Accept": "application/json, text/event-stream",
156 "Accept-Encoding": "gzip, deflate, br, zstd",
157 "Content-Type": "application/json",
158 "Authorization": f"Bearer {api_key}",
159 }
160 full_message = "\n".join([msg['content'] for msg in messages])
161 message_chunks = split_message(full_message, max_length=1000)
162
163 data = {
164 "messages": [{"role": "user", "content": chunk} for chunk in message_chunks],
165 "model": model,
166 "max_tokens": max_tokens,
167 "temperature": temperature,
168 "top_p": top_p,
169 "stream": stream,
143 170 }
144 if seed is None:
145 seed = random.randint(0, 100000)
146
147 async with StreamSession(headers=headers, proxy=proxy) as session:
148 params = {
149 "model": model,
150 "prompt": prompt,
151 "size": size,
152 "seed": seed
153 }
154 async with session.get(f"{cls.api_endpoint_imagine}", params=params) as response:
155 await raise_for_status(response)
156 content_type = response.headers.get('Content-Type', '').lower()
157
158 if 'application/json' in content_type:
159 raise RuntimeError(await response.json().get("error", {}).get("message"))
160 elif content_type.startswith("image/"):
161 image_url = f"{cls.api_endpoint_imagine}?model={model}&prompt={quote(prompt)}&size={size}&seed={seed}"
162 yield ImageResponse(images=image_url, alt=prompt)
171
172 async with ClientSession(headers=headers) as session:
173 async with session.post(cls.api_endpoint_completions, json=data, proxy=proxy) as response:
174 response.raise_for_status()
175
176 if stream:
177 async for line in response.content:
178 line = line.decode('utf-8').strip()
179 if line.startswith('data: '):
180 try:
181 json_str = line[6:] # Remove 'data: ' prefix
182 chunk = json.loads(json_str)
183 if 'choices' in chunk and chunk['choices']:
184 delta = chunk['choices'][0].get('delta', {})
185 if 'content' in delta:
186 filtered_content = cls._filter_response(delta['content'])
187 yield filtered_content
188 except json.JSONDecodeError:
189 continue
190 else:
191 # Non-streaming response
192 result = await response.json()
193 if 'choices' in result and result['choices']:
194 message = result['choices'][0].get('message', {})
195 content = message.get('content', '')
196 filtered_content = cls._filter_response(content)
197 yield filtered_content
163 198
164 199 @classmethod
165 async def _generate_text(
200 async def create_async_generator(
166 201 cls,
167 202 model: str,
168 203 messages: Messages,
204 prompt: str = None,
169 205 proxy: str = None,
170 stream: bool = False,
171 206 max_tokens: int = 4096,
172 207 temperature: float = 1,
173 208 top_p: float = 1,
209 stream: bool = True,
210 api_key: str = None,
211 size: str = "1:1",
212 seed: int = None,
174 213 **kwargs
175 214 ) -> AsyncResult:
176 headers = {
177 "accept": "*/*",
178 "accept-language": "en-US,en;q=0.9",
179 "authorization": "Bearer missing api key",
180 "content-type": "application/json",
181 "user-agent": "Mozilla/5.0"
182 }
215 if not await cls.check_api_key(api_key):
216 pass
183 217
184 full_message = "\n".join(
185 [f"{msg['role'].capitalize()}: {msg['content']}" for msg in messages]
186 )
187
188 message_chunks = split_message(full_message, max_length=1000)
189
190 async with StreamSession(headers=headers, proxy=proxy) as session:
191 full_response = ""
192 for chunk in message_chunks:
193 data = {
194 "messages": [{"role": "user", "content": chunk}],
195 "model": model,
196 "max_tokens": max_tokens,
197 "temperature": temperature,
198 "top_p": top_p,
199 "stream": stream
200 }
201
202 async with session.post(cls.api_endpoint_completions, json=data) as response:
203 await raise_for_status(response)
204 content_type = response.headers.get('Content-Type', '').lower()
205
206 if 'application/json' in content_type:
207 json_data = await response.json()
208 if json_data.get("model") == "error":
209 raise RuntimeError(json_data['choices'][0]['message'].get('content', ''))
210 if stream:
211 async for line in response.iter_lines():
212 if line:
213 line = line.decode('utf-8').strip()
214 if line.startswith("data: ") and line != "data: [DONE]":
215 json_data = json.loads(line[6:])
216 content = json_data['choices'][0]['delta'].get('content', '')
217 if content:
218 yield cls._filter_content(content)
219 else:
220 content = json_data['choices'][0]['message']['content']
221 full_response += cls._filter_content(content)
222
223 yield full_response
218 if cls.is_image_model(model):
219 if prompt is None:
220 prompt = messages[-1]['content']
221 if seed is None:
222 seed = random.randint(0, 10000)
223
224 async for result in cls.generate_image(model, prompt, api_key, size, seed, proxy):
225 yield result
226 else:
227 async for result in cls.generate_text(model, messages, max_tokens, temperature, top_p, stream, api_key, proxy):
228 yield result
224 229
225 230 @classmethod
226 231 def _filter_content(cls, part_response: str) -> str:
@@ -229,16 +234,19 @@ class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
229 234 '',
230 235 part_response
231 236 )
232
237
233 238 part_response = re.sub(
234 239 r"Rate limit \(\d+\/minute\) exceeded\. Join our discord for more: .+https:\/\/discord\.com\/invite\/\S+",
235 240 '',
236 241 part_response
237 242 )
238
239 part_response = re.sub(
240 r"\[ERROR\] '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}'", # any-uncensored
241 '',
242 part_response
243 )
243
244 244 return part_response
245
246 @classmethod
247 def _filter_response(cls, response: str) -> str:
248 filtered_response = re.sub(r"\[ERROR\] '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}'", '', response) # any-uncensored
249 filtered_response = re.sub(r'<\|im_end\|>', '', response) # hermes-2-pro-mistral-7b
250 filtered_response = re.sub(r'</s>', '', response) # neural-chat-7b-v3-1
251 filtered_response = cls._filter_content(filtered_response)
252 return filtered_response
Modified g4f/Provider/AmigoChat.py +11 -6
@@ -129,8 +129,6 @@ class AmigoChat(AsyncGeneratorProvider, ProviderModelMixin):
129 129 ### image ###
130 130 "flux-realism": "flux-realism",
131 131 "flux-dev": "flux/dev",
132
133 "dalle-3": "dall-e-3",
134 132 }
135 133
136 134 @classmethod
@@ -141,7 +139,12 @@ class AmigoChat(AsyncGeneratorProvider, ProviderModelMixin):
141 139 return MODELS['image'][model]['persona_id']
142 140 else:
143 141 raise ValueError(f"Unknown model: {model}")
144
142
143 @staticmethod
144 def generate_chat_id() -> str:
145 """Generate a chat ID in format: 8-4-4-4-12 hexadecimal digits"""
146 return str(uuid.uuid4())
147
145 148 @classmethod
146 149 async def create_async_generator(
147 150 cls,
@@ -182,22 +185,24 @@ class AmigoChat(AsyncGeneratorProvider, ProviderModelMixin):
182 185 "x-device-language": "en-US",
183 186 "x-device-platform": "web",
184 187 "x-device-uuid": device_uuid,
185 "x-device-version": "1.0.42"
188 "x-device-version": "1.0.45"
186 189 }
187 190
188 191 async with StreamSession(headers=headers, proxy=proxy) as session:
189 192 if model not in cls.image_models:
190 193 data = {
194 "chatId": cls.generate_chat_id(),
195 "frequency_penalty": frequency_penalty,
196 "max_tokens": max_tokens,
191 197 "messages": messages,
192 198 "model": model,
193 199 "personaId": cls.get_personaId(model),
194 "frequency_penalty": frequency_penalty,
195 "max_tokens": max_tokens,
196 200 "presence_penalty": presence_penalty,
197 201 "stream": stream,
198 202 "temperature": temperature,
199 203 "top_p": top_p
200 204 }
205 print(data)
201 206 async with session.post(cls.chat_api_endpoint, json=data, timeout=timeout) as response:
202 207 await raise_for_status(response)
203 208 async for line in response.iter_lines():
Modified g4f/Provider/Blackbox.py +18 -11
@@ -25,14 +25,14 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
25 25
26 26 default_model = 'blackboxai'
27 27 default_vision_model = default_model
28 default_image_model = 'Image Generation'
29 image_models = ['Image Generation', 'repomap']
28 default_image_model = 'flux'
29 image_models = ['flux', 'repomap']
30 30 vision_models = [default_model, 'gpt-4o', 'gemini-pro', 'gemini-1.5-flash', 'llama-3.1-8b', 'llama-3.1-70b', 'llama-3.1-405b']
31 31
32 32 userSelectedModel = ['gpt-4o', 'gemini-pro', 'claude-sonnet-3.5', 'blackboxai-pro']
33 33
34 34 agentMode = {
35 'Image Generation': {'mode': True, 'id': "ImageGenerationLV45LJp", 'name': "Image Generation"},
35 'flux': {'mode': True, 'id': "ImageGenerationLV45LJp", 'name': "Image Generation"}
36 36 }
37 37
38 38 trendingAgentMode = {
@@ -79,9 +79,9 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
79 79 }
80 80
81 81 additional_prefixes = {
82 'gpt-4o': '@gpt-4o',
83 'gemini-pro': '@gemini-pro',
84 'claude-sonnet-3.5': '@claude-sonnet'
82 'gpt-4o': '@GPT-4o',
83 'gemini-pro': '@Gemini-PRO',
84 'claude-sonnet-3.5': '@Claude-Sonnet-3.5'
85 85 }
86 86
87 87 model_prefixes = {
@@ -95,9 +95,9 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
95 95 models = list(dict.fromkeys([default_model, *userSelectedModel, *list(agentMode.keys()), *list(trendingAgentMode.keys())]))
96 96
97 97 model_aliases = {
98 "gpt-3.5-turbo": "blackboxai",
98 99 "gemini-flash": "gemini-1.5-flash",
99 "claude-3.5-sonnet": "claude-sonnet-3.5",
100 "flux": "Image Generation",
100 "claude-3.5-sonnet": "claude-sonnet-3.5"
101 101 }
102 102
103 103 @classmethod
@@ -173,9 +173,14 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
173 173
174 174 if image is not None:
175 175 messages[-1]['data'] = {
176 'fileText': '',
177 'imageBase64': to_data_uri(image),
178 'title': image_name
176 "imagesData": [
177 {
178 "filePath": f"MultipleFiles/{image_name}",
179 "contents": to_data_uri(image)
180 }
181 ],
182 "fileText": "",
183 "title": ""
179 184 }
180 185
181 186 headers = {
@@ -219,6 +224,8 @@ class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
219 224 "userSelectedModel": model if model in cls.userSelectedModel else None,
220 225 "webSearchMode": web_search,
221 226 "validated": validated_value,
227 "imageGenerationMode": False,
228 "webSearchModePrompt": False
222 229 }
223 230
224 231 async with ClientSession(headers=headers) as session:
Added g4f/Provider/Blackbox2.py +69 -0
@@ -0,0 +1,69 @@
1 from __future__ import annotations
2
3 import random
4 import asyncio
5 from aiohttp import ClientSession
6
7 from ..typing import AsyncResult, Messages
8 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
9
10 class Blackbox2(AsyncGeneratorProvider, ProviderModelMixin):
11 url = "https://www.blackbox.ai"
12 api_endpoint = "https://www.blackbox.ai/api/improve-prompt"
13 working = True
14 supports_system_message = True
15 supports_message_history = True
16
17 default_model = 'llama-3.1-70b'
18 models = [default_model]
19
20 @classmethod
21 async def create_async_generator(
22 cls,
23 model: str,
24 messages: Messages,
25 proxy: str = None,
26 max_retries: int = 3,
27 delay: int = 1,
28 **kwargs
29 ) -> AsyncResult:
30 headers = {
31 'accept': '*/*',
32 'accept-language': 'en-US,en;q=0.9',
33 'content-type': 'text/plain;charset=UTF-8',
34 'dnt': '1',
35 'origin': 'https://www.blackbox.ai',
36 'priority': 'u=1, i',
37 'referer': 'https://www.blackbox.ai',
38 'sec-ch-ua': '"Chromium";v="131", "Not_A Brand";v="24"',
39 'sec-ch-ua-mobile': '?0',
40 'sec-ch-ua-platform': '"Linux"',
41 'sec-fetch-dest': 'empty',
42 'sec-fetch-mode': 'cors',
43 'sec-fetch-site': 'same-origin',
44 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
45 }
46
47 data = {
48 "messages": messages,
49 "max_tokens": None
50 }
51
52 async with ClientSession(headers=headers) as session:
53 for attempt in range(max_retries):
54 try:
55 async with session.post(cls.api_endpoint, json=data, proxy=proxy) as response:
56 response.raise_for_status()
57 response_data = await response.json()
58 if 'prompt' in response_data:
59 yield response_data['prompt']
60 return
61 else:
62 raise KeyError("'prompt' key not found in the response")
63 except Exception as e:
64 if attempt == max_retries - 1:
65 yield f"Error after {max_retries} attempts: {str(e)}"
66 else:
67 wait_time = delay * (2 ** attempt) + random.uniform(0, 1)
68 print(f"Attempt {attempt + 1} failed. Retrying in {wait_time:.2f} seconds...")
69 await asyncio.sleep(wait_time)
Modified g4f/Provider/DeepInfraChat.py +13 -35
@@ -1,11 +1,11 @@
1 1 from __future__ import annotations
2 2
3 from aiohttp import ClientSession
3 from aiohttp import ClientSession, ClientResponseError
4 4 import json
5
6 5 from ..typing import AsyncResult, Messages, ImageType
7 6 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
8 7
8
9 9 class DeepInfraChat(AsyncGeneratorProvider, ProviderModelMixin):
10 10 url = "https://deepinfra.com/chat"
11 11 api_endpoint = "https://api.deepinfra.com/v1/openai/chat/completions"
@@ -13,11 +13,12 @@ class DeepInfraChat(AsyncGeneratorProvider, ProviderModelMixin):
13 13 supports_stream = True
14 14 supports_system_message = True
15 15 supports_message_history = True
16
16
17 17 default_model = 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo'
18 18 models = [
19 19 'meta-llama/Meta-Llama-3.1-8B-Instruct',
20 20 default_model,
21 'Qwen/QwQ-32B-Preview',
21 22 'microsoft/WizardLM-2-8x22B',
22 23 'Qwen/Qwen2.5-72B-Instruct',
23 24 'Qwen/Qwen2.5-Coder-32B-Instruct',
@@ -26,60 +27,37 @@ class DeepInfraChat(AsyncGeneratorProvider, ProviderModelMixin):
26 27 model_aliases = {
27 28 "llama-3.1-8b": "meta-llama/Meta-Llama-3.1-8B-Instruct",
28 29 "llama-3.1-70b": "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
30 "qwq-32b": "Qwen/QwQ-32B-Preview",
29 31 "wizardlm-2-8x22b": "microsoft/WizardLM-2-8x22B",
30 32 "qwen-2-72b": "Qwen/Qwen2.5-72B-Instruct",
31 33 "qwen-2.5-coder-32b": "Qwen2.5-Coder-32B-Instruct",
32 34 "nemotron-70b": "nvidia/Llama-3.1-Nemotron-70B-Instruct",
33 35 }
34 36
35
36 @classmethod
37 def get_model(cls, model: str) -> str:
38 if model in cls.models:
39 return model
40 elif model in cls.model_aliases:
41 return cls.model_aliases[model]
42 else:
43 return cls.default_model
44
45 37 @classmethod
46 38 async def create_async_generator(
47 39 cls,
48 40 model: str,
49 41 messages: Messages,
50 42 proxy: str = None,
51 image: ImageType = None,
52 image_name: str = None,
53 43 **kwargs
54 44 ) -> AsyncResult:
55 model = cls.get_model(model)
56
57 45 headers = {
58 'Accept-Language': 'en-US,en;q=0.9',
59 'Cache-Control': 'no-cache',
60 'Connection': 'keep-alive',
61 46 'Content-Type': 'application/json',
62 47 'Origin': 'https://deepinfra.com',
63 'Pragma': 'no-cache',
64 48 'Referer': 'https://deepinfra.com/',
65 'Sec-Fetch-Dest': 'empty',
66 'Sec-Fetch-Mode': 'cors',
67 'Sec-Fetch-Site': 'same-site',
68 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
69 'X-Deepinfra-Source': 'web-embed',
49 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
50 'X-Deepinfra-Source': 'web-page',
70 51 'accept': 'text/event-stream',
71 'sec-ch-ua': '"Not;A=Brand";v="24", "Chromium";v="128"',
72 'sec-ch-ua-mobile': '?0',
73 'sec-ch-ua-platform': '"Linux"',
74 52 }
75 53
76 async with ClientSession(headers=headers) as session:
77 data = {
78 'model': model,
79 'messages': messages,
80 'stream': True
81 }
54 data = {
55 'model': model,
56 'messages': messages,
57 'stream': True
58 }
82 59
60 async with ClientSession(headers=headers) as session:
83 61 async with session.post(cls.api_endpoint, json=data, proxy=proxy) as response:
84 62 response.raise_for_status()
85 63 async for line in response.content:
Modified g4f/Provider/ReplicateHome.py +0 -2
@@ -28,8 +28,6 @@ class ReplicateHome(AsyncGeneratorProvider, ProviderModelMixin):
28 28 ]
29 29
30 30 text_models = [
31 'meta/meta-llama-3-70b-instruct',
32 'mistralai/mixtral-8x7b-instruct-v0.1',
33 31 'google-deepmind/gemma-2b-it',
34 32 'yorickvp/llava-13b',
35 33 ]
Modified g4f/Provider/__init__.py +1 -1
@@ -14,6 +14,7 @@ from .local import *
14 14 from .Airforce import Airforce
15 15 from .AmigoChat import AmigoChat
16 16 from .Blackbox import Blackbox
17 from .Blackbox2 import Blackbox2
17 18 from .ChatGpt import ChatGpt
18 19 from .ChatGptEs import ChatGptEs
19 20 from .Cloudflare import Cloudflare
@@ -24,7 +25,6 @@ from .DeepInfraChat import DeepInfraChat
24 25 from .Free2GPT import Free2GPT
25 26 from .FreeGpt import FreeGpt
26 27 from .GizAI import GizAI
27 from .HuggingChat import HuggingChat
28 28 from .Liaobots import Liaobots
29 29 from .MagickPen import MagickPen
30 30 from .PerplexityLabs import PerplexityLabs
Renamed g4f/Provider/needs_auth/HuggingChat.py +11 -8
@@ -8,22 +8,24 @@ try:
8 8 has_curl_cffi = True
9 9 except ImportError:
10 10 has_curl_cffi = False
11 from ..typing import CreateResult, Messages
12 from ..errors import MissingRequirementsError
13 from ..requests.raise_for_status import raise_for_status
14 from .base_provider import ProviderModelMixin, AbstractProvider
15 from .helper import format_prompt
11 from ...typing import CreateResult, Messages
12 from ...errors import MissingRequirementsError
13 from ...requests.raise_for_status import raise_for_status
14 from ..base_provider import ProviderModelMixin, AbstractProvider
15 from ..helper import format_prompt
16 16
17 17 class HuggingChat(AbstractProvider, ProviderModelMixin):
18 18 url = "https://huggingface.co/chat"
19 19 working = True
20 20 supports_stream = True
21 needs_auth = True
21 22 default_model = "meta-llama/Meta-Llama-3.1-70B-Instruct"
22 23
23 24 models = [
25 'Qwen/Qwen2.5-72B-Instruct',
24 26 'meta-llama/Meta-Llama-3.1-70B-Instruct',
25 27 'CohereForAI/c4ai-command-r-plus-08-2024',
26 'Qwen/Qwen2.5-72B-Instruct',
28 'Qwen/QwQ-32B-Preview',
27 29 'nvidia/Llama-3.1-Nemotron-70B-Instruct-HF',
28 30 'Qwen/Qwen2.5-Coder-32B-Instruct',
29 31 'meta-llama/Llama-3.2-11B-Vision-Instruct',
@@ -33,9 +35,10 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
33 35 ]
34 36
35 37 model_aliases = {
38 "qwen-2.5-72b": "Qwen/Qwen2.5-72B-Instruct",
36 39 "llama-3.1-70b": "meta-llama/Meta-Llama-3.1-70B-Instruct",
37 40 "command-r-plus": "CohereForAI/c4ai-command-r-plus-08-2024",
38 "qwen-2-72b": "Qwen/Qwen2.5-72B-Instruct",
41 "qwq-32b": "Qwen/QwQ-32B-Preview",
39 42 "nemotron-70b": "nvidia/Llama-3.1-Nemotron-70B-Instruct-HF",
40 43 "qwen-2.5-coder-32b": "Qwen/Qwen2.5-Coder-32B-Instruct",
41 44 "llama-3.2-11b": "meta-llama/Llama-3.2-11B-Vision-Instruct",
@@ -173,4 +176,4 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
173 176 full_response = full_response.replace('<|im_end|', '').replace('\u0000', '').strip()
174 177
175 178 if not stream:
176 yield full_response
179 yield full_response
Modified g4f/Provider/needs_auth/HuggingFace.py +2 -2
@@ -7,7 +7,7 @@ from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
7 7 from ...errors import ModelNotFoundError
8 8 from ...requests import StreamSession, raise_for_status
9 9
10 from ..HuggingChat import HuggingChat
10 from .HuggingChat import HuggingChat
11 11
12 12 class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
13 13 url = "https://huggingface.co/chat"
@@ -88,4 +88,4 @@ def format_prompt(messages: Messages) -> str:
88 88 for idx, message in enumerate(messages)
89 89 if message["role"] == "assistant"
90 90 ])
91 return f"{history}<s>[INST] {question} [/INST]"
91 return f"{history}<s>[INST] {question} [/INST]"
Modified g4f/Provider/needs_auth/HuggingFace2.py +2 -2
Modified g4f/Provider/needs_auth/__init__.py +2 -1
Modified g4f/client/__init__.py +20 -14
Modified g4f/models.py +36 -14