返回提交历史
Modified
etc/tool/readme_table.py
+24
-3
Modified
g4f/Provider/BingCreateImages.py
+1
-0
Modified
g4f/Provider/DeepInfraImage.py
+2
-0
Modified
g4f/Provider/MetaAI.py
+3
-4
Modified
g4f/Provider/MetaAIAccount.py
+1
-0
Modified
g4f/Provider/ReplicateImage.py
+1
-0
Modified
g4f/Provider/You.py
+13
-6
Modified
g4f/Provider/bing/conversation.py
+2
-0
Modified
g4f/Provider/needs_auth/Gemini.py
+1
-0
Modified
g4f/Provider/needs_auth/OpenaiAccount.py
+2
-1
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+16
-14
Modified
g4f/Provider/openai/har_file.py
+11
-7
Modified
g4f/Provider/you/har_file.py
+17
-50
Modified
g4f/gui/server/api.py
+24
-4
Modified
g4f/gui/server/backend.py
+4
-0
Modified
g4f/providers/base_provider.py
+2
-2
Modified
g4f/providers/helper.py
+5
-2
XFEstudio/gpt4free
Add image model list
a26421bc
代码差异
17 个文件
+129
-93
@@ -14,6 +14,8 @@ async def test_async(provider: ProviderType):
14
14
return False
15
15
messages = [{"role": "user", "content": "Hello Assistant!"}]
16
16
try:
17
if "webdriver" in provider.get_parameters():
18
return False
17
19
response = await asyncio.wait_for(ChatCompletion.create_async(
18
20
model=models.default,
19
21
messages=messages,
@@ -88,7 +90,7 @@ def print_models():
88
90
"huggingface": "Huggingface",
89
91
"anthropic": "Anthropic",
90
92
"inflection": "Inflection",
91
"meta": "Meta"
93
"meta": "Meta",
92
94
}
93
95
provider_urls = {
94
96
"google": "https://gemini.google.com/",
@@ -96,7 +98,7 @@ def print_models():
96
98
"huggingface": "https://huggingface.co/",
97
99
"anthropic": "https://www.anthropic.com/",
98
100
"inflection": "https://inflection.ai/",
99
"meta": "https://llama.meta.com/"
101
"meta": "https://llama.meta.com/",
100
102
}
101
103
102
104
lines = [
@@ -108,6 +110,8 @@ def print_models():
108
110
if name not in ("gpt-3.5-turbo", "gpt-4", "gpt-4-turbo"):
109
111
continue
110
112
name = re.split(r":|/", model.name)[-1]
113
if model.base_provider not in base_provider_names:
114
continue
111
115
base_provider = base_provider_names[model.base_provider]
112
116
if not isinstance(model.best_provider, BaseRetryProvider):
113
117
provider_name = f"g4f.Provider.{model.best_provider.__name__}"
@@ -121,7 +125,24 @@ def print_models():
121
125
122
126
print("\n".join(lines))
123
127
128
def print_image_models():
129
lines = [
130
"| Label | Provider | Model | Website |",
131
"| ----- | -------- | ----- | ------- |",
132
]
133
from g4f.gui.server.api import Api
134
for image_model in Api.get_image_models():
135
provider_url = image_model["url"]
136
netloc = urlparse(provider_url).netloc.replace("www.", "")
137
website = f"[{netloc}]({provider_url})"
138
label = image_model["provider"] if image_model["label"] is None else image_model["label"]
139
lines.append(f'| {label} | {image_model["provider"]} | {image_model["image_model"]} | {website} |')
140
141
print("\n".join(lines))
142
124
143
if __name__ == "__main__":
125
144
print_providers()
126
145
print("\n", "-" * 50, "\n")
127
print_models()
146
print_models()
147
print("\n", "-" * 50, "\n")
148
print_image_models()
@@ -16,6 +16,7 @@ class BingCreateImages(AsyncGeneratorProvider, ProviderModelMixin):
16
16
url = "https://www.bing.com/images/create"
17
17
working = True
18
18
needs_auth = True
19
image_models = ["dall-e"]
19
20
20
21
def __init__(self, cookies: Cookies = None, proxy: str = None) -> None:
21
22
self.cookies: Cookies = cookies
@@ -11,6 +11,7 @@ class DeepInfraImage(AsyncGeneratorProvider, ProviderModelMixin):
11
11
url = "https://deepinfra.com"
12
12
working = True
13
13
default_model = 'stability-ai/sdxl'
14
image_models = [default_model]
14
15
15
16
@classmethod
16
17
def get_models(cls):
@@ -18,6 +19,7 @@ class DeepInfraImage(AsyncGeneratorProvider, ProviderModelMixin):
18
19
url = 'https://api.deepinfra.com/models/featured'
19
20
models = requests.get(url).json()
20
21
cls.models = [model['model_name'] for model in models if model["reported_type"] == "text-to-image"]
22
cls.image_models = cls.models
21
23
return cls.models
22
24
23
25
@classmethod
@@ -13,7 +13,7 @@ from ..requests import raise_for_status, DEFAULT_HEADERS
13
13
from ..image import ImageResponse, ImagePreview
14
14
from ..errors import ResponseError
15
15
from .base_provider import AsyncGeneratorProvider
16
from .helper import format_prompt, get_connector
16
from .helper import format_prompt, get_connector, format_cookies
17
17
18
18
class Sources():
19
19
def __init__(self, link_list: List[Dict[str, str]]) -> None:
@@ -48,7 +48,6 @@ class MetaAI(AsyncGeneratorProvider):
48
48
49
49
async def update_access_token(self, birthday: str = "1999-01-01"):
50
50
url = "https://www.meta.ai/api/graphql/"
51
52
51
payload = {
53
52
"lsd": self.lsd,
54
53
"fb_api_caller_class": "RelayModern",
@@ -90,7 +89,7 @@ class MetaAI(AsyncGeneratorProvider):
90
89
headers = {}
91
90
headers = {
92
91
'content-type': 'application/x-www-form-urlencoded',
93
'cookie': "; ".join([f"{k}={v}" for k, v in cookies.items()]),
92
'cookie': format_cookies(cookies),
94
93
'origin': 'https://www.meta.ai',
95
94
'referer': 'https://www.meta.ai/',
96
95
'x-asbd-id': '129477',
@@ -194,7 +193,7 @@ class MetaAI(AsyncGeneratorProvider):
194
193
**headers
195
194
}
196
195
async with self.session.post(url, headers=headers, cookies=self.cookies, data=payload) as response:
197
await raise_for_status(response)
196
await raise_for_status(response, "Fetch sources failed")
198
197
text = await response.text()
199
198
if "<h1>Something Went Wrong</h1>" in text:
200
199
raise ResponseError("Response: Something Went Wrong")
@@ -6,6 +6,7 @@ from .MetaAI import MetaAI
6
6
7
7
class MetaAIAccount(MetaAI):
8
8
needs_auth = True
9
image_models = ["meta"]
9
10
10
11
@classmethod
11
12
async def create_async_generator(
@@ -17,6 +17,7 @@ class ReplicateImage(AsyncGeneratorProvider, ProviderModelMixin):
17
17
"39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
18
18
"2b017d9b67edd2ee1401238df49d75da53c523f36e363881e057f5dc3ed3c5b2"
19
19
]
20
image_models = [default_model]
20
21
21
22
@classmethod
22
23
async def create_async_generator(
@@ -8,7 +8,7 @@ import uuid
8
8
from ..typing import AsyncResult, Messages, ImageType, Cookies
9
9
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
10
10
from .helper import format_prompt
11
from ..image import ImageResponse, to_bytes, is_accepted_format
11
from ..image import ImageResponse, ImagePreview, to_bytes, is_accepted_format
12
12
from ..requests import StreamSession, FormData, raise_for_status
13
13
from .you.har_file import get_telemetry_ids
14
14
from .. import debug
@@ -34,6 +34,7 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
34
34
model_aliases = {
35
35
"claude-v2": "claude-2"
36
36
}
37
image_models = ["dall-e"]
37
38
_cookies = None
38
39
_cookies_used = 0
39
40
_telemetry_ids = []
@@ -67,7 +68,7 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
67
68
timeout=(30, timeout)
68
69
) as session:
69
70
cookies = await cls.get_cookies(session) if chat_mode != "default" else None
70
71
71
72
upload = json.dumps([await cls.upload_file(session, cookies, to_bytes(image), image_name)]) if image else ""
72
73
headers = {
73
74
"Accept": "text/event-stream",
@@ -102,11 +103,17 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
102
103
if event == "youChatToken" and event in data:
103
104
yield data[event]
104
105
elif event == "youChatUpdate" and "t" in data and data["t"] is not None:
105
match = re.search(r"!\[fig\]\((.+?)\)", data["t"])
106
if match:
107
yield ImageResponse(match.group(1), messages[-1]["content"])
106
if chat_mode == "create":
107
match = re.search(r"!\[(.+?)\]\((.+?)\)", data["t"])
108
if match:
109
if match.group(1) == "fig":
110
yield ImagePreview(match.group(2), messages[-1]["content"])
111
else:
112
yield ImageResponse(match.group(2), match.group(1))
113
else:
114
yield data["t"]
108
115
else:
109
yield data["t"]
116
yield data["t"]
110
117
111
118
@classmethod
112
119
async def upload_file(cls, client: StreamSession, cookies: Cookies, file: bytes, filename: str = None) -> dict:
@@ -41,6 +41,8 @@ async def create_conversation(session: StreamSession, headers: dict, tone: str)
41
41
raise RateLimitError("Response 404: Do less requests and reuse conversations")
42
42
await raise_for_status(response, "Failed to create conversation")
43
43
data = await response.json()
44
if not data:
45
raise RuntimeError('Empty response: Failed to create conversation')
44
46
conversationId = data.get('conversationId')
45
47
clientId = data.get('clientId')
46
48
conversationSignature = response.headers.get('X-Sydney-Encryptedconversationsignature')
@@ -53,6 +53,7 @@ class Gemini(AsyncGeneratorProvider):
53
53
url = "https://gemini.google.com"
54
54
needs_auth = True
55
55
working = True
56
image_models = ["gemini"]
56
57
57
58
@classmethod
58
59
async def create_async_generator(
@@ -3,4 +3,5 @@ from __future__ import annotations
3
3
from .OpenaiChat import OpenaiChat
4
4
5
5
class OpenaiAccount(OpenaiChat):
6
needs_auth = True
6
needs_auth = True
7
image_models = ["dall-e"]
@@ -29,6 +29,7 @@ from ...requests.aiohttp import StreamSession
29
29
from ...image import to_image, to_bytes, ImageResponse, ImageRequest
30
30
from ...errors import MissingAuthError, ResponseError
31
31
from ...providers.conversation import BaseConversation
32
from ..helper import format_cookies
32
33
from ..openai.har_file import getArkoseAndAccessToken, NoValidHarFileError
33
34
from ... import debug
34
35
@@ -44,7 +45,12 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
44
45
supports_system_message = True
45
46
default_model = None
46
47
models = ["gpt-3.5-turbo", "gpt-4", "gpt-4-gizmo"]
47
model_aliases = {"text-davinci-002-render-sha": "gpt-3.5-turbo", "": "gpt-3.5-turbo", "gpt-4-turbo-preview": "gpt-4"}
48
model_aliases = {
49
"text-davinci-002-render-sha": "gpt-3.5-turbo",
50
"": "gpt-3.5-turbo",
51
"gpt-4-turbo-preview": "gpt-4",
52
"dall-e": "gpt-4",
53
}
48
54
_api_key: str = None
49
55
_headers: dict = None
50
56
_cookies: Cookies = None
@@ -364,8 +370,8 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
364
370
arkose_token = None
365
371
if cls.default_model is None:
366
372
try:
367
arkose_token, api_key, cookies = await getArkoseAndAccessToken(proxy)
368
cls._create_request_args(cookies)
373
arkose_token, api_key, cookies, headers = await getArkoseAndAccessToken(proxy)
374
cls._create_request_args(cookies, headers)
369
375
cls._set_api_key(api_key)
370
376
except NoValidHarFileError as e:
371
377
...
@@ -393,8 +399,8 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
393
399
print(f'Arkose: {need_arkose} Turnstile: {data["turnstile"]["required"]}')
394
400
395
401
if need_arkose and arkose_token is None:
396
arkose_token, api_key, cookies = await getArkoseAndAccessToken(proxy)
397
cls._create_request_args(cookies)
402
arkose_token, api_key, cookies, headers = await getArkoseAndAccessToken(proxy)
403
cls._create_request_args(cookies, headers)
398
404
cls._set_api_key(api_key)
399
405
if arkose_token is None:
400
406
raise MissingAuthError("No arkose token found in .har file")
@@ -613,7 +619,7 @@ this.fetch = async (url, options) => {
613
619
cookies[c.name] = c.value
614
620
user_agent = await page.evaluate("window.navigator.userAgent")
615
621
await page.close()
616
cls._create_request_args(cookies, user_agent)
622
cls._create_request_args(cookies, user_agent=user_agent)
617
623
cls._set_api_key(api_key)
618
624
619
625
@classmethod
@@ -667,16 +673,12 @@ this.fetch = async (url, options) => {
667
673
"oai-language": "en-US",
668
674
}
669
675
670
@staticmethod
671
def _format_cookies(cookies: Cookies):
672
return "; ".join(f"{k}={v}" for k, v in cookies.items() if k != "access_token")
673
674
676
@classmethod
675
def _create_request_args(cls, cookies: Cookies = None, user_agent: str = None):
676
cls._headers = cls.get_default_headers()
677
def _create_request_args(cls, cookies: Cookies = None, headers: dict = None, user_agent: str = None):
678
cls._headers = cls.get_default_headers() if headers is None else headers
677
679
if user_agent is not None:
678
680
cls._headers["user-agent"] = user_agent
679
cls._cookies = {} if cookies is None else cookies
681
cls._cookies = {} if cookies is None else {k: v for k, v in cookies.items() if k != "access_token"}
680
682
cls._update_cookie_header()
681
683
682
684
@classmethod
@@ -693,7 +695,7 @@ this.fetch = async (url, options) => {
693
695
694
696
@classmethod
695
697
def _update_cookie_header(cls):
696
cls._headers["cookie"] = cls._format_cookies(cls._cookies)
698
cls._headers["cookie"] = format_cookies(cls._cookies)
697
699
698
700
class Conversation(BaseConversation):
699
701
"""
@@ -59,17 +59,21 @@ def readHAR():
59
59
except KeyError:
60
60
continue
61
61
cookies = {c['name']: c['value'] for c in v['request']['cookies']}
62
headers = get_headers(v)
62
63
if not accessToken:
63
64
raise NoValidHarFileError("No accessToken found in .har files")
64
65
if not chatArks:
65
return None, accessToken, cookies
66
return chatArks.pop(), accessToken, cookies
66
return None, accessToken, cookies, headers
67
return chatArks.pop(), accessToken, cookies, headers
68
69
def get_headers(entry) -> dict:
70
return {h['name'].lower(): h['value'] for h in entry['request']['headers'] if h['name'].lower() not in ['content-length', 'cookie'] and not h['name'].startswith(':')}
67
71
68
72
def parseHAREntry(entry) -> arkReq:
69
73
tmpArk = arkReq(
70
74
arkURL=entry['request']['url'],
71
75
arkBx="",
72
arkHeader={h['name'].lower(): h['value'] for h in entry['request']['headers'] if h['name'].lower() not in ['content-length', 'cookie'] and not h['name'].startswith(':')},
76
arkHeader=get_headers(entry),
73
77
arkBody={p['name']: unquote(p['value']) for p in entry['request']['postData']['params'] if p['name'] not in ['rnd']},
74
78
arkCookies={c['name']: c['value'] for c in entry['request']['cookies']},
75
79
userAgent=""
@@ -123,11 +127,11 @@ def getN() -> str:
123
127
timestamp = str(int(time.time()))
124
128
return base64.b64encode(timestamp.encode()).decode()
125
129
126
async def getArkoseAndAccessToken(proxy: str):
130
async def getArkoseAndAccessToken(proxy: str) -> tuple[str, str, dict, dict]:
127
131
global chatArk, accessToken, cookies
128
132
if chatArk is None or accessToken is None:
129
chatArk, accessToken, cookies = readHAR()
133
chatArk, accessToken, cookies, headers = readHAR()
130
134
if chatArk is None:
131
return None, accessToken, cookies
135
return None, accessToken, cookies, headers
132
136
newReq = genArkReq(chatArk)
133
return await sendRequest(newReq, proxy), accessToken, cookies
137
return await sendRequest(newReq, proxy), accessToken, cookies, headers