webscout 5.1__py3-none-any.whl → 5.3__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 (40) hide show
  1. webscout/AIauto.py +83 -277
  2. webscout/AIbase.py +106 -4
  3. webscout/AIutel.py +41 -10
  4. webscout/Agents/Onlinesearcher.py +91 -104
  5. webscout/Agents/__init__.py +2 -1
  6. webscout/Agents/ai.py +186 -0
  7. webscout/Agents/functioncall.py +57 -27
  8. webscout/Bing_search.py +73 -43
  9. webscout/DWEBS.py +99 -77
  10. webscout/Local/_version.py +1 -1
  11. webscout/Provider/AI21.py +177 -0
  12. webscout/Provider/Chatify.py +174 -0
  13. webscout/Provider/Cloudflare.py +0 -4
  14. webscout/Provider/EDITEE.py +215 -0
  15. webscout/Provider/{Berlin4h.py → NetFly.py} +81 -82
  16. webscout/Provider/RUBIKSAI.py +11 -5
  17. webscout/Provider/TTI/PollinationsAI.py +138 -0
  18. webscout/Provider/TTI/__init__.py +2 -0
  19. webscout/Provider/TTI/deepinfra.py +148 -0
  20. webscout/Provider/TTS/__init__.py +2 -0
  21. webscout/Provider/TTS/streamElements.py +292 -0
  22. webscout/Provider/TTS/voicepod.py +118 -0
  23. webscout/Provider/{liaobots.py → TeachAnything.py} +31 -122
  24. webscout/Provider/__init__.py +14 -4
  25. webscout/Provider/ai4chat.py +14 -8
  26. webscout/Provider/cerebras.py +199 -0
  27. webscout/Provider/felo_search.py +28 -68
  28. webscout/Provider/x0gpt.py +181 -0
  29. webscout/__init__.py +4 -2
  30. webscout/exceptions.py +2 -1
  31. webscout/transcriber.py +195 -140
  32. webscout/version.py +1 -1
  33. {webscout-5.1.dist-info → webscout-5.3.dist-info}/METADATA +41 -82
  34. {webscout-5.1.dist-info → webscout-5.3.dist-info}/RECORD +38 -28
  35. webscout/async_providers.py +0 -21
  36. webscout/voice.py +0 -34
  37. {webscout-5.1.dist-info → webscout-5.3.dist-info}/LICENSE.md +0 -0
  38. {webscout-5.1.dist-info → webscout-5.3.dist-info}/WHEEL +0 -0
  39. {webscout-5.1.dist-info → webscout-5.3.dist-info}/entry_points.txt +0 -0
  40. {webscout-5.1.dist-info → webscout-5.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,118 @@
1
+ import requests
2
+ import json
3
+ import pygame
4
+ import time
5
+ from pathlib import Path
6
+ from typing import Generator
7
+ from playsound import playsound
8
+ from webscout import exceptions
9
+ from webscout.AIbase import TTSProvider
10
+
11
+ class Voicepods(TTSProvider):
12
+ """
13
+ A class to interact with the Voicepods text-to-speech API.
14
+ """
15
+
16
+ def __init__(self, timeout: int = 20, proxies: dict = None):
17
+ """
18
+ Initializes the Voicepods API client.
19
+ """
20
+ self.api_endpoint = "https://voicepods-stream.vercel.app/api/resemble"
21
+ self.headers = {
22
+ 'Accept': '*/*',
23
+ 'Accept-Encoding': 'gzip, deflate, br, zstd',
24
+ 'Accept-Language': 'en-US,en;q=0.9,en-IN;q=0.8',
25
+ 'Content-Type': 'application/json',
26
+ 'DNT': '1',
27
+ 'Origin': 'https://voicepods-stream.vercel.app',
28
+ 'Referer': 'https://voicepods-stream.vercel.app/',
29
+ 'Sec-CH-UA': '"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"',
30
+ 'Sec-CH-UA-Mobile': '?0',
31
+ 'Sec-CH-UA-Platform': '"Windows"',
32
+ 'Sec-Fetch-Dest': 'empty',
33
+ 'Sec-Fetch-Mode': 'cors',
34
+ 'Sec-Fetch-Site': 'same-origin',
35
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0',
36
+ }
37
+ self.session = requests.Session()
38
+ self.session.headers.update(self.headers)
39
+ if proxies:
40
+ self.session.proxies.update(proxies)
41
+ self.timeout = timeout
42
+ self.audio_cache_dir = Path("./audio_cache")
43
+
44
+ def tts(self, text: str) -> str:
45
+ """
46
+ Converts text to speech using the Voicepods API.
47
+
48
+ Args:
49
+ text (str): The text to be converted to speech.
50
+
51
+ Returns:
52
+ str: The filename of the saved audio file.
53
+
54
+ Raises:
55
+ exceptions.FailedToGenerateResponseError: If there is an error generating or saving the audio.
56
+ """
57
+ payload = json.dumps({"query": text})
58
+ filename = self.audio_cache_dir / f"{int(time.time())}.wav" # Using timestamp for filename
59
+
60
+ try:
61
+ response = self.session.post(self.api_endpoint, data=payload, timeout=self.timeout)
62
+ response.raise_for_status()
63
+
64
+ content_type = response.headers.get('Content-Type', '')
65
+ if 'audio' not in content_type.lower():
66
+ raise ValueError(f"Unexpected content type: {content_type}")
67
+
68
+ audio_data = response.content
69
+ self._save_audio(audio_data, filename)
70
+ return filename.as_posix() # Return the filename as a string
71
+
72
+ except requests.exceptions.RequestException as e:
73
+ raise exceptions.FailedToGenerateResponseError(f"Error generating audio: {e}")
74
+
75
+ def _save_audio(self, audio_data: bytes, filename: Path):
76
+ """Saves the audio data to a WAV file in the audio cache directory."""
77
+ try:
78
+ # Create the audio_cache directory if it doesn't exist
79
+ self.audio_cache_dir.mkdir(parents=True, exist_ok=True)
80
+
81
+ riff_start = audio_data.find(b'RIFF')
82
+ if riff_start == -1:
83
+ raise ValueError("RIFF header not found in audio data")
84
+
85
+ trimmed_audio_data = audio_data[riff_start:]
86
+
87
+ with open(filename, "wb") as f:
88
+ f.write(trimmed_audio_data)
89
+
90
+ except Exception as e:
91
+ raise exceptions.FailedToGenerateResponseError(f"Error saving audio: {e}")
92
+
93
+ def play_audio(self, filename: str):
94
+ """
95
+ Plays an audio file using playsound.
96
+
97
+ Args:
98
+ filename (str): The path to the audio file.
99
+
100
+ Raises:
101
+ RuntimeError: If there is an error playing the audio.
102
+ """
103
+ try:
104
+ playsound(filename)
105
+ except Exception as e:
106
+ raise RuntimeError(f"Error playing audio: {e}")
107
+
108
+ # Example usage
109
+ if __name__ == "__main__":
110
+
111
+ voicepods = Voicepods()
112
+ text = "Hello, this is a test of the Voicepods text-to-speech system."
113
+
114
+ print("Generating audio...")
115
+ audio_file = voicepods.tts(text)
116
+
117
+ print("Playing audio...")
118
+ voicepods.play_audio(audio_file)
@@ -1,40 +1,19 @@
1
- import json
2
- import re
3
- import uuid
4
- import gzip
5
- import zlib
6
- from typing import Any, Dict, Generator, Union
7
-
8
1
  import requests
2
+ from requests.exceptions import RequestException
3
+ from typing import Any, Dict
4
+ import logging
5
+ import random
9
6
 
10
- from webscout.AIutel import Optimizers
11
- from webscout.AIutel import Conversation
12
- from webscout.AIutel import AwesomePrompts
13
- from webscout.AIbase import Provider
14
- from webscout import exceptions
7
+ from webscout.AIutel import Conversation, Optimizers
15
8
 
16
- class LiaoBots(Provider):
9
+ class TeachAnything:
17
10
  """
18
- A class to interact with the LiaoBots API.
11
+ A class to interact with the Teach-Anything API.
19
12
  """
20
13
 
21
- # List of available models
22
- AVAILABLE_MODELS = [
23
- "gpt-4o-mini",
24
- "gpt-4o-free",
25
- "gpt-4o-mini-free",
26
- "gpt-4-turbo-2024-04-09",
27
- "gpt-4o",
28
- "gpt-4-0613",
29
- "claude-3-5-sonnet-20240620",
30
- "gemini-1.5-pro-latest",
31
- "gemini-1.5-flash-latest"
32
- ]
33
14
 
34
15
  def __init__(
35
16
  self,
36
- auth_code: str = "G3USRn7M5zsXn",
37
- cookie: str = "gkp2=pevIjZCYj8wMcrWPEAq6",
38
17
  is_conversation: bool = True,
39
18
  max_tokens: int = 600,
40
19
  timeout: int = 30,
@@ -44,15 +23,11 @@ class LiaoBots(Provider):
44
23
  proxies: dict = {},
45
24
  history_offset: int = 10250,
46
25
  act: str = None,
47
- model: str = "claude-3-5-sonnet-20240620",
48
- system_prompt: str = "You are a helpful assistant."
49
26
  ) -> None:
50
27
  """
51
- Initializes the LiaoBots API with given parameters.
28
+ Initializes the Teach-Anything API with given parameters.
52
29
 
53
30
  Args:
54
- auth_code (str): The auth code for authentication.
55
- cookie (str): The cookie for authentication.
56
31
  is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
57
32
  max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
58
33
  timeout (int, optional): Http request timeout. Defaults to 30.
@@ -62,57 +37,29 @@ class LiaoBots(Provider):
62
37
  proxies (dict, optional): Http request proxies. Defaults to {}.
63
38
  history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
64
39
  act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
65
- model (str, optional): AI model to use for text generation. Defaults to "claude-3-5-sonnet-20240620".
66
- system_prompt (str, optional): System prompt for LiaoBots. Defaults to "You are a helpful assistant.".
40
+ model (str, optional): AI model to use for text generation. Defaults to "gpt4".
67
41
  """
68
42
 
69
- # Check if the chosen model is available
70
- if model not in self.AVAILABLE_MODELS:
71
- raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
72
43
 
73
- self.auth_code = auth_code
74
- self.cookie = cookie
75
- self.api_endpoint = "https://liaobots.work/api/chat"
76
- self.model = model
77
- self.system_prompt = system_prompt
78
44
  self.session = requests.Session()
79
45
  self.is_conversation = is_conversation
80
46
  self.max_tokens_to_sample = max_tokens
81
- self.stream_chunk_size = 64
47
+ self.api_endpoint = "https://www.teach-anything.com/api/generate"
82
48
  self.timeout = timeout
83
49
  self.last_response = {}
84
50
  self.headers = {
51
+ "authority": "www.teach-anything.com",
52
+ "path": "/api/generate",
53
+ "scheme": "https",
85
54
  "accept": "*/*",
86
55
  "accept-encoding": "gzip, deflate, br, zstd",
87
56
  "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
88
57
  "content-type": "application/json",
89
- "cookie": self.cookie,
90
- "dnt": "1",
91
- "origin": "https://liaobots.work",
92
- "priority": "u=1, i",
93
- "referer": "https://liaobots.work/en",
94
- "sec-ch-ua": '"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"',
95
- "sec-ch-ua-mobile": "?0",
96
- "sec-ch-ua-platform": '"Windows"',
97
- "sec-fetch-dest": "empty",
98
- "sec-fetch-mode": "cors",
99
- "sec-fetch-site": "same-origin",
58
+ "origin": "https://www.teach-anything.com",
59
+ "referer": "https://www.teach-anything.com/",
100
60
  "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.0",
101
- "x-Auth-Code": self.auth_code,
102
61
  }
103
- self.__available_optimizers = (
104
- method
105
- for method in dir(Optimizers)
106
- if callable(getattr(Optimizers, method)) and not method.startswith("__")
107
- )
108
62
  self.session.headers.update(self.headers)
109
- Conversation.intro = (
110
- AwesomePrompts().get_act(
111
- act, raise_not_found=True, default=None, case_insensitive=True
112
- )
113
- if act
114
- else intro or Conversation.intro
115
- )
116
63
  self.conversation = Conversation(
117
64
  is_conversation, self.max_tokens_to_sample, filepath, update_file
118
65
  )
@@ -126,12 +73,11 @@ class LiaoBots(Provider):
126
73
  raw: bool = False,
127
74
  optimizer: str = None,
128
75
  conversationally: bool = False,
129
- ) -> Dict[str, Any]:
130
- """
131
- Sends a prompt to the LiaoBots API and returns the response.
76
+ ) -> dict:
77
+ """Chat with AI
132
78
 
133
79
  Args:
134
- prompt: The text prompt to generate text from.
80
+ prompt (str): Prompt to be send.
135
81
  stream (bool, optional): Whether to stream the response. Defaults to False.
136
82
  raw (bool, optional): Whether to return the raw response. Defaults to False.
137
83
  optimizer (str, optional): The name of the optimizer to use. Defaults to None.
@@ -151,61 +97,23 @@ class LiaoBots(Provider):
151
97
  f"Optimizer is not one of {self.__available_optimizers}"
152
98
  )
153
99
 
154
- payload: Dict[str, any] = {
155
- "conversationId": str(uuid.uuid4()),
156
- "model": {
157
- "id": self.model
158
- },
159
- "messages": [
160
- {
161
- "role": "user",
162
- "content": conversation_prompt
163
- }
164
- ],
165
- "key": "",
166
- "prompt": self.system_prompt
100
+ payload = {
101
+ "prompt": conversation_prompt
167
102
  }
168
-
169
103
  def for_stream():
170
- response = self.session.post(
171
- self.api_endpoint, json=payload, headers=self.headers, stream=True, timeout=self.timeout
172
- )
173
-
104
+ response = self.session.post(self.api_endpoint, headers=self.headers, json=payload, timeout=self.timeout)
174
105
  if not response.ok:
175
- raise exceptions.FailedToGenerateResponseError(
176
- f"Failed to generate response - ({response.status_code}, {response.reason})"
106
+ raise RequestException(
107
+ f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
177
108
  )
178
109
 
179
- streaming_response = ""
180
- content_encoding = response.headers.get('Content-Encoding')
181
- # Stream the response
182
- for chunk in response.iter_content():
183
- if chunk:
184
- try:
185
- # Decompress the chunk if necessary
186
- if content_encoding == 'gzip':
187
- chunk = gzip.decompress(chunk)
188
- elif content_encoding == 'deflate':
189
- chunk = zlib.decompress(chunk)
190
-
191
- # Decode the chunk
192
- decoded_chunk = chunk.decode('utf-8')
193
- streaming_response += decoded_chunk
194
- except UnicodeDecodeError:
195
- # Handle non-textual data
196
- pass
197
- else:
198
- pass
199
- self.last_response.update(dict(text=streaming_response))
110
+ resp = response.text
111
+ self.last_response.update(dict(text=resp))
200
112
  self.conversation.update_chat_history(
201
113
  prompt, self.get_message(self.last_response)
202
114
  )
203
-
204
- if stream:
205
- yield from [] # Yield nothing when streaming, focus on side effects
206
- else:
207
- return [] # Return empty list for non-streaming case
208
-
115
+ return self.last_response
116
+
209
117
  def for_non_stream():
210
118
  for _ in for_stream():
211
119
  pass
@@ -260,9 +168,10 @@ class LiaoBots(Provider):
260
168
  assert isinstance(response, dict), "Response should be of dict data-type only"
261
169
  return response["text"]
262
170
 
171
+
263
172
  if __name__ == '__main__':
264
173
  from rich import print
265
- liaobots = LiaoBots()
266
- response = liaobots.chat("tell me about india")
174
+ ai = TeachAnything()
175
+ response = ai.chat(input(">>> "))
267
176
  for chunk in response:
268
- print(chunk, end="", flush=True)
177
+ print(chunk, end="", flush=True)
@@ -20,7 +20,6 @@ from .Phind import Phindv2
20
20
  from .Phind import AsyncPhindv2
21
21
  from .ai4chat import *
22
22
  from .Gemini import GEMINI
23
- from .Berlin4h import Berlin4h
24
23
  from .Poe import POE
25
24
  from .BasedGPT import BasedGPT
26
25
  from .Deepseek import DeepSeek
@@ -34,7 +33,6 @@ from .DARKAI import *
34
33
  from .koala import *
35
34
  from .RUBIKSAI import *
36
35
  from .meta import *
37
- from .liaobots import *
38
36
  from .DiscordRocks import *
39
37
  from .felo_search import *
40
38
  from .xdash import *
@@ -43,6 +41,13 @@ from .Youchat import *
43
41
  from .yep import *
44
42
  from .Cloudflare import *
45
43
  from .turboseek import *
44
+ from .NetFly import *
45
+ from .EDITEE import *
46
+ from .TeachAnything import *
47
+ from .AI21 import *
48
+ from .Chatify import *
49
+ from .x0gpt import *
50
+ from .cerebras import *
46
51
  __all__ = [
47
52
  'ThinkAnyAI',
48
53
  'Farfalle',
@@ -62,7 +67,6 @@ __all__ = [
62
67
  'AsyncPhindSearch',
63
68
  'Felo',
64
69
  'GEMINI',
65
- 'Berlin4h',
66
70
  'POE',
67
71
  'BasedGPT',
68
72
  'DeepSeek',
@@ -80,7 +84,6 @@ __all__ = [
80
84
  'KOALA',
81
85
  'RUBIKSAI',
82
86
  'Meta',
83
- 'LiaoBots',
84
87
  'DiscordRocks',
85
88
  'PiAI',
86
89
  'XDASH',
@@ -89,4 +92,11 @@ __all__ = [
89
92
  'YEPCHAT',
90
93
  'Cloudflare',
91
94
  'TurboSeek',
95
+ 'NetFly',
96
+ 'Editee',
97
+ 'TeachAnything',
98
+ 'AI21',
99
+ 'Chatify',
100
+ 'X0GPT',
101
+ 'Cerebras'
92
102
  ]
@@ -1,7 +1,7 @@
1
1
  import requests
2
2
  import json
3
3
  import html
4
- from re import sub
4
+ import re
5
5
  from typing import Any, Dict
6
6
 
7
7
  from webscout.AIutel import Optimizers
@@ -94,7 +94,7 @@ class AI4Chat(Provider):
94
94
  def ask(
95
95
  self,
96
96
  prompt: str,
97
- stream: bool = False, # Streaming is not supported by AI4Chat
97
+ stream: bool = False,
98
98
  raw: bool = False,
99
99
  optimizer: str = None,
100
100
  conversationally: bool = False,
@@ -137,9 +137,17 @@ class AI4Chat(Provider):
137
137
  response_data = response.json()
138
138
  message_content = response_data.get('message', 'No message found')
139
139
 
140
- # Decode HTML entities and remove HTML tags
140
+ # Decode HTML entities
141
141
  decoded_message = html.unescape(message_content)
142
- cleaned_text = sub('<[^<]+?>', '', decoded_message)
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)
148
+
149
+ # Remove extra newlines
150
+ cleaned_text = re.sub(r'\n{3,}', '\n\n', cleaned_text.strip())
143
151
 
144
152
  self.last_response.update(dict(text=cleaned_text))
145
153
  self.conversation.update_chat_history(prompt, cleaned_text)
@@ -183,11 +191,9 @@ class AI4Chat(Provider):
183
191
  """
184
192
  assert isinstance(response, dict), "Response should be of dict data-type only"
185
193
  return response["text"]
194
+
186
195
  if __name__ == "__main__":
187
196
  from rich import print
188
-
189
197
  ai = AI4Chat()
190
- # Stream the response
191
198
  response = ai.chat(input(">>> "))
192
- for chunk in response:
193
- print(chunk, end="", flush=True)
199
+ print(response)
@@ -0,0 +1,199 @@
1
+ import json
2
+ import requests
3
+ from webscout.AIutel import Optimizers, Conversation, AwesomePrompts
4
+ from webscout.AIbase import Provider
5
+ from webscout import exceptions
6
+ from typing import Dict, Any
7
+
8
+ class Cerebras(Provider):
9
+ """
10
+ A class to interact with the Cerebras AI API.
11
+ """
12
+
13
+ AVAILABLE_MODELS = ["llama3.1-8b", "llama3.1-70b"]
14
+
15
+ def __init__(
16
+ self,
17
+ api_key: str,
18
+ is_conversation: bool = True,
19
+ max_tokens: int = 4096,
20
+ timeout: int = 30,
21
+ intro: str = None,
22
+ filepath: str = None,
23
+ update_file: bool = True,
24
+ proxies: dict = {},
25
+ history_offset: int = 10250,
26
+ act: str = None,
27
+ model: str = "llama3.1-8b",
28
+ system_prompt: str = "Please try to provide useful, helpful and actionable answers.",
29
+ ):
30
+ """
31
+ Initializes the Cerebras AI API with given parameters.
32
+ """
33
+ if model not in self.AVAILABLE_MODELS:
34
+ raise ValueError(f"Invalid model: {model}. Available models are: {', '.join(self.AVAILABLE_MODELS)}")
35
+
36
+ self.session = requests.Session()
37
+ self.is_conversation = is_conversation
38
+ self.max_tokens_to_sample = max_tokens
39
+ self.api_endpoint = "https://api.cerebras.ai/v1/chat/completions"
40
+ self.timeout = timeout
41
+ self.last_response = {}
42
+ self.model = model
43
+ self.system_prompt = system_prompt
44
+ self.headers = {
45
+ "accept": "application/json",
46
+ "accept-encoding": "gzip, deflate, br, zstd",
47
+ "accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
48
+ "authorization": f"Bearer {api_key}",
49
+ "content-type": "application/json",
50
+ "dnt": "1",
51
+ "origin": "https://inference.cerebras.ai",
52
+ "referer": "https://inference.cerebras.ai/",
53
+ "sec-ch-ua": '"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"',
54
+ "sec-ch-ua-mobile": "?0",
55
+ "sec-ch-ua-platform": '"Windows"',
56
+ "sec-fetch-dest": "empty",
57
+ "sec-fetch-mode": "cors",
58
+ "sec-fetch-site": "same-site",
59
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0",
60
+ }
61
+
62
+ self.__available_optimizers = (
63
+ method
64
+ for method in dir(Optimizers)
65
+ if callable(getattr(Optimizers, method)) and not method.startswith("__")
66
+ )
67
+ self.session.headers.update(self.headers)
68
+ Conversation.intro = (
69
+ AwesomePrompts().get_act(
70
+ act, raise_not_found=True, default=None, case_insensitive=True
71
+ )
72
+ if act
73
+ else intro or Conversation.intro
74
+ )
75
+ self.conversation = Conversation(
76
+ is_conversation, self.max_tokens_to_sample, filepath, update_file
77
+ )
78
+ self.conversation.history_offset = history_offset
79
+ self.session.proxies = proxies
80
+
81
+ def ask(
82
+ self,
83
+ prompt: str,
84
+ stream: bool = False,
85
+ raw: bool = False,
86
+ optimizer: str = None,
87
+ conversationally: bool = False,
88
+ ) -> Dict[str, Any]:
89
+ conversation_prompt = self.conversation.gen_complete_prompt(prompt)
90
+ if optimizer:
91
+ if optimizer in self.__available_optimizers:
92
+ conversation_prompt = getattr(Optimizers, optimizer)(
93
+ conversation_prompt if conversationally else prompt
94
+ )
95
+ else:
96
+ raise Exception(
97
+ f"Optimizer is not one of {self.__available_optimizers}"
98
+ )
99
+
100
+ payload = {
101
+ "messages": [
102
+ {"role": "system", "content": self.system_prompt},
103
+ {"role": "user", "content": conversation_prompt},
104
+ ],
105
+ "model": self.model,
106
+ "stream": True,
107
+ "temperature": 0.2,
108
+ "top_p": 1,
109
+ "max_tokens": self.max_tokens_to_sample
110
+ }
111
+
112
+ def for_stream():
113
+ response = self.session.post(
114
+ self.api_endpoint, json=payload, stream=True, timeout=self.timeout
115
+ )
116
+
117
+ if not response.ok:
118
+ raise exceptions.FailedToGenerateResponseError(
119
+ f"Failed to generate response - ({response.status_code}, {response.reason})"
120
+ )
121
+
122
+ full_response = ""
123
+ for line in response.iter_lines():
124
+ if line:
125
+ line_data = line.decode('utf-8').strip()
126
+ if line_data.startswith("data: "):
127
+ json_str = line_data[6:]
128
+ if json_str != "[DONE]":
129
+ chunk = json.loads(json_str)
130
+ if 'choices' in chunk and 'delta' in chunk['choices'][0]:
131
+ content = chunk['choices'][0]['delta'].get('content', '')
132
+ full_response += content
133
+ yield content if raw else dict(text=content)
134
+ else:
135
+ break
136
+
137
+ self.last_response.update(dict(text=full_response))
138
+ self.conversation.update_chat_history(
139
+ prompt, self.get_message(self.last_response)
140
+ )
141
+
142
+ def for_non_stream():
143
+ full_response = ""
144
+ for chunk in for_stream():
145
+ if isinstance(chunk, dict):
146
+ full_response += chunk['text']
147
+ else:
148
+ full_response += chunk
149
+ return dict(text=full_response)
150
+
151
+ return for_stream() if stream else for_non_stream()
152
+
153
+ def chat(
154
+ self,
155
+ prompt: str,
156
+ stream: bool = False,
157
+ optimizer: str = None,
158
+ conversationally: bool = False,
159
+ ) -> str:
160
+ def for_stream():
161
+ for response in self.ask(
162
+ prompt, True, optimizer=optimizer, conversationally=conversationally
163
+ ):
164
+ yield self.get_message(response)
165
+
166
+ def for_non_stream():
167
+ return self.get_message(
168
+ self.ask(
169
+ prompt,
170
+ False,
171
+ optimizer=optimizer,
172
+ conversationally=conversationally,
173
+ )
174
+ )
175
+
176
+ return for_stream() if stream else for_non_stream()
177
+
178
+ def get_message(self, response: dict) -> str:
179
+ """Retrieves message only from response
180
+
181
+ Args:
182
+ response (dict): Response generated by `self.ask`
183
+
184
+ Returns:
185
+ str: Message extracted
186
+ """
187
+ assert isinstance(response, dict), "Response should be of dict data-type only"
188
+ return response["text"]
189
+
190
+ if __name__ == '__main__':
191
+ from rich import print
192
+
193
+ # You can replace this with your actual API key
194
+ api_key = "YOUR_API_KEY_HERE"
195
+
196
+ ai = Cerebras(api_key=api_key)
197
+ response = ai.chat(input(">>> "), stream=True)
198
+ for chunk in response:
199
+ print(chunk, end="", flush=True)