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

XFEstudio/gpt4free

refactor(g4f/Provider/Airforce.py): enhance Airforce provider functionality

6bf4c4bc
kqlio67 <kqlio67@users.noreply.github.com>
提交于

代码差异

1 个文件 +332 -160
Modified g4f/Provider/Airforce.py +332 -160
@@ -1,76 +1,200 @@
1 1 from __future__ import annotations
2
3 from aiohttp import ClientSession, ClientResponseError
2 import random
4 3 import json
4 from aiohttp import ClientSession
5 5 from ..typing import AsyncResult, Messages
6 6 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
7 7 from ..image import ImageResponse
8 from .helper import format_prompt
9 from ..errors import ResponseStatusError
8
9 def split_long_message(message: str, max_length: int = 4000) -> list[str]:
10 return [message[i:i+max_length] for i in range(0, len(message), max_length)]
10 11
11 12 class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
13 label = "Airforce"
12 14 url = "https://api.airforce"
13 text_api_endpoint = "https://api.airforce/chat/completions"
14 15 image_api_endpoint = "https://api.airforce/imagine2"
16 text_api_endpoint = "https://api.airforce/chat/completions"
15 17 working = True
18
19 default_model = 'llama-3-70b-chat'
20
16 21 supports_gpt_35_turbo = True
17 22 supports_gpt_4 = True
18 23 supports_stream = True
19 24 supports_system_message = True
20 25 supports_message_history = True
21 default_model = 'llama-3-70b-chat'
26
22 27 text_models = [
23 # Open source models
24 'llama-2-13b-chat',
25 'llama-3-70b-chat',
26 'llama-3-70b-chat-turbo',
27 'llama-3-70b-chat-lite',
28 'llama-3-8b-chat',
29 'llama-3-8b-chat-turbo',
30 'llama-3-8b-chat-lite',
31 'llama-3.1-405b-turbo',
32 'llama-3.1-70b-turbo',
33 'llama-3.1-8b-turbo',
34 'LlamaGuard-2-8b',
35 'Llama-Guard-7b',
36 'Meta-Llama-Guard-3-8B',
37 'Mixtral-8x7B-Instruct-v0.1',
38 'Mixtral-8x22B-Instruct-v0.1',
39 'Mistral-7B-Instruct-v0.1',
40 'Mistral-7B-Instruct-v0.2',
41 'Mistral-7B-Instruct-v0.3',
42 'Qwen1.5-72B-Chat',
43 'Qwen1.5-110B-Chat',
44 'Qwen2-72B-Instruct',
45 'gemma-2b-it',
46 'gemma-2-9b-it',
47 'gemma-2-27b-it',
48 'dbrx-instruct',
49 'deepseek-llm-67b-chat',
50 'Nous-Hermes-2-Mixtral-8x7B-DPO',
51 'Nous-Hermes-2-Yi-34B',
52 'WizardLM-2-8x22B',
53 'SOLAR-10.7B-Instruct-v1.0',
54 'StripedHyena-Nous-7B',
55 'sparkdesk',
56
57 # Other models
58 'chatgpt-4o-latest',
59 'gpt-4',
60 'gpt-4-turbo',
61 'gpt-4o-mini-2024-07-18',
62 'gpt-4o-mini',
63 'gpt-4o',
64 'gpt-3.5-turbo',
65 'gpt-3.5-turbo-0125',
66 'gpt-3.5-turbo-1106',
67 'gpt-3.5-turbo-16k',
68 'gpt-3.5-turbo-0613',
69 'gpt-3.5-turbo-16k-0613',
70 'gemini-1.5-flash',
71 'gemini-1.5-pro',
28 # anthorpic
29 'claude-3-haiku-20240307',
30 'claude-3-sonnet-20240229',
31 'claude-3-5-sonnet-20240620',
32 'claude-3-opus-20240229',
33
34 # openai
35 'chatgpt-4o-latest',
36 'gpt-4',
37 #'gpt-4-0613',
38 'gpt-4-turbo',
39 'gpt-4o-mini-2024-07-18',
40 'gpt-4o-mini',
41 'gpt-3.5-turbo',
42 'gpt-3.5-turbo-0125',
43 'gpt-3.5-turbo-1106',
44 #'gpt-3.5-turbo-16k', # No response from the API.
45 #'gpt-3.5-turbo-0613', # No response from the API.
46 #'gpt-3.5-turbo-16k-0613', # No response from the API.
47 'gpt-4o',
48 #'o1-mini', # No response from the API.
49
50 # meta-llama
51 'llama-3-70b-chat',
52 'llama-3-70b-chat-turbo',
53 'llama-3-8b-chat',
54 'llama-3-8b-chat-turbo',
55 'llama-3-70b-chat-lite',
56 'llama-3-8b-chat-lite',
57 #'llama-2-70b-chat', # Failed to load response after multiple retries.
58 'llama-2-13b-chat',
59 #'llama-2-7b-chat', # Failed to load response after multiple retries.
60 'llama-3.1-405b-turbo',
61 'llama-3.1-70b-turbo',
62 'llama-3.1-8b-turbo',
63 'LlamaGuard-2-8b',
64 'Llama-Guard-7b',
65 'Llama-3.2-90B-Vision-Instruct-Turbo',
66
67 # codellama
68 #'CodeLlama-7b-Python-hf', # Failed to load response after multiple retries.
69 #'CodeLlama-7b-Python',
70 #'CodeLlama-13b-Python-hf', # Failed to load response after multiple retries.
71 #'CodeLlama-34b-Python-hf', # Failed to load response after multiple retries.
72 #'CodeLlama-70b-Python-hf', # Failed to load response after multiple retries.
73
74 # 01-ai
75 #'Yi-34B-Chat', # Failed to load response after multiple retries.
76 #'Yi-34B', # Failed to load response after multiple retries.
77 #'Yi-6B', # Failed to load response after multiple retries.
78
79 # mistral-ai
80 #'Mixtral-8x7B-v0.1',
81 #'Mixtral-8x22B', # Failed to load response after multiple retries.
82 'Mixtral-8x7B-Instruct-v0.1',
83 'Mixtral-8x22B-Instruct-v0.1',
84 'Mistral-7B-Instruct-v0.1',
85 'Mistral-7B-Instruct-v0.2',
86 'Mistral-7B-Instruct-v0.3',
87
88 # openchat
89 #'openchat-3.5', # Failed to load response after multiple retries.
90
91 # wizardlm
92 #'WizardLM-13B-V1.2', # Failed to load response after multiple retries.
93 #'WizardCoder-Python-34B-V1.0', # Failed to load response after multiple retries.
94
95 # qwen
96 #'Qwen1.5-0.5B-Chat', # Failed to load response after multiple retries.
97 #'Qwen1.5-1.8B-Chat', # Failed to load response after multiple retries.
98 #'Qwen1.5-4B-Chat', # Failed to load response after multiple retries.
99 'Qwen1.5-7B-Chat',
100 'Qwen1.5-14B-Chat',
101 'Qwen1.5-72B-Chat',
102 'Qwen1.5-110B-Chat',
103 'Qwen2-72B-Instruct',
104
105 # google
106 'gemma-2b-it',
107 #'gemma-7b-it', # Failed to load response after multiple retries.
108 #'gemma-2b', # Failed to load response after multiple retries.
109 #'gemma-7b', # Failed to load response after multiple retries.
110 'gemma-2-9b-it', # fix bug
111 'gemma-2-27b-it',
112
113 # gemini
114 'gemini-1.5-flash',
115 'gemini-1.5-pro',
116
117 # databricks
118 'dbrx-instruct',
119
120 # lmsys
121 #'vicuna-7b-v1.5', # Failed to load response after multiple retries.
122 #'vicuna-13b-v1.5', # Failed to load response after multiple retries.
123
124 # cognitivecomputations
125 #'dolphin-2.5-mixtral-8x7b', # Failed to load response after multiple retries.
126
127 # deepseek-ai
128 #'deepseek-coder-33b-instruct', # No response from the API.
129 #'deepseek-coder-67b-instruct', # Failed to load response after multiple retries.
130 'deepseek-llm-67b-chat',
131
132 # NousResearch
133 #'Nous-Capybara-7B-V1p9', # Failed to load response after multiple retries.
134 'Nous-Hermes-2-Mixtral-8x7B-DPO',
135 #'Nous-Hermes-2-Mixtral-8x7B-SFT', # Failed to load response after multiple retries.
136 #'Nous-Hermes-llama-2-7b', # Failed to load response after multiple retries.
137 #'Nous-Hermes-Llama2-13b', # Failed to load response after multiple retries.
138 'Nous-Hermes-2-Yi-34B',
139
140 # Open-Orca
141 #'Mistral-7B-OpenOrca', # Failed to load response after multiple retries.
142
143 # togethercomputer
144 #'alpaca-7b', # Failed to load response after multiple retries.
145
146 # teknium
147 #'OpenHermes-2-Mistral-7B', # Failed to load response after multiple retries.
148 #'OpenHermes-2.5-Mistral-7B', # Failed to load response after multiple retries.
149
150 # microsoft
151 'WizardLM-2-8x22B',
152
153 # Nexusflow
154 #'NexusRaven-V2-13B', # Failed to load response after multiple retries.
155
156 # Phind
157 #'Phind-CodeLlama-34B-v2', # Failed to load response after multiple retries.
158
159 # Snoflake
160 #'snowflake-arctic-instruct', # No response from the API.
161
162 # upstage
163 'SOLAR-10.7B-Instruct-v1.0',
164
165 # togethercomputer
166 #'StripedHyena-Hessian-7B', # Failed to load response after multiple retries.
167 #'StripedHyena-Nous-7B', # Failed to load response after multiple retries.
168 #'Llama-2-7B-32K-Instruct', # Failed to load response after multiple retries.
169 #'CodeLlama-13b-Instruct', # No response from the API.
170 #'evo-1-131k-base', # Failed to load response after multiple retries.
171 #'OLMo-7B-Instruct', # Failed to load response after multiple retries.
172
173 # garage-bAInd
174 #'Platypus2-70B-instruct', # Failed to load response after multiple retries.
175
176 # snorkelai
177 #'Snorkel-Mistral-PairRM-DPO', # Failed to load response after multiple retries.
178
179 # Undi95
180 #'ReMM-SLERP-L2-13B', # Failed to load response after multiple retries.
181
182 # Gryphe
183 'MythoMax-L2-13b',
184
185 # Autism
186 #'chronos-hermes-13b', # Failed to load response after multiple retries.
187
188 # Undi95
189 #'Toppy-M-7B', # Failed to load response after multiple retries.
190
191 # iFlytek
192 #'sparkdesk', # Failed to load response after multiple retries.
193
194 # pawan
195 'cosmosrp',
196
72 197 ]
73
74 198 image_models = [
75 199 'flux',
76 200 'flux-realism',
@@ -85,158 +209,206 @@ class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
85 209
86 210 models = [
87 211 *text_models,
88 *image_models
212 *image_models,
89 213 ]
90 214 model_aliases = {
91 # Open source models
92 "llama-2-13b": "llama-2-13b-chat",
215 # anthorpic
216 "claude-3-haiku": "claude-3-haiku-20240307",
217 "claude-3-sonnet": "claude-3-sonnet-20240229",
218 "claude-3-5-sonnet": "claude-3-5-sonnet-20240620",
219 "claude-3-opus": "claude-3-opus-20240229",
220
221 # openai
222 "gpt-4o": "chatgpt-4o-latest",
223 "gpt-4o-mini": "gpt-4o-mini-2024-07-18",
224 "gpt-3.5-turbo": "gpt-3.5-turbo-0125",
225 "gpt-3.5-turbo": "gpt-3.5-turbo-1106",
226
227 # meta-llama
93 228 "llama-3-70b": "llama-3-70b-chat",
94 229 "llama-3-70b": "llama-3-70b-chat-turbo",
95 "llama-3-70b": "llama-3-70b-chat-lite",
96 230 "llama-3-8b": "llama-3-8b-chat",
97 231 "llama-3-8b": "llama-3-8b-chat-turbo",
232 "llama-3-70b": "llama-3-70b-chat-lite",
98 233 "llama-3-8b": "llama-3-8b-chat-lite",
234 "llama-2-13b": "llama-2-13b-chat",
99 235 "llama-3.1-405b": "llama-3.1-405b-turbo",
100 236 "llama-3.1-70b": "llama-3.1-70b-turbo",
101 237 "llama-3.1-8b": "llama-3.1-8b-turbo",
238 "llamaguard-2-8b": "LlamaGuard-2-8b",
239 "llamaguard-7b": "Llama-Guard-7b",
240 "llama-3.2-90b": "Llama-3.2-90B-Vision-Instruct-Turbo",
241
242 # mistral-ai
102 243 "mixtral-8x7b": "Mixtral-8x7B-Instruct-v0.1",
103 244 "mixtral-8x22b": "Mixtral-8x22B-Instruct-v0.1",
104 245 "mistral-7b": "Mistral-7B-Instruct-v0.1",
105 246 "mistral-7b": "Mistral-7B-Instruct-v0.2",
106 247 "mistral-7b": "Mistral-7B-Instruct-v0.3",
107 "mixtral-8x7b-dpo": "Nous-Hermes-2-Mixtral-8x7B-DPO",
248
249 # qwen
250 "qwen-1.5-7b": "Qwen1.5-7B-Chat",
251 "qwen-1.5-14b": "Qwen1.5-14B-Chat",
108 252 "qwen-1.5-72b": "Qwen1.5-72B-Chat",
109 253 "qwen-1.5-110b": "Qwen1.5-110B-Chat",
110 254 "qwen-2-72b": "Qwen2-72B-Instruct",
255
256 # google
111 257 "gemma-2b": "gemma-2b-it",
112 "gemma-2b-9b": "gemma-2-9b-it",
113 "gemma-2b-27b": "gemma-2-27b-it",
258 "gemma-2-9b": "gemma-2-9b-it",
259 "gemma-2-27b": "gemma-2-27b-it",
260
261 # gemini
262 "gemini-flash": "gemini-1.5-flash",
263 "gemini-pro": "gemini-1.5-pro",
264
265 # deepseek-ai
114 266 "deepseek": "deepseek-llm-67b-chat",
267
268 # NousResearch
269 "mixtral-8x7b-dpo": "Nous-Hermes-2-Mixtral-8x7B-DPO",
115 270 "yi-34b": "Nous-Hermes-2-Yi-34B",
271
272 # microsoft
116 273 "wizardlm-2-8x22b": "WizardLM-2-8x22B",
117 "solar-10-7b": "SOLAR-10.7B-Instruct-v1.0",
118 "sh-n-7b": "StripedHyena-Nous-7B",
119 "sparkdesk-v1.1": "sparkdesk",
120 274
121 # Other models
122 "gpt-4o": "chatgpt-4o-latest",
123 "gpt-4o-mini": "gpt-4o-mini-2024-07-18",
124 "gpt-3.5-turbo": "gpt-3.5-turbo-0125",
125 "gpt-3.5-turbo": "gpt-3.5-turbo-1106",
126 "gpt-3.5-turbo": "gpt-3.5-turbo-16k",
127 "gpt-3.5-turbo": "gpt-3.5-turbo-0613",
128 "gpt-3.5-turbo": "gpt-3.5-turbo-16k-0613",
129 "gemini-flash": "gemini-1.5-flash",
130 "gemini-pro": "gemini-1.5-pro",
275 # upstage
276 "solar-10.7b": "SOLAR-10.7B-Instruct-v1.0",
131 277
132 # Image models
133 "dalle-3": "dall-e-3",
278 # Gryphe
279 "mythomax-l2-13b": "MythoMax-L2-13b",
134 280 }
135 281
282 @classmethod
283 def get_model(cls, model: str) -> str:
284 if model in cls.models:
285 return model
286 elif model in cls.model_aliases:
287 return cls.model_aliases.get(model, cls.default_model)
288 else:
289 return cls.default_model
290
136 291 @classmethod
137 292 async def create_async_generator(
138 293 cls,
139 294 model: str,
140 295 messages: Messages,
141 296 proxy: str = None,
297 seed: int = None,
298 size: str = "1:1",
299 stream: bool = False,
142 300 **kwargs
143 301 ) -> AsyncResult:
144 302 model = cls.get_model(model)
145
303
304 # If the model is an image model, use the image API
305 if model in cls.image_models:
306 async for result in cls._generate_image(model, messages, proxy, seed, size):
307 yield result
308 # If the model is a text model, use the text API
309 elif model in cls.text_models:
310 async for result in cls._generate_text(model, messages, proxy, stream):
311 yield result
312
313 @classmethod
314 async def _generate_image(
315 cls,
316 model: str,
317 messages: Messages,
318 proxy: str = None,
319 seed: int = None,
320 size: str = "1:1",
321 **kwargs
322 ) -> AsyncResult:
146 323 headers = {
147 324 "accept": "*/*",
148 325 "accept-language": "en-US,en;q=0.9",
149 "content-type": "application/json",
150 "origin": "https://api.airforce",
151 "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
152 "authorization": "Bearer null",
153 326 "cache-control": "no-cache",
154 "pragma": "no-cache",
155 "priority": "u=1, i",
156 "referer": "https://llmplayground.net/",
157 "sec-ch-ua": '"Not;A=Brand";v="24", "Chromium";v="128"',
158 "sec-ch-ua-mobile": "?0",
159 "sec-ch-ua-platform": '"Linux"',
160 "sec-fetch-dest": "empty",
161 "sec-fetch-mode": "cors",
162 "sec-fetch-site": "cross-site",
327 "origin": "https://llmplayground.net",
328 "user-agent": "Mozilla/5.0"
163 329 }
164 330
165 if model in cls.image_models:
166 async for item in cls.generate_image(model, messages, headers, proxy, **kwargs):
167 yield item
168 else:
169 async for item in cls.generate_text(model, messages, headers, proxy, **kwargs):
170 yield item
331 if seed is None:
332 seed = random.randint(0, 100000)
171 333
172 @classmethod
173 async def generate_text(cls, model: str, messages: Messages, headers: dict, proxy: str, **kwargs) -> AsyncResult:
174 async with ClientSession() as session:
175 data = {
176 "messages": [{"role": "user", "content": message['content']} for message in messages],
334 # Assume the first message is the prompt for the image
335 prompt = messages[0]['content']
336
337 async with ClientSession(headers=headers) as session:
338 params = {
177 339 "model": model,
178 "max_tokens": kwargs.get('max_tokens', 4096),
179 "temperature": kwargs.get('temperature', 1),
180 "top_p": kwargs.get('top_p', 1),
181 "stream": True
340 "prompt": prompt,
341 "size": size,
342 "seed": seed
182 343 }
344 async with session.get(f"{cls.image_api_endpoint}", params=params, proxy=proxy) as response:
345 response.raise_for_status()
346 content_type = response.headers.get('Content-Type', '').lower()
183 347
184 try:
185 async with session.post(cls.text_api_endpoint, json=data, headers=headers, proxy=proxy) as response:
186 response.raise_for_status()
187 async for line in response.content:
188 if line:
189 line = line.decode('utf-8').strip()
190 if line.startswith("data: "):
191 if line == "data: [DONE]":
192 break
193 try:
194 data = json.loads(line[6:])
195 if 'choices' in data and len(data['choices']) > 0:
196 delta = data['choices'][0].get('delta', {})
197 if 'content' in delta:
198 content = delta['content']
199 if "One message exceeds the 1000chars per message limit" in content:
200 raise ResponseStatusError(
201 "Message too long",
202 400,
203 "Please try a shorter message."
204 )
205 yield content
206 except json.JSONDecodeError:
207 continue
208 except ResponseStatusError as e:
209 raise e
210 except Exception as e:
211 raise ResponseStatusError(str(e), 500, "An unexpected error occurred")
348 if 'application/json' in content_type:
349 async for chunk in response.content.iter_chunked(1024):
350 if chunk:
351 yield chunk.decode('utf-8')
352 elif 'image' in content_type:
353 image_data = b""
354 async for chunk in response.content.iter_chunked(1024):
355 if chunk:
356 image_data += chunk
357 image_url = f"{cls.image_api_endpoint}?model={model}&prompt={prompt}&size={size}&seed={seed}"
358 alt_text = f"Generated image for prompt: {prompt}"
359 yield ImageResponse(images=image_url, alt=alt_text)
212 360
213 361 @classmethod
214 async def generate_image(cls, model: str, messages: Messages, headers: dict, proxy: str, **kwargs) -> AsyncResult:
215 prompt = messages[-1]['content'] if messages else ""
216 params = {
217 "prompt": prompt,
218 "size": kwargs.get("size", "1:1"),
219 "seed": kwargs.get("seed"),
220 "model": model
362 async def _generate_text(
363 cls,
364 model: str,
365 messages: Messages,
366 proxy: str = None,
367 stream: bool = False,
368 **kwargs
369 ) -> AsyncResult:
370 headers = {
371 "accept": "*/*",
372 "accept-language": "en-US,en;q=0.9",
373 "authorization": "Bearer missing api key",
374 "content-type": "application/json",
375 "user-agent": "Mozilla/5.0"
221 376 }
222 params = {k: v for k, v in params.items() if v is not None}
223 377
224 try:
225 async with ClientSession(headers=headers) as session:
226 async with session.get(cls.image_api_endpoint, params=params, proxy=proxy) as response:
378 async with ClientSession(headers=headers) as session:
379 formatted_prompt = cls._format_messages(messages)
380 prompt_parts = split_long_message(formatted_prompt)
381 full_response = ""
382
383 for part in prompt_parts:
384 data = {
385 "messages": [{"role": "user", "content": part}],
386 "model": model,
387 "max_tokens": 4096,
388 "temperature": 1,
389 "top_p": 1,
390 "stream": stream
391 }
392 async with session.post(cls.text_api_endpoint, json=data, proxy=proxy) as response:
227 393 response.raise_for_status()
228 content = await response.read()
229
230 if response.content_type.startswith('image/'):
231 image_url = str(response.url)
232 yield ImageResponse(image_url, prompt)
394 part_response = ""
395 if stream:
396 async for line in response.content:
397 if line:
398 line = line.decode('utf-8').strip()
399 if line.startswith("data: ") and line != "data: [DONE]":
400 json_data = json.loads(line[6:])
401 content = json_data['choices'][0]['delta'].get('content', '')
402 part_response += content
233 403 else:
234 try:
235 text = content.decode('utf-8', errors='ignore')
236 raise ResponseStatusError("Image generation failed", response.status, text)
237 except Exception as decode_error:
238 raise ResponseStatusError("Decoding error", 500, str(decode_error))
239 except ClientResponseError as e:
240 raise ResponseStatusError(f"HTTP {e.status}", e.status, e.message)
241 except Exception as e:
242 raise ResponseStatusError("Unexpected error", 500, str(e))
404 json_data = await response.json()
405 content = json_data['choices'][0]['message']['content']
406 part_response = content
407
408 full_response += part_response
409 yield full_response
410
411 @classmethod
412 def _format_messages(cls, messages: Messages) -> str:
413 """Formats messages for text generation."""
414 return " ".join([msg['content'] for msg in messages])