summaryrefslogtreecommitdiffstats
path: root/g4f/Provider/Phind.py
diff options
context:
space:
mode:
Diffstat (limited to 'g4f/Provider/Phind.py')
-rw-r--r--g4f/Provider/Phind.py165
1 files changed, 99 insertions, 66 deletions
diff --git a/g4f/Provider/Phind.py b/g4f/Provider/Phind.py
index 8f3e7942..56100d87 100644
--- a/g4f/Provider/Phind.py
+++ b/g4f/Provider/Phind.py
@@ -1,83 +1,116 @@
from __future__ import annotations
-import random, string
-from datetime import datetime
+import time
+from urllib.parse import quote
+try:
+ from selenium.webdriver.remote.webdriver import WebDriver
+except ImportError:
+ class WebDriver():
+ pass
-from ..typing import AsyncResult, Messages
-from ..requests import StreamSession
-from .base_provider import AsyncGeneratorProvider, format_prompt
+from ..typing import CreateResult, Messages
+from .base_provider import BaseProvider
+from .helper import format_prompt, get_browser
-
-class Phind(AsyncGeneratorProvider):
+class Phind(BaseProvider):
url = "https://www.phind.com"
working = True
supports_gpt_4 = True
+ supports_stream = True
@classmethod
- async def create_async_generator(
+ def create_completion(
cls,
model: str,
messages: Messages,
+ stream: bool,
proxy: str = None,
timeout: int = 120,
+ browser: WebDriver = None,
+ creative_mode: bool = None,
+ display: bool = True,
**kwargs
- ) -> AsyncResult:
- chars = string.ascii_lowercase + string.digits
- user_id = ''.join(random.choice(chars) for _ in range(24))
- data = {
- "question": format_prompt(messages),
- "webResults": [],
- "options": {
- "date": datetime.now().strftime("%d.%m.%Y"),
- "language": "en",
- "detailed": True,
- "anonUserId": user_id,
- "answerModel": "GPT-4",
- "creativeMode": False,
- "customLinks": []
- },
- "context":""
- }
- headers = {
- "Authority": cls.url,
- "Accept": "application/json, text/plain, */*",
- "Origin": cls.url,
- "Referer": f"{cls.url}/"
- }
- async with StreamSession(
- headers=headers,
- timeout=(5, timeout),
- proxies={"https": proxy},
- impersonate="chrome107"
- ) as session:
- async with session.post(f"{cls.url}/api/infer/answer", json=data) as response:
- response.raise_for_status()
- new_lines = 0
- async for line in response.iter_lines():
- if not line:
- continue
- if line.startswith(b"data: "):
- line = line[6:]
- if line.startswith(b"<PHIND_METADATA>"):
- continue
- if line:
- if new_lines:
- yield "".join(["\n" for _ in range(int(new_lines / 2))])
- new_lines = 0
- yield line.decode()
- else:
- new_lines += 1
+ ) -> CreateResult:
+ from selenium.webdriver.common.by import By
+ from selenium.webdriver.support.ui import WebDriverWait
+ from selenium.webdriver.support import expected_conditions as EC
+ if browser:
+ driver = browser
+ else:
+ if display:
+ driver, display = get_browser("", True, proxy)
+ else:
+ driver = get_browser("", False, proxy)
- @classmethod
- @property
- def params(cls):
- params = [
- ("model", "str"),
- ("messages", "list[dict[str, str]]"),
- ("stream", "bool"),
- ("proxy", "str"),
- ("timeout", "int"),
- ]
- param = ", ".join([": ".join(p) for p in params])
- return f"g4f.provider.{cls.__name__} supports: ({param})" \ No newline at end of file
+ prompt = quote(format_prompt(messages))
+ driver.get(f"{cls.url}/search?q={prompt}&source=searchbox")
+
+ if model.startswith("gpt-4") or creative_mode:
+ wait = WebDriverWait(driver, timeout)
+ # Open dropdown
+ wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button.text-dark.dropdown-toggle")))
+ driver.find_element(By.CSS_SELECTOR, "button.text-dark.dropdown-toggle").click()
+ # Enable GPT-4
+ wait.until(EC.visibility_of_element_located((By.XPATH, "//button[text()='GPT-4']")))
+ if model.startswith("gpt-4"):
+ driver.find_element(By.XPATH, "//button[text()='GPT-4']").click()
+ # Enable creative mode
+ if creative_mode or creative_mode == None:
+ driver.find_element(By.ID, "Creative Mode").click()
+ # Submit question
+ driver.find_element(By.CSS_SELECTOR, ".search-bar-input-group button[type='submit']").click()
+ wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".search-container")))
+
+ try:
+ script = """
+window._fetch = window.fetch;
+window.fetch = (url, options) => {
+ const result = window._fetch(url, options);
+ if (url != "/api/infer/answer") return result;
+ result.then((response) => {
+ if (!response.body.locked) {
+ window.reader = response.body.getReader();
+ }
+ });
+ return new Promise((resolve, reject) => {
+ resolve(new Response(new ReadableStream()))
+ });
+}
+"""
+ driver.execute_script(script)
+ script = """
+if(window.reader) {
+ chunk = await window.reader.read();
+ if (chunk['done']) return null;
+ text = await (new Response(chunk['value']).text());
+ content = '';
+ text.split('\\r\\n').forEach((line, index) => {
+ if (line.startsWith('data: ')) {
+ line = line.substring('data: '.length);
+ if (!line.startsWith('<PHIND_METADATA>')) {
+ if (line) content += line;
+ else content += '\\n';
+ }
+ }
+ });
+ return content.replace('\\n\\n', '\\n');
+} else {
+ return ''
+}
+"""
+ while True:
+ chunk = driver.execute_script(script)
+ if chunk:
+ yield chunk
+ elif chunk != "":
+ break
+ else:
+ time.sleep(0.1)
+ finally:
+ driver.close()
+ if not browser:
+ time.sleep(0.1)
+ driver.quit()
+ if display:
+ display.stop() \ No newline at end of file