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

XFEstudio/gpt4free

Add webdriver module

08e30834
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

14 个文件 +219 -269
Modified g4f/Provider/AItianhuSpace.py +4 -3
@@ -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
Modified g4f/Provider/MyShell.py +10 -8
@@ -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));
Modified g4f/Provider/PerplexityAi.py +4 -3
@@ -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
Modified g4f/Provider/Phind.py +25 -25
@@ -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>')) {
Modified g4f/Provider/TalkAi.py +3 -3
@@ -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
Modified g4f/Provider/helper.py +1 -83
@@ -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)
Modified g4f/Provider/needs_auth/Bard.py +6 -5
@@ -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")))
Modified g4f/Provider/needs_auth/HuggingChat.py +1 -14
@@ -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()
Modified g4f/Provider/needs_auth/OpenAssistant.py +0 -12
@@ -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})"
Modified g4f/Provider/needs_auth/OpenaiChat.py +56 -75
@@ -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,
Modified g4f/Provider/needs_auth/Poe.py +6 -5
@@ -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']")))
Modified g4f/Provider/needs_auth/Raycast.py +0 -15
@@ -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})"
Modified g4f/Provider/needs_auth/Theb.py +11 -18
Added g4f/Provider/webdriver.py +92 -0