webscout 4.6__py3-none-any.whl → 4.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/Agents/functioncall.py +97 -37
- webscout/Bard.py +365 -0
- webscout/Local/_version.py +1 -1
- webscout/Provider/Andi.py +7 -1
- webscout/Provider/BasedGPT.py +11 -5
- webscout/Provider/Berlin4h.py +11 -5
- webscout/Provider/Blackboxai.py +10 -4
- webscout/Provider/Cohere.py +11 -5
- webscout/Provider/DARKAI.py +25 -7
- webscout/Provider/Deepinfra.py +2 -1
- webscout/Provider/Deepseek.py +25 -9
- webscout/Provider/DiscordRocks.py +389 -0
- webscout/Provider/{ChatGPTUK.py → Farfalle.py} +80 -67
- webscout/Provider/Gemini.py +1 -1
- webscout/Provider/Groq.py +244 -110
- webscout/Provider/Llama.py +13 -5
- webscout/Provider/Llama3.py +15 -2
- webscout/Provider/OLLAMA.py +8 -7
- webscout/Provider/Perplexity.py +422 -52
- webscout/Provider/Phind.py +6 -5
- webscout/Provider/PizzaGPT.py +7 -1
- webscout/Provider/__init__.py +15 -31
- webscout/Provider/ai4chat.py +193 -0
- webscout/Provider/koala.py +11 -5
- webscout/Provider/{VTLchat.py → liaobots.py} +120 -104
- webscout/Provider/meta.py +779 -0
- webscout/exceptions.py +6 -0
- webscout/version.py +1 -1
- webscout/webai.py +2 -64
- webscout/webscout_search.py +1 -1
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/METADATA +254 -297
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/RECORD +36 -40
- webscout/Provider/FreeGemini.py +0 -169
- webscout/Provider/Geminiflash.py +0 -152
- webscout/Provider/Geminipro.py +0 -152
- webscout/Provider/Leo.py +0 -469
- webscout/Provider/OpenGPT.py +0 -867
- webscout/Provider/Xjai.py +0 -230
- webscout/Provider/Yepchat.py +0 -478
- webscout/Provider/Youchat.py +0 -225
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/LICENSE.md +0 -0
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/WHEEL +0 -0
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/entry_points.txt +0 -0
- {webscout-4.6.dist-info → webscout-4.8.dist-info}/top_level.txt +0 -0
webscout/Provider/OLLAMA.py
CHANGED
|
@@ -13,10 +13,10 @@ import io
|
|
|
13
13
|
import re
|
|
14
14
|
import json
|
|
15
15
|
import yaml
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
16
|
+
from webscout.AIutel import Optimizers
|
|
17
|
+
from webscout.AIutel import Conversation
|
|
18
|
+
from webscout.AIutel import AwesomePrompts, sanitize_stream
|
|
19
|
+
from webscout.AIbase import Provider, AsyncProvider
|
|
20
20
|
from webscout import exceptions
|
|
21
21
|
from typing import Any, AsyncGenerator, Dict
|
|
22
22
|
import logging
|
|
@@ -182,6 +182,7 @@ class OLLAMA(Provider):
|
|
|
182
182
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
183
183
|
return response["text"]
|
|
184
184
|
if __name__ == "__main__":
|
|
185
|
-
ollama_provider = OLLAMA(model="
|
|
186
|
-
response = ollama_provider.chat("
|
|
187
|
-
|
|
185
|
+
ollama_provider = OLLAMA(model="qwen:0.5b")
|
|
186
|
+
response = ollama_provider.chat("hi")
|
|
187
|
+
for r in response:
|
|
188
|
+
print(r, end="", flush=True)
|
webscout/Provider/Perplexity.py
CHANGED
|
@@ -1,37 +1,29 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import time
|
|
2
3
|
import uuid
|
|
3
|
-
from
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
from selenium.webdriver.support import expected_conditions as EC
|
|
7
|
-
from selenium.webdriver.support.ui import WebDriverWait
|
|
8
|
-
import click
|
|
9
|
-
import requests
|
|
10
|
-
from requests import get
|
|
4
|
+
from typing import Iterable, Dict, Any, Generator
|
|
5
|
+
|
|
6
|
+
from os import listdir
|
|
11
7
|
from uuid import uuid4
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
import
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
import io
|
|
19
|
-
import re
|
|
20
|
-
import json
|
|
8
|
+
from time import sleep, time
|
|
9
|
+
from threading import Thread
|
|
10
|
+
from json import loads, dumps
|
|
11
|
+
from random import getrandbits
|
|
12
|
+
from websocket import WebSocketApp
|
|
13
|
+
from requests import Session, get, post
|
|
21
14
|
import yaml
|
|
22
|
-
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
26
|
-
from
|
|
15
|
+
|
|
16
|
+
from webscout.AIutel import Optimizers
|
|
17
|
+
from webscout.AIutel import Conversation
|
|
18
|
+
from webscout.AIutel import AwesomePrompts, sanitize_stream
|
|
19
|
+
from webscout.AIbase import Provider, AsyncProvider
|
|
27
20
|
from webscout import exceptions
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
#------------------------------------------------------PERPLEXITY--------------------------------------------------------
|
|
32
|
-
class PERPLEXITY(Provider):
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Perplexity(Provider):
|
|
33
24
|
def __init__(
|
|
34
25
|
self,
|
|
26
|
+
email: str = None,
|
|
35
27
|
is_conversation: bool = True,
|
|
36
28
|
max_tokens: int = 600,
|
|
37
29
|
timeout: int = 30,
|
|
@@ -42,11 +34,12 @@ class PERPLEXITY(Provider):
|
|
|
42
34
|
history_offset: int = 10250,
|
|
43
35
|
act: str = None,
|
|
44
36
|
quiet: bool = False,
|
|
45
|
-
):
|
|
37
|
+
) -> None:
|
|
46
38
|
"""Instantiates PERPLEXITY
|
|
47
39
|
|
|
48
40
|
Args:
|
|
49
|
-
|
|
41
|
+
email (str, optional): Your perplexity.ai email. Defaults to None.
|
|
42
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
50
43
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
51
44
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
52
45
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
@@ -63,6 +56,44 @@ class PERPLEXITY(Provider):
|
|
|
63
56
|
self.web_results: dict = {}
|
|
64
57
|
self.quiet = quiet
|
|
65
58
|
|
|
59
|
+
self.session: Session = Session()
|
|
60
|
+
self.user_agent: dict = {
|
|
61
|
+
"User-Agent": "Ask/2.9.1/2406 (iOS; iPhone; Version 17.1) isiOSOnMac/false",
|
|
62
|
+
"X-Client-Name": "Perplexity-iOS",
|
|
63
|
+
"X-App-ApiClient": "ios",
|
|
64
|
+
}
|
|
65
|
+
self.session.headers.update(self.user_agent)
|
|
66
|
+
|
|
67
|
+
if email and ".perplexity_session" in listdir():
|
|
68
|
+
self._recover_session(email)
|
|
69
|
+
else:
|
|
70
|
+
self._init_session_without_login()
|
|
71
|
+
|
|
72
|
+
if email:
|
|
73
|
+
self._login(email)
|
|
74
|
+
|
|
75
|
+
self.email: str = email
|
|
76
|
+
self.t: str = self._get_t()
|
|
77
|
+
self.sid: str = self._get_sid()
|
|
78
|
+
|
|
79
|
+
self.n: int = 1
|
|
80
|
+
self.base: int = 420
|
|
81
|
+
self.queue: list = []
|
|
82
|
+
self.finished: bool = True
|
|
83
|
+
self.last_uuid: str = None
|
|
84
|
+
self.backend_uuid: str = (
|
|
85
|
+
None # unused because we can't yet follow-up questions
|
|
86
|
+
)
|
|
87
|
+
self.frontend_session_id: str = str(uuid4())
|
|
88
|
+
|
|
89
|
+
assert self._ask_anonymous_user(), "failed to ask anonymous user"
|
|
90
|
+
self.ws: WebSocketApp = self._init_websocket()
|
|
91
|
+
self.ws_thread: Thread = Thread(target=self.ws.run_forever).start()
|
|
92
|
+
self._auth_session()
|
|
93
|
+
|
|
94
|
+
while not (self.ws.sock and self.ws.sock.connected):
|
|
95
|
+
sleep(0.01)
|
|
96
|
+
|
|
66
97
|
self.__available_optimizers = (
|
|
67
98
|
method
|
|
68
99
|
for method in dir(Optimizers)
|
|
@@ -79,6 +110,347 @@ class PERPLEXITY(Provider):
|
|
|
79
110
|
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
80
111
|
)
|
|
81
112
|
self.conversation.history_offset = history_offset
|
|
113
|
+
self.session.proxies = proxies
|
|
114
|
+
|
|
115
|
+
def _recover_session(self, email: str) -> None:
|
|
116
|
+
with open(".perplexity_session", "r") as f:
|
|
117
|
+
perplexity_session: dict = loads(f.read())
|
|
118
|
+
|
|
119
|
+
if email in perplexity_session:
|
|
120
|
+
self.session.cookies.update(perplexity_session[email])
|
|
121
|
+
else:
|
|
122
|
+
self._login(email, perplexity_session)
|
|
123
|
+
|
|
124
|
+
def _login(self, email: str, ps: dict = None) -> None:
|
|
125
|
+
self.session.post(
|
|
126
|
+
url="https://www.perplexity.ai/api/auth/signin-email",
|
|
127
|
+
data={"email": email},
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
email_link: str = str(input("paste the link you received by email: "))
|
|
131
|
+
self.session.get(email_link)
|
|
132
|
+
|
|
133
|
+
if ps:
|
|
134
|
+
ps[email] = self.session.cookies.get_dict()
|
|
135
|
+
else:
|
|
136
|
+
ps = {email: self.session.cookies.get_dict()}
|
|
137
|
+
|
|
138
|
+
with open(".perplexity_session", "w") as f:
|
|
139
|
+
f.write(dumps(ps))
|
|
140
|
+
|
|
141
|
+
def _init_session_without_login(self) -> None:
|
|
142
|
+
self.session.get(url=f"https://www.perplexity.ai/search/{str(uuid4())}")
|
|
143
|
+
self.session.headers.update(self.user_agent)
|
|
144
|
+
|
|
145
|
+
def _auth_session(self) -> None:
|
|
146
|
+
self.session.get(url="https://www.perplexity.ai/api/auth/session")
|
|
147
|
+
|
|
148
|
+
def _get_t(self) -> str:
|
|
149
|
+
return format(getrandbits(32), "08x")
|
|
150
|
+
|
|
151
|
+
def _get_sid(self) -> str:
|
|
152
|
+
return loads(
|
|
153
|
+
self.session.get(
|
|
154
|
+
url=f"https://www.perplexity.ai/socket.io/?EIO=4&transport=polling&t={self.t}"
|
|
155
|
+
).text[1:]
|
|
156
|
+
)["sid"]
|
|
157
|
+
|
|
158
|
+
def _ask_anonymous_user(self) -> bool:
|
|
159
|
+
response = self.session.post(
|
|
160
|
+
url=f"https://www.perplexity.ai/socket.io/?EIO=4&transport=polling&t={self.t}&sid={self.sid}",
|
|
161
|
+
data='40{"jwt":"anonymous-ask-user"}',
|
|
162
|
+
).text
|
|
163
|
+
|
|
164
|
+
return response == "OK"
|
|
165
|
+
|
|
166
|
+
def _start_interaction(self) -> None:
|
|
167
|
+
self.finished = False
|
|
168
|
+
|
|
169
|
+
if self.n == 9:
|
|
170
|
+
self.n = 0
|
|
171
|
+
self.base *= 10
|
|
172
|
+
else:
|
|
173
|
+
self.n += 1
|
|
174
|
+
|
|
175
|
+
self.queue = []
|
|
176
|
+
|
|
177
|
+
def _get_cookies_str(self) -> str:
|
|
178
|
+
cookies = ""
|
|
179
|
+
for key, value in self.session.cookies.get_dict().items():
|
|
180
|
+
cookies += f"{key}={value}; "
|
|
181
|
+
return cookies[:-2]
|
|
182
|
+
|
|
183
|
+
def _write_file_url(self, filename: str, file_url: str) -> None:
|
|
184
|
+
if ".perplexity_files_url" in listdir():
|
|
185
|
+
with open(".perplexity_files_url", "r") as f:
|
|
186
|
+
perplexity_files_url: dict = loads(f.read())
|
|
187
|
+
else:
|
|
188
|
+
perplexity_files_url: dict = {}
|
|
189
|
+
|
|
190
|
+
perplexity_files_url[filename] = file_url
|
|
191
|
+
|
|
192
|
+
with open(".perplexity_files_url", "w") as f:
|
|
193
|
+
f.write(dumps(perplexity_files_url))
|
|
194
|
+
|
|
195
|
+
def _init_websocket(self) -> WebSocketApp:
|
|
196
|
+
def on_open(ws: WebSocketApp) -> None:
|
|
197
|
+
ws.send("2probe")
|
|
198
|
+
ws.send("5")
|
|
199
|
+
|
|
200
|
+
def on_message(ws: WebSocketApp, message: str) -> None:
|
|
201
|
+
if message == "2":
|
|
202
|
+
ws.send("3")
|
|
203
|
+
elif not self.finished:
|
|
204
|
+
if message.startswith("42"):
|
|
205
|
+
message: list = loads(message[2:])
|
|
206
|
+
content: dict = message[1]
|
|
207
|
+
if "mode" in content and content["mode"] == "copilot":
|
|
208
|
+
content["copilot_answer"] = loads(content["text"])
|
|
209
|
+
elif "mode" in content:
|
|
210
|
+
content.update(loads(content["text"]))
|
|
211
|
+
content.pop("text")
|
|
212
|
+
if (
|
|
213
|
+
not ("final" in content and content["final"])
|
|
214
|
+
) or ("status" in content and content["status"] == "completed"):
|
|
215
|
+
self.queue.append(content)
|
|
216
|
+
if message[0] == "query_answered":
|
|
217
|
+
self.last_uuid = content["uuid"]
|
|
218
|
+
self.finished = True
|
|
219
|
+
elif message.startswith("43"):
|
|
220
|
+
message: dict = loads(message[3:])[0]
|
|
221
|
+
if (
|
|
222
|
+
"uuid" in message and message["uuid"] != self.last_uuid
|
|
223
|
+
) or "uuid" not in message:
|
|
224
|
+
self.queue.append(message)
|
|
225
|
+
self.finished = True
|
|
226
|
+
|
|
227
|
+
return WebSocketApp(
|
|
228
|
+
url=f"wss://www.perplexity.ai/socket.io/?EIO=4&transport=websocket&sid={self.sid}",
|
|
229
|
+
header=self.user_agent,
|
|
230
|
+
cookie=self._get_cookies_str(),
|
|
231
|
+
on_open=on_open,
|
|
232
|
+
on_message=on_message,
|
|
233
|
+
on_error=lambda ws, err: print(f"websocket error: {err}"),
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def _s(
|
|
237
|
+
self,
|
|
238
|
+
query: str,
|
|
239
|
+
mode: str = "concise",
|
|
240
|
+
search_focus: str = "internet",
|
|
241
|
+
attachments: list[str] = [],
|
|
242
|
+
language: str = "en-GB",
|
|
243
|
+
in_page: str = None,
|
|
244
|
+
in_domain: str = None,
|
|
245
|
+
) -> None:
|
|
246
|
+
assert self.finished, "already searching"
|
|
247
|
+
assert mode in ["concise", "copilot"], "invalid mode"
|
|
248
|
+
assert len(attachments) <= 4, "too many attachments: max 4"
|
|
249
|
+
assert (
|
|
250
|
+
search_focus
|
|
251
|
+
in [
|
|
252
|
+
"internet",
|
|
253
|
+
"scholar",
|
|
254
|
+
"writing",
|
|
255
|
+
"wolfram",
|
|
256
|
+
"youtube",
|
|
257
|
+
"reddit",
|
|
258
|
+
]
|
|
259
|
+
), "invalid search focus"
|
|
260
|
+
|
|
261
|
+
if in_page:
|
|
262
|
+
search_focus = "in_page"
|
|
263
|
+
if in_domain:
|
|
264
|
+
search_focus = "in_domain"
|
|
265
|
+
|
|
266
|
+
self._start_interaction()
|
|
267
|
+
ws_message: str = (
|
|
268
|
+
f"{self.base + self.n}"
|
|
269
|
+
+ dumps(
|
|
270
|
+
[
|
|
271
|
+
"perplexity_ask",
|
|
272
|
+
query,
|
|
273
|
+
{
|
|
274
|
+
"version": "2.1",
|
|
275
|
+
"source": "default", # "ios"
|
|
276
|
+
"frontend_session_id": self.frontend_session_id,
|
|
277
|
+
"language": language,
|
|
278
|
+
"timezone": "CET",
|
|
279
|
+
"attachments": attachments,
|
|
280
|
+
"search_focus": search_focus,
|
|
281
|
+
"frontend_uuid": str(uuid4()),
|
|
282
|
+
"mode": mode,
|
|
283
|
+
# "use_inhouse_model": True
|
|
284
|
+
"in_page": in_page,
|
|
285
|
+
"in_domain": in_domain,
|
|
286
|
+
},
|
|
287
|
+
]
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
self.ws.send(ws_message)
|
|
292
|
+
|
|
293
|
+
def search(
|
|
294
|
+
self,
|
|
295
|
+
query: str,
|
|
296
|
+
mode: str = "concise",
|
|
297
|
+
search_focus: str = "internet",
|
|
298
|
+
attachments: list[str] = [],
|
|
299
|
+
language: str = "en-GB",
|
|
300
|
+
timeout: float = 30,
|
|
301
|
+
in_page: str = None,
|
|
302
|
+
in_domain: str = None,
|
|
303
|
+
) -> Iterable[Dict]:
|
|
304
|
+
self._s(query, mode, search_focus, attachments, language, in_page, in_domain)
|
|
305
|
+
|
|
306
|
+
start_time: float = time()
|
|
307
|
+
while (not self.finished) or len(self.queue) != 0:
|
|
308
|
+
if timeout and time() - start_time > timeout:
|
|
309
|
+
self.finished = True
|
|
310
|
+
return {"error": "timeout"}
|
|
311
|
+
if len(self.queue) != 0:
|
|
312
|
+
yield self.queue.pop(0)
|
|
313
|
+
|
|
314
|
+
def search_sync(
|
|
315
|
+
self,
|
|
316
|
+
query: str,
|
|
317
|
+
mode: str = "concise",
|
|
318
|
+
search_focus: str = "internet",
|
|
319
|
+
attachments: list[str] = [],
|
|
320
|
+
language: str = "en-GB",
|
|
321
|
+
timeout: float = 30,
|
|
322
|
+
in_page: str = None,
|
|
323
|
+
in_domain: str = None,
|
|
324
|
+
) -> dict:
|
|
325
|
+
self._s(query, mode, search_focus, attachments, language, in_page, in_domain)
|
|
326
|
+
|
|
327
|
+
start_time: float = time()
|
|
328
|
+
while not self.finished:
|
|
329
|
+
if timeout and time() - start_time > timeout:
|
|
330
|
+
self.finished = True
|
|
331
|
+
return {"error": "timeout"}
|
|
332
|
+
|
|
333
|
+
return self.queue.pop(-1)
|
|
334
|
+
|
|
335
|
+
def upload(self, filename: str) -> str:
|
|
336
|
+
assert self.finished, "already searching"
|
|
337
|
+
assert filename.split(".")[-1] in [
|
|
338
|
+
"txt",
|
|
339
|
+
"pdf",
|
|
340
|
+
], "invalid file format"
|
|
341
|
+
|
|
342
|
+
if filename.startswith("http"):
|
|
343
|
+
file = get(filename).content
|
|
344
|
+
else:
|
|
345
|
+
with open(filename, "rb") as f:
|
|
346
|
+
file = f.read()
|
|
347
|
+
|
|
348
|
+
self._start_interaction()
|
|
349
|
+
ws_message: str = (
|
|
350
|
+
f"{self.base + self.n}"
|
|
351
|
+
+ dumps(
|
|
352
|
+
[
|
|
353
|
+
"get_upload_url",
|
|
354
|
+
{
|
|
355
|
+
"version": "2.1",
|
|
356
|
+
"source": "default",
|
|
357
|
+
"content_type": "text/plain"
|
|
358
|
+
if filename.split(".")[-1] == "txt"
|
|
359
|
+
else "application/pdf",
|
|
360
|
+
},
|
|
361
|
+
]
|
|
362
|
+
)
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
self.ws.send(ws_message)
|
|
366
|
+
|
|
367
|
+
while not self.finished or len(self.queue) != 0:
|
|
368
|
+
if len(self.queue) != 0:
|
|
369
|
+
upload_data = self.queue.pop(0)
|
|
370
|
+
|
|
371
|
+
assert not upload_data["rate_limited"], "rate limited"
|
|
372
|
+
|
|
373
|
+
post(
|
|
374
|
+
url=upload_data["url"],
|
|
375
|
+
files={
|
|
376
|
+
"acl": (None, upload_data["fields"]["acl"]),
|
|
377
|
+
"Content-Type": (None, upload_data["fields"]["Content-Type"]),
|
|
378
|
+
"key": (None, upload_data["fields"]["key"]),
|
|
379
|
+
"AWSAccessKeyId": (None, upload_data["fields"]["AWSAccessKeyId"]),
|
|
380
|
+
"x-amz-security-token": (
|
|
381
|
+
None,
|
|
382
|
+
upload_data["fields"]["x-amz-security-token"],
|
|
383
|
+
),
|
|
384
|
+
"policy": (None, upload_data["fields"]["policy"]),
|
|
385
|
+
"signature": (None, upload_data["fields"]["signature"]),
|
|
386
|
+
"file": (filename, file),
|
|
387
|
+
},
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
file_url: str = (
|
|
391
|
+
upload_data["url"] + upload_data["fields"]["key"].split("$")[0] + filename
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
self._write_file_url(filename, file_url)
|
|
395
|
+
|
|
396
|
+
return file_url
|
|
397
|
+
|
|
398
|
+
def threads(self, query: str = None, limit: int = None) -> list[dict]:
|
|
399
|
+
assert self.email, "not logged in"
|
|
400
|
+
assert self.finished, "already searching"
|
|
401
|
+
|
|
402
|
+
if not limit:
|
|
403
|
+
limit = 20
|
|
404
|
+
data: dict = {"version": "2.1", "source": "default", "limit": limit, "offset": 0}
|
|
405
|
+
if query:
|
|
406
|
+
data["search_term"] = query
|
|
407
|
+
|
|
408
|
+
self._start_interaction()
|
|
409
|
+
ws_message: str = f"{self.base + self.n}" + dumps(["list_ask_threads", data])
|
|
410
|
+
|
|
411
|
+
self.ws.send(ws_message)
|
|
412
|
+
|
|
413
|
+
while not self.finished or len(self.queue) != 0:
|
|
414
|
+
if len(self.queue) != 0:
|
|
415
|
+
return self.queue.pop(0)
|
|
416
|
+
|
|
417
|
+
def list_autosuggest(self, query: str = "", search_focus: str = "internet") -> list[dict]:
|
|
418
|
+
assert self.finished, "already searching"
|
|
419
|
+
|
|
420
|
+
self._start_interaction()
|
|
421
|
+
ws_message: str = (
|
|
422
|
+
f"{self.base + self.n}"
|
|
423
|
+
+ dumps(
|
|
424
|
+
[
|
|
425
|
+
"list_autosuggest",
|
|
426
|
+
query,
|
|
427
|
+
{
|
|
428
|
+
"has_attachment": False,
|
|
429
|
+
"search_focus": search_focus,
|
|
430
|
+
"source": "default",
|
|
431
|
+
"version": "2.1",
|
|
432
|
+
},
|
|
433
|
+
]
|
|
434
|
+
)
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
self.ws.send(ws_message)
|
|
438
|
+
|
|
439
|
+
while not self.finished or len(self.queue) != 0:
|
|
440
|
+
if len(self.queue) != 0:
|
|
441
|
+
return self.queue.pop(0)
|
|
442
|
+
|
|
443
|
+
def close(self) -> None:
|
|
444
|
+
self.ws.close()
|
|
445
|
+
|
|
446
|
+
if self.email:
|
|
447
|
+
with open(".perplexity_session", "r") as f:
|
|
448
|
+
perplexity_session: dict = loads(f.read())
|
|
449
|
+
|
|
450
|
+
perplexity_session[self.email] = self.session.cookies.get_dict()
|
|
451
|
+
|
|
452
|
+
with open(".perplexity_session", "w") as f:
|
|
453
|
+
f.write(dumps(perplexity_session))
|
|
82
454
|
|
|
83
455
|
def ask(
|
|
84
456
|
self,
|
|
@@ -87,7 +459,7 @@ class PERPLEXITY(Provider):
|
|
|
87
459
|
raw: bool = False,
|
|
88
460
|
optimizer: str = None,
|
|
89
461
|
conversationally: bool = False,
|
|
90
|
-
) -> dict:
|
|
462
|
+
) -> dict | Generator:
|
|
91
463
|
"""Chat with AI
|
|
92
464
|
|
|
93
465
|
Args:
|
|
@@ -134,18 +506,19 @@ class PERPLEXITY(Provider):
|
|
|
134
506
|
)
|
|
135
507
|
|
|
136
508
|
def for_stream():
|
|
137
|
-
for response in
|
|
138
|
-
yield
|
|
509
|
+
for response in self.search(conversation_prompt):
|
|
510
|
+
yield dumps(response) if raw else response
|
|
139
511
|
self.last_response.update(response)
|
|
140
512
|
|
|
141
513
|
self.conversation.update_chat_history(
|
|
142
|
-
prompt,
|
|
143
|
-
self.get_message(self.last_response),
|
|
514
|
+
prompt, self.get_message(self.last_response)
|
|
144
515
|
)
|
|
145
516
|
|
|
146
517
|
def for_non_stream():
|
|
147
|
-
|
|
148
|
-
|
|
518
|
+
self.last_response.update(self.search_sync(conversation_prompt))
|
|
519
|
+
self.conversation.update_chat_history(
|
|
520
|
+
prompt, self.get_message(self.last_response)
|
|
521
|
+
)
|
|
149
522
|
return self.last_response
|
|
150
523
|
|
|
151
524
|
return for_stream() if stream else for_non_stream()
|
|
@@ -156,7 +529,7 @@ class PERPLEXITY(Provider):
|
|
|
156
529
|
stream: bool = False,
|
|
157
530
|
optimizer: str = None,
|
|
158
531
|
conversationally: bool = False,
|
|
159
|
-
) -> str:
|
|
532
|
+
) -> str | Generator:
|
|
160
533
|
"""Generate response `str`
|
|
161
534
|
Args:
|
|
162
535
|
prompt (str): Prompt to be send.
|
|
@@ -211,20 +584,17 @@ class PERPLEXITY(Provider):
|
|
|
211
584
|
self.web_results.clear()
|
|
212
585
|
update_web_results(web_results)
|
|
213
586
|
|
|
214
|
-
return
|
|
215
|
-
text_str
|
|
216
|
-
if self.quiet or not self.web_results
|
|
217
|
-
else text_str + "\n\n# WEB-RESULTS\n\n" + yaml.dump(self.web_results)
|
|
218
|
-
)
|
|
587
|
+
return text_str
|
|
219
588
|
|
|
220
589
|
else:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
590
|
+
return text_str
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
if __name__ == "__main__":
|
|
594
|
+
perplexity = Perplexity()
|
|
595
|
+
# Stream the response
|
|
596
|
+
response = perplexity.chat("What is the meaning of life?")
|
|
597
|
+
for chunk in response:
|
|
598
|
+
print(chunk, end="", flush=True)
|
|
599
|
+
|
|
600
|
+
perplexity.close()
|
webscout/Provider/Phind.py
CHANGED
|
@@ -19,10 +19,10 @@ import io
|
|
|
19
19
|
import re
|
|
20
20
|
import json
|
|
21
21
|
import yaml
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
22
|
+
from webscout.AIutel import Optimizers
|
|
23
|
+
from webscout.AIutel import Conversation
|
|
24
|
+
from webscout.AIutel import AwesomePrompts, sanitize_stream
|
|
25
|
+
from webscout.AIbase import Provider, AsyncProvider
|
|
26
26
|
from Helpingai_T2 import Perplexity
|
|
27
27
|
from webscout import exceptions
|
|
28
28
|
from typing import Any, AsyncGenerator, Dict
|
|
@@ -1004,4 +1004,5 @@ class AsyncPhindv2(AsyncProvider):
|
|
|
1004
1004
|
response["choices"][0]["delta"].get("content")
|
|
1005
1005
|
if response["choices"][0].get("finish_reason") is None
|
|
1006
1006
|
else ""
|
|
1007
|
-
)
|
|
1007
|
+
)
|
|
1008
|
+
|
webscout/Provider/PizzaGPT.py
CHANGED
|
@@ -175,4 +175,10 @@ class PIZZAGPT(Provider):
|
|
|
175
175
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
176
176
|
return response["text"]
|
|
177
177
|
if __name__ == "__main__":
|
|
178
|
-
print
|
|
178
|
+
from rich import print
|
|
179
|
+
|
|
180
|
+
ai = PIZZAGPT()
|
|
181
|
+
# Stream the response
|
|
182
|
+
response = ai.chat(input(">>> "))
|
|
183
|
+
for chunk in response:
|
|
184
|
+
print(chunk, end="", flush=True)
|