webscout 7.9__py3-none-any.whl → 8.1__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.

Files changed (69) hide show
  1. webscout/Extra/GitToolkit/__init__.py +10 -0
  2. webscout/Extra/GitToolkit/gitapi/__init__.py +12 -0
  3. webscout/Extra/GitToolkit/gitapi/repository.py +195 -0
  4. webscout/Extra/GitToolkit/gitapi/user.py +96 -0
  5. webscout/Extra/GitToolkit/gitapi/utils.py +62 -0
  6. webscout/Extra/YTToolkit/ytapi/video.py +232 -103
  7. webscout/Provider/AISEARCH/DeepFind.py +1 -1
  8. webscout/Provider/AISEARCH/ISou.py +1 -1
  9. webscout/Provider/AISEARCH/__init__.py +6 -1
  10. webscout/Provider/AISEARCH/felo_search.py +1 -1
  11. webscout/Provider/AISEARCH/genspark_search.py +1 -1
  12. webscout/Provider/AISEARCH/hika_search.py +194 -0
  13. webscout/Provider/AISEARCH/iask_search.py +436 -0
  14. webscout/Provider/AISEARCH/monica_search.py +246 -0
  15. webscout/Provider/AISEARCH/scira_search.py +320 -0
  16. webscout/Provider/AISEARCH/webpilotai_search.py +281 -0
  17. webscout/Provider/AllenAI.py +255 -122
  18. webscout/Provider/DeepSeek.py +1 -2
  19. webscout/Provider/Deepinfra.py +17 -9
  20. webscout/Provider/ExaAI.py +261 -0
  21. webscout/Provider/ExaChat.py +8 -1
  22. webscout/Provider/GithubChat.py +2 -1
  23. webscout/Provider/Jadve.py +2 -2
  24. webscout/Provider/Netwrck.py +3 -2
  25. webscout/Provider/OPENAI/__init__.py +17 -0
  26. webscout/Provider/OPENAI/base.py +46 -0
  27. webscout/Provider/OPENAI/c4ai.py +347 -0
  28. webscout/Provider/OPENAI/chatgptclone.py +460 -0
  29. webscout/Provider/OPENAI/deepinfra.py +284 -0
  30. webscout/Provider/OPENAI/exaai.py +419 -0
  31. webscout/Provider/OPENAI/exachat.py +421 -0
  32. webscout/Provider/OPENAI/freeaichat.py +355 -0
  33. webscout/Provider/OPENAI/glider.py +314 -0
  34. webscout/Provider/OPENAI/heckai.py +337 -0
  35. webscout/Provider/OPENAI/llmchatco.py +325 -0
  36. webscout/Provider/OPENAI/netwrck.py +348 -0
  37. webscout/Provider/OPENAI/scirachat.py +459 -0
  38. webscout/Provider/OPENAI/sonus.py +294 -0
  39. webscout/Provider/OPENAI/typegpt.py +361 -0
  40. webscout/Provider/OPENAI/utils.py +211 -0
  41. webscout/Provider/OPENAI/venice.py +428 -0
  42. webscout/Provider/OPENAI/wisecat.py +381 -0
  43. webscout/Provider/OPENAI/x0gpt.py +389 -0
  44. webscout/Provider/OPENAI/yep.py +329 -0
  45. webscout/Provider/OpenGPT.py +199 -0
  46. webscout/Provider/PI.py +39 -24
  47. webscout/Provider/Venice.py +1 -1
  48. webscout/Provider/Youchat.py +326 -296
  49. webscout/Provider/__init__.py +16 -6
  50. webscout/Provider/ai4chat.py +58 -56
  51. webscout/Provider/akashgpt.py +34 -22
  52. webscout/Provider/freeaichat.py +1 -1
  53. webscout/Provider/labyrinth.py +121 -20
  54. webscout/Provider/llmchatco.py +306 -0
  55. webscout/Provider/scira_chat.py +274 -0
  56. webscout/Provider/typefully.py +280 -0
  57. webscout/Provider/typegpt.py +3 -184
  58. webscout/prompt_manager.py +2 -1
  59. webscout/version.py +1 -1
  60. webscout/webscout_search.py +118 -54
  61. webscout/webscout_search_async.py +109 -45
  62. webscout-8.1.dist-info/METADATA +683 -0
  63. {webscout-7.9.dist-info → webscout-8.1.dist-info}/RECORD +67 -33
  64. webscout/Provider/flowith.py +0 -207
  65. webscout-7.9.dist-info/METADATA +0 -995
  66. {webscout-7.9.dist-info → webscout-8.1.dist-info}/LICENSE.md +0 -0
  67. {webscout-7.9.dist-info → webscout-8.1.dist-info}/WHEEL +0 -0
  68. {webscout-7.9.dist-info → webscout-8.1.dist-info}/entry_points.txt +0 -0
  69. {webscout-7.9.dist-info → webscout-8.1.dist-info}/top_level.txt +0 -0
@@ -9,12 +9,13 @@ from .Openai import OPENAI
9
9
  from .Openai import AsyncOPENAI
10
10
  from .Koboldai import KOBOLDAI
11
11
  from .Koboldai import AsyncKOBOLDAI
12
- from .Blackboxai import BLACKBOXAI
13
- from .Phind import PhindSearch
12
+ from .Blackboxai import BLACKBOXAI
13
+ from .Phind import PhindSearch
14
14
  from .Phind import Phindv2
15
15
  from .ai4chat import *
16
16
  from .Gemini import GEMINI
17
17
  from .Deepinfra import DeepInfra
18
+ from .typefully import *
18
19
  from .cleeai import *
19
20
  from .OLLAMA import OLLAMA
20
21
  from .Andi import AndiSearch
@@ -47,6 +48,7 @@ from .aimathgpt import *
47
48
  from .gaurish import *
48
49
  from .geminiprorealtime import *
49
50
  from .llmchat import *
51
+ from .llmchatco import LLMChatCo # Add new LLMChat.co provider
50
52
  from .talkai import *
51
53
  from .askmyai import *
52
54
  from .llama3mitril import *
@@ -75,7 +77,6 @@ from .HuggingFaceChat import *
75
77
  from .GithubChat import *
76
78
  from .copilot import *
77
79
  from .C4ai import *
78
- from .flowith import *
79
80
  from .sonus import *
80
81
  from .uncovr import *
81
82
  from .labyrinth import *
@@ -87,12 +88,19 @@ from .ExaChat import *
87
88
  from .asksteve import *
88
89
  from .Aitopia import *
89
90
  from .searchchat import *
91
+ from .ExaAI import ExaAI
92
+ from .OpenGPT import OpenGPT
93
+ from .scira_chat import *
94
+ from .AISEARCH.iask_search import IAsk
90
95
  __all__ = [
91
96
  'LLAMA',
97
+ 'IAsk',
98
+ 'SciraAI',
92
99
  'LabyrinthAI',
93
- 'Flowith',
100
+ 'OpenGPT',
94
101
  'C4ai',
95
102
  'Venice',
103
+ 'ExaAI',
96
104
  'Copilot',
97
105
  'HuggingFaceChat',
98
106
  'TwoAI',
@@ -116,8 +124,8 @@ __all__ = [
116
124
  'AsyncOPENAI',
117
125
  'KOBOLDAI',
118
126
  'AsyncKOBOLDAI',
119
- 'BLACKBOXAI',
120
- 'PhindSearch',
127
+ 'BLACKBOXAI',
128
+ 'PhindSearch',
121
129
  'GEMINI',
122
130
  'DeepInfra',
123
131
  'AI4Chat',
@@ -146,6 +154,7 @@ __all__ = [
146
154
  'Cleeai',
147
155
  'Elmo',
148
156
  'ChatGPTClone',
157
+ 'TypefullyAI',
149
158
  'Free2GPT',
150
159
  'GPTWeb',
151
160
  'Netwrck',
@@ -158,6 +167,7 @@ __all__ = [
158
167
  'GaurishCerebras',
159
168
  'GeminiPro',
160
169
  'LLMChat',
170
+ 'LLMChatCo',
161
171
  'Talkai',
162
172
  'Llama3Mitril',
163
173
  'Marcus',
@@ -1,7 +1,5 @@
1
1
  import requests
2
- import json
3
- import html
4
- import re
2
+ import urllib.parse
5
3
  from typing import Union, Any, Dict
6
4
 
7
5
  from webscout.AIutel import Optimizers
@@ -11,7 +9,7 @@ from webscout.AIbase import Provider
11
9
 
12
10
  class AI4Chat(Provider):
13
11
  """
14
- A class to interact with the AI4Chat API.
12
+ A class to interact with the AI4Chat Riddle API.
15
13
  """
16
14
 
17
15
  def __init__(
@@ -26,6 +24,8 @@ class AI4Chat(Provider):
26
24
  history_offset: int = 10250,
27
25
  act: str = None,
28
26
  system_prompt: str = "You are a helpful and informative AI assistant.",
27
+ country: str = "Asia",
28
+ user_id: str = "usersmjb2oaz7y"
29
29
  ) -> None:
30
30
  """
31
31
  Initializes the AI4Chat API with given parameters.
@@ -41,34 +41,30 @@ class AI4Chat(Provider):
41
41
  history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
42
42
  act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
43
43
  system_prompt (str, optional): System prompt to guide the AI's behavior. Defaults to "You are a helpful and informative AI assistant.".
44
+ country (str, optional): Country parameter for API. Defaults to "Asia".
45
+ user_id (str, optional): User ID for API. Defaults to "usersmjb2oaz7y".
44
46
  """
45
47
  self.session = requests.Session()
46
48
  self.is_conversation = is_conversation
47
49
  self.max_tokens_to_sample = max_tokens
48
- self.api_endpoint = "https://www.ai4chat.co/generate-response"
50
+ self.api_endpoint = "https://yw85opafq6.execute-api.us-east-1.amazonaws.com/default/boss_mode_15aug"
49
51
  self.timeout = timeout
50
52
  self.last_response = {}
53
+ self.country = country
54
+ self.user_id = user_id
51
55
  self.headers = {
52
- "authority": "www.ai4chat.co",
53
- "method": "POST",
54
- "path": "/generate-response",
55
- "scheme": "https",
56
- "accept": "*/*",
57
- "accept-encoding": "gzip, deflate, br, zstd",
58
- "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
59
- "content-type": "application/json",
60
- "cookie": "messageCount=1",
61
- "dnt": "1",
62
- "origin": "https://www.ai4chat.co",
63
- "priority": "u=1, i",
64
- "referer": "https://www.ai4chat.co/gpt/talkdirtytome",
65
- "sec-ch-ua": '"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"',
66
- "sec-ch-ua-mobile": "?0",
67
- "sec-ch-ua-platform": '"Windows"',
68
- "sec-fetch-dest": "empty",
69
- "sec-fetch-mode": "cors",
70
- "sec-fetch-site": "same-origin",
71
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0"
56
+ "Accept": "*/*",
57
+ "Accept-Language": "id-ID,id;q=0.9",
58
+ "Origin": "https://www.ai4chat.co",
59
+ "Priority": "u=1, i",
60
+ "Referer": "https://www.ai4chat.co/",
61
+ "Sec-CH-UA": '"Chromium";v="131", "Not_A Brand";v="24", "Microsoft Edge Simulate";v="131", "Lemur";v="131"',
62
+ "Sec-CH-UA-Mobile": "?1",
63
+ "Sec-CH-UA-Platform": '"Android"',
64
+ "Sec-Fetch-Dest": "empty",
65
+ "Sec-Fetch-Mode": "cors",
66
+ "Sec-Fetch-Site": "cross-site",
67
+ "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36"
72
68
  }
73
69
 
74
70
  self.__available_optimizers = (
@@ -98,16 +94,20 @@ class AI4Chat(Provider):
98
94
  raw: bool = False,
99
95
  optimizer: str = None,
100
96
  conversationally: bool = False,
97
+ country: str = None,
98
+ user_id: str = None,
101
99
  ) -> Dict[str, Any]:
102
100
  """
103
101
  Sends a prompt to the AI4Chat API and returns the response.
104
102
 
105
103
  Args:
106
104
  prompt: The text prompt to generate text from.
107
- stream (bool, optional): Not used (AI4Chat doesn't support streaming).
105
+ stream (bool, optional): Not supported. Defaults to False.
108
106
  raw (bool, optional): Whether to return the raw response. Defaults to False.
109
107
  optimizer (str, optional): The name of the optimizer to use. Defaults to None.
110
108
  conversationally (bool, optional): Whether to chat conversationally. Defaults to False.
109
+ country (str, optional): Country parameter for API. Defaults to None.
110
+ user_id (str, optional): User ID for API. Defaults to None.
111
111
 
112
112
  Returns:
113
113
  dict: A dictionary containing the AI's response.
@@ -123,51 +123,52 @@ class AI4Chat(Provider):
123
123
  f"Optimizer is not one of {self.__available_optimizers}"
124
124
  )
125
125
 
126
- payload = {
127
- "messages": [
128
- {"role": "system", "content": self.system_prompt},
129
- {"role": "user", "content": conversation_prompt}
130
- ]
131
- }
132
-
133
- response = self.session.post(self.api_endpoint, headers=self.headers, json=payload, timeout=self.timeout)
126
+ # Use provided values or defaults
127
+ country_param = country or self.country
128
+ user_id_param = user_id or self.user_id
129
+
130
+ # Build the URL with parameters
131
+ encoded_text = urllib.parse.quote(conversation_prompt)
132
+ encoded_country = urllib.parse.quote(country_param)
133
+ encoded_user_id = urllib.parse.quote(user_id_param)
134
+
135
+ url = f"{self.api_endpoint}?text={encoded_text}&country={encoded_country}&user_id={encoded_user_id}"
136
+
137
+ response = self.session.get(url, headers=self.headers, timeout=self.timeout)
134
138
  if not response.ok:
135
139
  raise Exception(f"Failed to generate response: {response.status_code} - {response.reason}")
136
140
 
137
- response_data = response.json()
138
- message_content = response_data.get('message', 'No message found')
139
-
140
- # Decode HTML entities
141
- decoded_message = html.unescape(message_content)
142
-
143
- # Remove HTML tags while preserving newlines and list structure
144
- cleaned_text = re.sub(r'<p>(.*?)</p>', r'\1\n\n', decoded_message)
145
- cleaned_text = re.sub(r'<ol>|</ol>', '', cleaned_text)
146
- cleaned_text = re.sub(r'<li><p>(.*?)</p></li>', r'• \1\n', cleaned_text)
147
- cleaned_text = re.sub(r'</?[^>]+>', '', cleaned_text)
141
+ response_text = response.text
148
142
 
149
- # Remove extra newlines
150
- cleaned_text = re.sub(r'\n{3,}', '\n\n', cleaned_text.strip())
151
-
152
- self.last_response.update(dict(text=cleaned_text))
153
- self.conversation.update_chat_history(prompt, cleaned_text)
143
+ # Remove quotes from the start and end of the response
144
+ if response_text.startswith('"'):
145
+ response_text = response_text[1:]
146
+ if response_text.endswith('"'):
147
+ response_text = response_text[:-1]
148
+
149
+ self.last_response.update(dict(text=response_text))
150
+ self.conversation.update_chat_history(prompt, response_text)
154
151
  return self.last_response
155
152
 
156
153
  def chat(
157
154
  self,
158
155
  prompt: str,
159
- stream: bool = False, # Streaming is not supported by AI4Chat
156
+ stream: bool = False,
160
157
  optimizer: str = None,
161
158
  conversationally: bool = False,
159
+ country: str = None,
160
+ user_id: str = None,
162
161
  ) -> str:
163
162
  """
164
163
  Generates a response from the AI4Chat API.
165
164
 
166
165
  Args:
167
166
  prompt (str): The prompt to send to the AI.
168
- stream (bool, optional): Not used (AI4Chat doesn't support streaming).
167
+ stream (bool, optional): Not supported.
169
168
  optimizer (str, optional): The name of the optimizer to use. Defaults to None.
170
169
  conversationally (bool, optional): Whether to chat conversationally. Defaults to False.
170
+ country (str, optional): Country parameter for API. Defaults to None.
171
+ user_id (str, optional): User ID for API. Defaults to None.
171
172
 
172
173
  Returns:
173
174
  str: The response generated by the AI.
@@ -177,6 +178,8 @@ class AI4Chat(Provider):
177
178
  prompt,
178
179
  optimizer=optimizer,
179
180
  conversationally=conversationally,
181
+ country=country,
182
+ user_id=user_id,
180
183
  )
181
184
  )
182
185
 
@@ -190,11 +193,10 @@ class AI4Chat(Provider):
190
193
  str: Message extracted
191
194
  """
192
195
  assert isinstance(response, dict), "Response should be of dict data-type only"
193
- return response["text"]
196
+ return response["text"].replace('\\n', '\n').replace('\\n\\n', '\n\n')
194
197
 
195
198
  if __name__ == "__main__":
196
199
  from rich import print
197
200
  ai = AI4Chat()
198
- response = ai.chat("write me poem about AI", stream=True)
199
- for chunk in response:
200
- print(chunk, end="", flush=True)
201
+ response = ai.chat("Tell me something interesting")
202
+ print(response)
@@ -1,6 +1,6 @@
1
1
  from typing import Union, Any, Dict, Generator
2
2
  from uuid import uuid4
3
- import requests
3
+ import cloudscraper
4
4
  import re
5
5
  import json
6
6
  import time
@@ -29,16 +29,18 @@ class AkashGPT(Provider):
29
29
  """
30
30
 
31
31
  AVAILABLE_MODELS = [
32
- "Meta-Llama-3-3-70B-Instruct",
33
- "DeepSeek-R1",
34
- "Meta-Llama-3-1-405B-Instruct-FP8",
35
- # "Meta-Llama-3-2-3B-Instruct",
36
- # "Meta-Llama-3-1-8B-Instruct-FP8",
32
+ "meta-llama-3-3-70b-instruct",
33
+ "deepseek-r1",
34
+ "meta-llama-3-1-405b-instruct-fp8",
35
+ "meta-llama-llama-4-maverick-17b-128e-instruct-fp8",
36
+ "nvidia-llama-3-3-nemotron-super-49b-v1",
37
+
38
+ # "meta-llama-3-2-3b-instruct",
39
+ # "meta-llama-3-1-8b-instruct-fp8",
37
40
  # "mistral",
38
- # "nous-hermes2-mixtral",
41
+ # "nous-hermes2-mixtral",
39
42
  # "dolphin-mixtral",
40
- "Qwen-QwQ-32B"
41
-
43
+ "qwen-qwq-32b"
42
44
  ]
43
45
 
44
46
  def __init__(
@@ -53,7 +55,7 @@ class AkashGPT(Provider):
53
55
  history_offset: int = 10250,
54
56
  act: str = None,
55
57
  system_prompt: str = "You are a helpful assistant.",
56
- model: str = "Meta-Llama-3-3-70B-Instruct",
58
+ model: str = "meta-llama-3-3-70b-instruct",
57
59
  temperature: float = 0.6,
58
60
  top_p: float = 0.9,
59
61
  session_token: str = None
@@ -81,7 +83,7 @@ class AkashGPT(Provider):
81
83
  if model not in self.AVAILABLE_MODELS:
82
84
  raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
83
85
 
84
- self.session = requests.Session()
86
+ self.session = cloudscraper.create_scraper()
85
87
  self.is_conversation = is_conversation
86
88
  self.max_tokens_to_sample = max_tokens
87
89
  self.api_endpoint = "https://chat.akash.network/api/chat"
@@ -107,17 +109,20 @@ class AkashGPT(Provider):
107
109
  "scheme": "https",
108
110
  "accept": "*/*",
109
111
  "accept-encoding": "gzip, deflate, br, zstd",
110
- "accept-language": "en-US,en;q=0.9",
112
+ "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
111
113
  "content-type": "application/json",
112
114
  "dnt": "1",
113
115
  "origin": "https://chat.akash.network",
114
116
  "priority": "u=1, i",
115
117
  "referer": "https://chat.akash.network/",
116
- "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
118
+ "sec-ch-ua": '"Microsoft Edge";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
117
119
  "sec-ch-ua-mobile": "?0",
118
120
  "sec-ch-ua-platform": '"Windows"',
121
+ "sec-fetch-dest": "empty",
122
+ "sec-fetch-mode": "cors",
123
+ "sec-fetch-site": "same-origin",
124
+ "sec-gpc": "1",
119
125
  "user-agent": self.agent.random()
120
-
121
126
  }
122
127
 
123
128
  # Set cookies with the session token
@@ -181,15 +186,15 @@ class AkashGPT(Provider):
181
186
  )
182
187
 
183
188
  payload = {
184
- "id": str(uuid4()), # Generate a unique request ID
189
+ "id": str(uuid4()).replace("-", ""), # Generate a unique request ID in the correct format
185
190
  "messages": [
186
- {"role": "system", "content": self.system_prompt},
187
191
  {"role": "user", "content": conversation_prompt}
188
192
  ],
189
193
  "model": self.model,
190
- "temperature": self.temperature,
191
194
  "system": self.system_prompt,
192
- "topP": self.top_p
195
+ "temperature": self.temperature,
196
+ "topP": self.top_p,
197
+ "context": []
193
198
  }
194
199
 
195
200
  def for_stream():
@@ -218,17 +223,24 @@ class AkashGPT(Provider):
218
223
  # Parse content chunks
219
224
  if line.startswith('0:'):
220
225
  try:
221
- # Extract content between quotes
222
- content = line[2:].strip('"')
226
+ content = line[2:]
227
+ # Remove surrounding quotes if they exist
223
228
  if content.startswith('"') and content.endswith('"'):
224
229
  content = content[1:-1]
225
230
  streaming_response += content
226
231
  yield content if raw else dict(text=content)
227
- except Exception:
232
+ except Exception as e:
228
233
  continue
229
234
 
230
- # End of stream
235
+ # End of stream markers
231
236
  if line.startswith('e:') or line.startswith('d:'):
237
+ try:
238
+ finish_data = json.loads(line[2:])
239
+ finish_reason = finish_data.get("finishReason", "stop")
240
+ # Could store usage data if needed:
241
+ # usage = finish_data.get("usage", {})
242
+ except json.JSONDecodeError:
243
+ pass
232
244
  break
233
245
 
234
246
  self.last_response.update(dict(text=streaming_response, message_id=message_id))
@@ -43,8 +43,8 @@ class FreeAIChat(Provider):
43
43
  # Google Models
44
44
  "Gemini 1.5 Flash",
45
45
  "Gemini 1.5 Pro",
46
- "Gemini 2.0 Pro",
47
46
  "Gemini 2.0 Flash",
47
+ "Gemini 2.0 Pro",
48
48
  "Gemini 2.5 Pro",
49
49
 
50
50
  # Llama Models
@@ -1,7 +1,9 @@
1
+ from typing import Union, Any, Dict, Generator
2
+ from uuid import uuid4
1
3
  import requests
4
+ import re
2
5
  import json
3
- import uuid
4
- from typing import Any, Dict, Optional, Generator, Union
6
+
5
7
  from webscout.AIutel import Optimizers
6
8
  from webscout.AIutel import Conversation
7
9
  from webscout.AIutel import AwesomePrompts
@@ -12,6 +14,16 @@ from webscout.litagent import LitAgent
12
14
  class LabyrinthAI(Provider):
13
15
  """
14
16
  A class to interact with the Labyrinth AI chat API.
17
+
18
+ Attributes:
19
+ system_prompt (str): The system prompt to define the assistant's role.
20
+
21
+ Examples:
22
+ >>> from webscout.Provider.labyrinth import LabyrinthAI
23
+ >>> ai = LabyrinthAI()
24
+ >>> response = ai.chat("What's the weather today?")
25
+ >>> print(response)
26
+ 'The weather today is sunny with a high of 75°F.'
15
27
  """
16
28
 
17
29
  # AVAILABLE_MODELS = [
@@ -29,20 +41,42 @@ class LabyrinthAI(Provider):
29
41
  proxies: dict = {},
30
42
  history_offset: int = 10250,
31
43
  act: str = None,
44
+ system_prompt: str = "You are a helpful assistant.",
32
45
  # model: str = "gemini-2.0-flash",
33
46
  browser: str = "chrome"
34
47
  ):
35
- """Initializes the Labyrinth AI API client."""
48
+ """
49
+ Initializes the Labyrinth AI API with given parameters.
50
+
51
+ Args:
52
+ is_conversation (bool): Whether the provider is in conversation mode.
53
+ max_tokens (int): Maximum number of tokens to sample.
54
+ timeout (int): Timeout for API requests.
55
+ intro (str): Introduction message for the conversation.
56
+ filepath (str): Filepath for storing conversation history.
57
+ update_file (bool): Whether to update the conversation history file.
58
+ proxies (dict): Proxies for the API requests.
59
+ history_offset (int): Offset for conversation history.
60
+ act (str): Act for the conversation.
61
+ system_prompt (str): The system prompt to define the assistant's role.
62
+ browser (str): Browser type to emulate in the user agent.
63
+
64
+ Examples:
65
+ >>> ai = LabyrinthAI(system_prompt="You are a friendly assistant.")
66
+ >>> print(ai.system_prompt)
67
+ 'You are a friendly assistant.'
68
+ """
36
69
  # if model not in self.AVAILABLE_MODELS:
37
70
  # raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
38
-
71
+
39
72
  self.url = "https://labyrinth-ebon.vercel.app/api/chat"
40
-
73
+ self.system_prompt = system_prompt
74
+
41
75
  # Initialize LitAgent for user agent generation
42
76
  self.agent = LitAgent()
43
77
  # Use fingerprinting to create a consistent browser identity
44
78
  self.fingerprint = self.agent.generate_fingerprint(browser)
45
-
79
+
46
80
  # Use the fingerprint for headers
47
81
  self.headers = {
48
82
  "Accept": self.fingerprint["accept"],
@@ -61,7 +95,7 @@ class LabyrinthAI(Provider):
61
95
  "Sec-Fetch-Site": "same-origin",
62
96
  "Sec-GPC": "1"
63
97
  }
64
-
98
+
65
99
  self.session = requests.Session()
66
100
  self.session.headers.update(self.headers)
67
101
  self.session.proxies.update(proxies)
@@ -93,13 +127,13 @@ class LabyrinthAI(Provider):
93
127
  def refresh_identity(self, browser: str = None):
94
128
  """
95
129
  Refreshes the browser identity fingerprint.
96
-
130
+
97
131
  Args:
98
132
  browser: Specific browser to use for the new fingerprint
99
133
  """
100
134
  browser = browser or self.fingerprint.get("browser_type", "chrome")
101
135
  self.fingerprint = self.agent.generate_fingerprint(browser)
102
-
136
+
103
137
  # Update headers with new fingerprint
104
138
  self.headers.update({
105
139
  "Accept": self.fingerprint["accept"],
@@ -108,11 +142,11 @@ class LabyrinthAI(Provider):
108
142
  "Sec-CH-UA-Platform": f'"{self.fingerprint["platform"]}"',
109
143
  "User-Agent": self.fingerprint["user_agent"],
110
144
  })
111
-
145
+
112
146
  # Update session headers
113
147
  for header, value in self.headers.items():
114
148
  self.session.headers[header] = value
115
-
149
+
116
150
  return self.fingerprint
117
151
 
118
152
  def ask(
@@ -123,6 +157,25 @@ class LabyrinthAI(Provider):
123
157
  optimizer: str = None,
124
158
  conversationally: bool = False,
125
159
  ) -> Union[Dict[str, Any], Generator]:
160
+ """
161
+ Sends a prompt to the Labyrinth AI API and returns the response.
162
+
163
+ Args:
164
+ prompt (str): The prompt to send to the API.
165
+ stream (bool): Whether to stream the response.
166
+ raw (bool): Whether to return the raw response.
167
+ optimizer (str): Optimizer to use for the prompt.
168
+ conversationally (bool): Whether to generate the prompt conversationally.
169
+
170
+ Returns:
171
+ Union[Dict[str, Any], Generator]: The API response.
172
+
173
+ Examples:
174
+ >>> ai = LabyrinthAI()
175
+ >>> response = ai.ask("Tell me a joke!")
176
+ >>> print(response)
177
+ {'text': 'Why did the scarecrow win an award? Because he was outstanding in his field!'}
178
+ """
126
179
  conversation_prompt = self.conversation.gen_complete_prompt(prompt)
127
180
  if optimizer:
128
181
  if optimizer in self.__available_optimizers:
@@ -134,8 +187,12 @@ class LabyrinthAI(Provider):
134
187
 
135
188
  # Prepare the request payload
136
189
  payload = {
137
- "id": str(uuid.uuid4()),
190
+ "id": str(uuid4()),
138
191
  "messages": [
192
+ {
193
+ "role": "system",
194
+ "content": self.system_prompt
195
+ },
139
196
  {
140
197
  "role": "user",
141
198
  "content": conversation_prompt,
@@ -163,23 +220,24 @@ class LabyrinthAI(Provider):
163
220
  raise exceptions.FailedToGenerateResponseError(
164
221
  f"Request failed with status code {response.status_code}"
165
222
  )
166
-
223
+
167
224
  streaming_text = ""
168
225
  for line in response.iter_lines():
169
226
  if line:
170
227
  try:
171
228
  line = line.decode('utf-8')
172
- if line.startswith('0:'):
173
- content = line[2:].strip('"')
229
+ match = re.search(r'0:"(.*?)"', line)
230
+ if match:
231
+ content = match.group(1)
174
232
  streaming_text += content
175
233
  resp = dict(text=content)
176
234
  yield resp if raw else resp
177
235
  except UnicodeDecodeError:
178
236
  continue
179
-
237
+
180
238
  self.last_response = {"text": streaming_text}
181
239
  self.conversation.update_chat_history(prompt, streaming_text)
182
-
240
+
183
241
  except requests.RequestException as e:
184
242
  raise exceptions.FailedToGenerateResponseError(f"Request failed: {str(e)}")
185
243
 
@@ -204,8 +262,9 @@ class LabyrinthAI(Provider):
204
262
  if line:
205
263
  try:
206
264
  line = line.decode('utf-8')
207
- if line.startswith('0:'):
208
- content = line[2:].strip('"')
265
+ match = re.search(r'0:"(.*?)"', line)
266
+ if match:
267
+ content = match.group(1)
209
268
  full_response += content
210
269
  except UnicodeDecodeError:
211
270
  continue
@@ -225,6 +284,24 @@ class LabyrinthAI(Provider):
225
284
  optimizer: str = None,
226
285
  conversationally: bool = False,
227
286
  ) -> Union[str, Generator[str, None, None]]:
287
+ """
288
+ Generates a response from the Labyrinth AI API.
289
+
290
+ Args:
291
+ prompt (str): The prompt to send to the API.
292
+ stream (bool): Whether to stream the response.
293
+ optimizer (str): Optimizer to use for the prompt.
294
+ conversationally (bool): Whether to generate the prompt conversationally.
295
+
296
+ Returns:
297
+ Union[str, Generator[str, None, None]]: The API response.
298
+
299
+ Examples:
300
+ >>> ai = LabyrinthAI()
301
+ >>> response = ai.chat("What's the weather today?")
302
+ >>> print(response)
303
+ 'The weather today is sunny with a high of 75°F.'
304
+ """
228
305
  def for_stream():
229
306
  for response in self.ask(prompt, True, optimizer=optimizer, conversationally=conversationally):
230
307
  yield self.get_message(response)
@@ -235,5 +312,29 @@ class LabyrinthAI(Provider):
235
312
  return for_stream() if stream else for_non_stream()
236
313
 
237
314
  def get_message(self, response: dict) -> str:
315
+ """
316
+ Extracts the message from the API response.
317
+
318
+ Args:
319
+ response (dict): The API response.
320
+
321
+ Returns:
322
+ str: The message content.
323
+
324
+ Examples:
325
+ >>> ai = LabyrinthAI()
326
+ >>> response = ai.ask("Tell me a joke!")
327
+ >>> message = ai.get_message(response)
328
+ >>> print(message)
329
+ 'Why did the scarecrow win an award? Because he was outstanding in his field!'
330
+ """
238
331
  assert isinstance(response, dict), "Response should be of dict data-type only"
239
- return response["text"].replace('\\n', '\n').replace('\\n\\n', '\n\n')
332
+ formatted_text = response["text"].replace('\\n', '\n').replace('\\n\\n', '\n\n')
333
+ return formatted_text
334
+
335
+ if __name__ == "__main__":
336
+ from rich import print
337
+ ai = LabyrinthAI()
338
+ resp = ai.chat("What is the capital of France?", stream=True)
339
+ for message in resp:
340
+ print(message, end='', flush=True)