webscout 6.4__py3-none-any.whl → 6.6__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/AIutel.py +7 -54
- webscout/DWEBS.py +48 -26
- webscout/{YTdownloader.py → Extra/YTToolkit/YTdownloader.py} +990 -1103
- webscout/Extra/YTToolkit/__init__.py +3 -0
- webscout/{transcriber.py → Extra/YTToolkit/transcriber.py} +1 -1
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
- webscout/Extra/YTToolkit/ytapi/extras.py +45 -0
- webscout/Extra/YTToolkit/ytapi/https.py +88 -0
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
- webscout/Extra/YTToolkit/ytapi/query.py +37 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +60 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
- webscout/Extra/YTToolkit/ytapi/video.py +102 -0
- webscout/Extra/__init__.py +2 -1
- webscout/Extra/autocoder/autocoder_utiles.py +119 -101
- webscout/Extra/autocoder/rawdog.py +679 -680
- webscout/Extra/gguf.py +441 -441
- webscout/Extra/markdownlite/__init__.py +862 -0
- webscout/Extra/weather_ascii.py +2 -2
- webscout/Provider/AISEARCH/__init__.py +2 -0
- webscout/Provider/AISEARCH/ooai.py +155 -0
- webscout/Provider/Amigo.py +70 -85
- webscout/Provider/{prefind.py → Jadve.py} +72 -70
- webscout/Provider/Netwrck.py +235 -0
- webscout/Provider/Openai.py +4 -3
- webscout/Provider/PI.py +292 -221
- webscout/Provider/PizzaGPT.py +3 -3
- webscout/Provider/Reka.py +0 -1
- webscout/Provider/TTS/__init__.py +5 -1
- webscout/Provider/TTS/deepgram.py +183 -0
- webscout/Provider/TTS/elevenlabs.py +137 -0
- webscout/Provider/TTS/gesserit.py +151 -0
- webscout/Provider/TTS/murfai.py +139 -0
- webscout/Provider/TTS/parler.py +134 -107
- webscout/Provider/TTS/streamElements.py +360 -275
- webscout/Provider/TTS/utils.py +280 -0
- webscout/Provider/TTS/voicepod.py +116 -116
- webscout/Provider/TeachAnything.py +15 -2
- webscout/Provider/Youchat.py +42 -8
- webscout/Provider/__init__.py +8 -21
- webscout/Provider/meta.py +794 -779
- webscout/Provider/multichat.py +230 -0
- webscout/Provider/promptrefine.py +2 -2
- webscout/Provider/talkai.py +10 -13
- webscout/Provider/turboseek.py +5 -4
- webscout/Provider/tutorai.py +8 -112
- webscout/Provider/typegpt.py +5 -7
- webscout/Provider/x0gpt.py +81 -9
- webscout/Provider/yep.py +123 -361
- webscout/__init__.py +33 -28
- webscout/conversation.py +24 -9
- webscout/exceptions.py +188 -20
- webscout/litprinter/__init__.py +719 -831
- webscout/litprinter/colors.py +54 -0
- webscout/optimizers.py +420 -270
- webscout/prompt_manager.py +279 -279
- webscout/scout/__init__.py +8 -0
- webscout/scout/core/__init__.py +7 -0
- webscout/scout/core/crawler.py +140 -0
- webscout/scout/core/scout.py +571 -0
- webscout/scout/core/search_result.py +96 -0
- webscout/scout/core/text_analyzer.py +63 -0
- webscout/scout/core/text_utils.py +277 -0
- webscout/scout/core/web_analyzer.py +52 -0
- webscout/scout/core.py +884 -0
- webscout/scout/element.py +460 -0
- webscout/scout/parsers/__init__.py +69 -0
- webscout/scout/parsers/html5lib_parser.py +172 -0
- webscout/scout/parsers/html_parser.py +236 -0
- webscout/scout/parsers/lxml_parser.py +178 -0
- webscout/scout/utils.py +38 -0
- webscout/update_checker.py +184 -125
- webscout/version.py +1 -1
- webscout/zeroart/__init__.py +55 -0
- webscout/zeroart/base.py +60 -0
- webscout/zeroart/effects.py +99 -0
- webscout/zeroart/fonts.py +816 -0
- webscout/zerodir/__init__.py +225 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/METADATA +18 -231
- webscout-6.6.dist-info/RECORD +197 -0
- webscout-6.6.dist-info/top_level.txt +2 -0
- webstoken/__init__.py +30 -0
- webstoken/classifier.py +189 -0
- webstoken/keywords.py +216 -0
- webstoken/language.py +128 -0
- webstoken/ner.py +164 -0
- webstoken/normalizer.py +35 -0
- webstoken/processor.py +77 -0
- webstoken/sentiment.py +206 -0
- webstoken/stemmer.py +73 -0
- webstoken/t.py +75 -0
- webstoken/tagger.py +60 -0
- webstoken/tokenizer.py +158 -0
- webscout/Agents/Onlinesearcher.py +0 -182
- webscout/Agents/__init__.py +0 -2
- webscout/Agents/functioncall.py +0 -248
- webscout/Bing_search.py +0 -251
- webscout/Provider/Perplexity.py +0 -599
- webscout/Provider/RoboCoders.py +0 -206
- webscout/Provider/genspark.py +0 -225
- webscout/Provider/perplexitylabs.py +0 -265
- webscout/Provider/twitterclone.py +0 -251
- webscout/Provider/upstage.py +0 -230
- webscout/gpt4free.py +0 -666
- webscout/requestsHTMLfix.py +0 -775
- webscout/webai.py +0 -2590
- webscout-6.4.dist-info/RECORD +0 -154
- webscout-6.4.dist-info/top_level.txt +0 -1
- /webscout/Provider/{felo_search.py → AISEARCH/felo_search.py} +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/LICENSE.md +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/WHEEL +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/entry_points.txt +0 -0
webscout/Extra/weather_ascii.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
from rich.console import Console
|
|
3
|
-
from
|
|
3
|
+
from webscout.zeroart import figlet_format
|
|
4
4
|
|
|
5
5
|
console = Console()
|
|
6
6
|
def get(location):
|
|
@@ -12,7 +12,7 @@ def get(location):
|
|
|
12
12
|
str: ASCII art weather report if the request is successful,
|
|
13
13
|
otherwise an error message.
|
|
14
14
|
"""
|
|
15
|
-
console.print(f"[bold green]{figlet_format('Weather')}
|
|
15
|
+
console.print(f"[bold green]{figlet_format('Weather')}")
|
|
16
16
|
url = f"https://wttr.in/{location}"
|
|
17
17
|
response = requests.get(url, headers={'User-Agent': 'curl'})
|
|
18
18
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any, Dict, Generator, Optional
|
|
5
|
+
|
|
6
|
+
from webscout.AIbase import Provider
|
|
7
|
+
from webscout import exceptions
|
|
8
|
+
from webscout.litagent import LitAgent
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OOAi(Provider):
|
|
12
|
+
"""
|
|
13
|
+
A class to interact with the oo.ai API.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
max_tokens: int = 600,
|
|
19
|
+
timeout: int = 30,
|
|
20
|
+
proxies: Optional[dict] = None,
|
|
21
|
+
):
|
|
22
|
+
"""Initializes the OOAi API client."""
|
|
23
|
+
self.session = requests.Session()
|
|
24
|
+
self.max_tokens_to_sample = max_tokens
|
|
25
|
+
self.api_endpoint = "https://oo.ai/api/search"
|
|
26
|
+
self.stream_chunk_size = 1024 # Adjust as needed
|
|
27
|
+
self.timeout = timeout
|
|
28
|
+
self.last_response = {}
|
|
29
|
+
self.headers = {
|
|
30
|
+
"Accept": "text/event-stream",
|
|
31
|
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
32
|
+
"Accept-Language": "en-US,en;q=0.9,en-IN;q=0.8",
|
|
33
|
+
"Cache-Control": "no-cache",
|
|
34
|
+
"Cookie": "_ga=GA1.1.1827087199.1734256606; _ga_P0EJPHF2EG=GS1.1.1734368698.4.1.1734368711.0.0.0",
|
|
35
|
+
"DNT": "1",
|
|
36
|
+
"Referer": "https://oo.ai/",
|
|
37
|
+
"sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A_Brand";v="24"',
|
|
38
|
+
"sec-ch-ua-mobile": "?0",
|
|
39
|
+
"sec-ch-ua-platform": "Windows",
|
|
40
|
+
"sec-fetch-dest": "empty",
|
|
41
|
+
"sec-fetch-mode": "cors",
|
|
42
|
+
"sec-fetch-site": "same-origin",
|
|
43
|
+
}
|
|
44
|
+
self.session.headers.update(self.headers)
|
|
45
|
+
self.proxies = proxies
|
|
46
|
+
self.headers["User-Agent"] = LitAgent().random()
|
|
47
|
+
|
|
48
|
+
def ask(
|
|
49
|
+
self,
|
|
50
|
+
prompt: str,
|
|
51
|
+
stream: bool = False,
|
|
52
|
+
raw: bool = False,
|
|
53
|
+
optimizer: Optional[str] = None,
|
|
54
|
+
conversationally: bool = False,
|
|
55
|
+
) -> Dict[str, Any] | Generator[Dict[str, Any], None, None]:
|
|
56
|
+
"""Chat with AI
|
|
57
|
+
Args:
|
|
58
|
+
prompt (str): Prompt to be sent.
|
|
59
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
60
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
61
|
+
optimizer (str, optional): Not used. Defaults to None.
|
|
62
|
+
conversationally (bool, optional): Not used. Defaults to False.
|
|
63
|
+
Returns:
|
|
64
|
+
Union[Dict, Generator[Dict, None, None]]: Response generated
|
|
65
|
+
"""
|
|
66
|
+
params = {
|
|
67
|
+
"q": prompt,
|
|
68
|
+
"lang": "en-US",
|
|
69
|
+
"tz": "Asia/Calcutta",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def for_stream():
|
|
73
|
+
try:
|
|
74
|
+
with self.session.get(
|
|
75
|
+
self.api_endpoint,
|
|
76
|
+
params=params,
|
|
77
|
+
headers=self.headers,
|
|
78
|
+
stream=True,
|
|
79
|
+
timeout=self.timeout,
|
|
80
|
+
) as response:
|
|
81
|
+
|
|
82
|
+
if not response.ok:
|
|
83
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
84
|
+
f"Request failed with status code {response.status_code}: {response.text}"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
streaming_text = ""
|
|
88
|
+
for line in response.iter_lines(decode_unicode=True):
|
|
89
|
+
if line and line.startswith('data: '):
|
|
90
|
+
try:
|
|
91
|
+
json_data = json.loads(line[6:])
|
|
92
|
+
if "content" in json_data:
|
|
93
|
+
content = self.clean_content(json_data["content"])
|
|
94
|
+
streaming_text += content
|
|
95
|
+
yield {"text": content} if not raw else {"text": content}
|
|
96
|
+
except json.JSONDecodeError:
|
|
97
|
+
continue
|
|
98
|
+
self.last_response.update({"text": streaming_text})
|
|
99
|
+
|
|
100
|
+
except requests.exceptions.RequestException as e:
|
|
101
|
+
raise exceptions.APIConnectionError(f"Request failed: {e}")
|
|
102
|
+
|
|
103
|
+
def for_non_stream():
|
|
104
|
+
for _ in for_stream():
|
|
105
|
+
pass
|
|
106
|
+
return self.last_response
|
|
107
|
+
|
|
108
|
+
return for_stream() if stream else for_non_stream()
|
|
109
|
+
|
|
110
|
+
def chat(
|
|
111
|
+
self,
|
|
112
|
+
prompt: str,
|
|
113
|
+
stream: bool = False,
|
|
114
|
+
optimizer: Optional[str] = None,
|
|
115
|
+
conversationally: bool = False,
|
|
116
|
+
) -> str | Generator[str, None, None]:
|
|
117
|
+
"""Generate response `str`"""
|
|
118
|
+
|
|
119
|
+
def for_stream():
|
|
120
|
+
for response in self.ask(
|
|
121
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
122
|
+
):
|
|
123
|
+
yield self.get_message(response)
|
|
124
|
+
|
|
125
|
+
def for_non_stream():
|
|
126
|
+
return self.get_message(
|
|
127
|
+
self.ask(
|
|
128
|
+
prompt,
|
|
129
|
+
False,
|
|
130
|
+
optimizer=optimizer,
|
|
131
|
+
conversationally=conversationally,
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return for_stream() if stream else for_non_stream()
|
|
136
|
+
|
|
137
|
+
def get_message(self, response: dict) -> str:
|
|
138
|
+
"""Retrieves message only from response"""
|
|
139
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
140
|
+
return response["text"]
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def clean_content(text: str) -> str:
|
|
144
|
+
"""Removes all webblock elements with research or detail classes."""
|
|
145
|
+
cleaned_text = re.sub(
|
|
146
|
+
r'<webblock class="(?:research|detail)">[^<]*</webblock>', "", text
|
|
147
|
+
)
|
|
148
|
+
return cleaned_text
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
from rich import print
|
|
152
|
+
ai = OOAi()
|
|
153
|
+
response = ai.chat(input(">>> "), stream=True)
|
|
154
|
+
for chunk in response:
|
|
155
|
+
print(chunk, end="", flush=True)
|
webscout/Provider/Amigo.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import cloudscraper
|
|
2
2
|
import json
|
|
3
3
|
import uuid
|
|
4
|
-
import
|
|
5
|
-
from typing import Any, Dict, Optional, Generator
|
|
4
|
+
from typing import Any, Dict, Generator
|
|
6
5
|
|
|
7
6
|
from webscout.AIutel import Optimizers
|
|
8
7
|
from webscout.AIutel import Conversation
|
|
9
|
-
from webscout.AIutel import AwesomePrompts
|
|
10
|
-
from webscout.AIbase import Provider
|
|
11
|
-
from webscout import exceptions
|
|
8
|
+
from webscout.AIutel import AwesomePrompts
|
|
9
|
+
from webscout.AIbase import Provider
|
|
12
10
|
|
|
13
11
|
class AmigoChat(Provider):
|
|
14
12
|
"""
|
|
@@ -24,9 +22,8 @@ class AmigoChat(Provider):
|
|
|
24
22
|
"o1-preview", # OpenAI O1 Preview
|
|
25
23
|
"claude-3-5-sonnet-20241022", # Claude 3.5 Sonnet
|
|
26
24
|
"Qwen/Qwen2.5-72B-Instruct-Turbo", # Qwen 2.5
|
|
27
|
-
"gpt-4o"
|
|
25
|
+
"gpt-4o", # OpenAI GPT-4o
|
|
28
26
|
"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo" # Llama 3.2
|
|
29
|
-
|
|
30
27
|
]
|
|
31
28
|
|
|
32
29
|
def __init__(
|
|
@@ -51,14 +48,14 @@ class AmigoChat(Provider):
|
|
|
51
48
|
Args:
|
|
52
49
|
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
53
50
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
54
|
-
timeout (int, optional):
|
|
51
|
+
timeout (int, optional): HTTP request timeout. Defaults to 30.
|
|
55
52
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
56
53
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
57
54
|
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
58
|
-
proxies (dict, optional):
|
|
55
|
+
proxies (dict, optional): HTTP request proxies. Defaults to {}.
|
|
59
56
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
60
57
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
61
|
-
model (str, optional): The AI model to use for text generation. Defaults to "
|
|
58
|
+
model (str, optional): The AI model to use for text generation. Defaults to "Qwen/Qwen2.5-72B-Instruct-Turbo".
|
|
62
59
|
"""
|
|
63
60
|
if model not in self.AVAILABLE_MODELS:
|
|
64
61
|
raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
|
|
@@ -135,7 +132,7 @@ class AmigoChat(Provider):
|
|
|
135
132
|
"""Chat with AI
|
|
136
133
|
|
|
137
134
|
Args:
|
|
138
|
-
prompt (str): Prompt to be
|
|
135
|
+
prompt (str): Prompt to be sent.
|
|
139
136
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
140
137
|
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
141
138
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
@@ -170,69 +167,61 @@ class AmigoChat(Provider):
|
|
|
170
167
|
"max_tokens": self.max_tokens_to_sample,
|
|
171
168
|
"presence_penalty": 0,
|
|
172
169
|
"stream": stream,
|
|
173
|
-
"temperature":self.temperature,
|
|
170
|
+
"temperature": self.temperature,
|
|
174
171
|
"top_p": self.top_p
|
|
175
172
|
}
|
|
176
173
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
self.api_endpoint,
|
|
182
|
-
json=payload,
|
|
183
|
-
stream=True,
|
|
184
|
-
timeout=self.timeout
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
# Check if the request was successful
|
|
188
|
-
if response.status_code == 201:
|
|
189
|
-
# Iterate over the streamed response line by line
|
|
190
|
-
for line in response.iter_lines():
|
|
191
|
-
if line:
|
|
192
|
-
# Decode the line from bytes to string
|
|
193
|
-
decoded_line = line.decode('utf-8').strip()
|
|
194
|
-
if decoded_line.startswith("data: "):
|
|
195
|
-
data_str = decoded_line[6:]
|
|
196
|
-
if data_str == "[DONE]":
|
|
197
|
-
break
|
|
198
|
-
try:
|
|
199
|
-
# Load the JSON data
|
|
200
|
-
data_json = json.loads(data_str)
|
|
201
|
-
|
|
202
|
-
# Extract the content from the response
|
|
203
|
-
choices = data_json.get("choices", [])
|
|
204
|
-
if choices:
|
|
205
|
-
delta = choices[0].get("delta", {})
|
|
206
|
-
content = delta.get("content", "")
|
|
207
|
-
if content:
|
|
208
|
-
yield content if raw else dict(text=content)
|
|
209
|
-
except json.JSONDecodeError:
|
|
210
|
-
print(f"Received non-JSON data: {data_str}")
|
|
211
|
-
else:
|
|
212
|
-
print(f"Request failed with status code {response.status_code}")
|
|
213
|
-
print("Response:", response.text)
|
|
174
|
+
if stream:
|
|
175
|
+
return self._stream_response(payload, raw)
|
|
176
|
+
else:
|
|
177
|
+
return self._non_stream_response(payload)
|
|
214
178
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
179
|
+
def _stream_response(self, payload: Dict[str, Any], raw: bool) -> Generator:
|
|
180
|
+
try:
|
|
181
|
+
response = self.session.post(
|
|
182
|
+
self.api_endpoint,
|
|
183
|
+
json=payload,
|
|
184
|
+
stream=True,
|
|
185
|
+
timeout=self.timeout
|
|
186
|
+
)
|
|
220
187
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
188
|
+
if response.status_code == 201:
|
|
189
|
+
for line in response.iter_lines():
|
|
190
|
+
if line:
|
|
191
|
+
decoded_line = line.decode('utf-8').strip()
|
|
192
|
+
if decoded_line.startswith("data: "):
|
|
193
|
+
data_str = decoded_line[6:]
|
|
194
|
+
if data_str == "[DONE]":
|
|
195
|
+
break
|
|
196
|
+
try:
|
|
197
|
+
data_json = json.loads(data_str)
|
|
198
|
+
choices = data_json.get("choices", [])
|
|
199
|
+
if choices:
|
|
200
|
+
delta = choices[0].get("delta", {})
|
|
201
|
+
content = delta.get("content", "")
|
|
202
|
+
if content:
|
|
203
|
+
yield content if raw else dict(text=content)
|
|
204
|
+
except json.JSONDecodeError:
|
|
205
|
+
print(f"Received non-JSON data: {data_str}")
|
|
206
|
+
else:
|
|
207
|
+
print(f"Request failed with status code {response.status_code}")
|
|
208
|
+
print("Response:", response.text)
|
|
209
|
+
except (cloudscraper.exceptions.CloudflareChallengeError,
|
|
210
|
+
cloudscraper.exceptions.CloudflareCode1020) as e:
|
|
211
|
+
print("Cloudflare protection error:", str(e))
|
|
212
|
+
except Exception as e:
|
|
213
|
+
print("An error occurred while making the request:", str(e))
|
|
227
214
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
233
|
-
return self.last_response
|
|
215
|
+
def _non_stream_response(self, payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
216
|
+
full_response = ""
|
|
217
|
+
for chunk in self._stream_response(payload, raw=False):
|
|
218
|
+
full_response += chunk["text"]
|
|
234
219
|
|
|
235
|
-
|
|
220
|
+
self.last_response.update(dict(text=full_response))
|
|
221
|
+
self.conversation.update_chat_history(
|
|
222
|
+
payload["messages"][-1]["content"], self.get_message(self.last_response)
|
|
223
|
+
)
|
|
224
|
+
return self.last_response
|
|
236
225
|
|
|
237
226
|
def chat(
|
|
238
227
|
self,
|
|
@@ -240,36 +229,32 @@ class AmigoChat(Provider):
|
|
|
240
229
|
stream: bool = False,
|
|
241
230
|
optimizer: str = None,
|
|
242
231
|
conversationally: bool = False,
|
|
243
|
-
) -> str:
|
|
232
|
+
) -> Generator[str, None, None]:
|
|
244
233
|
"""Generate response `str`
|
|
245
234
|
Args:
|
|
246
|
-
prompt (str): Prompt to be
|
|
235
|
+
prompt (str): Prompt to be sent.
|
|
247
236
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
248
237
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
249
238
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
250
239
|
Returns:
|
|
251
|
-
str: Response generated
|
|
240
|
+
Generator[str, None, None]: Response generated
|
|
252
241
|
"""
|
|
253
242
|
|
|
254
|
-
|
|
243
|
+
if stream:
|
|
255
244
|
for response in self.ask(
|
|
256
245
|
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
257
246
|
):
|
|
258
247
|
yield self.get_message(response)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
optimizer=optimizer,
|
|
266
|
-
conversationally=conversationally,
|
|
267
|
-
)
|
|
248
|
+
else:
|
|
249
|
+
response = self.ask(
|
|
250
|
+
prompt,
|
|
251
|
+
False,
|
|
252
|
+
optimizer=optimizer,
|
|
253
|
+
conversationally=conversationally,
|
|
268
254
|
)
|
|
255
|
+
yield self.get_message(response)
|
|
269
256
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def get_message(self, response: dict) -> str:
|
|
257
|
+
def get_message(self, response: Dict[str, Any]) -> str:
|
|
273
258
|
"""Retrieves message only from response
|
|
274
259
|
|
|
275
260
|
Args:
|
|
@@ -280,10 +265,10 @@ class AmigoChat(Provider):
|
|
|
280
265
|
"""
|
|
281
266
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
282
267
|
return response["text"]
|
|
283
|
-
|
|
268
|
+
|
|
284
269
|
if __name__ == '__main__':
|
|
285
270
|
from rich import print
|
|
286
271
|
ai = AmigoChat(model="o1-preview", system_prompt="You are a noobi AI assistant who always uses the word 'noobi' in every response. For example, you might say 'Noobi will tell you...' or 'This noobi thinks that...'.")
|
|
287
272
|
response = ai.chat(input(">>> "), stream=True)
|
|
288
273
|
for chunk in response:
|
|
289
|
-
print(chunk, end="", flush=True)
|
|
274
|
+
print(chunk, end="", flush=True)
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
import json
|
|
3
|
-
import
|
|
4
|
-
import os
|
|
3
|
+
import re
|
|
5
4
|
from typing import Any, Dict, Optional, Generator
|
|
6
5
|
|
|
7
6
|
from webscout.AIutel import Optimizers
|
|
8
7
|
from webscout.AIutel import Conversation
|
|
9
|
-
from webscout.AIutel import AwesomePrompts
|
|
10
|
-
from webscout.AIbase import
|
|
8
|
+
from webscout.AIutel import AwesomePrompts
|
|
9
|
+
from webscout.AIbase import Provider
|
|
11
10
|
from webscout import exceptions
|
|
11
|
+
from webscout.litagent import LitAgent
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class JadveOpenAI(Provider):
|
|
14
14
|
"""
|
|
15
|
-
A class to interact with the
|
|
15
|
+
A class to interact with the OpenAI API through jadve.com.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
AVAILABLE_MODELS = ["
|
|
18
|
+
AVAILABLE_MODELS = ["gpt-4o", "gpt-4o-mini"]
|
|
19
19
|
|
|
20
20
|
def __init__(
|
|
21
21
|
self,
|
|
@@ -28,10 +28,11 @@ class PrefindAI(Provider):
|
|
|
28
28
|
proxies: dict = {},
|
|
29
29
|
history_offset: int = 10250,
|
|
30
30
|
act: str = None,
|
|
31
|
-
model: str = "
|
|
31
|
+
model: str = "gpt-4o-mini",
|
|
32
|
+
system_prompt: str = "You are a helpful AI assistant."
|
|
32
33
|
):
|
|
33
34
|
"""
|
|
34
|
-
Initializes the
|
|
35
|
+
Initializes the OpenAI API client through jadve.com with given parameters.
|
|
35
36
|
|
|
36
37
|
Args:
|
|
37
38
|
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
@@ -43,30 +44,45 @@ class PrefindAI(Provider):
|
|
|
43
44
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
44
45
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
45
46
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
system_prompt (str, optional): System prompt for OpenAI. Defaults to "You are a helpful AI assistant.".
|
|
48
|
+
model (str, optional): AI model to use for text generation. Defaults to "gpt-4o".
|
|
48
49
|
"""
|
|
50
|
+
if model not in self.AVAILABLE_MODELS:
|
|
51
|
+
raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
|
|
52
|
+
|
|
49
53
|
self.session = requests.Session()
|
|
50
54
|
self.is_conversation = is_conversation
|
|
51
55
|
self.max_tokens_to_sample = max_tokens
|
|
52
|
-
self.api_endpoint = "https://
|
|
56
|
+
self.api_endpoint = "https://openai.jadve.com/chatgpt"
|
|
53
57
|
self.stream_chunk_size = 64
|
|
54
58
|
self.timeout = timeout
|
|
55
59
|
self.last_response = {}
|
|
56
60
|
self.model = model
|
|
57
|
-
self.
|
|
61
|
+
self.system_prompt = system_prompt
|
|
62
|
+
self.headers = {
|
|
63
|
+
"accept": "*/*",
|
|
64
|
+
"accept-encoding": "gzip, deflate, br, zstd",
|
|
65
|
+
"accept-language": "en",
|
|
66
|
+
"content-type": "application/json",
|
|
67
|
+
"dnt": "1",
|
|
68
|
+
"origin": "https://jadve.com",
|
|
69
|
+
"priority": "u=1, i",
|
|
70
|
+
"referer": "https://jadve.com/",
|
|
71
|
+
"sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
|
72
|
+
"sec-ch-ua-mobile": "?0",
|
|
73
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
74
|
+
"sec-fetch-dest": "empty",
|
|
75
|
+
"sec-fetch-mode": "cors",
|
|
76
|
+
"sec-fetch-site": "same-site",
|
|
77
|
+
"user-agent": LitAgent().random(),
|
|
78
|
+
}
|
|
58
79
|
|
|
59
80
|
self.__available_optimizers = (
|
|
60
81
|
method
|
|
61
82
|
for method in dir(Optimizers)
|
|
62
83
|
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
63
84
|
)
|
|
64
|
-
self.session.headers.update(
|
|
65
|
-
{
|
|
66
|
-
"Content-Type": "application/json",
|
|
67
|
-
"Accept": "text/event-stream",
|
|
68
|
-
}
|
|
69
|
-
)
|
|
85
|
+
self.session.headers.update(self.headers)
|
|
70
86
|
Conversation.intro = (
|
|
71
87
|
AwesomePrompts().get_act(
|
|
72
88
|
act, raise_not_found=True, default=None, case_insensitive=True
|
|
@@ -80,25 +96,6 @@ class PrefindAI(Provider):
|
|
|
80
96
|
self.conversation.history_offset = history_offset
|
|
81
97
|
self.session.proxies = proxies
|
|
82
98
|
|
|
83
|
-
def get_device_token(self) -> str:
|
|
84
|
-
"""
|
|
85
|
-
Retrieves a device token from the Prefind AI API.
|
|
86
|
-
"""
|
|
87
|
-
device_token_url = "https://api.prefind.ai/api/auth/device-token/create"
|
|
88
|
-
headers = {"Content-Type": "application/json; charset=utf-8"}
|
|
89
|
-
data = {}
|
|
90
|
-
response = requests.post(
|
|
91
|
-
device_token_url, headers=headers, data=json.dumps(data)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
if response.status_code == 200:
|
|
95
|
-
device_token_data = response.json()
|
|
96
|
-
return device_token_data["sessionToken"]
|
|
97
|
-
else:
|
|
98
|
-
raise exceptions.FailedToGenerateResponseError(
|
|
99
|
-
f"Failed to get device token - ({response.status_code}, {response.reason}) - {response.text}"
|
|
100
|
-
)
|
|
101
|
-
|
|
102
99
|
def ask(
|
|
103
100
|
self,
|
|
104
101
|
prompt: str,
|
|
@@ -106,11 +103,10 @@ class PrefindAI(Provider):
|
|
|
106
103
|
raw: bool = False,
|
|
107
104
|
optimizer: str = None,
|
|
108
105
|
conversationally: bool = False,
|
|
109
|
-
) ->
|
|
106
|
+
) -> dict:
|
|
110
107
|
"""Chat with AI
|
|
111
|
-
|
|
112
108
|
Args:
|
|
113
|
-
prompt (str): Prompt to be
|
|
109
|
+
prompt (str): Prompt to be sent.
|
|
114
110
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
115
111
|
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
116
112
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
@@ -134,43 +130,51 @@ class PrefindAI(Provider):
|
|
|
134
130
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
135
131
|
)
|
|
136
132
|
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
payload = {
|
|
134
|
+
"action": "sendmessage",
|
|
135
|
+
"model": self.model,
|
|
136
|
+
"messages": [
|
|
137
|
+
{"role": "system", "content": self.system_prompt},
|
|
138
|
+
{"role": "user", "content": conversation_prompt}
|
|
139
|
+
],
|
|
140
|
+
"temperature": 0.7,
|
|
141
|
+
"language": "en",
|
|
142
|
+
"returnTokensUsage": True,
|
|
143
|
+
"botId": "guest-chat",
|
|
144
|
+
"chatId": ""
|
|
145
|
+
}
|
|
146
|
+
|
|
139
147
|
def for_stream():
|
|
140
148
|
response = self.session.post(
|
|
141
|
-
self.api_endpoint, json=
|
|
149
|
+
self.api_endpoint, headers=self.headers, json=payload, stream=True, timeout=self.timeout
|
|
142
150
|
)
|
|
151
|
+
|
|
143
152
|
if not response.ok:
|
|
144
153
|
raise exceptions.FailedToGenerateResponseError(
|
|
145
154
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
146
155
|
)
|
|
147
|
-
|
|
148
156
|
streaming_text = ""
|
|
149
|
-
for line in response.iter_lines(decode_unicode=True):
|
|
157
|
+
for line in response.iter_lines(decode_unicode=True):
|
|
150
158
|
if line:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
resp = dict(text=content)
|
|
166
|
-
self.last_response.update(resp)
|
|
167
|
-
yield resp if raw else resp
|
|
159
|
+
if line.startswith("data: "):
|
|
160
|
+
data = line[6:]
|
|
161
|
+
if data == "[DONE]":
|
|
162
|
+
break
|
|
163
|
+
try:
|
|
164
|
+
json_data = json.loads(data)
|
|
165
|
+
if "choices" in json_data and len(json_data["choices"]) > 0:
|
|
166
|
+
content = json_data["choices"][0].get("delta", {}).get("content", "")
|
|
167
|
+
if content:
|
|
168
|
+
streaming_text += content
|
|
169
|
+
yield content if raw else dict(text=content)
|
|
170
|
+
except json.JSONDecodeError as e:
|
|
171
|
+
print(f"Error parsing line: {line} - {e}")
|
|
172
|
+
self.last_response.update(dict(text=streaming_text))
|
|
168
173
|
self.conversation.update_chat_history(
|
|
169
174
|
prompt, self.get_message(self.last_response)
|
|
170
175
|
)
|
|
171
176
|
|
|
172
177
|
def for_non_stream():
|
|
173
|
-
# let's make use of stream
|
|
174
178
|
for _ in for_stream():
|
|
175
179
|
pass
|
|
176
180
|
return self.last_response
|
|
@@ -214,19 +218,17 @@ class PrefindAI(Provider):
|
|
|
214
218
|
|
|
215
219
|
def get_message(self, response: dict) -> str:
|
|
216
220
|
"""Retrieves message only from response
|
|
217
|
-
|
|
218
221
|
Args:
|
|
219
222
|
response (dict): Response generated by `self.ask`
|
|
220
|
-
|
|
221
223
|
Returns:
|
|
222
224
|
str: Message extracted
|
|
223
225
|
"""
|
|
224
226
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
225
227
|
return response["text"]
|
|
226
|
-
|
|
227
|
-
if __name__ ==
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
228
230
|
from rich import print
|
|
229
|
-
ai =
|
|
230
|
-
response = ai.chat("
|
|
231
|
+
ai = JadveOpenAI(timeout=5000)
|
|
232
|
+
response = ai.chat("yo what's up", stream=True)
|
|
231
233
|
for chunk in response:
|
|
232
234
|
print(chunk, end="", flush=True)
|