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
+ 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
+ # Register fetch hook
35
+ source = """
36
+ window._fetch = window.fetch;
37
+ window.fetch = async (url, options) => {
38
+ const response = await window._fetch(url, options);
39
+ if (url != "/api/infer/answer") {
40
+ return response;
41
+ }
42
+ copy = response.clone();
43
+ window._reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
44
+ return copy;
45
+ }
46
+ """
47
+ driver .execute_cdp_cmd ("Page.addScriptToEvaluateOnNewDocument" , {
48
+ "source" : source
49
+ })
50
+
51
+ prompt = quote (format_prompt (messages ))
52
+ driver .get (f"{ cls .url } /search?q={ prompt } &source=searchbox" )
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
+ }
91
+ }
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 )
0 commit comments