返回提交历史
Modified
g4f/Provider/AItianhuSpace.py
+4
-3
Modified
g4f/Provider/MyShell.py
+10
-8
Modified
g4f/Provider/PerplexityAi.py
+4
-3
Modified
g4f/Provider/Phind.py
+25
-25
Modified
g4f/Provider/TalkAi.py
+3
-3
Modified
g4f/Provider/helper.py
+1
-83
Modified
g4f/Provider/needs_auth/Bard.py
+6
-5
Modified
g4f/Provider/needs_auth/HuggingChat.py
+1
-14
Modified
g4f/Provider/needs_auth/OpenAssistant.py
+0
-12
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+56
-75
Modified
g4f/Provider/needs_auth/Poe.py
+6
-5
Modified
g4f/Provider/needs_auth/Raycast.py
+0
-15
Modified
g4f/Provider/needs_auth/Theb.py
+11
-18
Added
g4f/Provider/webdriver.py
+92
-0
XFEstudio/gpt4free
Add webdriver module
08e30834
代码差异
14 个文件
+219
-269
@@ -5,7 +5,8 @@ import random
5
5
6
6
from ..typing import CreateResult, Messages
7
7
from .base_provider import BaseProvider
8
from .helper import WebDriver, WebDriverSession, format_prompt, get_random_string
8
from .helper import format_prompt, get_random_string
9
from .webdriver import WebDriver, WebDriverSession
9
10
from .. import debug
10
11
11
12
class AItianhuSpace(BaseProvider):
@@ -24,7 +25,7 @@ class AItianhuSpace(BaseProvider):
24
25
domain: str = None,
25
26
proxy: str = None,
26
27
timeout: int = 120,
27
web_driver: WebDriver = None,
28
webdriver: WebDriver = None,
28
29
headless: bool = True,
29
30
**kwargs
30
31
) -> CreateResult:
@@ -39,7 +40,7 @@ class AItianhuSpace(BaseProvider):
39
40
url = f"https://{domain}"
40
41
prompt = format_prompt(messages)
41
42
42
with WebDriverSession(web_driver, "", headless=headless, proxy=proxy) as driver:
43
with WebDriverSession(webdriver, "", headless=headless, proxy=proxy) as driver:
43
44
from selenium.webdriver.common.by import By
44
45
from selenium.webdriver.support.ui import WebDriverWait
45
46
from selenium.webdriver.support import expected_conditions as EC
@@ -4,7 +4,8 @@ import time, json
4
4
5
5
from ..typing import CreateResult, Messages
6
6
from .base_provider import BaseProvider
7
from .helper import WebDriver, WebDriverSession, format_prompt
7
from .helper import format_prompt
8
from .webdriver import WebDriver, WebDriverSession
8
9
9
10
class MyShell(BaseProvider):
10
11
url = "https://app.myshell.ai/chat"
@@ -20,10 +21,10 @@ class MyShell(BaseProvider):
20
21
stream: bool,
21
22
proxy: str = None,
22
23
timeout: int = 120,
23
web_driver: WebDriver = None,
24
webdriver: WebDriver = None,
24
25
**kwargs
25
26
) -> CreateResult:
26
with WebDriverSession(web_driver, "", proxy=proxy) as driver:
27
with WebDriverSession(webdriver, "", proxy=proxy) as driver:
27
28
from selenium.webdriver.common.by import By
28
29
from selenium.webdriver.support.ui import WebDriverWait
29
30
from selenium.webdriver.support import expected_conditions as EC
@@ -52,15 +53,16 @@ response = await fetch("https://api.myshell.ai/v1/bot/chat/send_message", {
52
53
"body": '{body}',
53
54
"method": "POST"
54
55
})
55
window.reader = response.body.getReader();
56
window._reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
56
57
"""
57
58
driver.execute_script(script.replace("{body}", json.dumps(data)))
58
59
script = """
59
chunk = await window.reader.read();
60
if (chunk['done']) return null;
61
text = (new TextDecoder()).decode(chunk['value']);
60
chunk = await window._reader.read();
61
if (chunk['done']) {
62
return null;
63
}
62
64
content = '';
63
text.split('\\n').forEach((line, index) => {
65
chunk['value'].split('\\n').forEach((line, index) => {
64
66
if (line.startsWith('data: ')) {
65
67
try {
66
68
const data = JSON.parse(line.substring('data: '.length));
@@ -4,7 +4,8 @@ import time
4
4
5
5
from ..typing import CreateResult, Messages
6
6
from .base_provider import BaseProvider
7
from .helper import WebDriver, WebDriverSession, format_prompt
7
from .helper import format_prompt
8
from .webdriver import WebDriver, WebDriverSession
8
9
9
10
class PerplexityAi(BaseProvider):
10
11
url = "https://www.perplexity.ai"
@@ -20,12 +21,12 @@ class PerplexityAi(BaseProvider):
20
21
stream: bool,
21
22
proxy: str = None,
22
23
timeout: int = 120,
23
web_driver: WebDriver = None,
24
webdriver: WebDriver = None,
24
25
virtual_display: bool = True,
25
26
copilot: bool = False,
26
27
**kwargs
27
28
) -> CreateResult:
28
with WebDriverSession(web_driver, "", virtual_display=virtual_display, proxy=proxy) as driver:
29
with WebDriverSession(webdriver, "", virtual_display=virtual_display, proxy=proxy) as driver:
29
30
from selenium.webdriver.common.by import By
30
31
from selenium.webdriver.support.ui import WebDriverWait
31
32
from selenium.webdriver.support import expected_conditions as EC
@@ -5,7 +5,8 @@ from urllib.parse import quote
5
5
6
6
from ..typing import CreateResult, Messages
7
7
from .base_provider import BaseProvider
8
from .helper import WebDriver, WebDriverSession, format_prompt
8
from .helper import format_prompt
9
from .webdriver import WebDriver, WebDriverSession
9
10
10
11
class Phind(BaseProvider):
11
12
url = "https://www.phind.com"
@@ -21,11 +22,11 @@ class Phind(BaseProvider):
21
22
stream: bool,
22
23
proxy: str = None,
23
24
timeout: int = 120,
24
web_driver: WebDriver = None,
25
webdriver: WebDriver = None,
25
26
creative_mode: bool = None,
26
27
**kwargs
27
28
) -> CreateResult:
28
with WebDriverSession(web_driver, "", proxy=proxy) as driver:
29
with WebDriverSession(webdriver, "", proxy=proxy) as driver:
29
30
from selenium.webdriver.common.by import By
30
31
from selenium.webdriver.support.ui import WebDriverWait
31
32
from selenium.webdriver.support import expected_conditions as EC
@@ -34,40 +35,38 @@ class Phind(BaseProvider):
34
35
driver.get(f"{cls.url}/search?q={prompt}&source=searchbox")
35
36
36
37
# Register fetch hook
37
driver.execute_script("""
38
source = """
38
39
window._fetch = window.fetch;
39
window.fetch = (url, options) => {
40
// Call parent fetch method
41
const result = window._fetch(url, options);
40
window.fetch = async (url, options) => {
41
const response = await window._fetch(url, options);
42
42
if (url != "/api/infer/answer") {
43
return result;
43
return response;
44
44
}
45
// Load response reader
46
result.then((response) => {
47
if (!response.body.locked) {
48
window._reader = response.body.getReader();
49
}
50
});
51
// Return dummy response
52
return new Promise((resolve, reject) => {
53
resolve(new Response(new ReadableStream()))
54
});
45
copy = response.clone();
46
window._reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
47
return copy;
55
48
}
56
""")
49
"""
50
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
51
"source": source
52
})
57
53
58
54
# Need to change settings
59
if model.startswith("gpt-4") or creative_mode:
60
wait = WebDriverWait(driver, timeout)
55
wait = WebDriverWait(driver, timeout)
56
def open_dropdown():
61
57
# Open settings dropdown
62
58
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.text-dark.dropdown-toggle")))
63
59
driver.find_element(By.CSS_SELECTOR, "button.text-dark.dropdown-toggle").click()
64
60
# Wait for dropdown toggle
65
61
wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='GPT-4']")))
66
# Enable GPT-4
62
if model.startswith("gpt-4") or creative_mode:
63
# Enable GPT-4
67
64
if model.startswith("gpt-4"):
65
open_dropdown()
68
66
driver.find_element(By.XPATH, "//button[text()='GPT-4']").click()
69
67
# Enable creative mode
70
68
if creative_mode or creative_mode == None:
69
open_dropdown()
71
70
driver.find_element(By.ID, "Creative Mode").click()
72
71
# Submit changes
73
72
driver.find_element(By.CSS_SELECTOR, ".search-bar-input-group button[type='submit']").click()
@@ -78,10 +77,11 @@ window.fetch = (url, options) => {
78
77
chunk = driver.execute_script("""
79
78
if(window._reader) {
80
79
chunk = await window._reader.read();
81
if (chunk['done']) return null;
82
text = (new TextDecoder()).decode(chunk['value']);
80
if (chunk['done']) {
81
return null;
82
}
83
83
content = '';
84
text.split('\\r\\n').forEach((line, index) => {
84
chunk['value'].split('\\r\\n').forEach((line, index) => {
85
85
if (line.startsWith('data: ')) {
86
86
line = line.substring('data: '.length);
87
87
if (!line.startsWith('<PHIND_METADATA>')) {
@@ -4,7 +4,7 @@ import time, json, time
4
4
5
5
from ..typing import CreateResult, Messages
6
6
from .base_provider import BaseProvider
7
from .helper import WebDriver, WebDriverSession
7
from .webdriver import WebDriver, WebDriverSession
8
8
9
9
class TalkAi(BaseProvider):
10
10
url = "https://talkai.info"
@@ -19,10 +19,10 @@ class TalkAi(BaseProvider):
19
19
messages: Messages,
20
20
stream: bool,
21
21
proxy: str = None,
22
web_driver: WebDriver = None,
22
webdriver: WebDriver = None,
23
23
**kwargs
24
24
) -> CreateResult:
25
with WebDriverSession(web_driver, "", virtual_display=True, proxy=proxy) as driver:
25
with WebDriverSession(webdriver, "", virtual_display=True, proxy=proxy) as driver:
26
26
from selenium.webdriver.common.by import By
27
27
from selenium.webdriver.support.ui import WebDriverWait
28
28
from selenium.webdriver.support import expected_conditions as EC
@@ -6,7 +6,6 @@ import webbrowser
6
6
import random
7
7
import string
8
8
import secrets
9
import time
10
9
from os import path
11
10
from asyncio import AbstractEventLoop
12
11
from platformdirs import user_config_dir
@@ -21,26 +20,8 @@ from browser_cookie3 import (
21
20
firefox,
22
21
BrowserCookieError
23
22
)
24
try:
25
from selenium.webdriver.remote.webdriver import WebDriver
26
except ImportError:
27
class WebDriver():
28
pass
29
try:
30
from undetected_chromedriver import Chrome, ChromeOptions
31
except ImportError:
32
class Chrome():
33
def __init__():
34
raise RuntimeError('Please install the "undetected_chromedriver" package')
35
class ChromeOptions():
36
def add_argument():
37
pass
38
try:
39
from pyvirtualdisplay import Display
40
except ImportError:
41
pass
42
23
43
from ..typing import Dict, Messages, Union, Tuple
24
from ..typing import Dict, Messages
44
25
from .. import debug
45
26
46
27
# Change event loop policy on windows
@@ -135,74 +116,11 @@ def format_prompt(messages: Messages, add_special_tokens=False) -> str:
135
116
return f"{formatted}\nAssistant:"
136
117
137
118
138
def get_browser(
139
user_data_dir: str = None,
140
headless: bool = False,
141
proxy: str = None,
142
options: ChromeOptions = None
143
) -> Chrome:
144
if user_data_dir == None:
145
user_data_dir = user_config_dir("g4f")
146
if proxy:
147
if not options:
148
options = ChromeOptions()
149
options.add_argument(f'--proxy-server={proxy}')
150
return Chrome(options=options, user_data_dir=user_data_dir, headless=headless)
151
152
class WebDriverSession():
153
def __init__(
154
self,
155
web_driver: WebDriver = None,
156
user_data_dir: str = None,
157
headless: bool = False,
158
virtual_display: bool = False,
159
proxy: str = None,
160
options: ChromeOptions = None
161
):
162
self.web_driver = web_driver
163
self.user_data_dir = user_data_dir
164
self.headless = headless
165
self.virtual_display = virtual_display
166
self.proxy = proxy
167
self.options = options
168
169
def reopen(
170
self,
171
user_data_dir: str = None,
172
headless: bool = False,
173
virtual_display: bool = False
174
) -> WebDriver:
175
if user_data_dir == None:
176
user_data_dir = self.user_data_dir
177
self.default_driver.quit()
178
if not virtual_display and self.virtual_display:
179
self.virtual_display.stop()
180
self.default_driver = get_browser(user_data_dir, headless, self.proxy)
181
return self.default_driver
182
183
def __enter__(self) -> WebDriver:
184
if self.web_driver:
185
return self.web_driver
186
if self.virtual_display == True:
187
self.virtual_display = Display(size=(1920,1080))
188
self.virtual_display.start()
189
self.default_driver = get_browser(self.user_data_dir, self.headless, self.proxy, self.options)
190
return self.default_driver
191
192
def __exit__(self, exc_type, exc_val, exc_tb):
193
if self.default_driver:
194
self.default_driver.close()
195
time.sleep(0.1)
196
self.default_driver.quit()
197
if self.virtual_display:
198
self.virtual_display.stop()
199
200
119
def get_random_string(length: int = 10) -> str:
201
120
return ''.join(
202
121
random.choice(string.ascii_lowercase + string.digits)
203
122
for _ in range(length)
204
123
)
205
124
206
207
125
def get_random_hex() -> str:
208
126
return secrets.token_hex(16).zfill(32)
@@ -4,7 +4,8 @@ import time
4
4
5
5
from ...typing import CreateResult, Messages
6
6
from ..base_provider import BaseProvider
7
from ..helper import WebDriver, WebDriverSession, format_prompt
7
from ..helper import format_prompt
8
from ..webdriver import WebDriver, WebDriverSession
8
9
9
10
class Bard(BaseProvider):
10
11
url = "https://bard.google.com"
@@ -18,13 +19,13 @@ class Bard(BaseProvider):
18
19
messages: Messages,
19
20
stream: bool,
20
21
proxy: str = None,
21
web_driver: WebDriver = None,
22
webdriver: WebDriver = None,
22
23
user_data_dir: str = None,
23
24
headless: bool = True,
24
25
**kwargs
25
26
) -> CreateResult:
26
27
prompt = format_prompt(messages)
27
session = WebDriverSession(web_driver, user_data_dir, headless, proxy=proxy)
28
session = WebDriverSession(webdriver, user_data_dir, headless, proxy=proxy)
28
29
with session as driver:
29
30
from selenium.webdriver.common.by import By
30
31
from selenium.webdriver.support.ui import WebDriverWait
@@ -36,8 +37,8 @@ class Bard(BaseProvider):
36
37
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.ql-editor.textarea")))
37
38
except:
38
39
# Reopen browser for login
39
if not web_driver:
40
driver = session.reopen(headless=False)
40
if not webdriver:
41
driver = session.reopen()
41
42
driver.get(f"{cls.url}/chat")
42
43
wait = WebDriverWait(driver, 240)
43
44
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.ql-editor.textarea")))
@@ -59,17 +59,4 @@ class HuggingChat(AsyncGeneratorProvider):
59
59
break
60
60
61
61
async with session.delete(f"{cls.url}/conversation/{conversation_id}", proxy=proxy) as response:
62
response.raise_for_status()
63
64
65
@classmethod
66
@property
67
def params(cls):
68
params = [
69
("model", "str"),
70
("messages", "list[dict[str, str]]"),
71
("stream", "bool"),
72
("proxy", "str"),
73
]
74
param = ", ".join([": ".join(p) for p in params])
75
return f"g4f.provider.{cls.__name__} supports: ({param})"
62
response.raise_for_status()
@@ -87,15 +87,3 @@ class OpenAssistant(AsyncGeneratorProvider):
87
87
}
88
88
async with session.delete("https://open-assistant.io/api/chat", proxy=proxy, params=params) as response:
89
89
response.raise_for_status()
90
91
@classmethod
92
@property
93
def params(cls):
94
params = [
95
("model", "str"),
96
("messages", "list[dict[str, str]]"),
97
("stream", "bool"),
98
("proxy", "str"),
99
]
100
param = ", ".join([": ".join(p) for p in params])
101
return f"g4f.provider.{cls.__name__} supports: ({param})"
@@ -6,7 +6,8 @@ from asyncstdlib.itertools import tee
6
6
from async_property import async_cached_property
7
7
8
8
from ..base_provider import AsyncGeneratorProvider
9
from ..helper import get_browser, get_event_loop
9
from ..helper import get_event_loop
10
from ..webdriver import get_browser
10
11
from ...typing import AsyncResult, Messages
11
12
from ...requests import StreamSession
12
13
@@ -38,7 +39,10 @@ class OpenaiChat(AsyncGeneratorProvider):
38
39
**kwargs
39
40
) -> Response:
40
41
if prompt:
41
messages.append({"role": "user", "content": prompt})
42
messages.append({
43
"role": "user",
44
"content": prompt
45
})
42
46
generator = cls.create_async_generator(
43
47
model,
44
48
messages,
@@ -49,12 +53,9 @@ class OpenaiChat(AsyncGeneratorProvider):
49
53
response_fields=True,
50
54
**kwargs
51
55
)
52
fields: ResponseFields = await anext(generator)
53
if "access_token" not in kwargs:
54
kwargs["access_token"] = cls._access_token
55
56
return Response(
56
57
generator,
57
fields,
58
await anext(generator),
58
59
action,
59
60
messages,
60
61
kwargs
@@ -87,7 +88,6 @@ class OpenaiChat(AsyncGeneratorProvider):
87
88
headers = {
88
89
"Accept": "text/event-stream",
89
90
"Authorization": f"Bearer {access_token}",
90
"Cookie": 'intercom-device-id-dgkjq2bp=0f047573-a750-46c8-be62-6d54b56e7bf0; ajs_user_id=user-iv3vxisaoNodwWpxmNpMfekH; ajs_anonymous_id=fd91be0b-0251-4222-ac1e-84b1071e9ec1; __Host-next-auth.csrf-token=d2b5f67d56f7dd6a0a42ae4becf2d1a6577b820a5edc88ab2018a59b9b506886%7Ce5c33eecc460988a137cbc72d90ee18f1b4e2f672104f368046df58e364376ac; _cfuvid=gt_mA.q6rue1.7d2.AR0KHpbVBS98i_ppfi.amj2._o-1700353424353-0-604800000; cf_clearance=GkHCfPSFU.NXGcHROoe4FantnqmnNcluhTNHz13Tk.M-1700353425-0-1-dfe77f81.816e9bc2.714615da-0.2.1700353425; __Secure-next-auth.callback-url=https%3A%2F%2Fchat.openai.com; intercom-session-dgkjq2bp=UWdrS1hHazk5VXN1c0V5Q1F0VXdCQmsyTU9pVjJMUkNpWnFnU3dKWmtIdGwxTC9wbjZuMk5hcEc0NWZDOGdndS0tSDNiaDNmMEdIL1RHU1dFWDBwOHFJUT09--f754361b91fddcd23a13b288dcb2bf8c7f509e91; _uasid="Z0FBQUFBQmxXVnV0a3dmVno4czRhcDc2ZVcwaUpSNUdZejlDR25YSk5NYTJQQkpyNmRvOGxjTHMyTlAxWmJhaURrMVhjLXZxQXdZeVpBbU1aczA5WUpHT2dwaS1MOWc4MnhyNWFnbGRzeGdJcGFKT0ZRdnBTMVJHcGV2MGNTSnVQY193c0hqUWIycHhQRVF4dENlZ3phcDdZeHgxdVhoalhrZmtZME9NbWhMQjdVR3Vzc3FRRk0ybjJjNWMwTWtIRjdPb19lUkFtRmV2MDVqd1kwWU11QTYtQkdZenEzVHhLMGplY1hZM3FlYUt1cVZaNWFTRldleEJETzJKQjk1VTJScy1GUnMxUVZWMnVxYklxMjdockVZbkZyd1R4U1RtMnA1ZzlSeXphdmVOVk9xeEdrRkVOSjhwTVd1QzFtQjhBcWdDaE92Q1VlM2pwcjFQTXRuLVJNRVlZSGpIdlZ0aGV3PT0="; _dd_s=rum=0&expire=1700356244884; __Secure-next-auth.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..3aK6Fbdy2_8f07bf.8eT2xgonrCnz7ySY6qXFsg3kzL6UQfXKAYaw3tyn-6_X9657zy47k9qGvmi9mF0QKozj5jau3_Ca62AQQ7FmeC6Y2F1urtzqrXqwTTsQ2LuzFPIQkx6KKb2DXc8zW2-oyEzJ_EY5yxfLB2RlRkSh3M7bYNZh4_ltEcfkj38s_kIPGMxv34udtPWGWET99MCjkdwQWXylJag4s0fETA0orsBAKnGCyqAUNJbb_D7BYtGSV-MQ925kZMG6Di_QmfO0HQWURDYjmdRNcuy1PT_xJ1DJko8sjL42i4j3RhkNDkhqCIqyYImz2eHFWHW7rYKxTkrBhlCPMS5hRdcCswD7JYPcSBiwnVRYgyOocFGXoFvQgIZ2FX9NiZ3SMEVM1VwIGSE-qH0H2nMa8_iBvsOgOWJgKjVAvzzyzZvRVDUUHzJrikSFPNONVDU3h-04c1kVL4qIu9DfeTPN7n8AvNmYwMbro0L9-IUAeXNo4-pwF0Kt-AtTsamqWvMqnK4O_YOyLnDDlvkmnOvDC2d5uinwlQIxr6APO6qFfGLlHiLZemKoekxEE1Fx70dl-Ouhk1VIzbF3OC6XNNxeBm9BUYUiHdL0wj2H9rHgX4cz6ZmS_3VTgpD6UJh-evu5KJ2gIvjYmVbyzEN0aPNDxfvBaOm-Ezpy4bUJ2bUrOwNn-0knWkDiTvjYmNhCyefPCtCF6rpKNay8PCw_yh79C4SdEP6Q4V7LI0Tvdi5uz7kLCiBC4AT9L0ao1WDX03mkUOpjvzHDvPLmj8chW3lTVm_kA0eYGQY4wT0jzleWlfV0Q8rB2oYECNLWksA3F1zlGfcl4lQjprvTXRePkvAbMpoJEsZD3Ylq7-foLDLk4-M2LYAFZDs282AY04sFjAjQBxTELFCCuDgTIgTXSIskY_XCxpVXDbdLlbCJY7XVK45ybwtfqwlKRp8Mo0B131uQAFc-migHaUaoGujxJJk21bP8F0OmhNYHBo4FQqE1rQm2JH5bNM7txKeh5KXdJgVUVbRSr7OIp_OF5-Bx_v9eRBGAIDkue26E2-O8Rnrp5zQ5TnvecQLDaUzWavCLPwsZ0_gsOLBxNOmauNYZtF8IElCsQSFDdhoiMxXsYUm4ZYKEAy3GWq8HGTAvBhNkh1hvnI7y-d8-DOaZf_D_D98-olZfm-LUkeosLNpPB9rxYMqViCiW3KrXE9Yx0wlFm5ePKaVvR7Ym_EPhSOhJBKFPCvdTdMZSNPUcW0ZJBVByq0A9sxD51lYq3gaFyqh94S4s_ox182AQ3szGzHkdgLcnQmJG9OYvKxAVcd43eg6_gODAYhx02GjbMw-7JTAhyXSeCrlMteHyOXl8hai-3LilC3PmMzi7Vbu49dhF1s4LcVlUowen5ira44rQQaB26mdaOUoQfodgt66M3RTWGPXyK1Nb72AzSXsCKyaQPbzeb6cN0fdGSdG4ktwvR04eFNEkquo_3aKu2GmUKTD0XcRx9dYrfXjgY-X1DDTVs1YND2gRhdx7FFEeBVjtbj2UqmG3Rvd4IcHGe7OnYWw2MHDcol68SsR1KckXWwWREz7YTGUnDB2M1kx_H4W2mjclytnlHOnYU3RflegRPeSTbdzUZJvGKXCCz45luHkQWN_4DExE76D-9YqbFIz-RY5yL4h-Zs-i2xjm2K-4xCMM9nQIOqhLMqixIZQ2ldDAidKoYtbs5ppzbcBLyrZM96bq9DwRBY3aacqWdlRd-TfX0wv5KO4fo0sSh5FsuhuN0zcEV_NNXgqIEM_p14EcPqgbrAvCBQ8os70TRBQLXiF0EniSofGjxwF8kQvUk3C6Wfc8cTTeN-E6GxCVTn91HBwA1iSEZlRLMVb8_BcRJNqwbgnb_07jR6-eo42u88CR3KQdAWwbQRdMxsURFwZ0ujHXVGG0Ll6qCFBcHXWyDO1x1yHdHnw8_8yF26pnA2iPzrFR-8glMgIA-639sLuGAxjO1_ZuvJ9CAB41Az9S_jaZwaWy215Hk4-BRYD-MKmHtonwo3rrxhE67WJgbbu14efsw5nT6ow961pffgwXov5VA1Rg7nv1E8RvQOx7umWW6o8R4W6L8f2COsmPTXfgwIjoJKkjhUqAQ8ceG7cM0ET-38yaC0ObU8EkXfdGGgxI28qTEZWczG66_iM4hw7QEGCY5Cz2kbO6LETAiw9OsSigtBvDS7f0Ou0bZ41pdK7G3FmvdZAnjWPjObnDF4k4uWfn7mzt0fgj3FyqK20JezRDyGuAbUUhOvtZpc9sJpzxR34eXEZTouuALrHcGuNij4z6rx51FrQsaMtiup8QVrhtZbXtKLMYnWYSbkhuTeN2wY-xV1ZUsQlakIZszzGF7kuIG87KKWMpuPMvbXjz6Pp_gWJiIC6aQuk8xl5g0iBPycf_6Q-MtpuYxzNE2TpI1RyR9mHeXmteoRzrFiWp7yEC-QGNFyAJgxTqxM3CjHh1Jt6IddOsmn89rUo1dZM2Smijv_fbIv3avXLkIPX1KZjILeJCtpU0wAdsihDaRiRgDdx8fG__F8zuP0n7ziHas73cwrfg-Ujr6DhC0gTNxyd9dDA_oho9N7CQcy6EFmfNF2te7zpLony0859jtRv2t1TnpzAa1VvMK4u6mXuJ2XDo04_6GzLO3aPHinMdl1BcIAWnqAqWAu3euGFLTHOhXlfijut9N1OCifd_zWjhVtzlR39uFeCQBU5DyQArzQurdoMx8U1ETsnWgElxGSStRW-YQoPsAJ87eg9trqKspFpTVlAVN3t1GtoEAEhcwhe81SDssLmKGLc.7PqS6jRGTIfgTPlO7Ognvg; __cf_bm=VMWoAKEB45hQSwxXtnYXcurPaGZDJS4dMi6dIMFLwdw-1700355394-0-ATVsbq97iCaTaJbtYr8vtg1Zlbs3nLrJLKVBHYa2Jn7hhkGclqAy8Gbyn5ePEhDRqj93MsQmtayfYLqY5n4WiLY=; __cflb=0H28vVfF4aAyg2hkHFH9CkdHRXPsfCUf6VpYf2kz3RX'
91
91
}
92
92
async with StreamSession(
93
93
proxies={"https": proxy},
@@ -95,24 +95,22 @@ class OpenaiChat(AsyncGeneratorProvider):
95
95
headers=headers,
96
96
timeout=timeout
97
97
) as session:
98
data = {
99
"action": action,
100
"arkose_token": await get_arkose_token(proxy, timeout),
101
"conversation_id": conversation_id,
102
"parent_message_id": parent_id,
103
"model": models[model],
104
"history_and_training_disabled": history_disabled and not auto_continue,
105
}
106
if action != "continue":
107
data["messages"] = [{
108
"id": str(uuid.uuid4()),
109
"author": {"role": "user"},
110
"content": {"content_type": "text", "parts": [messages[-1]["content"]]},
111
}]
112
first = True
113
98
end_turn = EndTurn()
114
while first or auto_continue and not end_turn.is_end:
115
first = False
99
while not end_turn.is_end:
100
data = {
101
"action": action,
102
"arkose_token": await get_arkose_token(proxy, timeout),
103
"conversation_id": conversation_id,
104
"parent_message_id": parent_id,
105
"model": models[model],
106
"history_and_training_disabled": history_disabled and not auto_continue,
107
}
108
if action != "continue":
109
data["messages"] = [{
110
"id": str(uuid.uuid4()),
111
"author": {"role": "user"},
112
"content": {"content_type": "text", "parts": [messages[-1]["content"]]},
113
}]
116
114
async with session.post(f"{cls.url}/backend-api/conversation", json=data) as response:
117
115
try:
118
116
response.raise_for_status()
@@ -120,43 +118,38 @@ class OpenaiChat(AsyncGeneratorProvider):
120
118
raise RuntimeError(f"Error {response.status_code}: {await response.text()}")
121
119
last_message = 0
122
120
async for line in response.iter_lines():
123
if line.startswith(b"data: "):
124
line = line[6:]
125
if line == b"[DONE]":
126
break
127
try:
128
line = json.loads(line)
129
except:
130
continue
131
if "message" not in line:
132
continue
133
if "error" in line and line["error"]:
134
raise RuntimeError(line["error"])
135
if "message_type" not in line["message"]["metadata"]:
136
continue
137
if line["message"]["author"]["role"] != "assistant":
138
continue
139
if line["message"]["metadata"]["message_type"] in ("next", "continue", "variant"):
140
conversation_id = line["conversation_id"]
141
parent_id = line["message"]["id"]
142
if response_fields:
143
response_fields = False
144
yield ResponseFields(conversation_id, parent_id, end_turn)
145
new_message = line["message"]["content"]["parts"][0]
146
yield new_message[last_message:]
147
last_message = len(new_message)
148
if "finish_details" in line["message"]["metadata"]:
149
if line["message"]["metadata"]["finish_details"]["type"] == "max_tokens":
150
end_turn.end()
151
152
data = {
153
"action": "continue",
154
"arkose_token": await get_arkose_token(proxy, timeout),
155
"conversation_id": conversation_id,
156
"parent_message_id": parent_id,
157
"model": models[model],
158
"history_and_training_disabled": False,
159
}
121
if not line.startswith(b"data: "):
122
continue
123
line = line[6:]
124
if line == b"[DONE]":
125
break
126
try:
127
line = json.loads(line)
128
except:
129
continue
130
if "message" not in line:
131
continue
132
if "error" in line and line["error"]:
133
raise RuntimeError(line["error"])
134
if "message_type" not in line["message"]["metadata"]:
135
continue
136
if line["message"]["author"]["role"] != "assistant":
137
continue
138
if line["message"]["metadata"]["message_type"] in ("next", "continue", "variant"):
139
conversation_id = line["conversation_id"]
140
parent_id = line["message"]["id"]
141
if response_fields:
142
response_fields = False
143
yield ResponseFields(conversation_id, parent_id, end_turn)
144
new_message = line["message"]["content"]["parts"][0]
145
yield new_message[last_message:]
146
last_message = len(new_message)
147
if "finish_details" in line["message"]["metadata"]:
148
if line["message"]["metadata"]["finish_details"]["type"] == "stop":
149
end_turn.end()
150
if not auto_continue:
151
break
152
action = "continue"
160
153
await asyncio.sleep(5)
161
154
162
155
@classmethod
@@ -167,7 +160,7 @@ class OpenaiChat(AsyncGeneratorProvider):
167
160
from selenium.webdriver.support.ui import WebDriverWait
168
161
from selenium.webdriver.support import expected_conditions as EC
169
162
170
driver = get_browser("~/openai", proxy=proxy)
163
driver = get_browser(proxy=proxy)
171
164
except ImportError:
172
165
return
173
166
try:
@@ -193,18 +186,6 @@ class OpenaiChat(AsyncGeneratorProvider):
193
186
raise RuntimeError("Read access token failed")
194
187
return cls._access_token
195
188
196
@classmethod
197
@property
198
def params(cls):
199
params = [
200
("model", "str"),
201
("messages", "list[dict[str, str]]"),
202
("stream", "bool"),
203
("proxy", "str"),
204
("access_token", "str"),
205
]
206
param = ", ".join([": ".join(p) for p in params])
207
return f"g4f.provider.{cls.__name__} supports: ({param})"
208
189
209
190
async def get_arkose_token(proxy: str = None, timeout: int = None) -> str:
210
191
config = {
@@ -293,7 +274,7 @@ class Response():
293
274
294
275
async def variant(self, **kwargs) -> Response:
295
276
if self.action != "next":
296
raise RuntimeError("Can't create variant with continue or variant request.")
277
raise RuntimeError("Can't create variant from continue or variant request.")
297
278
return await OpenaiChat.create(
298
279
**self._options,
299
280
messages=self._messages,
@@ -4,7 +4,8 @@ import time
4
4
5
5
from ...typing import CreateResult, Messages
6
6
from ..base_provider import BaseProvider
7
from ..helper import WebDriver, WebDriverSession, format_prompt
7
from ..helper import format_prompt
8
from ..webdriver import WebDriver, WebDriverSession
8
9
9
10
models = {
10
11
"meta-llama/Llama-2-7b-chat-hf": {"name": "Llama-2-7b"},
@@ -33,7 +34,7 @@ class Poe(BaseProvider):
33
34
messages: Messages,
34
35
stream: bool,
35
36
proxy: str = None,
36
web_driver: WebDriver = None,
37
webdriver: WebDriver = None,
37
38
user_data_dir: str = None,
38
39
headless: bool = True,
39
40
**kwargs
@@ -44,7 +45,7 @@ class Poe(BaseProvider):
44
45
raise ValueError(f"Model are not supported: {model}")
45
46
prompt = format_prompt(messages)
46
47
47
session = WebDriverSession(web_driver, user_data_dir, headless, proxy=proxy)
48
session = WebDriverSession(webdriver, user_data_dir, headless, proxy=proxy)
48
49
with session as driver:
49
50
from selenium.webdriver.common.by import By
50
51
from selenium.webdriver.support.ui import WebDriverWait
@@ -80,8 +81,8 @@ class Poe(BaseProvider):
80
81
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "textarea[class^='GrowingTextArea']")))
81
82
except:
82
83
# Reopen browser for login
83
if not web_driver:
84
driver = session.reopen(headless=False)
84
if not webdriver:
85
driver = session.reopen()
85
86
driver.get(f"{cls.url}/{models[model]['name']}")
86
87
wait = WebDriverWait(driver, 240)
87
88
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "textarea[class^='GrowingTextArea']")))
@@ -60,18 +60,3 @@ class Raycast(BaseProvider):
60
60
token = completion_chunk['text']
61
61
if token != None:
62
62
yield token
63
64
@classmethod
65
@property
66
def params(cls):
67
params = [
68
("model", "str"),
69
("messages", "list[dict[str, str]]"),
70
("stream", "bool"),
71
("temperature", "float"),
72
("top_p", "int"),
73
("model", "str"),
74
("auth", "str"),
75
]
76
param = ", ".join([": ".join(p) for p in params])
77
return f"g4f.provider.{cls.__name__} supports: ({param})"