返回提交历史
Added
g4f/Provider/ChatAnywhere.py
+53
-0
Modified
g4f/Provider/MyShell.py
+75
-72
Added
g4f/Provider/PerplexityAi.py
+121
-0
Modified
g4f/Provider/Phind.py
+99
-66
Modified
g4f/Provider/__init__.py
+22
-146
Modified
g4f/Provider/helper.py
+49
-8
Deleted
g4f/Provider/unfinished/PerplexityAi.py
+0
-100
Modified
g4f/Provider/unfinished/__init__.py
+0
-1
Modified
g4f/models.py
+16
-9
XFEstudio/gpt4free
Fix Phind and PerplexityAi - GPT-4 Providers Fix MyShell Provider Refactor Provider __init__ Add ChatAnywhere Provider Update models list
0c4e5e51
代码差异
9 个文件
+435
-402
@@ -0,0 +1,53 @@
1
from __future__ import annotations
2
3
from aiohttp import ClientSession
4
5
from ..typing import AsyncResult, Messages
6
from .base_provider import AsyncGeneratorProvider
7
8
9
class ChatAnywhere(AsyncGeneratorProvider):
10
url = "https://chatanywhere.cn"
11
supports_gpt_35_turbo = True
12
supports_message_history = True
13
working = True
14
15
@classmethod
16
async def create_async_generator(
17
cls,
18
model: str,
19
messages: Messages,
20
proxy: str = None,
21
temperature: float = 0.5,
22
**kwargs
23
) -> AsyncResult:
24
headers = {
25
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0",
26
"Accept": "application/json, text/plain, */*",
27
"Accept-Language": "de,en-US;q=0.7,en;q=0.3",
28
"Accept-Encoding": "gzip, deflate, br",
29
"Content-Type": "application/json",
30
"Referer": f"{cls.url}/",
31
"Origin": cls.url,
32
"Sec-Fetch-Dest": "empty",
33
"Sec-Fetch-Mode": "cors",
34
"Sec-Fetch-Site": "same-origin",
35
"Authorization": "",
36
"Connection": "keep-alive",
37
"TE": "trailers"
38
}
39
async with ClientSession(headers=headers) as session:
40
data = {
41
"list": messages,
42
"id": "s1_qYuOLXjI3rEpc7WHfQ",
43
"title": messages[-1]["content"],
44
"prompt": "",
45
"temperature": temperature,
46
"models": "61490748",
47
"continuous": True
48
}
49
async with session.post(f"{cls.url}/v1/chat/gpt/", json=data, proxy=proxy) as response:
50
response.raise_for_status()
51
async for chunk in response.content.iter_any():
52
if chunk:
53
yield chunk.decode()
@@ -1,91 +1,94 @@
1
1
from __future__ import annotations
2
2
3
import time, random, json
3
import time, json
4
4
5
from ..requests import StreamSession
6
from ..typing import AsyncResult, Messages
7
from .base_provider import AsyncGeneratorProvider
8
from .helper import format_prompt
5
try:
6
from selenium.webdriver.remote.webdriver import WebDriver
7
except ImportError:
8
class WebDriver():
9
pass
9
10
10
class MyShell(AsyncGeneratorProvider):
11
from ..typing import CreateResult, Messages
12
from .base_provider import BaseProvider
13
from .helper import format_prompt, get_browser
14
15
class MyShell(BaseProvider):
11
16
url = "https://app.myshell.ai/chat"
12
17
working = True
13
18
supports_gpt_35_turbo = True
19
supports_stream = True
14
20
15
21
@classmethod
16
async def create_async_generator(
22
def create_completion(
17
23
cls,
18
24
model: str,
19
25
messages: Messages,
26
stream: bool,
20
27
proxy: str = None,
21
28
timeout: int = 120,
29
browser: WebDriver = None,
30
display: bool = True,
22
31
**kwargs
23
) -> AsyncResult:
24
user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
25
headers = {
26
"User-Agent": user_agent,
27
"Myshell-Service-Name": "organics-api",
28
"Visitor-Id": generate_visitor_id(user_agent)
29
}
30
async with StreamSession(
31
impersonate="chrome107",
32
proxies={"https": proxy},
33
timeout=timeout,
34
headers=headers
35
) as session:
36
prompt = format_prompt(messages)
32
) -> CreateResult:
33
if not browser:
34
if display:
35
driver, display = get_browser("", True, proxy)
36
else:
37
display = get_browser("", False, proxy)
38
else:
39
driver = browser
40
41
from selenium.webdriver.common.by import By
42
from selenium.webdriver.support.ui import WebDriverWait
43
from selenium.webdriver.support import expected_conditions as EC
44
45
driver.get(cls.url)
46
try:
47
WebDriverWait(driver, timeout).until(
48
EC.presence_of_element_located((By.CSS_SELECTOR, "body:not(.no-js)"))
49
)
50
script = """
51
response = await fetch("https://api.myshell.ai/v1/bot/chat/send_message", {
52
"headers": {
53
"accept": "application/json",
54
"content-type": "application/json",
55
"myshell-service-name": "organics-api",
56
"visitor-id": localStorage.getItem("mix_visitorId")
57
},
58
"body": '{body}',
59
"method": "POST"
60
})
61
window.reader = response.body.getReader();
62
"""
37
63
data = {
38
"botId": "1",
64
"botId": "4738",
39
65
"conversation_scenario": 3,
40
"message": prompt,
66
"message": format_prompt(messages),
41
67
"messageType": 1
42
68
}
43
async with session.post("https://api.myshell.ai/v1/bot/chat/send_message", json=data) as response:
44
response.raise_for_status()
45
event = None
46
async for line in response.iter_lines():
47
if line.startswith(b"event: "):
48
event = line[7:]
49
elif event == b"MESSAGE_REPLY_SSE_ELEMENT_EVENT_NAME_TEXT":
50
if line.startswith(b"data: "):
51
yield json.loads(line[6:])["content"]
52
if event == b"MESSAGE_REPLY_SSE_ELEMENT_EVENT_NAME_TEXT_STREAM_PUSH_FINISHED":
53
break
54
55
56
def xor_hash(B: str):
57
r = []
58
i = 0
59
60
def o(e, t):
61
o_val = 0
62
for i in range(len(t)):
63
o_val |= r[i] << (8 * i)
64
return e ^ o_val
65
66
for e in range(len(B)):
67
t = ord(B[e])
68
r.insert(0, 255 & t)
69
70
if len(r) >= 4:
71
i = o(i, r)
72
r = []
73
74
if len(r) > 0:
75
i = o(i, r)
76
77
return hex(i)[2:]
78
79
def performance() -> str:
80
t = int(time.time() * 1000)
81
e = 0
82
while t == int(time.time() * 1000):
83
e += 1
84
return hex(t)[2:] + hex(e)[2:]
85
86
def generate_visitor_id(user_agent: str) -> str:
87
f = performance()
88
r = hex(int(random.random() * (16**16)))[2:-2]
89
d = xor_hash(user_agent)
90
e = hex(1080 * 1920)[2:]
91
return f"{f}-{r}-{d}-{e}-{f}"
69
driver.execute_script(script.replace("{body}", json.dumps(data)))
70
script = """
71
chunk = await window.reader.read();
72
text = await (new Response(chunk['value']).text());
73
content = '';
74
text.split('\\n').forEach((line, index) => {
75
if (line.startsWith('data: ')) {
76
try {
77
const data = JSON.parse(line.substring('data: '.length));
78
if ('content' in data) {
79
content += data['content'];
80
}
81
} catch(e) {}
82
}
83
});
84
return content;
85
"""
86
while chunk := driver.execute_script(script):
87
yield chunk
88
finally:
89
driver.close()
90
if not browser:
91
time.sleep(0.1)
92
driver.quit()
93
if display:
94
display.stop()
@@ -0,0 +1,121 @@
1
from __future__ import annotations
2
3
import time
4
try:
5
from selenium.webdriver.remote.webdriver import WebDriver
6
except ImportError:
7
class WebDriver():
8
pass
9
10
from ..typing import CreateResult, Messages
11
from .base_provider import BaseProvider
12
from .helper import format_prompt, get_browser
13
14
class PerplexityAi(BaseProvider):
15
url = "https://www.perplexity.ai"
16
working = True
17
supports_gpt_4 = True
18
supports_stream = True
19
20
@classmethod
21
def create_completion(
22
cls,
23
model: str,
24
messages: Messages,
25
stream: bool,
26
proxy: str = None,
27
timeout: int = 120,
28
browser: WebDriver = None,
29
copilot: bool = False,
30
display: bool = True,
31
**kwargs
32
) -> CreateResult:
33
from selenium.webdriver.common.by import By
34
from selenium.webdriver.support.ui import WebDriverWait
35
from selenium.webdriver.support import expected_conditions as EC
36
37
if browser:
38
driver = browser
39
else:
40
if display:
41
driver, display = get_browser("", True, proxy)
42
else:
43
driver = get_browser("", False, proxy)
44
45
prompt = format_prompt(messages)
46
47
driver.get(f"{cls.url}/")
48
wait = WebDriverWait(driver, timeout)
49
50
script = """
51
window._message = window._last_message = "";
52
window._message_finished = false;
53
const _socket_send = WebSocket.prototype.send;
54
WebSocket.prototype.send = function(...args) {
55
if (!window.socket_onmessage) {
56
window._socket_onmessage = this;
57
this.addEventListener("message", (event) => {
58
if (event.data.startsWith("42")) {
59
let data = JSON.parse(event.data.substring(2));
60
if (data[0] =="query_progress" || data[0] == "query_answered") {
61
let content = JSON.parse(data[1]["text"]);
62
if (data[1]["mode"] == "copilot") {
63
content = content[content.length-1]["content"]["answer"];
64
content = JSON.parse(content);
65
}
66
window._message = content["answer"];
67
window._message_finished = data[0] == "query_answered";
68
window._web_results = content["web_results"];
69
}
70
}
71
});
72
}
73
return _socket_send.call(this, ...args);
74
};
75
"""
76
driver.execute_script(script)
77
78
# Page loaded?
79
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "textarea[placeholder='Ask anything...']")))
80
81
if copilot:
82
try:
83
driver.find_element(By.CSS_SELECTOR, "img[alt='User avatar']")
84
driver.find_element(By.CSS_SELECTOR, "button[data-testid='copilot-toggle']").click()
85
except:
86
pass
87
88
# Enter question
89
driver.find_element(By.CSS_SELECTOR, "textarea[placeholder='Ask anything...']").send_keys(prompt)
90
# Submit question
91
driver.find_element(By.CSS_SELECTOR, "button.bg-super svg[data-icon='arrow-right']").click()
92
93
try:
94
script = """
95
if(window._message && window._message != window._last_message) {
96
try {
97
return window._message.substring(window._last_message.length);
98
} finally {
99
window._last_message = window._message;
100
}
101
} else if(window._message_finished) {
102
return null;
103
} else {
104
return '';
105
}
106
"""
107
while True:
108
chunk = driver.execute_script(script)
109
if chunk:
110
yield chunk
111
elif chunk != "":
112
break
113
else:
114
time.sleep(0.1)
115
finally:
116
driver.close()
117
if not browser:
118
time.sleep(0.1)
119
driver.quit()
120
if display:
121
display.stop()
@@ -1,83 +1,116 @@
1
1
from __future__ import annotations
2
2
3
import random, string
4
from datetime import datetime
3
import time
4
from urllib.parse import quote
5
try:
6
from selenium.webdriver.remote.webdriver import WebDriver
7
except ImportError:
8
class WebDriver():
9
pass
5
10
6
from ..typing import AsyncResult, Messages
7
from ..requests import StreamSession
8
from .base_provider import AsyncGeneratorProvider, format_prompt
11
from ..typing import CreateResult, Messages
12
from .base_provider import BaseProvider
13
from .helper import format_prompt, get_browser
9
14
10
11
class Phind(AsyncGeneratorProvider):
15
class Phind(BaseProvider):
12
16
url = "https://www.phind.com"
13
17
working = True
14
18
supports_gpt_4 = True
19
supports_stream = True
15
20
16
21
@classmethod
17
async def create_async_generator(
22
def create_completion(
18
23
cls,
19
24
model: str,
20
25
messages: Messages,
26
stream: bool,
21
27
proxy: str = None,
22
28
timeout: int = 120,
29
browser: WebDriver = None,
30
creative_mode: bool = None,
31
display: bool = True,
23
32
**kwargs
24
) -> AsyncResult:
25
chars = string.ascii_lowercase + string.digits
26
user_id = ''.join(random.choice(chars) for _ in range(24))
27
data = {
28
"question": format_prompt(messages),
29
"webResults": [],
30
"options": {
31
"date": datetime.now().strftime("%d.%m.%Y"),
32
"language": "en",
33
"detailed": True,
34
"anonUserId": user_id,
35
"answerModel": "GPT-4",
36
"creativeMode": False,
37
"customLinks": []
38
},
39
"context":""
40
}
41
headers = {
42
"Authority": cls.url,
43
"Accept": "application/json, text/plain, */*",
44
"Origin": cls.url,
45
"Referer": f"{cls.url}/"
46
}
47
async with StreamSession(
48
headers=headers,
49
timeout=(5, timeout),
50
proxies={"https": proxy},
51
impersonate="chrome107"
52
) as session:
53
async with session.post(f"{cls.url}/api/infer/answer", json=data) as response:
54
response.raise_for_status()
55
new_lines = 0
56
async for line in response.iter_lines():
57
if not line:
58
continue
59
if line.startswith(b"data: "):
60
line = line[6:]
61
if line.startswith(b"<PHIND_METADATA>"):
62
continue
63
if line:
64
if new_lines:
65
yield "".join(["\n" for _ in range(int(new_lines / 2))])
66
new_lines = 0
67
yield line.decode()
68
else:
69
new_lines += 1
33
) -> CreateResult:
34
from selenium.webdriver.common.by import By
35
from selenium.webdriver.support.ui import WebDriverWait
36
from selenium.webdriver.support import expected_conditions as EC
70
37
38
if browser:
39
driver = browser
40
else:
41
if display:
42
driver, display = get_browser("", True, proxy)
43
else:
44
driver = get_browser("", False, proxy)
71
45
72
@classmethod
73
@property
74
def params(cls):
75
params = [
76
("model", "str"),
77
("messages", "list[dict[str, str]]"),
78
("stream", "bool"),
79
("proxy", "str"),
80
("timeout", "int"),
81
]
82
param = ", ".join([": ".join(p) for p in params])
83
return f"g4f.provider.{cls.__name__} supports: ({param})"
46
prompt = quote(format_prompt(messages))
47
driver.get(f"{cls.url}/search?q={prompt}&source=searchbox")
48
49
if model.startswith("gpt-4") or creative_mode:
50
wait = WebDriverWait(driver, timeout)
51
# Open dropdown
52
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.text-dark.dropdown-toggle")))
53
driver.find_element(By.CSS_SELECTOR, "button.text-dark.dropdown-toggle").click()
54
# Enable GPT-4
55
wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='GPT-4']")))
56
if model.startswith("gpt-4"):
57
driver.find_element(By.XPATH, "//button[text()='GPT-4']").click()
58
# Enable creative mode
59
if creative_mode or creative_mode == None:
60
driver.find_element(By.ID, "Creative Mode").click()
61
# Submit question
62
driver.find_element(By.CSS_SELECTOR, ".search-bar-input-group button[type='submit']").click()
63
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".search-container")))
64
65
try:
66
script = """
67
window._fetch = window.fetch;
68
window.fetch = (url, options) => {
69
const result = window._fetch(url, options);
70
if (url != "/api/infer/answer") return result;
71
result.then((response) => {
72
if (!response.body.locked) {
73
window.reader = response.body.getReader();
74
}
75
});
76
return new Promise((resolve, reject) => {
77
resolve(new Response(new ReadableStream()))
78
});
79
}
80
"""
81
driver.execute_script(script)
82
script = """
83
if(window.reader) {
84
chunk = await window.reader.read();
85
if (chunk['done']) return null;
86
text = await (new Response(chunk['value']).text());
87
content = '';
88
text.split('\\r\\n').forEach((line, index) => {
89
if (line.startsWith('data: ')) {
90
line = line.substring('data: '.length);
91
if (!line.startsWith('<PHIND_METADATA>')) {
92
if (line) content += line;
93
else content += '\\n';
94
}
95
}
96
});
97
return content.replace('\\n\\n', '\\n');
98
} else {
99
return ''
100
}
101
"""
102
while True:
103
chunk = driver.execute_script(script)
104
if chunk:
105
yield chunk
106
elif chunk != "":
107
break
108
else:
109
time.sleep(0.1)
110
finally:
111
driver.close()
112
if not browser:
113
time.sleep(0.1)
114
driver.quit()
115
if display:
116
display.stop()
@@ -1,10 +1,12 @@
1
from __future__ import annotations
1
from __future__ import annotations
2
2
3
from .AiAsk import AiAsk
3
4
from .Aichat import Aichat
4
5
from .AItianhu import AItianhu
5
6
from .AItianhuSpace import AItianhuSpace
6
7
from .Berlin import Berlin
7
8
from .Bing import Bing
9
from .ChatAnywhere import ChatAnywhere
8
10
from .ChatBase import ChatBase
9
11
from .ChatForAi import ChatForAi
10
12
from .Chatgpt4Online import Chatgpt4Online
@@ -28,6 +30,7 @@ from .Llama2 import Llama2
28
30
from .MyShell import MyShell
29
31
from .NoowAi import NoowAi
30
32
from .Opchatgpts import Opchatgpts
33
from .PerplexityAi import PerplexityAi
31
34
from .Phind import Phind
32
35
from .Vercel import Vercel
33
36
from .Ylokh import Ylokh
@@ -41,150 +44,23 @@ from .deprecated import *
41
44
from .needs_auth import *
42
45
from .unfinished import *
43
46
44
class ProviderUtils:
45
convert: dict[str, BaseProvider] = {
46
'AItianhu': AItianhu,
47
'AItianhuSpace': AItianhuSpace,
48
'Acytoo': Acytoo,
49
'AiAsk': AiAsk,
50
'AiService': AiService,
51
'Aibn': Aibn,
52
'Aichat': Aichat,
53
'Ails': Ails,
54
'Aivvm': Aivvm,
55
'AsyncGeneratorProvider': AsyncGeneratorProvider,
56
'AsyncProvider': AsyncProvider,
57
'Bard': Bard,
58
'BaseProvider': BaseProvider,
59
'Berlin': Berlin,
60
'Bing': Bing,
61
'ChatBase': ChatBase,
62
'ChatForAi': ChatForAi,
63
'Chatgpt4Online': Chatgpt4Online,
64
'ChatgptAi': ChatgptAi,
65
'ChatgptDemo': ChatgptDemo,
66
'ChatgptDuo': ChatgptDuo,
67
'ChatgptFree': ChatgptFree,
68
'ChatgptLogin': ChatgptLogin,
69
'ChatgptX': ChatgptX,
70
'CodeLinkAva': CodeLinkAva,
71
'Cromicle': Cromicle,
72
'DeepInfra': DeepInfra,
73
'DfeHub': DfeHub,
74
'EasyChat': EasyChat,
75
'Equing': Equing,
76
'FastGpt': FastGpt,
77
'Forefront': Forefront,
78
'FakeGpt': FakeGpt,
79
'FreeGpt': FreeGpt,
80
'GPTalk': GPTalk,
81
'GptChatly': GptChatly,
82
'GetGpt': GetGpt,
83
'GptForLove': GptForLove,
84
'GptGo': GptGo,
85
'GptGod': GptGod,
86
'Hashnode': Hashnode,
87
'H2o': H2o,
88
'HuggingChat': HuggingChat,
89
'Komo': Komo,
90
'Koala': Koala,
91
'Liaobots': Liaobots,
92
'Llama2': Llama2,
93
'Lockchat': Lockchat,
94
'MikuChat': MikuChat,
95
'Myshell': Myshell,
96
'MyShell': MyShell,
97
'NoowAi': NoowAi,
98
'Opchatgpts': Opchatgpts,
99
'OpenAssistant': OpenAssistant,
100
'OpenaiChat': OpenaiChat,
101
'PerplexityAi': PerplexityAi,
102
'Phind': Phind,
103
'Raycast': Raycast,
104
'Theb': Theb,
105
'V50': V50,
106
'Vercel': Vercel,
107
'Vitalentum': Vitalentum,
108
'Wewordle': Wewordle,
109
'Wuguokai': Wuguokai,
110
'Ylokh': Ylokh,
111
'You': You,
112
'Yqcloud': Yqcloud,
113
'GeekGpt': GeekGpt,
114
115
'BaseProvider': BaseProvider,
116
'AsyncProvider': AsyncProvider,
117
'AsyncGeneratorProvider': AsyncGeneratorProvider,
118
'RetryProvider': RetryProvider,
119
}
47
import sys
120
48
121
__all__ = [
122
'BaseProvider',
123
'AsyncProvider',
124
'AsyncGeneratorProvider',
125
'RetryProvider',
126
'Acytoo',
127
'AiAsk',
128
'Aibn',
129
'Aichat',
130
'Ails',
131
'Aivvm',
132
'AiService',
133
'AItianhu',
134
'AItianhuSpace',
135
'Aivvm',
136
'Bard',
137
'Berlin',
138
'Bing',
139
'ChatBase',
140
'ChatForAi',
141
'Chatgpt4Online',
142
'ChatgptAi',
143
'ChatgptDemo',
144
'ChatgptDuo',
145
'ChatgptFree',
146
'ChatgptLogin',
147
'ChatgptX',
148
'Cromicle',
149
'DeepInfra',
150
'CodeLinkAva',
151
'DfeHub',
152
'EasyChat',
153
'Forefront',
154
'FakeGpt',
155
'FreeGpt',
156
'GPTalk',
157
'GptChatly',
158
'GptForLove',
159
'GetGpt',
160
'GptGo',
161
'GptGod',
162
'Hashnode',
163
'H2o',
164
'HuggingChat',
165
'Koala',
166
'Liaobots',
167
'Llama2',
168
'Lockchat',
169
'Myshell',
170
'MyShell',
171
'NoowAi',
172
'Opchatgpts',
173
'Raycast',
174
'OpenaiChat',
175
'OpenAssistant',
176
'PerplexityAi',
177
'Phind',
178
'Theb',
179
'Vercel',
180
'Vitalentum',
181
'Wewordle',
182
'Ylokh',
183
'You',
184
'Yqcloud',
185
'Equing',
186
'FastGpt',
187
'Wuguokai',
188
'V50',
189
'GeekGpt'
49
__modules__: list = [
50
getattr(sys.modules[__name__], provider) for provider in dir()
51
if not provider.startswith("__")
52
]
53
__providers__: list[type[BaseProvider]] = [
54
provider for provider in __modules__
55
if isinstance(provider, type)
56
and issubclass(provider, BaseProvider)
190
57
]
58
__all__: list[str] = [
59
provider.__name__ for provider in __providers__
60
]
61
__map__: dict[str, BaseProvider] = dict([
62
(provider.__name__, provider) for provider in __providers__
63
])
64
65
class ProviderUtils:
66
convert: dict[str, BaseProvider] = __map__
@@ -3,13 +3,39 @@ from __future__ import annotations
3
3
import sys
4
4
import asyncio
5
5
import webbrowser
6
7
6
from os import path
8
7
from asyncio import AbstractEventLoop
9
8
from platformdirs import user_config_dir
9
from browser_cookie3 import (
10
chrome,
11
chromium,
12
opera,
13
opera_gx,
14
brave,
15
edge,
16
vivaldi,
17
firefox,
18
BrowserCookieError
19
)
20
try:
21
from undetected_chromedriver import Chrome, ChromeOptions
22
except ImportError:
23
class Chrome():
24
def __init__():
25
raise RuntimeError('Please install "undetected_chromedriver" and "pyvirtualdisplay" package')
26
class ChromeOptions():
27
def add_argument():
28
pass
29
try:
30
from pyvirtualdisplay import Display
31
except ImportError:
32
class Display():
33
def start():
34
pass
35
def stop():
36
pass
10
37
11
from ..typing import Dict, Messages
12
from browser_cookie3 import chrome, chromium, opera, opera_gx, brave, edge, vivaldi, firefox, BrowserCookieError
38
from ..typing import Dict, Messages, Union, Tuple
13
39
from .. import debug
14
40
15
41
# Change event loop policy on windows
@@ -106,10 +132,25 @@ def format_prompt(messages: Messages, add_special_tokens=False) -> str:
106
132
return f"{formatted}\nAssistant:"
107
133
108
134
109
def get_browser(user_data_dir: str = None):
110
from undetected_chromedriver import Chrome
111
112
if not user_data_dir:
135
def get_browser(
136
user_data_dir: str = None,
137
display: bool = False,
138
proxy: str = None
139
) -> Union[Chrome, Tuple[Chrome, Display]] :
140
if user_data_dir == None:
113
141
user_data_dir = user_config_dir("g4f")
114
142
115
return Chrome(user_data_dir=user_data_dir)
143
if display:
144
display = Display(visible=0, size=(1920, 1080))
145
display.start()
146
147
options = None
148
if proxy:
149
options = ChromeOptions()
150
options.add_argument(f'--proxy-server={proxy}')
151
152
browser = Chrome(user_data_dir=user_data_dir, options=options)
153
if display:
154
return browser, display
155
156
return browser
@@ -1,100 +0,0 @@
1
from __future__ import annotations
2
3
import json
4
import time
5
import base64
6
from curl_cffi.requests import AsyncSession
7
8
from ..base_provider import AsyncProvider, format_prompt, get_cookies
9
10
11
class PerplexityAi(AsyncProvider):
12
url = "https://www.perplexity.ai"
13
supports_gpt_35_turbo = True
14
_sources = []
15
16
@classmethod
17
async def create_async(
18
cls,
19
model: str,
20
messages: list[dict[str, str]],
21
proxy: str = None,
22
**kwargs
23
) -> str:
24
url = f"{cls.url}/socket.io/?EIO=4&transport=polling"
25
headers = {
26
"Referer": f"{cls.url}/"
27
}
28
async with AsyncSession(headers=headers, proxies={"https": proxy}, impersonate="chrome107") as session:
29
url_session = "https://www.perplexity.ai/api/auth/session"
30
response = await session.get(url_session)
31
response.raise_for_status()
32
33
url_session = "https://www.perplexity.ai/api/auth/session"
34
response = await session.get(url_session)
35
response.raise_for_status()
36
37
response = await session.get(url, params={"t": timestamp()})
38
response.raise_for_status()
39
sid = json.loads(response.text[1:])["sid"]
40
41
response = await session.get(url, params={"t": timestamp(), "sid": sid})
42
response.raise_for_status()
43
44
data = '40{"jwt":"anonymous-ask-user"}'
45
response = await session.post(url, params={"t": timestamp(), "sid": sid}, data=data)
46
response.raise_for_status()
47
48
response = await session.get(url, params={"t": timestamp(), "sid": sid})
49
response.raise_for_status()
50
51
data = "424" + json.dumps([
52
"perplexity_ask",
53
format_prompt(messages),
54
{
55
"version":"2.1",
56
"source":"default",
57
"language":"en",
58
"timezone": time.tzname[0],
59
"search_focus":"internet",
60
"mode":"concise"
61
}
62
])
63
response = await session.post(url, params={"t": timestamp(), "sid": sid}, data=data)
64
response.raise_for_status()
65
66
while True:
67
response = await session.get(url, params={"t": timestamp(), "sid": sid})
68
response.raise_for_status()
69
for line in response.text.splitlines():
70
if line.startswith("434"):
71
result = json.loads(json.loads(line[3:])[0]["text"])
72
73
cls._sources = [{
74
"title": source["name"],
75
"url": source["url"],
76
"snippet": source["snippet"]
77
} for source in result["web_results"]]
78
79
return result["answer"]
80
81
@classmethod
82
def get_sources(cls):
83
return cls._sources
84
85
86
@classmethod
87
@property
88
def params(cls):
89
params = [
90
("model", "str"),
91
("messages", "list[dict[str, str]]"),
92
("stream", "bool"),
93
("proxy", "str"),
94
]
95
param = ", ".join([": ".join(p) for p in params])
96
return f"g4f.provider.{cls.__name__} supports: ({param})"
97
98
99
def timestamp() -> str:
100
return base64.urlsafe_b64encode(int(time.time()-1407782612).to_bytes(4, 'big')).decode()
@@ -1,5 +1,4 @@
1
1
from .MikuChat import MikuChat
2
from .PerplexityAi import PerplexityAi
3
2
from .Komo import Komo
4
3
from .TalkAi import TalkAi
5
4
from .ChatAiGpt import ChatAiGpt
@@ -3,6 +3,9 @@ from dataclasses import dataclass
3
3
from .typing import Union
4
4
from .Provider import BaseProvider, RetryProvider
5
5
from .Provider import (
6
Chatgpt4Online,
7
ChatAnywhere,
8
PerplexityAi,
6
9
GptForLove,
7
10
ChatgptAi,
8
11
DeepInfra,
@@ -11,14 +14,12 @@ from .Provider import (
11
14
GeekGpt,
12
15
FakeGpt,
13
16
FreeGpt,
14
NoowAi,
15
17
Berlin,
16
18
Llama2,
17
19
Vercel,
18
GPTalk,
20
Phind,
19
21
Koala,
20
22
GptGo,
21
Phind,
22
23
Bard,
23
24
Bing,
24
25
You,
@@ -39,20 +40,24 @@ default = Model(
39
40
name = "",
40
41
base_provider = "",
41
42
best_provider = RetryProvider([
42
Bing, # Not fully GPT 3 or 4
43
Bing,
43
44
ChatgptAi, GptGo, GeekGpt,
44
Phind, You
45
You,
46
Chatgpt4Online,
47
ChatAnywhere,
45
48
])
46
49
)
47
50
48
# GPT-3.5 too, but all providers supports long responses and a custom timeouts
51
# GPT-3.5 too, but all providers supports long requests and responses
49
52
gpt_35_long = Model(
50
53
name = 'gpt-3.5-turbo',
51
54
base_provider = 'openai',
52
55
best_provider = RetryProvider([
53
56
FreeGpt, You,
54
57
GeekGpt, FakeGpt,
55
Berlin, Koala
58
Berlin, Koala,
59
Chatgpt4Online,
60
ChatAnywhere,
56
61
])
57
62
)
58
63
@@ -62,7 +67,9 @@ gpt_35_turbo = Model(
62
67
base_provider = 'openai',
63
68
best_provider=RetryProvider([
64
69
ChatgptX, GptGo, You,
65
NoowAi, GPTalk, GptForLove, Phind, ChatBase
70
GptForLove, ChatBase,
71
Chatgpt4Online,
72
ChatAnywhere,
66
73
])
67
74
)
68
75
@@ -70,7 +77,7 @@ gpt_4 = Model(
70
77
name = 'gpt-4',
71
78
base_provider = 'openai',
72
79
best_provider = RetryProvider([
73
Bing, GeekGpt, Phind
80
Bing, Phind, PerplexityAi
74
81
])
75
82
)
76
83