返回提交历史
Modified
g4f/Provider/DeepInfra.py
+1
-2
Modified
g4f/Provider/Reka.py
+13
-13
Modified
g4f/Provider/Replicate.py
+1
-0
Modified
g4f/Provider/You.py
+3
-10
Modified
g4f/Provider/needs_auth/Gemini.py
+6
-3
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+6
-3
Added
g4f/Provider/needs_auth/PerplexityApi.py
+31
-0
Modified
g4f/Provider/needs_auth/__init__.py
+2
-1
Modified
g4f/Provider/you/har_file.py
+8
-10
Modified
g4f/providers/retry_provider.py
+1
-1
XFEstudio/gpt4free
Add needs auth to provierds, Add PerplexityApi provider Add proxy support to nodriver
24c5502d
代码差异
10 个文件
+72
-43
@@ -8,8 +8,7 @@ class DeepInfra(Openai):
8
8
label = "DeepInfra"
9
9
url = "https://deepinfra.com"
10
10
working = True
11
needs_auth = False
12
has_auth = True
11
needs_auth = True
13
12
supports_stream = True
14
13
supports_message_history = True
15
14
default_model = "meta-llama/Meta-Llama-3-70b-instruct"
@@ -9,6 +9,7 @@ from ..image import to_bytes
9
9
class Reka(AbstractProvider):
10
10
url = "https://chat.reka.ai/"
11
11
working = True
12
needs_auth = True
12
13
supports_stream = True
13
14
default_vision_model = "reka"
14
15
cookies = {}
@@ -20,13 +21,12 @@ class Reka(AbstractProvider):
20
21
messages: Messages,
21
22
stream: bool,
22
23
proxy: str = None,
23
timeout: int = 180,
24
24
api_key: str = None,
25
25
image: ImageType = None,
26
26
**kwargs
27
27
) -> CreateResult:
28
28
cls.proxy = proxy
29
29
30
30
if not api_key:
31
31
cls.cookies = get_cookies("chat.reka.ai")
32
32
if not cls.cookies:
@@ -34,19 +34,19 @@ class Reka(AbstractProvider):
34
34
elif "appSession" not in cls.cookies:
35
35
raise ValueError("No appSession found in cookies for chat.reka.ai, log in or provide bearer_auth")
36
36
api_key = cls.get_access_token(cls)
37
37
38
38
conversation = []
39
39
for message in messages:
40
40
conversation.append({
41
41
"type": "human",
42
42
"text": message["content"],
43
43
})
44
44
45
45
if image:
46
46
image_url = cls.upload_image(cls, api_key, image)
47
47
conversation[-1]["image_url"] = image_url
48
48
conversation[-1]["media_type"] = "image"
49
49
50
50
headers = {
51
51
'accept': '*/*',
52
52
'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
@@ -64,7 +64,7 @@ class Reka(AbstractProvider):
64
64
'sec-fetch-site': 'same-origin',
65
65
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
66
66
}
67
67
68
68
json_data = {
69
69
'conversation_history': conversation,
70
70
'stream': True,
@@ -73,7 +73,7 @@ class Reka(AbstractProvider):
73
73
'model_name': 'reka-core',
74
74
'random_seed': int(time.time() * 1000),
75
75
}
76
76
77
77
tokens = ''
78
78
79
79
response = requests.post('https://chat.reka.ai/api/chat',
@@ -82,11 +82,11 @@ class Reka(AbstractProvider):
82
82
for completion in response.iter_lines():
83
83
if b'data' in completion:
84
84
token_data = json.loads(completion.decode('utf-8')[5:])['text']
85
85
86
86
yield (token_data.replace(tokens, ''))
87
87
88
88
tokens = token_data
89
89
90
90
def upload_image(cls, access_token, image: ImageType) -> str:
91
91
boundary_token = os.urandom(8).hex()
92
92
@@ -120,7 +120,7 @@ class Reka(AbstractProvider):
120
120
cookies=cls.cookies, headers=headers, proxies=cls.proxy, data=data.encode('latin-1'))
121
121
122
122
return response.json()['media_url']
123
123
124
124
def get_access_token(cls):
125
125
headers = {
126
126
'accept': '*/*',
@@ -141,8 +141,8 @@ class Reka(AbstractProvider):
141
141
try:
142
142
response = requests.get('https://chat.reka.ai/bff/auth/access_token',
143
143
cookies=cls.cookies, headers=headers, proxies=cls.proxy)
144
144
145
145
return response.json()['accessToken']
146
146
147
147
except Exception as e:
148
148
raise ValueError(f"Failed to get access token: {e}, refresh your cookies / log in into chat.reka.ai")
@@ -10,6 +10,7 @@ from ..errors import ResponseError, MissingAuthError
10
10
class Replicate(AsyncGeneratorProvider, ProviderModelMixin):
11
11
url = "https://replicate.com"
12
12
working = True
13
needs_auth = True
13
14
default_model = "meta/meta-llama-3-70b-instruct"
14
15
model_aliases = {
15
16
"meta-llama/Meta-Llama-3-70B-Instruct": default_model
@@ -1,3 +1,5 @@
1
from __future__ import annotations
2
1
3
import re
2
4
import json
3
5
import base64
@@ -42,7 +44,6 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
42
44
]
43
45
model_aliases = {
44
46
"claude-v2": "claude-2",
45
"gpt-4o": "gpt-4o",
46
47
}
47
48
_cookies = None
48
49
_cookies_used = 0
@@ -185,15 +186,7 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
185
186
@classmethod
186
187
async def create_cookies(cls, client: StreamSession) -> Cookies:
187
188
if not cls._telemetry_ids:
188
try:
189
cls._telemetry_ids = await get_telemetry_ids()
190
except RuntimeError as e:
191
if str(e) == "Event loop is closed":
192
if debug.logging:
193
print("Event loop is closed error occurred in create_cookies.")
194
else:
195
raise
196
189
cls._telemetry_ids = await get_telemetry_ids()
197
190
user_uuid = str(uuid.uuid4())
198
191
telemetry_id = cls._telemetry_ids.pop()
199
192
if debug.logging:
@@ -59,7 +59,7 @@ class Gemini(AsyncGeneratorProvider):
59
59
_cookies: Cookies = None
60
60
61
61
@classmethod
62
async def nodriver_login(cls) -> AsyncIterator[str]:
62
async def nodriver_login(cls, proxy: str = None) -> AsyncIterator[str]:
63
63
try:
64
64
import nodriver as uc
65
65
except ImportError:
@@ -71,7 +71,10 @@ class Gemini(AsyncGeneratorProvider):
71
71
user_data_dir = None
72
72
if debug.logging:
73
73
print(f"Open nodriver with user_dir: {user_data_dir}")
74
browser = await uc.start(user_data_dir=user_data_dir)
74
browser = await uc.start(
75
user_data_dir=user_data_dir,
76
browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
77
)
75
78
login_url = os.environ.get("G4F_LOGIN_URL")
76
79
if login_url:
77
80
yield f"Please login: [Google Gemini]({login_url})\n\n"
@@ -134,7 +137,7 @@ class Gemini(AsyncGeneratorProvider):
134
137
) as session:
135
138
snlm0e = await cls.fetch_snlm0e(session, cls._cookies) if cls._cookies else None
136
139
if not snlm0e:
137
async for chunk in cls.nodriver_login():
140
async for chunk in cls.nodriver_login(proxy):
138
141
yield chunk
139
142
if cls._cookies is None:
140
143
async for chunk in cls.webdriver_login(proxy):
@@ -403,7 +403,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
403
403
except NoValidHarFileError as e:
404
404
error = e
405
405
if cls._api_key is None:
406
await cls.nodriver_access_token()
406
await cls.nodriver_access_token(proxy)
407
407
if cls._api_key is None and cls.needs_auth:
408
408
raise error
409
409
cls.default_model = cls.get_model(await cls.get_default_model(session, cls._headers))
@@ -625,7 +625,7 @@ this.fetch = async (url, options) => {
625
625
cls._update_cookie_header()
626
626
627
627
@classmethod
628
async def nodriver_access_token(cls):
628
async def nodriver_access_token(cls, proxy: str = None):
629
629
try:
630
630
import nodriver as uc
631
631
except ImportError:
@@ -637,7 +637,10 @@ this.fetch = async (url, options) => {
637
637
user_data_dir = None
638
638
if debug.logging:
639
639
print(f"Open nodriver with user_dir: {user_data_dir}")
640
browser = await uc.start(user_data_dir=user_data_dir)
640
browser = await uc.start(
641
user_data_dir=user_data_dir,
642
browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
643
)
641
644
page = await browser.get("https://chatgpt.com/")
642
645
await page.select("[id^=headlessui-menu-button-]", 240)
643
646
api_key = await page.evaluate(
@@ -0,0 +1,31 @@
1
from __future__ import annotations
2
3
from .Openai import Openai
4
from ...typing import AsyncResult, Messages
5
6
class PerplexityApi(Openai):
7
label = "Perplexity API"
8
url = "https://www.perplexity.ai"
9
working = True
10
default_model = "llama-3-sonar-large-32k-online"
11
models = [
12
"llama-3-sonar-small-32k-chat",
13
"llama-3-sonar-small-32k-online",
14
"llama-3-sonar-large-32k-chat",
15
"llama-3-sonar-large-32k-online",
16
"llama-3-8b-instruct",
17
"llama-3-70b-instruct",
18
"mixtral-8x7b-instruct"
19
]
20
21
@classmethod
22
def create_async_generator(
23
cls,
24
model: str,
25
messages: Messages,
26
api_base: str = "https://api.perplexity.ai",
27
**kwargs
28
) -> AsyncResult:
29
return super().create_async_generator(
30
model, messages, api_base=api_base, **kwargs
31
)
@@ -7,4 +7,5 @@ from .Poe import Poe
7
7
from .Openai import Openai
8
8
from .Groq import Groq
9
9
from .OpenRouter import OpenRouter
10
from .OpenaiAccount import OpenaiAccount
10
from .OpenaiAccount import OpenaiAccount
11
from .PerplexityApi import PerplexityApi
@@ -88,36 +88,34 @@ async def get_telemetry_ids(proxy: str = None) -> list:
88
88
except NoValidHarFileError as e:
89
89
if debug.logging:
90
90
logging.error(e)
91
if debug.logging:
92
logging.error('Getting telemetry_id for you.com with nodriver')
91
93
92
try:
94
93
from nodriver import start
95
94
except ImportError:
96
95
raise MissingRequirementsError('Add .har file from you.com or install "nodriver" package | pip install -U nodriver')
97
page = None
96
if debug.logging:
97
logging.error('Getting telemetry_id for you.com with nodriver')
98
99
browser = page = None
98
100
try:
99
browser = await start()
101
browser = await start(
102
browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
103
)
100
104
page = await browser.get("https://you.com")
101
102
105
while not await page.evaluate('"GetTelemetryID" in this'):
103
106
await page.sleep(1)
104
105
107
async def get_telemetry_id():
106
108
return await page.evaluate(
107
109
f'this.GetTelemetryID("{public_token}", "{telemetry_url}");',
108
110
await_promise=True
109
111
)
110
111
112
return [await get_telemetry_id()]
112
113
113
finally:
114
114
try:
115
115
if page is not None:
116
116
await page.close()
117
118
117
if browser is not None:
119
118
await browser.close()
120
121
119
except Exception as e:
122
120
if debug.logging:
123
121
logging.error(e)
@@ -133,7 +133,7 @@ class NewBaseRetryProvider(BaseRetryProvider):
133
133
if not stream:
134
134
yield await provider.create_async(model, messages, **kwargs)
135
135
elif hasattr(provider, "create_async_generator"):
136
async for token in provider.create_async_generator(model, messages, stream, **kwargs):
136
async for token in provider.create_async_generator(model, messages, stream=stream, **kwargs):
137
137
yield token
138
138
else:
139
139
for token in provider.create_completion(model, messages, stream, **kwargs):