返回提交历史
Modified
g4f/Provider/GptGo.py
+19
-39
Modified
g4f/Provider/Phind.py
+57
-86
Modified
g4f/Provider/__init__.py
+7
-6
Added
g4f/Provider/selenium/Phind.py
+104
-0
Added
g4f/Provider/selenium/__init__.py
+1
-0
XFEstudio/gpt4free
Fix Phind and GptGo Provider
ea3cb0d5
代码差异
5 个文件
+188
-131
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
3
3
from aiohttp import ClientSession
4
4
import json
5
import base64
5
6
6
7
from ..typing import AsyncResult, Messages
7
8
from .base_provider import AsyncGeneratorProvider, format_prompt
@@ -23,9 +24,12 @@ class GptGo(AsyncGeneratorProvider):
23
24
headers = {
24
25
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
25
26
"Accept": "*/*",
26
"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",
27
"Accept-language": "en-US",
27
28
"Origin": cls.url,
28
29
"Referer": f"{cls.url}/",
30
"sec-ch-ua": '"Google Chrome";v="116", "Chromium";v="116", "Not?A_Brand";v="24"',
31
"sec-ch-ua-mobile": "?0",
32
"sec-ch-ua-platform": '"Windows"',
29
33
"Sec-Fetch-Dest": "empty",
30
34
"Sec-Fetch-Mode": "cors",
31
35
"Sec-Fetch-Site": "same-origin",
@@ -33,50 +37,26 @@ class GptGo(AsyncGeneratorProvider):
33
37
async with ClientSession(
34
38
headers=headers
35
39
) as session:
36
async with session.get(
37
"https://gptgo.ai/action_get_token.php",
38
params={
39
"q": format_prompt(messages),
40
"hlgpt": "default",
41
"hl": "en"
42
},
40
async with session.post(
41
"https://gptgo.ai/get_token.php",
42
data={"ask": format_prompt(messages)},
43
43
proxy=proxy
44
44
) as response:
45
45
response.raise_for_status()
46
token = (await response.json(content_type=None))["token"]
46
token = await response.text();
47
token = base64.b64decode(token[10:-20]).decode()
47
48
48
49
async with session.get(
49
"https://gptgo.ai/action_ai_gpt.php",
50
params={
51
"token": token,
52
},
53
proxy=proxy
54
) as response:
50
"https://api.gptgo.ai/web.php",
51
params={"array_chat": token},
52
proxy=proxy
53
) as response:
55
54
response.raise_for_status()
56
start = "data: "
57
55
async for line in response.content:
58
line = line.decode()
59
if line.startswith("data: "):
60
if line.startswith("data: [DONE]"):
61
break
62
line = json.loads(line[len(start):-1])
63
if line["choices"][0]["finish_reason"] == "stop":
64
break
65
56
if line.startswith(b"data: [DONE]"):
57
break
58
if line.startswith(b"data: "):
59
line = json.loads(line[6:])
66
60
content = line["choices"][0]["delta"].get("content")
67
if content:
61
if content and content != "\n#GPTGO ":
68
62
yield content
69
70
71
@classmethod
72
@property
73
def params(cls):
74
params = [
75
("model", "str"),
76
("messages", "list[dict[str, str]]"),
77
("stream", "bool"),
78
("proxy", "str"),
79
("temperature", "float"),
80
]
81
param = ", ".join([": ".join(p) for p in params])
82
return f"g4f.provider.{cls.__name__} supports: ({param})"
@@ -1,103 +1,74 @@
1
1
from __future__ import annotations
2
2
3
import time
4
from urllib.parse import quote
3
from datetime import datetime
5
4
6
from ..typing import CreateResult, Messages
7
from .base_provider import BaseProvider
8
from .helper import format_prompt
9
from .webdriver import WebDriver, WebDriverSession
5
from ..typing import AsyncResult, Messages
6
from .base_provider import AsyncGeneratorProvider
7
from ..requests import StreamSession
10
8
11
class Phind(BaseProvider):
9
class Phind(AsyncGeneratorProvider):
12
10
url = "https://www.phind.com"
13
11
working = True
14
12
supports_gpt_4 = True
15
13
supports_stream = True
14
supports_message_history = True
16
15
17
16
@classmethod
18
def create_completion(
17
async def create_async_generator(
19
18
cls,
20
19
model: str,
21
20
messages: Messages,
22
stream: bool,
23
21
proxy: str = None,
24
22
timeout: int = 120,
25
webdriver: WebDriver = None,
26
creative_mode: bool = None,
23
creative_mode: bool = False,
27
24
**kwargs
28
) -> CreateResult:
29
with WebDriverSession(webdriver, "", proxy=proxy) as driver:
30
from selenium.webdriver.common.by import By
31
from selenium.webdriver.support.ui import WebDriverWait
32
from selenium.webdriver.support import expected_conditions as EC
33
34
prompt = quote(format_prompt(messages))
35
driver.get(f"{cls.url}/search?q={prompt}&source=searchbox")
36
37
# Register fetch hook
38
source = """
39
window._fetch = window.fetch;
40
window.fetch = async (url, options) => {
41
const response = await window._fetch(url, options);
42
if (url != "/api/infer/answer") {
43
return response;
44
}
45
copy = response.clone();
46
window._reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
47
return copy;
48
}
49
"""
50
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
51
"source": source
52
})
53
54
# Need to change settings
55
wait = WebDriverWait(driver, timeout)
56
def open_dropdown():
57
# Open settings dropdown
58
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.text-dark.dropdown-toggle")))
59
driver.find_element(By.CSS_SELECTOR, "button.text-dark.dropdown-toggle").click()
60
# Wait for dropdown toggle
61
wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='GPT-4']")))
62
if model.startswith("gpt-4") or creative_mode:
63
# Enable GPT-4
64
if model.startswith("gpt-4"):
65
open_dropdown()
66
driver.find_element(By.XPATH, "//button[text()='GPT-4']").click()
67
# Enable creative mode
68
if creative_mode or creative_mode == None:
69
open_dropdown()
70
driver.find_element(By.ID, "Creative Mode").click()
71
# Submit changes
72
driver.find_element(By.CSS_SELECTOR, ".search-bar-input-group button[type='submit']").click()
73
# Wait for page reload
74
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".search-container")))
75
76
while True:
77
chunk = driver.execute_script("""
78
if(window._reader) {
79
chunk = await window._reader.read();
80
if (chunk['done']) {
81
return null;
82
}
83
content = '';
84
chunk['value'].split('\\r\\n').forEach((line, index) => {
85
if (line.startsWith('data: ')) {
86
line = line.substring('data: '.length);
87
if (!line.startsWith('<PHIND_METADATA>')) {
88
if (line) content += line;
89
else content += '\\n';
90
}
25
) -> AsyncResult:
26
headers = {
27
"Accept": "*/*",
28
"Origin": cls.url,
29
"Referer": f"{cls.url}/search",
30
"Sec-Fetch-Dest": "empty",
31
"Sec-Fetch-Mode": "cors",
32
"Sec-Fetch-Site": "same-origin",
91
33
}
92
});
93
return content.replace('\\n\\n', '\\n');
94
} else {
95
return ''
96
}
97
""")
98
if chunk:
99
yield chunk
100
elif chunk != "":
101
break
102
else:
103
time.sleep(0.1)
34
async with StreamSession(
35
impersonate="chrome110",
36
proxies={"https": proxy},
37
timeout=timeout
38
) as session:
39
prompt = messages[-1]["content"]
40
data = {
41
"question": prompt,
42
"questionHistory": [
43
message["content"] for message in messages[:-1] if message["role"] == "user"
44
],
45
"answerHistory": [
46
message["content"] for message in messages if message["role"] == "assistant"
47
],
48
"webResults": [],
49
"options": {
50
"date": datetime.now().strftime("%d.%m.%Y"),
51
"language": "en-US",
52
"detailed": True,
53
"anonUserId": "",
54
"answerModel": "GPT-4" if model.startswith("gpt-4") else "Phind Model",
55
"creativeMode": creative_mode,
56
"customLinks": []
57
},
58
"context": "",
59
"rewrittenQuestion": prompt
60
}
61
async with session.post(f"{cls.url}/api/infer/followup/answer", headers=headers, json=data) as response:
62
new_line = False
63
async for line in response.iter_lines():
64
if line.startswith(b"data: "):
65
chunk = line[6:]
66
if chunk.startswith(b"<PHIND_METADATA>"):
67
pass
68
elif chunk:
69
yield chunk.decode()
70
elif new_line:
71
yield "\n"
72
new_line = False
73
else:
74
new_line = True
@@ -1,5 +1,12 @@
1
1
from __future__ import annotations
2
2
3
from .base_provider import BaseProvider, AsyncProvider, AsyncGeneratorProvider
4
from .retry_provider import RetryProvider
5
from .deprecated import *
6
from .needs_auth import *
7
from .unfinished import *
8
from .selenium import *
9
3
10
from .AiAsk import AiAsk
4
11
from .Aichat import Aichat
5
12
from .AiChatOnline import AiChatOnline
@@ -43,12 +50,6 @@ from .You import You
43
50
from .Yqcloud import Yqcloud
44
51
from .GeekGpt import GeekGpt
45
52
46
from .base_provider import BaseProvider, AsyncProvider, AsyncGeneratorProvider
47
from .retry_provider import RetryProvider
48
from .deprecated import *
49
from .needs_auth import *
50
from .unfinished import *
51
52
53
import sys
53
54
54
55
__modules__: list = [
@@ -0,0 +1,104 @@
1
from __future__ import annotations
2
3
import time
4
from urllib.parse import quote
5
6
from ...typing import CreateResult, Messages
7
from ..base_provider import BaseProvider
8
from ..helper import format_prompt
9
from ..webdriver import WebDriver, WebDriverSession
10
11
class Phind(BaseProvider):
12
url = "https://www.phind.com"
13
working = True
14
supports_gpt_4 = True
15
supports_stream = True
16
17
@classmethod
18
def create_completion(
19
cls,
20
model: str,
21
messages: Messages,
22
stream: bool,
23
proxy: str = None,
24
timeout: int = 120,
25
webdriver: WebDriver = None,
26
creative_mode: bool = None,
27
**kwargs
28
) -> CreateResult:
29
driver.start_session
30
with WebDriverSession(webdriver, "", proxy=proxy) as driver:
31
from selenium.webdriver.common.by import By
32
from selenium.webdriver.support.ui import WebDriverWait
33
from selenium.webdriver.support import expected_conditions as EC
34
35
# Register fetch hook
36
source = """
37
window._fetch = window.fetch;
38
window.fetch = async (url, options) => {
39
const response = await window._fetch(url, options);
40
if (url != "/api/infer/answer") {
41
return response;
42
}
43
copy = response.clone();
44
window._reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
45
return copy;
46
}
47
"""
48
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
49
"source": source
50
})
51
52
prompt = quote(format_prompt(messages))
53
driver.get(f"{cls.url}/search?q={prompt}&source=searchbox")
54
55
# Need to change settings
56
wait = WebDriverWait(driver, timeout)
57
def open_dropdown():
58
# Open settings dropdown
59
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.text-dark.dropdown-toggle")))
60
driver.find_element(By.CSS_SELECTOR, "button.text-dark.dropdown-toggle").click()
61
# Wait for dropdown toggle
62
wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='GPT-4']")))
63
if model.startswith("gpt-4") or creative_mode:
64
# Enable GPT-4
65
if model.startswith("gpt-4"):
66
open_dropdown()
67
driver.find_element(By.XPATH, "//button[text()='GPT-4']").click()
68
# Enable creative mode
69
if creative_mode or creative_mode == None:
70
open_dropdown()
71
driver.find_element(By.ID, "Creative Mode").click()
72
# Submit changes
73
driver.find_element(By.CSS_SELECTOR, ".search-bar-input-group button[type='submit']").click()
74
# Wait for page reload
75
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".search-container")))
76
77
while True:
78
chunk = driver.execute_script("""
79
if(window._reader) {
80
chunk = await window._reader.read();
81
if (chunk['done']) {
82
return null;
83
}
84
content = '';
85
chunk['value'].split('\\r\\n').forEach((line, index) => {
86
if (line.startsWith('data: ')) {
87
line = line.substring('data: '.length);
88
if (!line.startsWith('<PHIND_METADATA>')) {
89
if (line) content += line;
90
else content += '\\n';
91
}
92
}
93
});
94
return content.replace('\\n\\n', '\\n');
95
} else {
96
return ''
97
}
98
""")
99
if chunk:
100
yield chunk
101
elif chunk != "":
102
break
103
else:
104
time.sleep(0.1)
@@ -0,0 +1 @@
1
from .Phind import Phind