webscout 1.3.8__py3-none-any.whl → 1.3.9__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/AI.py +3132 -896
- webscout/AIbase.py +69 -1
- webscout/AIutel.py +19 -2
- webscout/__init__.py +2 -2
- webscout/async_providers.py +33 -0
- webscout/exceptions.py +4 -1
- webscout/g4f.py +193 -1
- webscout/version.py +1 -1
- webscout/webai.py +20 -2
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/METADATA +7 -19
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/RECORD +15 -14
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/LICENSE.md +0 -0
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/WHEEL +0 -0
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/entry_points.txt +0 -0
- {webscout-1.3.8.dist-info → webscout-1.3.9.dist-info}/top_level.txt +0 -0
webscout/AI.py
CHANGED
|
@@ -20,21 +20,24 @@ import json
|
|
|
20
20
|
import yaml
|
|
21
21
|
from webscout.AIutel import Optimizers
|
|
22
22
|
from webscout.AIutel import Conversation
|
|
23
|
-
from webscout.AIutel import AwesomePrompts
|
|
24
|
-
from webscout.AIbase import
|
|
23
|
+
from webscout.AIutel import AwesomePrompts, sanitize_stream
|
|
24
|
+
from webscout.AIbase import Provider, AsyncProvider
|
|
25
25
|
from Helpingai_T2 import Perplexity
|
|
26
|
-
from
|
|
26
|
+
from webscout import exceptions
|
|
27
|
+
from typing import Any, AsyncGenerator
|
|
27
28
|
import logging
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
import httpx
|
|
30
|
+
#-----------------------------------------------llama 3-------------------------------------------
|
|
31
|
+
class LLAMA2(Provider):
|
|
30
32
|
def __init__(
|
|
31
33
|
self,
|
|
32
|
-
api_key: str,
|
|
33
34
|
is_conversation: bool = True,
|
|
34
|
-
max_tokens: int =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
max_tokens: int = 800,
|
|
36
|
+
temperature: float = 0.75,
|
|
37
|
+
presence_penalty: int = 0,
|
|
38
|
+
frequency_penalty: int = 0,
|
|
39
|
+
top_p: float = 0.9,
|
|
40
|
+
model: str = "meta/meta-llama-3-70b-instruct",
|
|
38
41
|
timeout: int = 30,
|
|
39
42
|
intro: str = None,
|
|
40
43
|
filepath: str = None,
|
|
@@ -42,20 +45,17 @@ class Cohere(Provider):
|
|
|
42
45
|
proxies: dict = {},
|
|
43
46
|
history_offset: int = 10250,
|
|
44
47
|
act: str = None,
|
|
45
|
-
top_k: int = -1,
|
|
46
|
-
top_p: float = 0.999,
|
|
47
48
|
):
|
|
48
|
-
"""
|
|
49
|
+
"""Instantiates LLAMA2
|
|
49
50
|
|
|
50
51
|
Args:
|
|
51
|
-
api_key (str): Cohere API key.
|
|
52
52
|
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
53
|
-
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 800.
|
|
54
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.75.
|
|
55
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
56
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
57
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.9.
|
|
58
|
+
model (str, optional): LLM model name. Defaults to "meta/llama-2-70b-chat".
|
|
59
59
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
60
60
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
61
61
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -64,20 +64,22 @@ class Cohere(Provider):
|
|
|
64
64
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
65
65
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
66
66
|
"""
|
|
67
|
-
self.session = requests.Session()
|
|
68
67
|
self.is_conversation = is_conversation
|
|
69
68
|
self.max_tokens_to_sample = max_tokens
|
|
70
|
-
self.api_key = api_key
|
|
71
69
|
self.model = model
|
|
72
70
|
self.temperature = temperature
|
|
73
|
-
self.
|
|
74
|
-
self.
|
|
71
|
+
self.presence_penalty = presence_penalty
|
|
72
|
+
self.frequency_penalty = frequency_penalty
|
|
73
|
+
self.top_p = top_p
|
|
74
|
+
self.chat_endpoint = "https://www.llama2.ai/api"
|
|
75
75
|
self.stream_chunk_size = 64
|
|
76
76
|
self.timeout = timeout
|
|
77
77
|
self.last_response = {}
|
|
78
78
|
self.headers = {
|
|
79
79
|
"Content-Type": "application/json",
|
|
80
|
-
"
|
|
80
|
+
"Referer": "https://www.llama2.ai/",
|
|
81
|
+
"Content-Type": "text/plain;charset=UTF-8",
|
|
82
|
+
"Origin": "https://www.llama2.ai",
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
self.__available_optimizers = (
|
|
@@ -119,7 +121,7 @@ class Cohere(Provider):
|
|
|
119
121
|
dict : {}
|
|
120
122
|
```json
|
|
121
123
|
{
|
|
122
|
-
"text" : "How may I
|
|
124
|
+
"text" : "How may I help you today?"
|
|
123
125
|
}
|
|
124
126
|
```
|
|
125
127
|
"""
|
|
@@ -134,30 +136,43 @@ class Cohere(Provider):
|
|
|
134
136
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
135
137
|
)
|
|
136
138
|
self.session.headers.update(self.headers)
|
|
139
|
+
|
|
137
140
|
payload = {
|
|
138
|
-
"
|
|
141
|
+
"prompt": f"{conversation_prompt}<s>[INST] {prompt} [/INST]",
|
|
139
142
|
"model": self.model,
|
|
143
|
+
"systemPrompt": "You are a helpful assistant.",
|
|
140
144
|
"temperature": self.temperature,
|
|
141
|
-
"
|
|
145
|
+
"topP": self.top_p,
|
|
146
|
+
"maxTokens": self.max_tokens_to_sample,
|
|
147
|
+
"image": None,
|
|
148
|
+
"audio": None,
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
def for_stream():
|
|
145
152
|
response = self.session.post(
|
|
146
153
|
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
147
154
|
)
|
|
148
|
-
if
|
|
149
|
-
|
|
150
|
-
|
|
155
|
+
if (
|
|
156
|
+
not response.ok
|
|
157
|
+
or not response.headers.get("Content-Type")
|
|
158
|
+
== "text/plain; charset=utf-8"
|
|
159
|
+
):
|
|
160
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
161
|
+
f"Failed to generate response - ({response.status_code}, {response.reason})"
|
|
151
162
|
)
|
|
152
163
|
|
|
164
|
+
message_load: str = ""
|
|
153
165
|
for value in response.iter_lines(
|
|
154
166
|
decode_unicode=True,
|
|
167
|
+
delimiter="\n",
|
|
155
168
|
chunk_size=self.stream_chunk_size,
|
|
156
169
|
):
|
|
157
170
|
try:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
171
|
+
if bool(value.strip()):
|
|
172
|
+
message_load += value + "\n"
|
|
173
|
+
resp: dict = dict(text=message_load)
|
|
174
|
+
yield value if raw else resp
|
|
175
|
+
self.last_response.update(resp)
|
|
161
176
|
except json.decoder.JSONDecodeError:
|
|
162
177
|
pass
|
|
163
178
|
self.conversation.update_chat_history(
|
|
@@ -165,7 +180,6 @@ class Cohere(Provider):
|
|
|
165
180
|
)
|
|
166
181
|
|
|
167
182
|
def for_non_stream():
|
|
168
|
-
# let's make use of stream
|
|
169
183
|
for _ in for_stream():
|
|
170
184
|
pass
|
|
171
185
|
return self.last_response
|
|
@@ -211,20 +225,23 @@ class Cohere(Provider):
|
|
|
211
225
|
"""Retrieves message only from response
|
|
212
226
|
|
|
213
227
|
Args:
|
|
214
|
-
response (
|
|
228
|
+
response (str): Response generated by `self.ask`
|
|
215
229
|
|
|
216
230
|
Returns:
|
|
217
231
|
str: Message extracted
|
|
218
232
|
"""
|
|
219
233
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
220
|
-
return response["
|
|
221
|
-
|
|
222
|
-
class REKA(Provider):
|
|
234
|
+
return response["text"]
|
|
235
|
+
class AsyncLLAMA2(AsyncProvider):
|
|
223
236
|
def __init__(
|
|
224
237
|
self,
|
|
225
|
-
api_key: str,
|
|
226
238
|
is_conversation: bool = True,
|
|
227
|
-
max_tokens: int =
|
|
239
|
+
max_tokens: int = 800,
|
|
240
|
+
temperature: float = 0.75,
|
|
241
|
+
presence_penalty: int = 0,
|
|
242
|
+
frequency_penalty: int = 0,
|
|
243
|
+
top_p: float = 0.9,
|
|
244
|
+
model: str = "meta/meta-llama-3-70b-instruct",
|
|
228
245
|
timeout: int = 30,
|
|
229
246
|
intro: str = None,
|
|
230
247
|
filepath: str = None,
|
|
@@ -232,16 +249,17 @@ class REKA(Provider):
|
|
|
232
249
|
proxies: dict = {},
|
|
233
250
|
history_offset: int = 10250,
|
|
234
251
|
act: str = None,
|
|
235
|
-
model: str = "reka-core",
|
|
236
|
-
system_prompt: str = "Be Helpful and Friendly. Keep your response straightforward, short and concise",
|
|
237
|
-
use_search_engine: bool = False,
|
|
238
|
-
use_code_interpreter: bool = False,
|
|
239
252
|
):
|
|
240
|
-
"""Instantiates
|
|
253
|
+
"""Instantiates LLAMA2
|
|
241
254
|
|
|
242
255
|
Args:
|
|
243
|
-
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
244
|
-
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to
|
|
256
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
257
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 800.
|
|
258
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.75.
|
|
259
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
260
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
261
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.9.
|
|
262
|
+
model (str, optional): LLM model name. Defaults to "meta/llama-2-70b-chat".
|
|
245
263
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
246
264
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
247
265
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -249,25 +267,23 @@ class REKA(Provider):
|
|
|
249
267
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
250
268
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
251
269
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
252
|
-
model (str, optional): REKA model name. Defaults to "reka-core".
|
|
253
|
-
system_prompt (str, optional): System prompt for REKA. Defaults to "Be Helpful and Friendly. Keep your response straightforward, short and concise".
|
|
254
|
-
use_search_engine (bool, optional): Whether to use the search engine. Defaults to False.
|
|
255
|
-
use_code_interpreter (bool, optional): Whether to use the code interpreter. Defaults to False.
|
|
256
270
|
"""
|
|
257
|
-
self.session = requests.Session()
|
|
258
271
|
self.is_conversation = is_conversation
|
|
259
272
|
self.max_tokens_to_sample = max_tokens
|
|
260
|
-
self.
|
|
273
|
+
self.model = model
|
|
274
|
+
self.temperature = temperature
|
|
275
|
+
self.presence_penalty = presence_penalty
|
|
276
|
+
self.frequency_penalty = frequency_penalty
|
|
277
|
+
self.top_p = top_p
|
|
278
|
+
self.chat_endpoint = "https://www.llama2.ai/api"
|
|
261
279
|
self.stream_chunk_size = 64
|
|
262
280
|
self.timeout = timeout
|
|
263
281
|
self.last_response = {}
|
|
264
|
-
self.model = model
|
|
265
|
-
self.system_prompt = system_prompt
|
|
266
|
-
self.use_search_engine = use_search_engine
|
|
267
|
-
self.use_code_interpreter = use_code_interpreter
|
|
268
|
-
self.access_token = api_key
|
|
269
282
|
self.headers = {
|
|
270
|
-
"
|
|
283
|
+
"Content-Type": "application/json",
|
|
284
|
+
"Referer": "https://www.llama2.ai/",
|
|
285
|
+
"Content-Type": "text/plain;charset=UTF-8",
|
|
286
|
+
"Origin": "https://www.llama2.ai",
|
|
271
287
|
}
|
|
272
288
|
|
|
273
289
|
self.__available_optimizers = (
|
|
@@ -275,7 +291,6 @@ class REKA(Provider):
|
|
|
275
291
|
for method in dir(Optimizers)
|
|
276
292
|
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
277
293
|
)
|
|
278
|
-
self.session.headers.update(self.headers)
|
|
279
294
|
Conversation.intro = (
|
|
280
295
|
AwesomePrompts().get_act(
|
|
281
296
|
act, raise_not_found=True, default=None, case_insensitive=True
|
|
@@ -287,17 +302,20 @@ class REKA(Provider):
|
|
|
287
302
|
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
288
303
|
)
|
|
289
304
|
self.conversation.history_offset = history_offset
|
|
290
|
-
self.session
|
|
305
|
+
self.session = httpx.AsyncClient(
|
|
306
|
+
headers=self.headers,
|
|
307
|
+
proxies=proxies,
|
|
308
|
+
)
|
|
291
309
|
|
|
292
|
-
def ask(
|
|
310
|
+
async def ask(
|
|
293
311
|
self,
|
|
294
312
|
prompt: str,
|
|
295
313
|
stream: bool = False,
|
|
296
314
|
raw: bool = False,
|
|
297
315
|
optimizer: str = None,
|
|
298
316
|
conversationally: bool = False,
|
|
299
|
-
) -> dict:
|
|
300
|
-
"""Chat with AI
|
|
317
|
+
) -> dict | AsyncGenerator:
|
|
318
|
+
"""Chat with AI asynchronously.
|
|
301
319
|
|
|
302
320
|
Args:
|
|
303
321
|
prompt (str): Prompt to be send.
|
|
@@ -306,10 +324,10 @@ class REKA(Provider):
|
|
|
306
324
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
307
325
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
308
326
|
Returns:
|
|
309
|
-
dict :
|
|
327
|
+
dict|AsyncGeneraror[dict] : ai content
|
|
310
328
|
```json
|
|
311
329
|
{
|
|
312
|
-
"text" : "How may I
|
|
330
|
+
"text" : "How may I help you today?"
|
|
313
331
|
}
|
|
314
332
|
```
|
|
315
333
|
"""
|
|
@@ -324,76 +342,77 @@ class REKA(Provider):
|
|
|
324
342
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
325
343
|
)
|
|
326
344
|
|
|
327
|
-
self.session.headers.update(self.headers)
|
|
328
345
|
payload = {
|
|
329
|
-
|
|
330
|
-
"
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
"
|
|
335
|
-
"
|
|
336
|
-
"
|
|
337
|
-
"model_name": self.model,
|
|
338
|
-
# "model_name": "reka-flash",
|
|
339
|
-
# "model_name": "reka-edge",
|
|
346
|
+
"prompt": f"{conversation_prompt}<s>[INST] {prompt} [/INST]",
|
|
347
|
+
"model": self.model,
|
|
348
|
+
"systemPrompt": "You are a helpful assistant.",
|
|
349
|
+
"temperature": self.temperature,
|
|
350
|
+
"topP": self.top_p,
|
|
351
|
+
"maxTokens": self.max_tokens_to_sample,
|
|
352
|
+
"image": None,
|
|
353
|
+
"audio": None,
|
|
340
354
|
}
|
|
341
355
|
|
|
342
|
-
def for_stream():
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
356
|
+
async def for_stream():
|
|
357
|
+
async with self.session.stream(
|
|
358
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
359
|
+
) as response:
|
|
360
|
+
if (
|
|
361
|
+
not response.is_success
|
|
362
|
+
or not response.headers.get("Content-Type")
|
|
363
|
+
== "text/plain; charset=utf-8"
|
|
364
|
+
):
|
|
365
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
366
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
367
|
+
)
|
|
368
|
+
message_load: str = ""
|
|
369
|
+
async for value in response.aiter_lines():
|
|
370
|
+
try:
|
|
371
|
+
if bool(value.strip()):
|
|
372
|
+
message_load += value + "\n"
|
|
373
|
+
resp: dict = dict(text=message_load)
|
|
374
|
+
yield value if raw else resp
|
|
375
|
+
self.last_response.update(resp)
|
|
376
|
+
except json.decoder.JSONDecodeError:
|
|
377
|
+
pass
|
|
359
378
|
self.conversation.update_chat_history(
|
|
360
|
-
prompt, self.get_message(self.last_response)
|
|
379
|
+
prompt, await self.get_message(self.last_response)
|
|
361
380
|
)
|
|
362
381
|
|
|
363
|
-
def for_non_stream():
|
|
364
|
-
|
|
365
|
-
for _ in for_stream():
|
|
382
|
+
async def for_non_stream():
|
|
383
|
+
async for _ in for_stream():
|
|
366
384
|
pass
|
|
367
385
|
return self.last_response
|
|
368
386
|
|
|
369
|
-
return for_stream() if stream else for_non_stream()
|
|
387
|
+
return for_stream() if stream else await for_non_stream()
|
|
370
388
|
|
|
371
|
-
def chat(
|
|
389
|
+
async def chat(
|
|
372
390
|
self,
|
|
373
391
|
prompt: str,
|
|
374
392
|
stream: bool = False,
|
|
375
393
|
optimizer: str = None,
|
|
376
394
|
conversationally: bool = False,
|
|
377
|
-
) -> str:
|
|
378
|
-
"""Generate response `str`
|
|
395
|
+
) -> str | AsyncGenerator:
|
|
396
|
+
"""Generate response `str` asynchronously.
|
|
379
397
|
Args:
|
|
380
398
|
prompt (str): Prompt to be send.
|
|
381
399
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
382
400
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
383
401
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
384
402
|
Returns:
|
|
385
|
-
str: Response generated
|
|
403
|
+
str|AsyncGenerator: Response generated
|
|
386
404
|
"""
|
|
387
405
|
|
|
388
|
-
def for_stream():
|
|
389
|
-
|
|
406
|
+
async def for_stream():
|
|
407
|
+
async_ask = await self.ask(
|
|
390
408
|
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
391
|
-
)
|
|
392
|
-
|
|
409
|
+
)
|
|
410
|
+
async for response in async_ask:
|
|
411
|
+
yield await self.get_message(response)
|
|
393
412
|
|
|
394
|
-
def for_non_stream():
|
|
395
|
-
return self.get_message(
|
|
396
|
-
self.ask(
|
|
413
|
+
async def for_non_stream():
|
|
414
|
+
return await self.get_message(
|
|
415
|
+
await self.ask(
|
|
397
416
|
prompt,
|
|
398
417
|
False,
|
|
399
418
|
optimizer=optimizer,
|
|
@@ -401,31 +420,29 @@ class REKA(Provider):
|
|
|
401
420
|
)
|
|
402
421
|
)
|
|
403
422
|
|
|
404
|
-
return for_stream() if stream else for_non_stream()
|
|
423
|
+
return for_stream() if stream else await for_non_stream()
|
|
405
424
|
|
|
406
|
-
def get_message(self, response: dict) -> str:
|
|
425
|
+
async def get_message(self, response: dict) -> str:
|
|
407
426
|
"""Retrieves message only from response
|
|
408
427
|
|
|
409
428
|
Args:
|
|
410
|
-
response (
|
|
429
|
+
response (str): Response generated by `self.ask`
|
|
411
430
|
|
|
412
431
|
Returns:
|
|
413
432
|
str: Message extracted
|
|
414
433
|
"""
|
|
415
434
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
416
|
-
return response
|
|
417
|
-
#-----------------------------------------------
|
|
418
|
-
class
|
|
435
|
+
return response["text"]
|
|
436
|
+
#-----------------------------------------------Cohere--------------------------------------------
|
|
437
|
+
class Cohere(Provider):
|
|
419
438
|
def __init__(
|
|
420
439
|
self,
|
|
421
440
|
api_key: str,
|
|
422
441
|
is_conversation: bool = True,
|
|
423
442
|
max_tokens: int = 600,
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
top_p: float = 1,
|
|
428
|
-
model: str = "mixtral-8x7b-32768",
|
|
443
|
+
model: str = "command-r-plus",
|
|
444
|
+
temperature: float = 0.7,
|
|
445
|
+
system_prompt: str = "You are helpful AI",
|
|
429
446
|
timeout: int = 30,
|
|
430
447
|
intro: str = None,
|
|
431
448
|
filepath: str = None,
|
|
@@ -433,18 +450,20 @@ class GROQ(Provider):
|
|
|
433
450
|
proxies: dict = {},
|
|
434
451
|
history_offset: int = 10250,
|
|
435
452
|
act: str = None,
|
|
453
|
+
top_k: int = -1,
|
|
454
|
+
top_p: float = 0.999,
|
|
436
455
|
):
|
|
437
|
-
"""
|
|
456
|
+
"""Initializes Cohere
|
|
438
457
|
|
|
439
458
|
Args:
|
|
440
|
-
api_key (
|
|
459
|
+
api_key (str): Cohere API key.
|
|
441
460
|
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
442
461
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
462
|
+
model (str, optional): Model to use for generating text. Defaults to "command-r-plus".
|
|
463
|
+
temperature (float, optional): Diversity of the generated text. Higher values produce more diverse outputs.
|
|
464
|
+
Defaults to 0.7.
|
|
465
|
+
system_prompt (str, optional): A system_prompt or context to set the style or tone of the generated text.
|
|
466
|
+
Defaults to "You are helpful AI".
|
|
448
467
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
449
468
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
450
469
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -459,10 +478,8 @@ class GROQ(Provider):
|
|
|
459
478
|
self.api_key = api_key
|
|
460
479
|
self.model = model
|
|
461
480
|
self.temperature = temperature
|
|
462
|
-
self.
|
|
463
|
-
self.
|
|
464
|
-
self.top_p = top_p
|
|
465
|
-
self.chat_endpoint = "https://api.groq.com/openai/v1/chat/completions"
|
|
481
|
+
self.system_prompt = system_prompt
|
|
482
|
+
self.chat_endpoint = "https://production.api.os.cohere.ai/coral/v1/chat"
|
|
466
483
|
self.stream_chunk_size = 64
|
|
467
484
|
self.timeout = timeout
|
|
468
485
|
self.last_response = {}
|
|
@@ -500,42 +517,19 @@ class GROQ(Provider):
|
|
|
500
517
|
) -> dict:
|
|
501
518
|
"""Chat with AI
|
|
502
519
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
520
|
+
Args:
|
|
521
|
+
prompt (str): Prompt to be send.
|
|
522
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
523
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
524
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
525
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
526
|
+
Returns:
|
|
527
|
+
dict : {}
|
|
528
|
+
```json
|
|
512
529
|
{
|
|
513
|
-
|
|
514
|
-
"object": "chat.completion",
|
|
515
|
-
"created": 1710852779,
|
|
516
|
-
"model": "mixtral-8x7b-32768",
|
|
517
|
-
"choices": [
|
|
518
|
-
{
|
|
519
|
-
"index": 0,
|
|
520
|
-
"message": {
|
|
521
|
-
"role": "assistant",
|
|
522
|
-
"content": "Hello! How can I assist you today? I'm here to help answer your questions and engage in conversation on a wide variety of topics. Feel free to ask me anything!"
|
|
523
|
-
},
|
|
524
|
-
"logprobs": null,
|
|
525
|
-
"finish_reason": "stop"
|
|
526
|
-
}
|
|
527
|
-
],
|
|
528
|
-
"usage": {
|
|
529
|
-
"prompt_tokens": 47,
|
|
530
|
-
"prompt_time": 0.03,
|
|
531
|
-
"completion_tokens": 37,
|
|
532
|
-
"completion_time": 0.069,
|
|
533
|
-
"total_tokens": 84,
|
|
534
|
-
"total_time": 0.099
|
|
535
|
-
},
|
|
536
|
-
"system_fingerprint": null
|
|
530
|
+
"text" : "How may I assist you today?"
|
|
537
531
|
}
|
|
538
|
-
|
|
532
|
+
```
|
|
539
533
|
"""
|
|
540
534
|
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
541
535
|
if optimizer:
|
|
@@ -549,13 +543,10 @@ class GROQ(Provider):
|
|
|
549
543
|
)
|
|
550
544
|
self.session.headers.update(self.headers)
|
|
551
545
|
payload = {
|
|
552
|
-
"
|
|
553
|
-
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
546
|
+
"message": conversation_prompt,
|
|
554
547
|
"model": self.model,
|
|
555
|
-
"presence_penalty": self.presence_penalty,
|
|
556
|
-
"stream": stream,
|
|
557
548
|
"temperature": self.temperature,
|
|
558
|
-
"
|
|
549
|
+
"preamble": self.system_prompt,
|
|
559
550
|
}
|
|
560
551
|
|
|
561
552
|
def for_stream():
|
|
@@ -567,22 +558,14 @@ class GROQ(Provider):
|
|
|
567
558
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
568
559
|
)
|
|
569
560
|
|
|
570
|
-
message_load = ""
|
|
571
561
|
for value in response.iter_lines(
|
|
572
562
|
decode_unicode=True,
|
|
573
|
-
delimiter="" if raw else "data:",
|
|
574
563
|
chunk_size=self.stream_chunk_size,
|
|
575
564
|
):
|
|
576
565
|
try:
|
|
577
|
-
resp = json.loads(value)
|
|
578
|
-
|
|
579
|
-
if
|
|
580
|
-
message_load += incomplete_message
|
|
581
|
-
resp["choices"][0]["delta"]["content"] = message_load
|
|
582
|
-
self.last_response.update(resp)
|
|
583
|
-
yield value if raw else resp
|
|
584
|
-
elif raw:
|
|
585
|
-
yield value
|
|
566
|
+
resp = json.loads(value.strip().split("\n")[-1])
|
|
567
|
+
self.last_response.update(resp)
|
|
568
|
+
yield value if raw else resp
|
|
586
569
|
except json.decoder.JSONDecodeError:
|
|
587
570
|
pass
|
|
588
571
|
self.conversation.update_chat_history(
|
|
@@ -590,19 +573,10 @@ class GROQ(Provider):
|
|
|
590
573
|
)
|
|
591
574
|
|
|
592
575
|
def for_non_stream():
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
raise Exception(
|
|
598
|
-
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
599
|
-
)
|
|
600
|
-
resp = response.json()
|
|
601
|
-
self.last_response.update(resp)
|
|
602
|
-
self.conversation.update_chat_history(
|
|
603
|
-
prompt, self.get_message(self.last_response)
|
|
604
|
-
)
|
|
605
|
-
return resp
|
|
576
|
+
# let's make use of stream
|
|
577
|
+
for _ in for_stream():
|
|
578
|
+
pass
|
|
579
|
+
return self.last_response
|
|
606
580
|
|
|
607
581
|
return for_stream() if stream else for_non_stream()
|
|
608
582
|
|
|
@@ -651,26 +625,14 @@ class GROQ(Provider):
|
|
|
651
625
|
str: Message extracted
|
|
652
626
|
"""
|
|
653
627
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
return response["choices"][0]["message"]["content"]
|
|
658
|
-
except KeyError:
|
|
659
|
-
return ""
|
|
660
|
-
|
|
661
|
-
#----------------------------------------------------------OpenAI-----------------------------------
|
|
662
|
-
class OPENAI(Provider):
|
|
663
|
-
model = "gpt-3.5-turbo"
|
|
628
|
+
return response["result"]["chatStreamEndEvent"]["response"]["text"]
|
|
629
|
+
#-----------------------------------------------REKA-----------------------------------------------
|
|
630
|
+
class REKA(Provider):
|
|
664
631
|
def __init__(
|
|
665
632
|
self,
|
|
666
633
|
api_key: str,
|
|
667
634
|
is_conversation: bool = True,
|
|
668
635
|
max_tokens: int = 600,
|
|
669
|
-
temperature: float = 1,
|
|
670
|
-
presence_penalty: int = 0,
|
|
671
|
-
frequency_penalty: int = 0,
|
|
672
|
-
top_p: float = 1,
|
|
673
|
-
model: str = model,
|
|
674
636
|
timeout: int = 30,
|
|
675
637
|
intro: str = None,
|
|
676
638
|
filepath: str = None,
|
|
@@ -678,18 +640,16 @@ class OPENAI(Provider):
|
|
|
678
640
|
proxies: dict = {},
|
|
679
641
|
history_offset: int = 10250,
|
|
680
642
|
act: str = None,
|
|
643
|
+
model: str = "reka-core",
|
|
644
|
+
system_prompt: str = "Be Helpful and Friendly. Keep your response straightforward, short and concise",
|
|
645
|
+
use_search_engine: bool = False,
|
|
646
|
+
use_code_interpreter: bool = False,
|
|
681
647
|
):
|
|
682
|
-
"""Instantiates
|
|
648
|
+
"""Instantiates REKA
|
|
683
649
|
|
|
684
650
|
Args:
|
|
685
|
-
|
|
686
|
-
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
651
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
687
652
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
688
|
-
temperature (float, optional): Charge of the generated text's randomness. Defaults to 1.
|
|
689
|
-
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
690
|
-
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
691
|
-
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
692
|
-
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
693
653
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
694
654
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
695
655
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -697,23 +657,25 @@ class OPENAI(Provider):
|
|
|
697
657
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
698
658
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
699
659
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
660
|
+
model (str, optional): REKA model name. Defaults to "reka-core".
|
|
661
|
+
system_prompt (str, optional): System prompt for REKA. Defaults to "Be Helpful and Friendly. Keep your response straightforward, short and concise".
|
|
662
|
+
use_search_engine (bool, optional): Whether to use the search engine. Defaults to False.
|
|
663
|
+
use_code_interpreter (bool, optional): Whether to use the code interpreter. Defaults to False.
|
|
700
664
|
"""
|
|
701
665
|
self.session = requests.Session()
|
|
702
666
|
self.is_conversation = is_conversation
|
|
703
667
|
self.max_tokens_to_sample = max_tokens
|
|
704
|
-
self.
|
|
705
|
-
self.model = model
|
|
706
|
-
self.temperature = temperature
|
|
707
|
-
self.presence_penalty = presence_penalty
|
|
708
|
-
self.frequency_penalty = frequency_penalty
|
|
709
|
-
self.top_p = top_p
|
|
710
|
-
self.chat_endpoint = "https://api.openai.com/v1/chat/completions"
|
|
668
|
+
self.api_endpoint = "https://chat.reka.ai/api/chat"
|
|
711
669
|
self.stream_chunk_size = 64
|
|
712
670
|
self.timeout = timeout
|
|
713
671
|
self.last_response = {}
|
|
672
|
+
self.model = model
|
|
673
|
+
self.system_prompt = system_prompt
|
|
674
|
+
self.use_search_engine = use_search_engine
|
|
675
|
+
self.use_code_interpreter = use_code_interpreter
|
|
676
|
+
self.access_token = api_key
|
|
714
677
|
self.headers = {
|
|
715
|
-
"
|
|
716
|
-
"Authorization": f"Bearer {self.api_key}",
|
|
678
|
+
"Authorization": f"Bearer {self.access_token}",
|
|
717
679
|
}
|
|
718
680
|
|
|
719
681
|
self.__available_optimizers = (
|
|
@@ -755,25 +717,7 @@ class OPENAI(Provider):
|
|
|
755
717
|
dict : {}
|
|
756
718
|
```json
|
|
757
719
|
{
|
|
758
|
-
|
|
759
|
-
"object": "chat.completion",
|
|
760
|
-
"created": 1704623244,
|
|
761
|
-
"model": "gpt-3.5-turbo",
|
|
762
|
-
"usage": {
|
|
763
|
-
"prompt_tokens": 0,
|
|
764
|
-
"completion_tokens": 0,
|
|
765
|
-
"total_tokens": 0
|
|
766
|
-
},
|
|
767
|
-
"choices": [
|
|
768
|
-
{
|
|
769
|
-
"message": {
|
|
770
|
-
"role": "assistant",
|
|
771
|
-
"content": "Hello! How can I assist you today?"
|
|
772
|
-
},
|
|
773
|
-
"finish_reason": "stop",
|
|
774
|
-
"index": 0
|
|
775
|
-
}
|
|
776
|
-
]
|
|
720
|
+
"text" : "How may I assist you today?"
|
|
777
721
|
}
|
|
778
722
|
```
|
|
779
723
|
"""
|
|
@@ -787,42 +731,37 @@ class OPENAI(Provider):
|
|
|
787
731
|
raise Exception(
|
|
788
732
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
789
733
|
)
|
|
734
|
+
|
|
790
735
|
self.session.headers.update(self.headers)
|
|
791
736
|
payload = {
|
|
792
|
-
|
|
793
|
-
"
|
|
794
|
-
|
|
795
|
-
|
|
737
|
+
|
|
738
|
+
"conversation_history": [
|
|
739
|
+
{"type": "human", "text": f"## SYSTEM PROMPT: {self.system_prompt}\n\n## QUERY: {conversation_prompt}"},
|
|
740
|
+
],
|
|
741
|
+
|
|
796
742
|
"stream": stream,
|
|
797
|
-
"
|
|
798
|
-
"
|
|
743
|
+
"use_search_engine": self.use_search_engine,
|
|
744
|
+
"use_code_interpreter": self.use_code_interpreter,
|
|
745
|
+
"model_name": self.model,
|
|
746
|
+
# "model_name": "reka-flash",
|
|
747
|
+
# "model_name": "reka-edge",
|
|
799
748
|
}
|
|
800
749
|
|
|
801
750
|
def for_stream():
|
|
802
|
-
response = self.session.post(
|
|
803
|
-
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
804
|
-
)
|
|
751
|
+
response = self.session.post(self.api_endpoint, json=payload, stream=True, timeout=self.timeout)
|
|
805
752
|
if not response.ok:
|
|
806
753
|
raise Exception(
|
|
807
754
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
808
755
|
)
|
|
809
756
|
|
|
810
|
-
message_load = ""
|
|
811
757
|
for value in response.iter_lines(
|
|
812
758
|
decode_unicode=True,
|
|
813
|
-
delimiter="" if raw else "data:",
|
|
814
759
|
chunk_size=self.stream_chunk_size,
|
|
815
760
|
):
|
|
816
761
|
try:
|
|
817
762
|
resp = json.loads(value)
|
|
818
|
-
|
|
819
|
-
if
|
|
820
|
-
message_load += incomplete_message
|
|
821
|
-
resp["choices"][0]["delta"]["content"] = message_load
|
|
822
|
-
self.last_response.update(resp)
|
|
823
|
-
yield value if raw else resp
|
|
824
|
-
elif raw:
|
|
825
|
-
yield value
|
|
763
|
+
self.last_response.update(resp)
|
|
764
|
+
yield value if raw else resp
|
|
826
765
|
except json.decoder.JSONDecodeError:
|
|
827
766
|
pass
|
|
828
767
|
self.conversation.update_chat_history(
|
|
@@ -830,22 +769,10 @@ class OPENAI(Provider):
|
|
|
830
769
|
)
|
|
831
770
|
|
|
832
771
|
def for_non_stream():
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
not response.ok
|
|
838
|
-
or not response.headers.get("Content-Type", "") == "application/json"
|
|
839
|
-
):
|
|
840
|
-
raise Exception(
|
|
841
|
-
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
842
|
-
)
|
|
843
|
-
resp = response.json()
|
|
844
|
-
self.last_response.update(resp)
|
|
845
|
-
self.conversation.update_chat_history(
|
|
846
|
-
prompt, self.get_message(self.last_response)
|
|
847
|
-
)
|
|
848
|
-
return resp
|
|
772
|
+
# let's make use of stream
|
|
773
|
+
for _ in for_stream():
|
|
774
|
+
pass
|
|
775
|
+
return self.last_response
|
|
849
776
|
|
|
850
777
|
return for_stream() if stream else for_non_stream()
|
|
851
778
|
|
|
@@ -894,27 +821,19 @@ class OPENAI(Provider):
|
|
|
894
821
|
str: Message extracted
|
|
895
822
|
"""
|
|
896
823
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
return response["choices"][0]["message"]["content"]
|
|
901
|
-
except KeyError:
|
|
902
|
-
return ""
|
|
903
|
-
#--------------------------------------LEO-----------------------------------------
|
|
904
|
-
class LEO(Provider):
|
|
905
|
-
|
|
906
|
-
# model = "llama-2-13b-chat"
|
|
907
|
-
|
|
908
|
-
# key = "qztbjzBqJueQZLFkwTTJrieu8Vw3789u"
|
|
824
|
+
return response.get("text")
|
|
825
|
+
#-----------------------------------------------GROQ-----------------------------------------------
|
|
826
|
+
class GROQ(Provider):
|
|
909
827
|
def __init__(
|
|
910
828
|
self,
|
|
829
|
+
api_key: str,
|
|
911
830
|
is_conversation: bool = True,
|
|
912
831
|
max_tokens: int = 600,
|
|
913
|
-
temperature: float =
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
832
|
+
temperature: float = 1,
|
|
833
|
+
presence_penalty: int = 0,
|
|
834
|
+
frequency_penalty: int = 0,
|
|
835
|
+
top_p: float = 1,
|
|
836
|
+
model: str = "mixtral-8x7b-32768",
|
|
918
837
|
timeout: int = 30,
|
|
919
838
|
intro: str = None,
|
|
920
839
|
filepath: str = None,
|
|
@@ -923,43 +842,43 @@ class LEO(Provider):
|
|
|
923
842
|
history_offset: int = 10250,
|
|
924
843
|
act: str = None,
|
|
925
844
|
):
|
|
926
|
-
"""
|
|
845
|
+
"""Instantiates GROQ
|
|
927
846
|
|
|
928
847
|
Args:
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
model (str, optional): Text generation model name. Defaults to "llama-2-13b-chat".
|
|
848
|
+
api_key (key): GROQ's API key.
|
|
849
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
932
850
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
933
|
-
temperature (float, optional): Charge of the generated text's randomness. Defaults to
|
|
934
|
-
|
|
851
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 1.
|
|
852
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
853
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
935
854
|
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
936
|
-
|
|
937
|
-
|
|
855
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
856
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
857
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
938
858
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
939
859
|
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
940
|
-
proxies (dict, optional)
|
|
860
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
941
861
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
942
862
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
943
863
|
"""
|
|
944
864
|
self.session = requests.Session()
|
|
945
865
|
self.is_conversation = is_conversation
|
|
946
866
|
self.max_tokens_to_sample = max_tokens
|
|
867
|
+
self.api_key = api_key
|
|
947
868
|
self.model = model
|
|
948
|
-
self.stop_sequences = ["</response>", "</s>"]
|
|
949
869
|
self.temperature = temperature
|
|
950
|
-
self.
|
|
870
|
+
self.presence_penalty = presence_penalty
|
|
871
|
+
self.frequency_penalty = frequency_penalty
|
|
951
872
|
self.top_p = top_p
|
|
952
|
-
self.chat_endpoint = "https://
|
|
873
|
+
self.chat_endpoint = "https://api.groq.com/openai/v1/chat/completions"
|
|
953
874
|
self.stream_chunk_size = 64
|
|
954
875
|
self.timeout = timeout
|
|
955
876
|
self.last_response = {}
|
|
956
877
|
self.headers = {
|
|
957
878
|
"Content-Type": "application/json",
|
|
958
|
-
"
|
|
959
|
-
"x-brave-key": brave_key,
|
|
960
|
-
"accept-language": "en-US,en;q=0.9",
|
|
961
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/110.0",
|
|
879
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
962
880
|
}
|
|
881
|
+
|
|
963
882
|
self.__available_optimizers = (
|
|
964
883
|
method
|
|
965
884
|
for method in dir(Optimizers)
|
|
@@ -978,14 +897,6 @@ class LEO(Provider):
|
|
|
978
897
|
)
|
|
979
898
|
self.conversation.history_offset = history_offset
|
|
980
899
|
self.session.proxies = proxies
|
|
981
|
-
self.system_prompt = (
|
|
982
|
-
"\n\nYour name is Leo, a helpful"
|
|
983
|
-
"respectful and honest AI assistant created by the company Brave. You will be replying to a user of the Brave browser. "
|
|
984
|
-
"Always respond in a neutral tone. Be polite and courteous. Answer concisely in no more than 50-80 words."
|
|
985
|
-
"\n\nPlease ensure that your responses are socially unbiased and positive in nature."
|
|
986
|
-
"If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. "
|
|
987
|
-
"If you don't know the answer to a question, please don't share false information.\n"
|
|
988
|
-
)
|
|
989
900
|
|
|
990
901
|
def ask(
|
|
991
902
|
self,
|
|
@@ -997,25 +908,42 @@ class LEO(Provider):
|
|
|
997
908
|
) -> dict:
|
|
998
909
|
"""Chat with AI
|
|
999
910
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
911
|
+
Args:
|
|
912
|
+
prompt (str): Prompt to be send.
|
|
913
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
914
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
915
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
916
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
917
|
+
Returns:
|
|
918
|
+
dict : {}
|
|
919
|
+
```json
|
|
1009
920
|
{
|
|
1010
|
-
"
|
|
1011
|
-
"
|
|
1012
|
-
"
|
|
1013
|
-
"
|
|
1014
|
-
"
|
|
1015
|
-
|
|
1016
|
-
|
|
921
|
+
"id": "c0c8d139-d2b9-9909-8aa1-14948bc28404",
|
|
922
|
+
"object": "chat.completion",
|
|
923
|
+
"created": 1710852779,
|
|
924
|
+
"model": "mixtral-8x7b-32768",
|
|
925
|
+
"choices": [
|
|
926
|
+
{
|
|
927
|
+
"index": 0,
|
|
928
|
+
"message": {
|
|
929
|
+
"role": "assistant",
|
|
930
|
+
"content": "Hello! How can I assist you today? I'm here to help answer your questions and engage in conversation on a wide variety of topics. Feel free to ask me anything!"
|
|
931
|
+
},
|
|
932
|
+
"logprobs": null,
|
|
933
|
+
"finish_reason": "stop"
|
|
934
|
+
}
|
|
935
|
+
],
|
|
936
|
+
"usage": {
|
|
937
|
+
"prompt_tokens": 47,
|
|
938
|
+
"prompt_time": 0.03,
|
|
939
|
+
"completion_tokens": 37,
|
|
940
|
+
"completion_time": 0.069,
|
|
941
|
+
"total_tokens": 84,
|
|
942
|
+
"total_time": 0.099
|
|
943
|
+
},
|
|
944
|
+
"system_fingerprint": null
|
|
1017
945
|
}
|
|
1018
|
-
|
|
946
|
+
```
|
|
1019
947
|
"""
|
|
1020
948
|
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
1021
949
|
if optimizer:
|
|
@@ -1027,15 +955,14 @@ class LEO(Provider):
|
|
|
1027
955
|
raise Exception(
|
|
1028
956
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1029
957
|
)
|
|
1030
|
-
|
|
1031
958
|
self.session.headers.update(self.headers)
|
|
1032
959
|
payload = {
|
|
1033
|
-
"
|
|
960
|
+
"frequency_penalty": self.frequency_penalty,
|
|
961
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
1034
962
|
"model": self.model,
|
|
1035
|
-
"
|
|
1036
|
-
"self.stop_sequence": self.stop_sequences,
|
|
963
|
+
"presence_penalty": self.presence_penalty,
|
|
1037
964
|
"stream": stream,
|
|
1038
|
-
"
|
|
965
|
+
"temperature": self.temperature,
|
|
1039
966
|
"top_p": self.top_p,
|
|
1040
967
|
}
|
|
1041
968
|
|
|
@@ -1043,15 +970,12 @@ class LEO(Provider):
|
|
|
1043
970
|
response = self.session.post(
|
|
1044
971
|
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
1045
972
|
)
|
|
1046
|
-
if
|
|
1047
|
-
not response.ok
|
|
1048
|
-
or not response.headers.get("Content-Type")
|
|
1049
|
-
== "text/event-stream; charset=utf-8"
|
|
1050
|
-
):
|
|
973
|
+
if not response.ok:
|
|
1051
974
|
raise Exception(
|
|
1052
975
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1053
976
|
)
|
|
1054
977
|
|
|
978
|
+
message_load = ""
|
|
1055
979
|
for value in response.iter_lines(
|
|
1056
980
|
decode_unicode=True,
|
|
1057
981
|
delimiter="" if raw else "data:",
|
|
@@ -1059,8 +983,14 @@ class LEO(Provider):
|
|
|
1059
983
|
):
|
|
1060
984
|
try:
|
|
1061
985
|
resp = json.loads(value)
|
|
1062
|
-
self.
|
|
1063
|
-
|
|
986
|
+
incomplete_message = self.get_message(resp)
|
|
987
|
+
if incomplete_message:
|
|
988
|
+
message_load += incomplete_message
|
|
989
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
990
|
+
self.last_response.update(resp)
|
|
991
|
+
yield value if raw else resp
|
|
992
|
+
elif raw:
|
|
993
|
+
yield value
|
|
1064
994
|
except json.decoder.JSONDecodeError:
|
|
1065
995
|
pass
|
|
1066
996
|
self.conversation.update_chat_history(
|
|
@@ -1071,10 +1001,7 @@ class LEO(Provider):
|
|
|
1071
1001
|
response = self.session.post(
|
|
1072
1002
|
self.chat_endpoint, json=payload, stream=False, timeout=self.timeout
|
|
1073
1003
|
)
|
|
1074
|
-
if
|
|
1075
|
-
not response.ok
|
|
1076
|
-
or not response.headers.get("Content-Type", "") == "application/json"
|
|
1077
|
-
):
|
|
1004
|
+
if not response.ok:
|
|
1078
1005
|
raise Exception(
|
|
1079
1006
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1080
1007
|
)
|
|
@@ -1132,15 +1059,23 @@ class LEO(Provider):
|
|
|
1132
1059
|
str: Message extracted
|
|
1133
1060
|
"""
|
|
1134
1061
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1062
|
+
try:
|
|
1063
|
+
if response["choices"][0].get("delta"):
|
|
1064
|
+
return response["choices"][0]["delta"]["content"]
|
|
1065
|
+
return response["choices"][0]["message"]["content"]
|
|
1066
|
+
except KeyError:
|
|
1067
|
+
return ""
|
|
1068
|
+
class AsyncGROQ(AsyncProvider):
|
|
1138
1069
|
def __init__(
|
|
1139
1070
|
self,
|
|
1071
|
+
api_key: str,
|
|
1140
1072
|
is_conversation: bool = True,
|
|
1141
1073
|
max_tokens: int = 600,
|
|
1142
1074
|
temperature: float = 1,
|
|
1075
|
+
presence_penalty: int = 0,
|
|
1076
|
+
frequency_penalty: int = 0,
|
|
1143
1077
|
top_p: float = 1,
|
|
1078
|
+
model: str = "mixtral-8x7b-32768",
|
|
1144
1079
|
timeout: int = 30,
|
|
1145
1080
|
intro: str = None,
|
|
1146
1081
|
filepath: str = None,
|
|
@@ -1149,35 +1084,40 @@ class KOBOLDAI(Provider):
|
|
|
1149
1084
|
history_offset: int = 10250,
|
|
1150
1085
|
act: str = None,
|
|
1151
1086
|
):
|
|
1152
|
-
"""
|
|
1087
|
+
"""Instantiates GROQ
|
|
1153
1088
|
|
|
1154
1089
|
Args:
|
|
1155
|
-
|
|
1090
|
+
api_key (key): GROQ's API key.
|
|
1091
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
1156
1092
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
1157
|
-
temperature (float, optional): Charge of the generated text's randomness. Defaults to
|
|
1093
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 1.
|
|
1094
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
1095
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
1158
1096
|
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
1159
|
-
|
|
1160
|
-
|
|
1097
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
1098
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
1099
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
1161
1100
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
1162
1101
|
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
1163
|
-
proxies (dict, optional)
|
|
1102
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
1164
1103
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1165
1104
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1166
1105
|
"""
|
|
1167
|
-
self.session = requests.Session()
|
|
1168
1106
|
self.is_conversation = is_conversation
|
|
1169
1107
|
self.max_tokens_to_sample = max_tokens
|
|
1108
|
+
self.api_key = api_key
|
|
1109
|
+
self.model = model
|
|
1170
1110
|
self.temperature = temperature
|
|
1111
|
+
self.presence_penalty = presence_penalty
|
|
1112
|
+
self.frequency_penalty = frequency_penalty
|
|
1171
1113
|
self.top_p = top_p
|
|
1172
|
-
self.chat_endpoint =
|
|
1173
|
-
"https://koboldai-koboldcpp-tiefighter.hf.space/api/extra/generate/stream"
|
|
1174
|
-
)
|
|
1114
|
+
self.chat_endpoint = "https://api.groq.com/openai/v1/chat/completions"
|
|
1175
1115
|
self.stream_chunk_size = 64
|
|
1176
1116
|
self.timeout = timeout
|
|
1177
1117
|
self.last_response = {}
|
|
1178
1118
|
self.headers = {
|
|
1179
1119
|
"Content-Type": "application/json",
|
|
1180
|
-
"
|
|
1120
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
1181
1121
|
}
|
|
1182
1122
|
|
|
1183
1123
|
self.__available_optimizers = (
|
|
@@ -1185,7 +1125,6 @@ class KOBOLDAI(Provider):
|
|
|
1185
1125
|
for method in dir(Optimizers)
|
|
1186
1126
|
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
1187
1127
|
)
|
|
1188
|
-
self.session.headers.update(self.headers)
|
|
1189
1128
|
Conversation.intro = (
|
|
1190
1129
|
AwesomePrompts().get_act(
|
|
1191
1130
|
act, raise_not_found=True, default=None, case_insensitive=True
|
|
@@ -1197,31 +1136,54 @@ class KOBOLDAI(Provider):
|
|
|
1197
1136
|
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
1198
1137
|
)
|
|
1199
1138
|
self.conversation.history_offset = history_offset
|
|
1200
|
-
self.session
|
|
1139
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
1201
1140
|
|
|
1202
|
-
def ask(
|
|
1141
|
+
async def ask(
|
|
1203
1142
|
self,
|
|
1204
1143
|
prompt: str,
|
|
1205
1144
|
stream: bool = False,
|
|
1206
1145
|
raw: bool = False,
|
|
1207
1146
|
optimizer: str = None,
|
|
1208
1147
|
conversationally: bool = False,
|
|
1209
|
-
) -> dict:
|
|
1210
|
-
"""Chat with AI
|
|
1148
|
+
) -> dict | AsyncGenerator:
|
|
1149
|
+
"""Chat with AI asynchronously.
|
|
1211
1150
|
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1151
|
+
Args:
|
|
1152
|
+
prompt (str): Prompt to be send.
|
|
1153
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1154
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
1155
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1156
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1157
|
+
Returns:
|
|
1158
|
+
dict|AsyncGenerator : ai content
|
|
1159
|
+
```json
|
|
1221
1160
|
{
|
|
1222
|
-
|
|
1161
|
+
"id": "c0c8d139-d2b9-9909-8aa1-14948bc28404",
|
|
1162
|
+
"object": "chat.completion",
|
|
1163
|
+
"created": 1710852779,
|
|
1164
|
+
"model": "mixtral-8x7b-32768",
|
|
1165
|
+
"choices": [
|
|
1166
|
+
{
|
|
1167
|
+
"index": 0,
|
|
1168
|
+
"message": {
|
|
1169
|
+
"role": "assistant",
|
|
1170
|
+
"content": "Hello! How can I assist you today? I'm here to help answer your questions and engage in conversation on a wide variety of topics. Feel free to ask me anything!"
|
|
1171
|
+
},
|
|
1172
|
+
"logprobs": null,
|
|
1173
|
+
"finish_reason": "stop"
|
|
1174
|
+
}
|
|
1175
|
+
],
|
|
1176
|
+
"usage": {
|
|
1177
|
+
"prompt_tokens": 47,
|
|
1178
|
+
"prompt_time": 0.03,
|
|
1179
|
+
"completion_tokens": 37,
|
|
1180
|
+
"completion_time": 0.069,
|
|
1181
|
+
"total_tokens": 84,
|
|
1182
|
+
"total_time": 0.099
|
|
1183
|
+
},
|
|
1184
|
+
"system_fingerprint": null
|
|
1223
1185
|
}
|
|
1224
|
-
|
|
1186
|
+
```
|
|
1225
1187
|
"""
|
|
1226
1188
|
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
1227
1189
|
if optimizer:
|
|
@@ -1233,75 +1195,90 @@ class KOBOLDAI(Provider):
|
|
|
1233
1195
|
raise Exception(
|
|
1234
1196
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1235
1197
|
)
|
|
1236
|
-
|
|
1237
|
-
self.session.headers.update(self.headers)
|
|
1238
1198
|
payload = {
|
|
1239
|
-
"
|
|
1199
|
+
"frequency_penalty": self.frequency_penalty,
|
|
1200
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
1201
|
+
"model": self.model,
|
|
1202
|
+
"presence_penalty": self.presence_penalty,
|
|
1203
|
+
"stream": stream,
|
|
1240
1204
|
"temperature": self.temperature,
|
|
1241
1205
|
"top_p": self.top_p,
|
|
1242
1206
|
}
|
|
1243
1207
|
|
|
1244
|
-
def for_stream():
|
|
1245
|
-
|
|
1246
|
-
self.chat_endpoint, json=payload,
|
|
1208
|
+
async def for_stream():
|
|
1209
|
+
async with self.session.stream(
|
|
1210
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
1211
|
+
) as response:
|
|
1212
|
+
if not response.is_success:
|
|
1213
|
+
raise Exception(
|
|
1214
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
1215
|
+
)
|
|
1216
|
+
|
|
1217
|
+
message_load = ""
|
|
1218
|
+
intro_value = "data:"
|
|
1219
|
+
async for value in response.aiter_lines():
|
|
1220
|
+
try:
|
|
1221
|
+
if value.startswith(intro_value):
|
|
1222
|
+
value = value[len(intro_value) :]
|
|
1223
|
+
resp = json.loads(value)
|
|
1224
|
+
incomplete_message = await self.get_message(resp)
|
|
1225
|
+
if incomplete_message:
|
|
1226
|
+
message_load += incomplete_message
|
|
1227
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
1228
|
+
self.last_response.update(resp)
|
|
1229
|
+
yield value if raw else resp
|
|
1230
|
+
elif raw:
|
|
1231
|
+
yield value
|
|
1232
|
+
except json.decoder.JSONDecodeError:
|
|
1233
|
+
pass
|
|
1234
|
+
self.conversation.update_chat_history(
|
|
1235
|
+
prompt, await self.get_message(self.last_response)
|
|
1247
1236
|
)
|
|
1248
|
-
|
|
1237
|
+
|
|
1238
|
+
async def for_non_stream():
|
|
1239
|
+
response = httpx.post(
|
|
1240
|
+
self.chat_endpoint, json=payload, timeout=self.timeout
|
|
1241
|
+
)
|
|
1242
|
+
if not response.is_success:
|
|
1249
1243
|
raise Exception(
|
|
1250
|
-
f"Failed to generate response - ({response.status_code}, {response.
|
|
1244
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
1251
1245
|
)
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
for value in response.iter_lines(
|
|
1255
|
-
decode_unicode=True,
|
|
1256
|
-
delimiter="" if raw else "event: message\ndata:",
|
|
1257
|
-
chunk_size=self.stream_chunk_size,
|
|
1258
|
-
):
|
|
1259
|
-
try:
|
|
1260
|
-
resp = json.loads(value)
|
|
1261
|
-
message_load += self.get_message(resp)
|
|
1262
|
-
resp["token"] = message_load
|
|
1263
|
-
self.last_response.update(resp)
|
|
1264
|
-
yield value if raw else resp
|
|
1265
|
-
except json.decoder.JSONDecodeError:
|
|
1266
|
-
pass
|
|
1246
|
+
resp = response.json()
|
|
1247
|
+
self.last_response.update(resp)
|
|
1267
1248
|
self.conversation.update_chat_history(
|
|
1268
|
-
prompt, self.get_message(self.last_response)
|
|
1249
|
+
prompt, await self.get_message(self.last_response)
|
|
1269
1250
|
)
|
|
1251
|
+
return resp
|
|
1270
1252
|
|
|
1271
|
-
|
|
1272
|
-
# let's make use of stream
|
|
1273
|
-
for _ in for_stream():
|
|
1274
|
-
pass
|
|
1275
|
-
return self.last_response
|
|
1276
|
-
|
|
1277
|
-
return for_stream() if stream else for_non_stream()
|
|
1253
|
+
return for_stream() if stream else await for_non_stream()
|
|
1278
1254
|
|
|
1279
|
-
def chat(
|
|
1255
|
+
async def chat(
|
|
1280
1256
|
self,
|
|
1281
1257
|
prompt: str,
|
|
1282
1258
|
stream: bool = False,
|
|
1283
1259
|
optimizer: str = None,
|
|
1284
1260
|
conversationally: bool = False,
|
|
1285
|
-
) -> str:
|
|
1286
|
-
"""Generate response `str`
|
|
1261
|
+
) -> str | AsyncGenerator:
|
|
1262
|
+
"""Generate response `str` asynchronously.
|
|
1287
1263
|
Args:
|
|
1288
1264
|
prompt (str): Prompt to be send.
|
|
1289
1265
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1290
1266
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1291
1267
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1292
1268
|
Returns:
|
|
1293
|
-
str: Response generated
|
|
1269
|
+
str|AsyncGenerator: Response generated
|
|
1294
1270
|
"""
|
|
1295
1271
|
|
|
1296
|
-
def for_stream():
|
|
1297
|
-
|
|
1272
|
+
async def for_stream():
|
|
1273
|
+
async_ask = await self.ask(
|
|
1298
1274
|
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
1299
|
-
)
|
|
1300
|
-
|
|
1275
|
+
)
|
|
1276
|
+
async for response in async_ask:
|
|
1277
|
+
yield await self.get_message(response)
|
|
1301
1278
|
|
|
1302
|
-
def for_non_stream():
|
|
1303
|
-
return self.get_message(
|
|
1304
|
-
self.ask(
|
|
1279
|
+
async def for_non_stream():
|
|
1280
|
+
return await self.get_message(
|
|
1281
|
+
await self.ask(
|
|
1305
1282
|
prompt,
|
|
1306
1283
|
False,
|
|
1307
1284
|
optimizer=optimizer,
|
|
@@ -1309,9 +1286,9 @@ class KOBOLDAI(Provider):
|
|
|
1309
1286
|
)
|
|
1310
1287
|
)
|
|
1311
1288
|
|
|
1312
|
-
return for_stream() if stream else for_non_stream()
|
|
1289
|
+
return for_stream() if stream else await for_non_stream()
|
|
1313
1290
|
|
|
1314
|
-
def get_message(self, response: dict) -> str:
|
|
1291
|
+
async def get_message(self, response: dict) -> str:
|
|
1315
1292
|
"""Retrieves message only from response
|
|
1316
1293
|
|
|
1317
1294
|
Args:
|
|
@@ -1321,13 +1298,24 @@ class KOBOLDAI(Provider):
|
|
|
1321
1298
|
str: Message extracted
|
|
1322
1299
|
"""
|
|
1323
1300
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1301
|
+
try:
|
|
1302
|
+
if response["choices"][0].get("delta"):
|
|
1303
|
+
return response["choices"][0]["delta"]["content"]
|
|
1304
|
+
return response["choices"][0]["message"]["content"]
|
|
1305
|
+
except KeyError:
|
|
1306
|
+
return ""
|
|
1307
|
+
#----------------------------------------------------------OpenAI-----------------------------------
|
|
1308
|
+
class OPENAI(Provider):
|
|
1327
1309
|
def __init__(
|
|
1328
1310
|
self,
|
|
1311
|
+
api_key: str,
|
|
1329
1312
|
is_conversation: bool = True,
|
|
1330
1313
|
max_tokens: int = 600,
|
|
1314
|
+
temperature: float = 1,
|
|
1315
|
+
presence_penalty: int = 0,
|
|
1316
|
+
frequency_penalty: int = 0,
|
|
1317
|
+
top_p: float = 1,
|
|
1318
|
+
model: str = "gpt-3.5-turbo",
|
|
1331
1319
|
timeout: int = 30,
|
|
1332
1320
|
intro: str = None,
|
|
1333
1321
|
filepath: str = None,
|
|
@@ -1336,11 +1324,17 @@ class OPENGPT:
|
|
|
1336
1324
|
history_offset: int = 10250,
|
|
1337
1325
|
act: str = None,
|
|
1338
1326
|
):
|
|
1339
|
-
"""Instantiates
|
|
1327
|
+
"""Instantiates OPENAI
|
|
1340
1328
|
|
|
1341
1329
|
Args:
|
|
1342
|
-
|
|
1330
|
+
api_key (key): OpenAI's API key.
|
|
1331
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
1343
1332
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
1333
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 1.
|
|
1334
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
1335
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
1336
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
1337
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
1344
1338
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
1345
1339
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
1346
1340
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -1349,30 +1343,21 @@ class OPENGPT:
|
|
|
1349
1343
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1350
1344
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1351
1345
|
"""
|
|
1352
|
-
self.session = requests.Session()
|
|
1353
|
-
self.max_tokens_to_sample = max_tokens
|
|
1354
1346
|
self.is_conversation = is_conversation
|
|
1355
|
-
self.
|
|
1356
|
-
|
|
1357
|
-
|
|
1347
|
+
self.max_tokens_to_sample = max_tokens
|
|
1348
|
+
self.api_key = api_key
|
|
1349
|
+
self.model = model
|
|
1350
|
+
self.temperature = temperature
|
|
1351
|
+
self.presence_penalty = presence_penalty
|
|
1352
|
+
self.frequency_penalty = frequency_penalty
|
|
1353
|
+
self.top_p = top_p
|
|
1354
|
+
self.chat_endpoint = "https://api.openai.com/v1/chat/completions"
|
|
1358
1355
|
self.stream_chunk_size = 64
|
|
1359
1356
|
self.timeout = timeout
|
|
1360
1357
|
self.last_response = {}
|
|
1361
|
-
self.assistant_id = "bca37014-6f97-4f2b-8928-81ea8d478d88"
|
|
1362
|
-
self.authority = "opengpts-example-vz4y4ooboq-uc.a.run.app"
|
|
1363
|
-
|
|
1364
1358
|
self.headers = {
|
|
1365
|
-
"
|
|
1366
|
-
"
|
|
1367
|
-
"accept-language": "en-US,en;q=0.7",
|
|
1368
|
-
"cache-control": "no-cache",
|
|
1369
|
-
"content-type": "application/json",
|
|
1370
|
-
"origin": "https://opengpts-example-vz4y4ooboq-uc.a.run.app",
|
|
1371
|
-
"pragma": "no-cache",
|
|
1372
|
-
"referer": "https://opengpts-example-vz4y4ooboq-uc.a.run.app/",
|
|
1373
|
-
"sec-fetch-site": "same-origin",
|
|
1374
|
-
"sec-gpc": "1",
|
|
1375
|
-
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
1359
|
+
"Content-Type": "application/json",
|
|
1360
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
1376
1361
|
}
|
|
1377
1362
|
|
|
1378
1363
|
self.__available_optimizers = (
|
|
@@ -1414,27 +1399,25 @@ class OPENGPT:
|
|
|
1414
1399
|
dict : {}
|
|
1415
1400
|
```json
|
|
1416
1401
|
{
|
|
1417
|
-
"
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1402
|
+
"id": "chatcmpl-TaREJpBZsRVQFRFic1wIA7Q7XfnaD",
|
|
1403
|
+
"object": "chat.completion",
|
|
1404
|
+
"created": 1704623244,
|
|
1405
|
+
"model": "gpt-3.5-turbo",
|
|
1406
|
+
"usage": {
|
|
1407
|
+
"prompt_tokens": 0,
|
|
1408
|
+
"completion_tokens": 0,
|
|
1409
|
+
"total_tokens": 0
|
|
1423
1410
|
},
|
|
1411
|
+
"choices": [
|
|
1424
1412
|
{
|
|
1425
|
-
"
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
"return_values": {
|
|
1429
|
-
"output": "Hello! How can I assist you today?"
|
|
1430
|
-
},
|
|
1431
|
-
"log": "Hello! How can I assist you today?",
|
|
1432
|
-
"type": "AgentFinish"
|
|
1433
|
-
}
|
|
1413
|
+
"message": {
|
|
1414
|
+
"role": "assistant",
|
|
1415
|
+
"content": "Hello! How can I assist you today?"
|
|
1434
1416
|
},
|
|
1435
|
-
"
|
|
1436
|
-
"
|
|
1437
|
-
}
|
|
1417
|
+
"finish_reason": "stop",
|
|
1418
|
+
"index": 0
|
|
1419
|
+
}
|
|
1420
|
+
]
|
|
1438
1421
|
}
|
|
1439
1422
|
```
|
|
1440
1423
|
"""
|
|
@@ -1445,10 +1428,1301 @@ class OPENGPT:
|
|
|
1445
1428
|
conversation_prompt if conversationally else prompt
|
|
1446
1429
|
)
|
|
1447
1430
|
else:
|
|
1448
|
-
raise
|
|
1431
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
1449
1432
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1450
1433
|
)
|
|
1451
|
-
|
|
1434
|
+
self.session.headers.update(self.headers)
|
|
1435
|
+
payload = {
|
|
1436
|
+
"frequency_penalty": self.frequency_penalty,
|
|
1437
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
1438
|
+
"model": self.model,
|
|
1439
|
+
"presence_penalty": self.presence_penalty,
|
|
1440
|
+
"stream": stream,
|
|
1441
|
+
"temperature": self.temperature,
|
|
1442
|
+
"top_p": self.top_p,
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
def for_stream():
|
|
1446
|
+
response = self.session.post(
|
|
1447
|
+
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
1448
|
+
)
|
|
1449
|
+
if not response.ok:
|
|
1450
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
1451
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1452
|
+
)
|
|
1453
|
+
|
|
1454
|
+
message_load = ""
|
|
1455
|
+
for value in response.iter_lines(
|
|
1456
|
+
decode_unicode=True,
|
|
1457
|
+
delimiter="" if raw else "data:",
|
|
1458
|
+
chunk_size=self.stream_chunk_size,
|
|
1459
|
+
):
|
|
1460
|
+
try:
|
|
1461
|
+
resp = json.loads(value)
|
|
1462
|
+
incomplete_message = self.get_message(resp)
|
|
1463
|
+
if incomplete_message:
|
|
1464
|
+
message_load += incomplete_message
|
|
1465
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
1466
|
+
self.last_response.update(resp)
|
|
1467
|
+
yield value if raw else resp
|
|
1468
|
+
elif raw:
|
|
1469
|
+
yield value
|
|
1470
|
+
except json.decoder.JSONDecodeError:
|
|
1471
|
+
pass
|
|
1472
|
+
self.conversation.update_chat_history(
|
|
1473
|
+
prompt, self.get_message(self.last_response)
|
|
1474
|
+
)
|
|
1475
|
+
|
|
1476
|
+
def for_non_stream():
|
|
1477
|
+
response = self.session.post(
|
|
1478
|
+
self.chat_endpoint, json=payload, stream=False, timeout=self.timeout
|
|
1479
|
+
)
|
|
1480
|
+
if (
|
|
1481
|
+
not response.ok
|
|
1482
|
+
or not response.headers.get("Content-Type", "") == "application/json"
|
|
1483
|
+
):
|
|
1484
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
1485
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1486
|
+
)
|
|
1487
|
+
resp = response.json()
|
|
1488
|
+
self.last_response.update(resp)
|
|
1489
|
+
self.conversation.update_chat_history(
|
|
1490
|
+
prompt, self.get_message(self.last_response)
|
|
1491
|
+
)
|
|
1492
|
+
return resp
|
|
1493
|
+
|
|
1494
|
+
return for_stream() if stream else for_non_stream()
|
|
1495
|
+
|
|
1496
|
+
def chat(
|
|
1497
|
+
self,
|
|
1498
|
+
prompt: str,
|
|
1499
|
+
stream: bool = False,
|
|
1500
|
+
optimizer: str = None,
|
|
1501
|
+
conversationally: bool = False,
|
|
1502
|
+
) -> str:
|
|
1503
|
+
"""Generate response `str`
|
|
1504
|
+
Args:
|
|
1505
|
+
prompt (str): Prompt to be send.
|
|
1506
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1507
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1508
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1509
|
+
Returns:
|
|
1510
|
+
str: Response generated
|
|
1511
|
+
"""
|
|
1512
|
+
|
|
1513
|
+
def for_stream():
|
|
1514
|
+
for response in self.ask(
|
|
1515
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
1516
|
+
):
|
|
1517
|
+
yield self.get_message(response)
|
|
1518
|
+
|
|
1519
|
+
def for_non_stream():
|
|
1520
|
+
return self.get_message(
|
|
1521
|
+
self.ask(
|
|
1522
|
+
prompt,
|
|
1523
|
+
False,
|
|
1524
|
+
optimizer=optimizer,
|
|
1525
|
+
conversationally=conversationally,
|
|
1526
|
+
)
|
|
1527
|
+
)
|
|
1528
|
+
|
|
1529
|
+
return for_stream() if stream else for_non_stream()
|
|
1530
|
+
|
|
1531
|
+
def get_message(self, response: dict) -> str:
|
|
1532
|
+
"""Retrieves message only from response
|
|
1533
|
+
|
|
1534
|
+
Args:
|
|
1535
|
+
response (dict): Response generated by `self.ask`
|
|
1536
|
+
|
|
1537
|
+
Returns:
|
|
1538
|
+
str: Message extracted
|
|
1539
|
+
"""
|
|
1540
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1541
|
+
try:
|
|
1542
|
+
if response["choices"][0].get("delta"):
|
|
1543
|
+
return response["choices"][0]["delta"]["content"]
|
|
1544
|
+
return response["choices"][0]["message"]["content"]
|
|
1545
|
+
except KeyError:
|
|
1546
|
+
return ""
|
|
1547
|
+
class AsyncOPENAI(AsyncProvider):
|
|
1548
|
+
def __init__(
|
|
1549
|
+
self,
|
|
1550
|
+
api_key: str,
|
|
1551
|
+
is_conversation: bool = True,
|
|
1552
|
+
max_tokens: int = 600,
|
|
1553
|
+
temperature: float = 1,
|
|
1554
|
+
presence_penalty: int = 0,
|
|
1555
|
+
frequency_penalty: int = 0,
|
|
1556
|
+
top_p: float = 1,
|
|
1557
|
+
model: str = "gpt-3.5-turbo",
|
|
1558
|
+
timeout: int = 30,
|
|
1559
|
+
intro: str = None,
|
|
1560
|
+
filepath: str = None,
|
|
1561
|
+
update_file: bool = True,
|
|
1562
|
+
proxies: dict = {},
|
|
1563
|
+
history_offset: int = 10250,
|
|
1564
|
+
act: str = None,
|
|
1565
|
+
):
|
|
1566
|
+
"""Instantiates OPENAI
|
|
1567
|
+
|
|
1568
|
+
Args:
|
|
1569
|
+
api_key (key): OpenAI's API key.
|
|
1570
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
1571
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
1572
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 1.
|
|
1573
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
1574
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
1575
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
1576
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
1577
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
1578
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
1579
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
1580
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
1581
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
1582
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1583
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1584
|
+
"""
|
|
1585
|
+
self.is_conversation = is_conversation
|
|
1586
|
+
self.max_tokens_to_sample = max_tokens
|
|
1587
|
+
self.api_key = api_key
|
|
1588
|
+
self.model = model
|
|
1589
|
+
self.temperature = temperature
|
|
1590
|
+
self.presence_penalty = presence_penalty
|
|
1591
|
+
self.frequency_penalty = frequency_penalty
|
|
1592
|
+
self.top_p = top_p
|
|
1593
|
+
self.chat_endpoint = "https://api.openai.com/v1/chat/completions"
|
|
1594
|
+
self.stream_chunk_size = 64
|
|
1595
|
+
self.timeout = timeout
|
|
1596
|
+
self.last_response = {}
|
|
1597
|
+
self.headers = {
|
|
1598
|
+
"Content-Type": "application/json",
|
|
1599
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
self.__available_optimizers = (
|
|
1603
|
+
method
|
|
1604
|
+
for method in dir(Optimizers)
|
|
1605
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
1606
|
+
)
|
|
1607
|
+
Conversation.intro = (
|
|
1608
|
+
AwesomePrompts().get_act(
|
|
1609
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
1610
|
+
)
|
|
1611
|
+
if act
|
|
1612
|
+
else intro or Conversation.intro
|
|
1613
|
+
)
|
|
1614
|
+
self.conversation = Conversation(
|
|
1615
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
1616
|
+
)
|
|
1617
|
+
self.conversation.history_offset = history_offset
|
|
1618
|
+
self.session = httpx.AsyncClient(
|
|
1619
|
+
headers=self.headers,
|
|
1620
|
+
proxies=proxies,
|
|
1621
|
+
)
|
|
1622
|
+
|
|
1623
|
+
async def ask(
|
|
1624
|
+
self,
|
|
1625
|
+
prompt: str,
|
|
1626
|
+
stream: bool = False,
|
|
1627
|
+
raw: bool = False,
|
|
1628
|
+
optimizer: str = None,
|
|
1629
|
+
conversationally: bool = False,
|
|
1630
|
+
) -> dict | AsyncGenerator:
|
|
1631
|
+
"""Chat with AI asynchronously.
|
|
1632
|
+
|
|
1633
|
+
Args:
|
|
1634
|
+
prompt (str): Prompt to be send.
|
|
1635
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1636
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
1637
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1638
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1639
|
+
Returns:
|
|
1640
|
+
dict|AsyncGenerator : ai content.
|
|
1641
|
+
```json
|
|
1642
|
+
{
|
|
1643
|
+
"id": "chatcmpl-TaREJpBZsRVQFRFic1wIA7Q7XfnaD",
|
|
1644
|
+
"object": "chat.completion",
|
|
1645
|
+
"created": 1704623244,
|
|
1646
|
+
"model": "gpt-3.5-turbo",
|
|
1647
|
+
"usage": {
|
|
1648
|
+
"prompt_tokens": 0,
|
|
1649
|
+
"completion_tokens": 0,
|
|
1650
|
+
"total_tokens": 0
|
|
1651
|
+
},
|
|
1652
|
+
"choices": [
|
|
1653
|
+
{
|
|
1654
|
+
"message": {
|
|
1655
|
+
"role": "assistant",
|
|
1656
|
+
"content": "Hello! How can I assist you today?"
|
|
1657
|
+
},
|
|
1658
|
+
"finish_reason": "stop",
|
|
1659
|
+
"index": 0
|
|
1660
|
+
}
|
|
1661
|
+
]
|
|
1662
|
+
}
|
|
1663
|
+
```
|
|
1664
|
+
"""
|
|
1665
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
1666
|
+
if optimizer:
|
|
1667
|
+
if optimizer in self.__available_optimizers:
|
|
1668
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
1669
|
+
conversation_prompt if conversationally else prompt
|
|
1670
|
+
)
|
|
1671
|
+
else:
|
|
1672
|
+
raise Exception(
|
|
1673
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1674
|
+
)
|
|
1675
|
+
payload = {
|
|
1676
|
+
"frequency_penalty": self.frequency_penalty,
|
|
1677
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
1678
|
+
"model": self.model,
|
|
1679
|
+
"presence_penalty": self.presence_penalty,
|
|
1680
|
+
"stream": stream,
|
|
1681
|
+
"temperature": self.temperature,
|
|
1682
|
+
"top_p": self.top_p,
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
async def for_stream():
|
|
1686
|
+
async with self.session.stream(
|
|
1687
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
1688
|
+
) as response:
|
|
1689
|
+
if not response.is_success:
|
|
1690
|
+
raise Exception(
|
|
1691
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
1692
|
+
)
|
|
1693
|
+
|
|
1694
|
+
message_load = ""
|
|
1695
|
+
async for value in response.aiter_lines():
|
|
1696
|
+
try:
|
|
1697
|
+
|
|
1698
|
+
resp = sanitize_stream(value)
|
|
1699
|
+
incomplete_message = await self.get_message(resp)
|
|
1700
|
+
if incomplete_message:
|
|
1701
|
+
message_load += incomplete_message
|
|
1702
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
1703
|
+
self.last_response.update(resp)
|
|
1704
|
+
yield value if raw else resp
|
|
1705
|
+
elif raw:
|
|
1706
|
+
yield value
|
|
1707
|
+
except json.decoder.JSONDecodeError:
|
|
1708
|
+
pass
|
|
1709
|
+
self.conversation.update_chat_history(
|
|
1710
|
+
prompt, await self.get_message(self.last_response)
|
|
1711
|
+
)
|
|
1712
|
+
|
|
1713
|
+
async def for_non_stream():
|
|
1714
|
+
response = httpx.post(
|
|
1715
|
+
self.chat_endpoint,
|
|
1716
|
+
json=payload,
|
|
1717
|
+
timeout=self.timeout,
|
|
1718
|
+
headers=self.headers,
|
|
1719
|
+
)
|
|
1720
|
+
if (
|
|
1721
|
+
not response.is_success
|
|
1722
|
+
or not response.headers.get("Content-Type", "") == "application/json"
|
|
1723
|
+
):
|
|
1724
|
+
raise Exception(
|
|
1725
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
1726
|
+
)
|
|
1727
|
+
resp = response.json()
|
|
1728
|
+
self.last_response.update(resp)
|
|
1729
|
+
self.conversation.update_chat_history(
|
|
1730
|
+
prompt, await self.get_message(self.last_response)
|
|
1731
|
+
)
|
|
1732
|
+
return resp
|
|
1733
|
+
|
|
1734
|
+
return for_stream() if stream else await for_non_stream()
|
|
1735
|
+
|
|
1736
|
+
async def chat(
|
|
1737
|
+
self,
|
|
1738
|
+
prompt: str,
|
|
1739
|
+
stream: bool = False,
|
|
1740
|
+
optimizer: str = None,
|
|
1741
|
+
conversationally: bool = False,
|
|
1742
|
+
) -> str | AsyncGenerator:
|
|
1743
|
+
"""Generate response `str` asynchronously.
|
|
1744
|
+
Args:
|
|
1745
|
+
prompt (str): Prompt to be send.
|
|
1746
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1747
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1748
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1749
|
+
Returns:
|
|
1750
|
+
str|AsyncGenerator: Response generated
|
|
1751
|
+
"""
|
|
1752
|
+
|
|
1753
|
+
async def for_stream():
|
|
1754
|
+
async_ask = await self.ask(
|
|
1755
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
1756
|
+
)
|
|
1757
|
+
async for response in async_ask:
|
|
1758
|
+
yield await self.get_message(response)
|
|
1759
|
+
|
|
1760
|
+
async def for_non_stream():
|
|
1761
|
+
return await self.get_message(
|
|
1762
|
+
await self.ask(
|
|
1763
|
+
prompt,
|
|
1764
|
+
False,
|
|
1765
|
+
optimizer=optimizer,
|
|
1766
|
+
conversationally=conversationally,
|
|
1767
|
+
)
|
|
1768
|
+
)
|
|
1769
|
+
|
|
1770
|
+
return for_stream() if stream else await for_non_stream()
|
|
1771
|
+
|
|
1772
|
+
async def get_message(self, response: dict) -> str:
|
|
1773
|
+
"""Retrieves message only from response asynchronously.
|
|
1774
|
+
|
|
1775
|
+
Args:
|
|
1776
|
+
response (dict): Response generated by `self.ask`
|
|
1777
|
+
|
|
1778
|
+
Returns:
|
|
1779
|
+
str: Message extracted
|
|
1780
|
+
"""
|
|
1781
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1782
|
+
try:
|
|
1783
|
+
if response["choices"][0].get("delta"):
|
|
1784
|
+
return response["choices"][0]["delta"]["content"]
|
|
1785
|
+
return response["choices"][0]["message"]["content"]
|
|
1786
|
+
except KeyError:
|
|
1787
|
+
return ""
|
|
1788
|
+
#--------------------------------------LEO-----------------------------------------
|
|
1789
|
+
class LEO(Provider):
|
|
1790
|
+
|
|
1791
|
+
def __init__(
|
|
1792
|
+
self,
|
|
1793
|
+
is_conversation: bool = True,
|
|
1794
|
+
max_tokens: int = 600,
|
|
1795
|
+
temperature: float = 0.2,
|
|
1796
|
+
top_k: int = -1,
|
|
1797
|
+
top_p: float = 0.999,
|
|
1798
|
+
model: str = "llama-2-13b-chat",
|
|
1799
|
+
brave_key: str = "qztbjzBqJueQZLFkwTTJrieu8Vw3789u",
|
|
1800
|
+
timeout: int = 30,
|
|
1801
|
+
intro: str = None,
|
|
1802
|
+
filepath: str = None,
|
|
1803
|
+
update_file: bool = True,
|
|
1804
|
+
proxies: dict = {},
|
|
1805
|
+
history_offset: int = 10250,
|
|
1806
|
+
act: str = None,
|
|
1807
|
+
):
|
|
1808
|
+
"""Instantiate TGPT
|
|
1809
|
+
|
|
1810
|
+
Args:
|
|
1811
|
+
is_conversation (str, optional): Flag for chatting conversationally. Defaults to True.
|
|
1812
|
+
brave_key (str, optional): Brave API access key. Defaults to "qztbjzBqJueQZLFkwTTJrieu8Vw3789u".
|
|
1813
|
+
model (str, optional): Text generation model name. Defaults to "llama-2-13b-chat".
|
|
1814
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
1815
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.2.
|
|
1816
|
+
top_k (int, optional): Chance of topic being repeated. Defaults to -1.
|
|
1817
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
1818
|
+
timeput (int, optional): Http requesting timeout. Defaults to 30
|
|
1819
|
+
intro (str, optional): Conversation introductory prompt. Defaults to `Conversation.intro`.
|
|
1820
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
1821
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
1822
|
+
proxies (dict, optional) : Http reqiuest proxies (socks). Defaults to {}.
|
|
1823
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1824
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1825
|
+
"""
|
|
1826
|
+
self.session = requests.Session()
|
|
1827
|
+
self.is_conversation = is_conversation
|
|
1828
|
+
self.max_tokens_to_sample = max_tokens
|
|
1829
|
+
self.model = model
|
|
1830
|
+
self.stop_sequences = ["</response>", "</s>"]
|
|
1831
|
+
self.temperature = temperature
|
|
1832
|
+
self.top_k = top_k
|
|
1833
|
+
self.top_p = top_p
|
|
1834
|
+
self.chat_endpoint = "https://ai-chat.bsg.brave.com/v1/complete"
|
|
1835
|
+
self.stream_chunk_size = 64
|
|
1836
|
+
self.timeout = timeout
|
|
1837
|
+
self.last_response = {}
|
|
1838
|
+
self.headers = {
|
|
1839
|
+
"Content-Type": "application/json",
|
|
1840
|
+
"accept": "text/event-stream",
|
|
1841
|
+
"x-brave-key": brave_key,
|
|
1842
|
+
"accept-language": "en-US,en;q=0.9",
|
|
1843
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/110.0",
|
|
1844
|
+
}
|
|
1845
|
+
self.__available_optimizers = (
|
|
1846
|
+
method
|
|
1847
|
+
for method in dir(Optimizers)
|
|
1848
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
1849
|
+
)
|
|
1850
|
+
self.session.headers.update(self.headers)
|
|
1851
|
+
Conversation.intro = (
|
|
1852
|
+
AwesomePrompts().get_act(
|
|
1853
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
1854
|
+
)
|
|
1855
|
+
if act
|
|
1856
|
+
else intro or Conversation.intro
|
|
1857
|
+
)
|
|
1858
|
+
self.conversation = Conversation(
|
|
1859
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
1860
|
+
)
|
|
1861
|
+
self.conversation.history_offset = history_offset
|
|
1862
|
+
self.session.proxies = proxies
|
|
1863
|
+
self.system_prompt = (
|
|
1864
|
+
"\n\nYour name is Leo, a helpful"
|
|
1865
|
+
"respectful and honest AI assistant created by the company Brave. You will be replying to a user of the Brave browser. "
|
|
1866
|
+
"Always respond in a neutral tone. Be polite and courteous. Answer concisely in no more than 50-80 words."
|
|
1867
|
+
"\n\nPlease ensure that your responses are socially unbiased and positive in nature."
|
|
1868
|
+
"If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. "
|
|
1869
|
+
"If you don't know the answer to a question, please don't share false information.\n"
|
|
1870
|
+
)
|
|
1871
|
+
|
|
1872
|
+
def ask(
|
|
1873
|
+
self,
|
|
1874
|
+
prompt: str,
|
|
1875
|
+
stream: bool = False,
|
|
1876
|
+
raw: bool = False,
|
|
1877
|
+
optimizer: str = None,
|
|
1878
|
+
conversationally: bool = False,
|
|
1879
|
+
) -> dict:
|
|
1880
|
+
"""Chat with AI
|
|
1881
|
+
|
|
1882
|
+
Args:
|
|
1883
|
+
prompt (str): Prompt to be send.
|
|
1884
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1885
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
1886
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1887
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1888
|
+
Returns:
|
|
1889
|
+
dict : {}
|
|
1890
|
+
```json
|
|
1891
|
+
{
|
|
1892
|
+
"completion": "\nNext: domestic cat breeds with short hair >>",
|
|
1893
|
+
"stop_reason": null,
|
|
1894
|
+
"truncated": false,
|
|
1895
|
+
"stop": null,
|
|
1896
|
+
"model": "llama-2-13b-chat",
|
|
1897
|
+
"log_id": "cmpl-3kYiYxSNDvgMShSzFooz6t",
|
|
1898
|
+
"exception": null
|
|
1899
|
+
}
|
|
1900
|
+
```
|
|
1901
|
+
"""
|
|
1902
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
1903
|
+
if optimizer:
|
|
1904
|
+
if optimizer in self.__available_optimizers:
|
|
1905
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
1906
|
+
conversation_prompt if conversationally else prompt
|
|
1907
|
+
)
|
|
1908
|
+
else:
|
|
1909
|
+
raise Exception(
|
|
1910
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1911
|
+
)
|
|
1912
|
+
|
|
1913
|
+
self.session.headers.update(self.headers)
|
|
1914
|
+
payload = {
|
|
1915
|
+
"max_tokens_to_sample": self.max_tokens_to_sample,
|
|
1916
|
+
"model": self.model,
|
|
1917
|
+
"prompt": f"<s>[INST] <<SYS>>{self.system_prompt}<</SYS>>{conversation_prompt} [/INST]",
|
|
1918
|
+
"self.stop_sequence": self.stop_sequences,
|
|
1919
|
+
"stream": stream,
|
|
1920
|
+
"top_k": self.top_k,
|
|
1921
|
+
"top_p": self.top_p,
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
def for_stream():
|
|
1925
|
+
response = self.session.post(
|
|
1926
|
+
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
1927
|
+
)
|
|
1928
|
+
if (
|
|
1929
|
+
not response.ok
|
|
1930
|
+
or not response.headers.get("Content-Type")
|
|
1931
|
+
== "text/event-stream; charset=utf-8"
|
|
1932
|
+
):
|
|
1933
|
+
raise Exception(
|
|
1934
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1935
|
+
)
|
|
1936
|
+
|
|
1937
|
+
for value in response.iter_lines(
|
|
1938
|
+
decode_unicode=True,
|
|
1939
|
+
delimiter="" if raw else "data:",
|
|
1940
|
+
chunk_size=self.stream_chunk_size,
|
|
1941
|
+
):
|
|
1942
|
+
try:
|
|
1943
|
+
resp = json.loads(value)
|
|
1944
|
+
self.last_response.update(resp)
|
|
1945
|
+
yield value if raw else resp
|
|
1946
|
+
except json.decoder.JSONDecodeError:
|
|
1947
|
+
pass
|
|
1948
|
+
self.conversation.update_chat_history(
|
|
1949
|
+
prompt, self.get_message(self.last_response)
|
|
1950
|
+
)
|
|
1951
|
+
|
|
1952
|
+
def for_non_stream():
|
|
1953
|
+
response = self.session.post(
|
|
1954
|
+
self.chat_endpoint, json=payload, stream=False, timeout=self.timeout
|
|
1955
|
+
)
|
|
1956
|
+
if (
|
|
1957
|
+
not response.ok
|
|
1958
|
+
or not response.headers.get("Content-Type", "") == "application/json"
|
|
1959
|
+
):
|
|
1960
|
+
raise Exception(
|
|
1961
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1962
|
+
)
|
|
1963
|
+
resp = response.json()
|
|
1964
|
+
self.last_response.update(resp)
|
|
1965
|
+
self.conversation.update_chat_history(
|
|
1966
|
+
prompt, self.get_message(self.last_response)
|
|
1967
|
+
)
|
|
1968
|
+
return resp
|
|
1969
|
+
|
|
1970
|
+
return for_stream() if stream else for_non_stream()
|
|
1971
|
+
|
|
1972
|
+
def chat(
|
|
1973
|
+
self,
|
|
1974
|
+
prompt: str,
|
|
1975
|
+
stream: bool = False,
|
|
1976
|
+
optimizer: str = None,
|
|
1977
|
+
conversationally: bool = False,
|
|
1978
|
+
) -> str:
|
|
1979
|
+
"""Generate response `str`
|
|
1980
|
+
Args:
|
|
1981
|
+
prompt (str): Prompt to be send.
|
|
1982
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
1983
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1984
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1985
|
+
Returns:
|
|
1986
|
+
str: Response generated
|
|
1987
|
+
"""
|
|
1988
|
+
|
|
1989
|
+
def for_stream():
|
|
1990
|
+
for response in self.ask(
|
|
1991
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
1992
|
+
):
|
|
1993
|
+
yield self.get_message(response)
|
|
1994
|
+
|
|
1995
|
+
def for_non_stream():
|
|
1996
|
+
return self.get_message(
|
|
1997
|
+
self.ask(
|
|
1998
|
+
prompt,
|
|
1999
|
+
False,
|
|
2000
|
+
optimizer=optimizer,
|
|
2001
|
+
conversationally=conversationally,
|
|
2002
|
+
)
|
|
2003
|
+
)
|
|
2004
|
+
|
|
2005
|
+
return for_stream() if stream else for_non_stream()
|
|
2006
|
+
|
|
2007
|
+
def get_message(self, response: dict) -> str:
|
|
2008
|
+
"""Retrieves message only from response
|
|
2009
|
+
|
|
2010
|
+
Args:
|
|
2011
|
+
response (dict): Response generated by `self.ask`
|
|
2012
|
+
|
|
2013
|
+
Returns:
|
|
2014
|
+
str: Message extracted
|
|
2015
|
+
"""
|
|
2016
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2017
|
+
return response.get("completion")
|
|
2018
|
+
class AsyncLEO(AsyncProvider):
|
|
2019
|
+
def __init__(
|
|
2020
|
+
self,
|
|
2021
|
+
is_conversation: bool = True,
|
|
2022
|
+
max_tokens: int = 600,
|
|
2023
|
+
temperature: float = 0.2,
|
|
2024
|
+
top_k: int = -1,
|
|
2025
|
+
top_p: float = 0.999,
|
|
2026
|
+
model: str = "llama-2-13b-chat",
|
|
2027
|
+
brave_key: str = "qztbjzBqJueQZLFkwTTJrieu8Vw3789u",
|
|
2028
|
+
timeout: int = 30,
|
|
2029
|
+
intro: str = None,
|
|
2030
|
+
filepath: str = None,
|
|
2031
|
+
update_file: bool = True,
|
|
2032
|
+
proxies: dict = {},
|
|
2033
|
+
history_offset: int = 10250,
|
|
2034
|
+
act: str = None,
|
|
2035
|
+
):
|
|
2036
|
+
"""Instantiate TGPT
|
|
2037
|
+
|
|
2038
|
+
Args:
|
|
2039
|
+
is_conversation (str, optional): Flag for chatting conversationally. Defaults to True.
|
|
2040
|
+
brave_key (str, optional): Brave API access key. Defaults to "qztbjzBqJueQZLFkwTTJrieu8Vw3789u".
|
|
2041
|
+
model (str, optional): Text generation model name. Defaults to "llama-2-13b-chat".
|
|
2042
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
2043
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.2.
|
|
2044
|
+
top_k (int, optional): Chance of topic being repeated. Defaults to -1.
|
|
2045
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
2046
|
+
timeput (int, optional): Http requesting timeout. Defaults to 30
|
|
2047
|
+
intro (str, optional): Conversation introductory prompt. Defaults to `Conversation.intro`.
|
|
2048
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
2049
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
2050
|
+
proxies (dict, optional) : Http reqiuest proxies (socks). Defaults to {}.
|
|
2051
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
2052
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
2053
|
+
"""
|
|
2054
|
+
self.is_conversation = is_conversation
|
|
2055
|
+
self.max_tokens_to_sample = max_tokens
|
|
2056
|
+
self.model = model
|
|
2057
|
+
self.stop_sequences = ["</response>", "</s>"]
|
|
2058
|
+
self.temperature = temperature
|
|
2059
|
+
self.top_k = top_k
|
|
2060
|
+
self.top_p = top_p
|
|
2061
|
+
self.chat_endpoint = "https://ai-chat.bsg.brave.com/v1/complete"
|
|
2062
|
+
self.stream_chunk_size = 64
|
|
2063
|
+
self.timeout = timeout
|
|
2064
|
+
self.last_response = {}
|
|
2065
|
+
self.headers = {
|
|
2066
|
+
"Content-Type": "application/json",
|
|
2067
|
+
"accept": "text/event-stream",
|
|
2068
|
+
"x-brave-key": brave_key,
|
|
2069
|
+
"accept-language": "en-US,en;q=0.9",
|
|
2070
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/110.0",
|
|
2071
|
+
}
|
|
2072
|
+
self.__available_optimizers = (
|
|
2073
|
+
method
|
|
2074
|
+
for method in dir(Optimizers)
|
|
2075
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2076
|
+
)
|
|
2077
|
+
Conversation.intro = (
|
|
2078
|
+
AwesomePrompts().get_act(
|
|
2079
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
2080
|
+
)
|
|
2081
|
+
if act
|
|
2082
|
+
else intro or Conversation.intro
|
|
2083
|
+
)
|
|
2084
|
+
self.conversation = Conversation(
|
|
2085
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2086
|
+
)
|
|
2087
|
+
self.conversation.history_offset = history_offset
|
|
2088
|
+
self.system_prompt = (
|
|
2089
|
+
"\n\nYour name is Leo, a helpful"
|
|
2090
|
+
"respectful and honest AI assistant created by the company Brave. You will be replying to a user of the Brave browser. "
|
|
2091
|
+
"Always respond in a neutral tone. Be polite and courteous. Answer concisely in no more than 50-80 words."
|
|
2092
|
+
"\n\nPlease ensure that your responses are socially unbiased and positive in nature."
|
|
2093
|
+
"If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. "
|
|
2094
|
+
"If you don't know the answer to a question, please don't share false information.\n"
|
|
2095
|
+
)
|
|
2096
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
2097
|
+
|
|
2098
|
+
async def ask(
|
|
2099
|
+
self,
|
|
2100
|
+
prompt: str,
|
|
2101
|
+
stream: bool = False,
|
|
2102
|
+
raw: bool = False,
|
|
2103
|
+
optimizer: str = None,
|
|
2104
|
+
conversationally: bool = False,
|
|
2105
|
+
) -> dict | AsyncGenerator:
|
|
2106
|
+
"""Chat with AI asynchronously.
|
|
2107
|
+
|
|
2108
|
+
Args:
|
|
2109
|
+
prompt (str): Prompt to be send.
|
|
2110
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2111
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
2112
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2113
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2114
|
+
Returns:
|
|
2115
|
+
dict|AsyncGenerator : ai content
|
|
2116
|
+
```json
|
|
2117
|
+
{
|
|
2118
|
+
"completion": "\nNext: domestic cat breeds with short hair >>",
|
|
2119
|
+
"stop_reason": null,
|
|
2120
|
+
"truncated": false,
|
|
2121
|
+
"stop": null,
|
|
2122
|
+
"model": "llama-2-13b-chat",
|
|
2123
|
+
"log_id": "cmpl-3kYiYxSNDvgMShSzFooz6t",
|
|
2124
|
+
"exception": null
|
|
2125
|
+
}
|
|
2126
|
+
```
|
|
2127
|
+
"""
|
|
2128
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
2129
|
+
if optimizer:
|
|
2130
|
+
if optimizer in self.__available_optimizers:
|
|
2131
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
2132
|
+
conversation_prompt if conversationally else prompt
|
|
2133
|
+
)
|
|
2134
|
+
else:
|
|
2135
|
+
raise Exception(
|
|
2136
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2137
|
+
)
|
|
2138
|
+
|
|
2139
|
+
payload = {
|
|
2140
|
+
"max_tokens_to_sample": self.max_tokens_to_sample,
|
|
2141
|
+
"model": self.model,
|
|
2142
|
+
"prompt": f"<s>[INST] <<SYS>>{self.system_prompt}<</SYS>>{conversation_prompt} [/INST]",
|
|
2143
|
+
"self.stop_sequence": self.stop_sequences,
|
|
2144
|
+
"stream": stream,
|
|
2145
|
+
"top_k": self.top_k,
|
|
2146
|
+
"top_p": self.top_p,
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
async def for_stream():
|
|
2150
|
+
async with self.session.stream(
|
|
2151
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
2152
|
+
) as response:
|
|
2153
|
+
if (
|
|
2154
|
+
not response.is_success
|
|
2155
|
+
or not response.headers.get("Content-Type")
|
|
2156
|
+
== "text/event-stream; charset=utf-8"
|
|
2157
|
+
):
|
|
2158
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
2159
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
2160
|
+
)
|
|
2161
|
+
async for value in response.aiter_lines():
|
|
2162
|
+
try:
|
|
2163
|
+
resp = sanitize_stream(value)
|
|
2164
|
+
self.last_response.update(resp)
|
|
2165
|
+
yield value if raw else resp
|
|
2166
|
+
except json.decoder.JSONDecodeError:
|
|
2167
|
+
pass
|
|
2168
|
+
|
|
2169
|
+
self.conversation.update_chat_history(
|
|
2170
|
+
prompt, await self.get_message(self.last_response)
|
|
2171
|
+
)
|
|
2172
|
+
|
|
2173
|
+
async def for_non_stream():
|
|
2174
|
+
async for _ in for_stream():
|
|
2175
|
+
pass
|
|
2176
|
+
return self.last_response
|
|
2177
|
+
|
|
2178
|
+
return for_stream() if stream else await for_non_stream()
|
|
2179
|
+
|
|
2180
|
+
async def chat(
|
|
2181
|
+
self,
|
|
2182
|
+
prompt: str,
|
|
2183
|
+
stream: bool = False,
|
|
2184
|
+
optimizer: str = None,
|
|
2185
|
+
conversationally: bool = False,
|
|
2186
|
+
) -> str | AsyncGenerator:
|
|
2187
|
+
"""Generate response `str` asynchronously.
|
|
2188
|
+
Args:
|
|
2189
|
+
prompt (str): Prompt to be send.
|
|
2190
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2191
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2192
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2193
|
+
Returns:
|
|
2194
|
+
str|AsyncGenerator: Response generated
|
|
2195
|
+
"""
|
|
2196
|
+
|
|
2197
|
+
async def for_stream():
|
|
2198
|
+
async_ask = await self.ask(
|
|
2199
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
2200
|
+
)
|
|
2201
|
+
async for response in async_ask:
|
|
2202
|
+
yield await self.get_message(response)
|
|
2203
|
+
|
|
2204
|
+
async def for_non_stream():
|
|
2205
|
+
return await self.get_message(
|
|
2206
|
+
await self.ask(
|
|
2207
|
+
prompt,
|
|
2208
|
+
False,
|
|
2209
|
+
optimizer=optimizer,
|
|
2210
|
+
conversationally=conversationally,
|
|
2211
|
+
)
|
|
2212
|
+
)
|
|
2213
|
+
|
|
2214
|
+
return for_stream() if stream else await for_non_stream()
|
|
2215
|
+
|
|
2216
|
+
async def get_message(self, response: dict) -> str:
|
|
2217
|
+
"""Retrieves message only from response
|
|
2218
|
+
|
|
2219
|
+
Args:
|
|
2220
|
+
response (dict): Response generated by `self.ask`
|
|
2221
|
+
|
|
2222
|
+
Returns:
|
|
2223
|
+
str: Message extracted
|
|
2224
|
+
"""
|
|
2225
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2226
|
+
return response.get("completion")
|
|
2227
|
+
#------------------------------------------------------KOBOLDAI-----------------------------------------------------------
|
|
2228
|
+
class KOBOLDAI(Provider):
|
|
2229
|
+
def __init__(
|
|
2230
|
+
self,
|
|
2231
|
+
is_conversation: bool = True,
|
|
2232
|
+
max_tokens: int = 600,
|
|
2233
|
+
temperature: float = 1,
|
|
2234
|
+
top_p: float = 1,
|
|
2235
|
+
timeout: int = 30,
|
|
2236
|
+
intro: str = None,
|
|
2237
|
+
filepath: str = None,
|
|
2238
|
+
update_file: bool = True,
|
|
2239
|
+
proxies: dict = {},
|
|
2240
|
+
history_offset: int = 10250,
|
|
2241
|
+
act: str = None,
|
|
2242
|
+
):
|
|
2243
|
+
"""Instantiate TGPT
|
|
2244
|
+
|
|
2245
|
+
Args:
|
|
2246
|
+
is_conversation (str, optional): Flag for chatting conversationally. Defaults to True.
|
|
2247
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
2248
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.2.
|
|
2249
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
2250
|
+
timeout (int, optional): Http requesting timeout. Defaults to 30
|
|
2251
|
+
intro (str, optional): Conversation introductory prompt. Defaults to `Conversation.intro`.
|
|
2252
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
2253
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
2254
|
+
proxies (dict, optional) : Http reqiuest proxies (socks). Defaults to {}.
|
|
2255
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
2256
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
2257
|
+
"""
|
|
2258
|
+
self.session = requests.Session()
|
|
2259
|
+
self.is_conversation = is_conversation
|
|
2260
|
+
self.max_tokens_to_sample = max_tokens
|
|
2261
|
+
self.temperature = temperature
|
|
2262
|
+
self.top_p = top_p
|
|
2263
|
+
self.chat_endpoint = (
|
|
2264
|
+
"https://koboldai-koboldcpp-tiefighter.hf.space/api/extra/generate/stream"
|
|
2265
|
+
)
|
|
2266
|
+
self.stream_chunk_size = 64
|
|
2267
|
+
self.timeout = timeout
|
|
2268
|
+
self.last_response = {}
|
|
2269
|
+
self.headers = {
|
|
2270
|
+
"Content-Type": "application/json",
|
|
2271
|
+
"Accept": "application/json",
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
self.__available_optimizers = (
|
|
2275
|
+
method
|
|
2276
|
+
for method in dir(Optimizers)
|
|
2277
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2278
|
+
)
|
|
2279
|
+
self.session.headers.update(self.headers)
|
|
2280
|
+
Conversation.intro = (
|
|
2281
|
+
AwesomePrompts().get_act(
|
|
2282
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
2283
|
+
)
|
|
2284
|
+
if act
|
|
2285
|
+
else intro or Conversation.intro
|
|
2286
|
+
)
|
|
2287
|
+
self.conversation = Conversation(
|
|
2288
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2289
|
+
)
|
|
2290
|
+
self.conversation.history_offset = history_offset
|
|
2291
|
+
self.session.proxies = proxies
|
|
2292
|
+
|
|
2293
|
+
def ask(
|
|
2294
|
+
self,
|
|
2295
|
+
prompt: str,
|
|
2296
|
+
stream: bool = False,
|
|
2297
|
+
raw: bool = False,
|
|
2298
|
+
optimizer: str = None,
|
|
2299
|
+
conversationally: bool = False,
|
|
2300
|
+
) -> dict:
|
|
2301
|
+
"""Chat with AI
|
|
2302
|
+
|
|
2303
|
+
Args:
|
|
2304
|
+
prompt (str): Prompt to be send.
|
|
2305
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2306
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
2307
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2308
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2309
|
+
Returns:
|
|
2310
|
+
dict : {}
|
|
2311
|
+
```json
|
|
2312
|
+
{
|
|
2313
|
+
"token" : "How may I assist you today?"
|
|
2314
|
+
}
|
|
2315
|
+
```
|
|
2316
|
+
"""
|
|
2317
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
2318
|
+
if optimizer:
|
|
2319
|
+
if optimizer in self.__available_optimizers:
|
|
2320
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
2321
|
+
conversation_prompt if conversationally else prompt
|
|
2322
|
+
)
|
|
2323
|
+
else:
|
|
2324
|
+
raise Exception(
|
|
2325
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2326
|
+
)
|
|
2327
|
+
|
|
2328
|
+
self.session.headers.update(self.headers)
|
|
2329
|
+
payload = {
|
|
2330
|
+
"prompt": conversation_prompt,
|
|
2331
|
+
"temperature": self.temperature,
|
|
2332
|
+
"top_p": self.top_p,
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
def for_stream():
|
|
2336
|
+
response = self.session.post(
|
|
2337
|
+
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
2338
|
+
)
|
|
2339
|
+
if not response.ok:
|
|
2340
|
+
raise Exception(
|
|
2341
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
2342
|
+
)
|
|
2343
|
+
|
|
2344
|
+
message_load = ""
|
|
2345
|
+
for value in response.iter_lines(
|
|
2346
|
+
decode_unicode=True,
|
|
2347
|
+
delimiter="" if raw else "event: message\ndata:",
|
|
2348
|
+
chunk_size=self.stream_chunk_size,
|
|
2349
|
+
):
|
|
2350
|
+
try:
|
|
2351
|
+
resp = json.loads(value)
|
|
2352
|
+
message_load += self.get_message(resp)
|
|
2353
|
+
resp["token"] = message_load
|
|
2354
|
+
self.last_response.update(resp)
|
|
2355
|
+
yield value if raw else resp
|
|
2356
|
+
except json.decoder.JSONDecodeError:
|
|
2357
|
+
pass
|
|
2358
|
+
self.conversation.update_chat_history(
|
|
2359
|
+
prompt, self.get_message(self.last_response)
|
|
2360
|
+
)
|
|
2361
|
+
|
|
2362
|
+
def for_non_stream():
|
|
2363
|
+
# let's make use of stream
|
|
2364
|
+
for _ in for_stream():
|
|
2365
|
+
pass
|
|
2366
|
+
return self.last_response
|
|
2367
|
+
|
|
2368
|
+
return for_stream() if stream else for_non_stream()
|
|
2369
|
+
|
|
2370
|
+
def chat(
|
|
2371
|
+
self,
|
|
2372
|
+
prompt: str,
|
|
2373
|
+
stream: bool = False,
|
|
2374
|
+
optimizer: str = None,
|
|
2375
|
+
conversationally: bool = False,
|
|
2376
|
+
) -> str:
|
|
2377
|
+
"""Generate response `str`
|
|
2378
|
+
Args:
|
|
2379
|
+
prompt (str): Prompt to be send.
|
|
2380
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2381
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2382
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2383
|
+
Returns:
|
|
2384
|
+
str: Response generated
|
|
2385
|
+
"""
|
|
2386
|
+
|
|
2387
|
+
def for_stream():
|
|
2388
|
+
for response in self.ask(
|
|
2389
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
2390
|
+
):
|
|
2391
|
+
yield self.get_message(response)
|
|
2392
|
+
|
|
2393
|
+
def for_non_stream():
|
|
2394
|
+
return self.get_message(
|
|
2395
|
+
self.ask(
|
|
2396
|
+
prompt,
|
|
2397
|
+
False,
|
|
2398
|
+
optimizer=optimizer,
|
|
2399
|
+
conversationally=conversationally,
|
|
2400
|
+
)
|
|
2401
|
+
)
|
|
2402
|
+
|
|
2403
|
+
return for_stream() if stream else for_non_stream()
|
|
2404
|
+
|
|
2405
|
+
def get_message(self, response: dict) -> str:
|
|
2406
|
+
"""Retrieves message only from response
|
|
2407
|
+
|
|
2408
|
+
Args:
|
|
2409
|
+
response (dict): Response generated by `self.ask`
|
|
2410
|
+
|
|
2411
|
+
Returns:
|
|
2412
|
+
str: Message extracted
|
|
2413
|
+
"""
|
|
2414
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2415
|
+
return response.get("token")
|
|
2416
|
+
class AsyncKOBOLDAI(AsyncProvider):
|
|
2417
|
+
def __init__(
|
|
2418
|
+
self,
|
|
2419
|
+
is_conversation: bool = True,
|
|
2420
|
+
max_tokens: int = 600,
|
|
2421
|
+
temperature: float = 1,
|
|
2422
|
+
top_p: float = 1,
|
|
2423
|
+
timeout: int = 30,
|
|
2424
|
+
intro: str = None,
|
|
2425
|
+
filepath: str = None,
|
|
2426
|
+
update_file: bool = True,
|
|
2427
|
+
proxies: dict = {},
|
|
2428
|
+
history_offset: int = 10250,
|
|
2429
|
+
act: str = None,
|
|
2430
|
+
):
|
|
2431
|
+
"""Instantiate TGPT
|
|
2432
|
+
|
|
2433
|
+
Args:
|
|
2434
|
+
is_conversation (str, optional): Flag for chatting conversationally. Defaults to True.
|
|
2435
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
2436
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.2.
|
|
2437
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.999.
|
|
2438
|
+
timeout (int, optional): Http requesting timeout. Defaults to 30
|
|
2439
|
+
intro (str, optional): Conversation introductory prompt. Defaults to `Conversation.intro`.
|
|
2440
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
2441
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
2442
|
+
proxies (dict, optional) : Http reqiuest proxies (socks). Defaults to {}.
|
|
2443
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
2444
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
2445
|
+
"""
|
|
2446
|
+
self.is_conversation = is_conversation
|
|
2447
|
+
self.max_tokens_to_sample = max_tokens
|
|
2448
|
+
self.temperature = temperature
|
|
2449
|
+
self.top_p = top_p
|
|
2450
|
+
self.chat_endpoint = (
|
|
2451
|
+
"https://koboldai-koboldcpp-tiefighter.hf.space/api/extra/generate/stream"
|
|
2452
|
+
)
|
|
2453
|
+
self.stream_chunk_size = 64
|
|
2454
|
+
self.timeout = timeout
|
|
2455
|
+
self.last_response = {}
|
|
2456
|
+
self.headers = {
|
|
2457
|
+
"Content-Type": "application/json",
|
|
2458
|
+
"Accept": "application/json",
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
self.__available_optimizers = (
|
|
2462
|
+
method
|
|
2463
|
+
for method in dir(Optimizers)
|
|
2464
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2465
|
+
)
|
|
2466
|
+
Conversation.intro = (
|
|
2467
|
+
AwesomePrompts().get_act(
|
|
2468
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
2469
|
+
)
|
|
2470
|
+
if act
|
|
2471
|
+
else intro or Conversation.intro
|
|
2472
|
+
)
|
|
2473
|
+
self.conversation = Conversation(
|
|
2474
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2475
|
+
)
|
|
2476
|
+
self.conversation.history_offset = history_offset
|
|
2477
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
2478
|
+
|
|
2479
|
+
async def ask(
|
|
2480
|
+
self,
|
|
2481
|
+
prompt: str,
|
|
2482
|
+
stream: bool = False,
|
|
2483
|
+
raw: bool = False,
|
|
2484
|
+
optimizer: str = None,
|
|
2485
|
+
conversationally: bool = False,
|
|
2486
|
+
) -> dict | AsyncGenerator:
|
|
2487
|
+
"""Chat with AI asynchronously.
|
|
2488
|
+
|
|
2489
|
+
Args:
|
|
2490
|
+
prompt (str): Prompt to be send.
|
|
2491
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2492
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
2493
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2494
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2495
|
+
Returns:
|
|
2496
|
+
dict|AsyncGenerator : ai content
|
|
2497
|
+
```json
|
|
2498
|
+
{
|
|
2499
|
+
"token" : "How may I assist you today?"
|
|
2500
|
+
}
|
|
2501
|
+
```
|
|
2502
|
+
"""
|
|
2503
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
2504
|
+
if optimizer:
|
|
2505
|
+
if optimizer in self.__available_optimizers:
|
|
2506
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
2507
|
+
conversation_prompt if conversationally else prompt
|
|
2508
|
+
)
|
|
2509
|
+
else:
|
|
2510
|
+
raise Exception(
|
|
2511
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2512
|
+
)
|
|
2513
|
+
|
|
2514
|
+
payload = {
|
|
2515
|
+
"prompt": conversation_prompt,
|
|
2516
|
+
"temperature": self.temperature,
|
|
2517
|
+
"top_p": self.top_p,
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
async def for_stream():
|
|
2521
|
+
async with self.session.stream(
|
|
2522
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
2523
|
+
) as response:
|
|
2524
|
+
if not response.is_success:
|
|
2525
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
2526
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
2527
|
+
)
|
|
2528
|
+
|
|
2529
|
+
message_load = ""
|
|
2530
|
+
async for value in response.aiter_lines():
|
|
2531
|
+
try:
|
|
2532
|
+
resp = sanitize_stream(value)
|
|
2533
|
+
message_load += await self.get_message(resp)
|
|
2534
|
+
resp["token"] = message_load
|
|
2535
|
+
self.last_response.update(resp)
|
|
2536
|
+
yield value if raw else resp
|
|
2537
|
+
except json.decoder.JSONDecodeError:
|
|
2538
|
+
pass
|
|
2539
|
+
|
|
2540
|
+
self.conversation.update_chat_history(
|
|
2541
|
+
prompt, await self.get_message(self.last_response)
|
|
2542
|
+
)
|
|
2543
|
+
|
|
2544
|
+
async def for_non_stream():
|
|
2545
|
+
# let's make use of stream
|
|
2546
|
+
async for _ in for_stream():
|
|
2547
|
+
pass
|
|
2548
|
+
return self.last_response
|
|
2549
|
+
|
|
2550
|
+
return for_stream() if stream else await for_non_stream()
|
|
2551
|
+
|
|
2552
|
+
async def chat(
|
|
2553
|
+
self,
|
|
2554
|
+
prompt: str,
|
|
2555
|
+
stream: bool = False,
|
|
2556
|
+
optimizer: str = None,
|
|
2557
|
+
conversationally: bool = False,
|
|
2558
|
+
) -> str | AsyncGenerator:
|
|
2559
|
+
"""Generate response `str` asynchronously.
|
|
2560
|
+
Args:
|
|
2561
|
+
prompt (str): Prompt to be send.
|
|
2562
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2563
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2564
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2565
|
+
Returns:
|
|
2566
|
+
str: Response generated
|
|
2567
|
+
"""
|
|
2568
|
+
|
|
2569
|
+
async def for_stream():
|
|
2570
|
+
async_ask = await self.ask(
|
|
2571
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
2572
|
+
)
|
|
2573
|
+
async for response in async_ask:
|
|
2574
|
+
yield await self.get_message(response)
|
|
2575
|
+
|
|
2576
|
+
async def for_non_stream():
|
|
2577
|
+
return await self.get_message(
|
|
2578
|
+
await self.ask(
|
|
2579
|
+
prompt,
|
|
2580
|
+
False,
|
|
2581
|
+
optimizer=optimizer,
|
|
2582
|
+
conversationally=conversationally,
|
|
2583
|
+
)
|
|
2584
|
+
)
|
|
2585
|
+
|
|
2586
|
+
return for_stream() if stream else await for_non_stream()
|
|
2587
|
+
|
|
2588
|
+
async def get_message(self, response: dict) -> str:
|
|
2589
|
+
"""Retrieves message only from response
|
|
2590
|
+
|
|
2591
|
+
Args:
|
|
2592
|
+
response (dict): Response generated by `self.ask`
|
|
2593
|
+
|
|
2594
|
+
Returns:
|
|
2595
|
+
str: Message extracted
|
|
2596
|
+
"""
|
|
2597
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2598
|
+
return response.get("token")
|
|
2599
|
+
#------------------------------------------------------OpenGPT-----------------------------------------------------------
|
|
2600
|
+
class OPENGPT:
|
|
2601
|
+
def __init__(
|
|
2602
|
+
self,
|
|
2603
|
+
is_conversation: bool = True,
|
|
2604
|
+
max_tokens: int = 600,
|
|
2605
|
+
timeout: int = 30,
|
|
2606
|
+
intro: str = None,
|
|
2607
|
+
filepath: str = None,
|
|
2608
|
+
update_file: bool = True,
|
|
2609
|
+
proxies: dict = {},
|
|
2610
|
+
history_offset: int = 10250,
|
|
2611
|
+
act: str = None,
|
|
2612
|
+
):
|
|
2613
|
+
"""Instantiates OPENGPT
|
|
2614
|
+
|
|
2615
|
+
Args:
|
|
2616
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
2617
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
2618
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
2619
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
2620
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
2621
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
2622
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
2623
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
2624
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
2625
|
+
"""
|
|
2626
|
+
self.session = requests.Session()
|
|
2627
|
+
self.max_tokens_to_sample = max_tokens
|
|
2628
|
+
self.is_conversation = is_conversation
|
|
2629
|
+
self.chat_endpoint = (
|
|
2630
|
+
"https://opengpts-example-vz4y4ooboq-uc.a.run.app/runs/stream"
|
|
2631
|
+
)
|
|
2632
|
+
self.stream_chunk_size = 64
|
|
2633
|
+
self.timeout = timeout
|
|
2634
|
+
self.last_response = {}
|
|
2635
|
+
self.assistant_id = "bca37014-6f97-4f2b-8928-81ea8d478d88"
|
|
2636
|
+
self.authority = "opengpts-example-vz4y4ooboq-uc.a.run.app"
|
|
2637
|
+
|
|
2638
|
+
self.headers = {
|
|
2639
|
+
"authority": self.authority,
|
|
2640
|
+
"accept": "text/event-stream",
|
|
2641
|
+
"accept-language": "en-US,en;q=0.7",
|
|
2642
|
+
"cache-control": "no-cache",
|
|
2643
|
+
"content-type": "application/json",
|
|
2644
|
+
"origin": "https://opengpts-example-vz4y4ooboq-uc.a.run.app",
|
|
2645
|
+
"pragma": "no-cache",
|
|
2646
|
+
"referer": "https://opengpts-example-vz4y4ooboq-uc.a.run.app/",
|
|
2647
|
+
"sec-fetch-site": "same-origin",
|
|
2648
|
+
"sec-gpc": "1",
|
|
2649
|
+
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
self.__available_optimizers = (
|
|
2653
|
+
method
|
|
2654
|
+
for method in dir(Optimizers)
|
|
2655
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2656
|
+
)
|
|
2657
|
+
self.session.headers.update(self.headers)
|
|
2658
|
+
Conversation.intro = (
|
|
2659
|
+
AwesomePrompts().get_act(
|
|
2660
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
2661
|
+
)
|
|
2662
|
+
if act
|
|
2663
|
+
else intro or Conversation.intro
|
|
2664
|
+
)
|
|
2665
|
+
self.conversation = Conversation(
|
|
2666
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2667
|
+
)
|
|
2668
|
+
self.conversation.history_offset = history_offset
|
|
2669
|
+
self.session.proxies = proxies
|
|
2670
|
+
|
|
2671
|
+
def ask(
|
|
2672
|
+
self,
|
|
2673
|
+
prompt: str,
|
|
2674
|
+
stream: bool = False,
|
|
2675
|
+
raw: bool = False,
|
|
2676
|
+
optimizer: str = None,
|
|
2677
|
+
conversationally: bool = False,
|
|
2678
|
+
) -> dict:
|
|
2679
|
+
"""Chat with AI
|
|
2680
|
+
|
|
2681
|
+
Args:
|
|
2682
|
+
prompt (str): Prompt to be send.
|
|
2683
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2684
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
2685
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2686
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2687
|
+
Returns:
|
|
2688
|
+
dict : {}
|
|
2689
|
+
```json
|
|
2690
|
+
{
|
|
2691
|
+
"messages": [
|
|
2692
|
+
{
|
|
2693
|
+
"content": "Hello there",
|
|
2694
|
+
"additional_kwargs": {},
|
|
2695
|
+
"type": "human",
|
|
2696
|
+
"example": false
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
"content": "Hello! How can I assist you today?",
|
|
2700
|
+
"additional_kwargs": {
|
|
2701
|
+
"agent": {
|
|
2702
|
+
"return_values": {
|
|
2703
|
+
"output": "Hello! How can I assist you today?"
|
|
2704
|
+
},
|
|
2705
|
+
"log": "Hello! How can I assist you today?",
|
|
2706
|
+
"type": "AgentFinish"
|
|
2707
|
+
}
|
|
2708
|
+
},
|
|
2709
|
+
"type": "ai",
|
|
2710
|
+
"example": false
|
|
2711
|
+
}]
|
|
2712
|
+
}
|
|
2713
|
+
```
|
|
2714
|
+
"""
|
|
2715
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
2716
|
+
if optimizer:
|
|
2717
|
+
if optimizer in self.__available_optimizers:
|
|
2718
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
2719
|
+
conversation_prompt if conversationally else prompt
|
|
2720
|
+
)
|
|
2721
|
+
else:
|
|
2722
|
+
raise Exception(
|
|
2723
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2724
|
+
)
|
|
2725
|
+
|
|
1452
2726
|
self.session.headers.update(self.headers)
|
|
1453
2727
|
self.session.headers.update(
|
|
1454
2728
|
dict(
|
|
@@ -1456,16 +2730,1062 @@ class OPENGPT:
|
|
|
1456
2730
|
)
|
|
1457
2731
|
)
|
|
1458
2732
|
payload = {
|
|
1459
|
-
"input": [
|
|
1460
|
-
{
|
|
1461
|
-
"content": conversation_prompt,
|
|
1462
|
-
"additional_kwargs": {},
|
|
1463
|
-
"type": "human",
|
|
1464
|
-
"example": False,
|
|
1465
|
-
},
|
|
2733
|
+
"input": [
|
|
2734
|
+
{
|
|
2735
|
+
"content": conversation_prompt,
|
|
2736
|
+
"additional_kwargs": {},
|
|
2737
|
+
"type": "human",
|
|
2738
|
+
"example": False,
|
|
2739
|
+
},
|
|
2740
|
+
],
|
|
2741
|
+
"assistant_id": self.assistant_id,
|
|
2742
|
+
"thread_id": "",
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
def for_stream():
|
|
2746
|
+
response = self.session.post(
|
|
2747
|
+
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
2748
|
+
)
|
|
2749
|
+
if (
|
|
2750
|
+
not response.ok
|
|
2751
|
+
or not response.headers.get("Content-Type")
|
|
2752
|
+
== "text/event-stream; charset=utf-8"
|
|
2753
|
+
):
|
|
2754
|
+
raise Exception(
|
|
2755
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
2756
|
+
)
|
|
2757
|
+
|
|
2758
|
+
for value in response.iter_lines(
|
|
2759
|
+
decode_unicode=True,
|
|
2760
|
+
chunk_size=self.stream_chunk_size,
|
|
2761
|
+
):
|
|
2762
|
+
try:
|
|
2763
|
+
modified_value = re.sub("data:", "", value)
|
|
2764
|
+
resp = json.loads(modified_value)
|
|
2765
|
+
if len(resp) == 1:
|
|
2766
|
+
continue
|
|
2767
|
+
self.last_response.update(resp[1])
|
|
2768
|
+
yield value if raw else resp[1]
|
|
2769
|
+
except json.decoder.JSONDecodeError:
|
|
2770
|
+
pass
|
|
2771
|
+
self.conversation.update_chat_history(
|
|
2772
|
+
prompt, self.get_message(self.last_response)
|
|
2773
|
+
)
|
|
2774
|
+
|
|
2775
|
+
def for_non_stream():
|
|
2776
|
+
for _ in for_stream():
|
|
2777
|
+
pass
|
|
2778
|
+
return self.last_response
|
|
2779
|
+
|
|
2780
|
+
return for_stream() if stream else for_non_stream()
|
|
2781
|
+
|
|
2782
|
+
def chat(
|
|
2783
|
+
self,
|
|
2784
|
+
prompt: str,
|
|
2785
|
+
stream: bool = False,
|
|
2786
|
+
optimizer: str = None,
|
|
2787
|
+
conversationally: bool = False,
|
|
2788
|
+
) -> str:
|
|
2789
|
+
"""Generate response `str`
|
|
2790
|
+
Args:
|
|
2791
|
+
prompt (str): Prompt to be send.
|
|
2792
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2793
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2794
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2795
|
+
Returns:
|
|
2796
|
+
str: Response generated
|
|
2797
|
+
"""
|
|
2798
|
+
|
|
2799
|
+
def for_stream():
|
|
2800
|
+
for response in self.ask(
|
|
2801
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
2802
|
+
):
|
|
2803
|
+
yield self.get_message(response)
|
|
2804
|
+
|
|
2805
|
+
def for_non_stream():
|
|
2806
|
+
return self.get_message(
|
|
2807
|
+
self.ask(
|
|
2808
|
+
prompt,
|
|
2809
|
+
False,
|
|
2810
|
+
optimizer=optimizer,
|
|
2811
|
+
conversationally=conversationally,
|
|
2812
|
+
)
|
|
2813
|
+
)
|
|
2814
|
+
|
|
2815
|
+
return for_stream() if stream else for_non_stream()
|
|
2816
|
+
|
|
2817
|
+
def get_message(self, response: dict) -> str:
|
|
2818
|
+
"""Retrieves message only from response
|
|
2819
|
+
|
|
2820
|
+
Args:
|
|
2821
|
+
response (dict): Response generated by `self.ask`
|
|
2822
|
+
|
|
2823
|
+
Returns:
|
|
2824
|
+
str: Message extracted
|
|
2825
|
+
"""
|
|
2826
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2827
|
+
return response["content"]
|
|
2828
|
+
class AsyncOPENGPT(AsyncProvider):
|
|
2829
|
+
def __init__(
|
|
2830
|
+
self,
|
|
2831
|
+
is_conversation: bool = True,
|
|
2832
|
+
max_tokens: int = 600,
|
|
2833
|
+
timeout: int = 30,
|
|
2834
|
+
intro: str = None,
|
|
2835
|
+
filepath: str = None,
|
|
2836
|
+
update_file: bool = True,
|
|
2837
|
+
proxies: dict = {},
|
|
2838
|
+
history_offset: int = 10250,
|
|
2839
|
+
act: str = None,
|
|
2840
|
+
):
|
|
2841
|
+
"""Instantiates OPENGPT
|
|
2842
|
+
|
|
2843
|
+
Args:
|
|
2844
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
2845
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
2846
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
2847
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
2848
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
2849
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
2850
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
2851
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
2852
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
2853
|
+
"""
|
|
2854
|
+
self.max_tokens_to_sample = max_tokens
|
|
2855
|
+
self.is_conversation = is_conversation
|
|
2856
|
+
self.chat_endpoint = (
|
|
2857
|
+
"https://opengpts-example-vz4y4ooboq-uc.a.run.app/runs/stream"
|
|
2858
|
+
)
|
|
2859
|
+
self.stream_chunk_size = 64
|
|
2860
|
+
self.timeout = timeout
|
|
2861
|
+
self.last_response = {}
|
|
2862
|
+
self.assistant_id = "bca37014-6f97-4f2b-8928-81ea8d478d88"
|
|
2863
|
+
self.authority = "opengpts-example-vz4y4ooboq-uc.a.run.app"
|
|
2864
|
+
|
|
2865
|
+
self.headers = {
|
|
2866
|
+
"authority": self.authority,
|
|
2867
|
+
"accept": "text/event-stream",
|
|
2868
|
+
"accept-language": "en-US,en;q=0.7",
|
|
2869
|
+
"cache-control": "no-cache",
|
|
2870
|
+
"content-type": "application/json",
|
|
2871
|
+
"origin": "https://opengpts-example-vz4y4ooboq-uc.a.run.app",
|
|
2872
|
+
"pragma": "no-cache",
|
|
2873
|
+
"referer": "https://opengpts-example-vz4y4ooboq-uc.a.run.app/",
|
|
2874
|
+
"sec-fetch-site": "same-origin",
|
|
2875
|
+
"sec-gpc": "1",
|
|
2876
|
+
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
self.__available_optimizers = (
|
|
2880
|
+
method
|
|
2881
|
+
for method in dir(Optimizers)
|
|
2882
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2883
|
+
)
|
|
2884
|
+
Conversation.intro = (
|
|
2885
|
+
AwesomePrompts().get_act(
|
|
2886
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
2887
|
+
)
|
|
2888
|
+
if act
|
|
2889
|
+
else intro or Conversation.intro
|
|
2890
|
+
)
|
|
2891
|
+
self.conversation = Conversation(
|
|
2892
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2893
|
+
)
|
|
2894
|
+
self.conversation.history_offset = history_offset
|
|
2895
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
2896
|
+
|
|
2897
|
+
async def ask(
|
|
2898
|
+
self,
|
|
2899
|
+
prompt: str,
|
|
2900
|
+
stream: bool = False,
|
|
2901
|
+
raw: bool = False,
|
|
2902
|
+
optimizer: str = None,
|
|
2903
|
+
conversationally: bool = False,
|
|
2904
|
+
) -> dict | AsyncGenerator:
|
|
2905
|
+
"""Chat with AI asynchronously
|
|
2906
|
+
|
|
2907
|
+
Args:
|
|
2908
|
+
prompt (str): Prompt to be send.
|
|
2909
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
2910
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
2911
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
2912
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
2913
|
+
Returns:
|
|
2914
|
+
dict|AsyncGenerator : ai content.
|
|
2915
|
+
```json
|
|
2916
|
+
{
|
|
2917
|
+
"messages": [
|
|
2918
|
+
{
|
|
2919
|
+
"content": "Hello there",
|
|
2920
|
+
"additional_kwargs": {},
|
|
2921
|
+
"type": "human",
|
|
2922
|
+
"example": false
|
|
2923
|
+
},
|
|
2924
|
+
{
|
|
2925
|
+
"content": "Hello! How can I assist you today?",
|
|
2926
|
+
"additional_kwargs": {
|
|
2927
|
+
"agent": {
|
|
2928
|
+
"return_values": {
|
|
2929
|
+
"output": "Hello! How can I assist you today?"
|
|
2930
|
+
},
|
|
2931
|
+
"log": "Hello! How can I assist you today?",
|
|
2932
|
+
"type": "AgentFinish"
|
|
2933
|
+
}
|
|
2934
|
+
},
|
|
2935
|
+
"type": "ai",
|
|
2936
|
+
"example": false
|
|
2937
|
+
}]
|
|
2938
|
+
}
|
|
2939
|
+
```
|
|
2940
|
+
"""
|
|
2941
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
2942
|
+
if optimizer:
|
|
2943
|
+
if optimizer in self.__available_optimizers:
|
|
2944
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
2945
|
+
conversation_prompt if conversationally else prompt
|
|
2946
|
+
)
|
|
2947
|
+
else:
|
|
2948
|
+
raise Exception(
|
|
2949
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2950
|
+
)
|
|
2951
|
+
self.headers.update(
|
|
2952
|
+
dict(
|
|
2953
|
+
cookie=f"opengpts_user_id={uuid4().__str__()}",
|
|
2954
|
+
)
|
|
2955
|
+
)
|
|
2956
|
+
payload = {
|
|
2957
|
+
"input": [
|
|
2958
|
+
{
|
|
2959
|
+
"content": conversation_prompt,
|
|
2960
|
+
"additional_kwargs": {},
|
|
2961
|
+
"type": "human",
|
|
2962
|
+
"example": False,
|
|
2963
|
+
},
|
|
2964
|
+
],
|
|
2965
|
+
"assistant_id": self.assistant_id,
|
|
2966
|
+
"thread_id": "",
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2969
|
+
async def for_stream():
|
|
2970
|
+
async with self.session.stream(
|
|
2971
|
+
"POST",
|
|
2972
|
+
self.chat_endpoint,
|
|
2973
|
+
json=payload,
|
|
2974
|
+
timeout=self.timeout,
|
|
2975
|
+
headers=self.headers,
|
|
2976
|
+
) as response:
|
|
2977
|
+
if (
|
|
2978
|
+
not response.is_success
|
|
2979
|
+
or not response.headers.get("Content-Type")
|
|
2980
|
+
== "text/event-stream; charset=utf-8"
|
|
2981
|
+
):
|
|
2982
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
2983
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase}) - {response.text}"
|
|
2984
|
+
)
|
|
2985
|
+
|
|
2986
|
+
async for value in response.aiter_lines():
|
|
2987
|
+
try:
|
|
2988
|
+
modified_value = re.sub("data:", "", value)
|
|
2989
|
+
resp = json.loads(modified_value)
|
|
2990
|
+
if len(resp) == 1:
|
|
2991
|
+
continue
|
|
2992
|
+
self.last_response.update(resp[1])
|
|
2993
|
+
yield value if raw else resp[1]
|
|
2994
|
+
except json.decoder.JSONDecodeError:
|
|
2995
|
+
pass
|
|
2996
|
+
|
|
2997
|
+
self.conversation.update_chat_history(
|
|
2998
|
+
prompt, await self.get_message(self.last_response)
|
|
2999
|
+
)
|
|
3000
|
+
|
|
3001
|
+
async def for_non_stream():
|
|
3002
|
+
async for _ in for_stream():
|
|
3003
|
+
pass
|
|
3004
|
+
return self.last_response
|
|
3005
|
+
|
|
3006
|
+
return for_stream() if stream else await for_non_stream()
|
|
3007
|
+
|
|
3008
|
+
async def chat(
|
|
3009
|
+
self,
|
|
3010
|
+
prompt: str,
|
|
3011
|
+
stream: bool = False,
|
|
3012
|
+
optimizer: str = None,
|
|
3013
|
+
conversationally: bool = False,
|
|
3014
|
+
) -> str | AsyncGenerator:
|
|
3015
|
+
"""Generate response `str` asynchronously.
|
|
3016
|
+
Args:
|
|
3017
|
+
prompt (str): Prompt to be send.
|
|
3018
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3019
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3020
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3021
|
+
Returns:
|
|
3022
|
+
str|AsyncGenerator: Response generated
|
|
3023
|
+
"""
|
|
3024
|
+
|
|
3025
|
+
async def for_stream():
|
|
3026
|
+
async_ask = await self.ask(
|
|
3027
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
3028
|
+
)
|
|
3029
|
+
async for response in async_ask:
|
|
3030
|
+
yield await self.get_message(response)
|
|
3031
|
+
|
|
3032
|
+
async def for_non_stream():
|
|
3033
|
+
return await self.get_message(
|
|
3034
|
+
await self.ask(
|
|
3035
|
+
prompt,
|
|
3036
|
+
False,
|
|
3037
|
+
optimizer=optimizer,
|
|
3038
|
+
conversationally=conversationally,
|
|
3039
|
+
)
|
|
3040
|
+
)
|
|
3041
|
+
|
|
3042
|
+
return for_stream() if stream else await for_non_stream()
|
|
3043
|
+
|
|
3044
|
+
async def get_message(self, response: dict) -> str:
|
|
3045
|
+
"""Retrieves message only from response
|
|
3046
|
+
|
|
3047
|
+
Args:
|
|
3048
|
+
response (dict): Response generated by `self.ask`
|
|
3049
|
+
|
|
3050
|
+
Returns:
|
|
3051
|
+
str: Message extracted
|
|
3052
|
+
"""
|
|
3053
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
3054
|
+
return response["content"]
|
|
3055
|
+
#------------------------------------------------------PERPLEXITY--------------------------------------------------------
|
|
3056
|
+
class PERPLEXITY(Provider):
|
|
3057
|
+
def __init__(
|
|
3058
|
+
self,
|
|
3059
|
+
is_conversation: bool = True,
|
|
3060
|
+
max_tokens: int = 600,
|
|
3061
|
+
timeout: int = 30,
|
|
3062
|
+
intro: str = None,
|
|
3063
|
+
filepath: str = None,
|
|
3064
|
+
update_file: bool = True,
|
|
3065
|
+
proxies: dict = {},
|
|
3066
|
+
history_offset: int = 10250,
|
|
3067
|
+
act: str = None,
|
|
3068
|
+
quiet: bool = False,
|
|
3069
|
+
):
|
|
3070
|
+
"""Instantiates PERPLEXITY
|
|
3071
|
+
|
|
3072
|
+
Args:
|
|
3073
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
3074
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
3075
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
3076
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
3077
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
3078
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
3079
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
3080
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
3081
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
3082
|
+
quiet (bool, optional): Ignore web search-results and yield final response only. Defaults to False.
|
|
3083
|
+
"""
|
|
3084
|
+
self.max_tokens_to_sample = max_tokens
|
|
3085
|
+
self.is_conversation = is_conversation
|
|
3086
|
+
self.last_response = {}
|
|
3087
|
+
self.web_results: dict = {}
|
|
3088
|
+
self.quiet = quiet
|
|
3089
|
+
|
|
3090
|
+
self.__available_optimizers = (
|
|
3091
|
+
method
|
|
3092
|
+
for method in dir(Optimizers)
|
|
3093
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
3094
|
+
)
|
|
3095
|
+
Conversation.intro = (
|
|
3096
|
+
AwesomePrompts().get_act(
|
|
3097
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
3098
|
+
)
|
|
3099
|
+
if act
|
|
3100
|
+
else intro or Conversation.intro
|
|
3101
|
+
)
|
|
3102
|
+
self.conversation = Conversation(
|
|
3103
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
3104
|
+
)
|
|
3105
|
+
self.conversation.history_offset = history_offset
|
|
3106
|
+
|
|
3107
|
+
def ask(
|
|
3108
|
+
self,
|
|
3109
|
+
prompt: str,
|
|
3110
|
+
stream: bool = False,
|
|
3111
|
+
raw: bool = False,
|
|
3112
|
+
optimizer: str = None,
|
|
3113
|
+
conversationally: bool = False,
|
|
3114
|
+
) -> dict:
|
|
3115
|
+
"""Chat with AI
|
|
3116
|
+
|
|
3117
|
+
Args:
|
|
3118
|
+
prompt (str): Prompt to be send.
|
|
3119
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3120
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
3121
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3122
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3123
|
+
Returns:
|
|
3124
|
+
dict : {}
|
|
3125
|
+
```json
|
|
3126
|
+
{
|
|
3127
|
+
"status": "pending",
|
|
3128
|
+
"uuid": "3604dfcc-611f-4b7d-989d-edca2a7233c7",
|
|
3129
|
+
"read_write_token": null,
|
|
3130
|
+
"frontend_context_uuid": "f6d43119-5231-481d-b692-f52e1f52d2c6",
|
|
3131
|
+
"final": false,
|
|
3132
|
+
"backend_uuid": "a6d6ec9e-da69-4841-af74-0de0409267a8",
|
|
3133
|
+
"media_items": [],
|
|
3134
|
+
"widget_data": [],
|
|
3135
|
+
"knowledge_cards": [],
|
|
3136
|
+
"expect_search_results": "false",
|
|
3137
|
+
"mode": "concise",
|
|
3138
|
+
"search_focus": "internet",
|
|
3139
|
+
"gpt4": false,
|
|
3140
|
+
"display_model": "turbo",
|
|
3141
|
+
"attachments": null,
|
|
3142
|
+
"answer": "",
|
|
3143
|
+
"web_results": [],
|
|
3144
|
+
"chunks": [],
|
|
3145
|
+
"extra_web_results": []
|
|
3146
|
+
}
|
|
3147
|
+
```
|
|
3148
|
+
"""
|
|
3149
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
3150
|
+
if optimizer:
|
|
3151
|
+
if optimizer in self.__available_optimizers:
|
|
3152
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
3153
|
+
conversation_prompt if conversationally else prompt
|
|
3154
|
+
)
|
|
3155
|
+
else:
|
|
3156
|
+
raise Exception(
|
|
3157
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
3158
|
+
)
|
|
3159
|
+
|
|
3160
|
+
def for_stream():
|
|
3161
|
+
for response in Perplexity().generate_answer(conversation_prompt):
|
|
3162
|
+
yield json.dumps(response) if raw else response
|
|
3163
|
+
self.last_response.update(response)
|
|
3164
|
+
|
|
3165
|
+
self.conversation.update_chat_history(
|
|
3166
|
+
prompt,
|
|
3167
|
+
self.get_message(self.last_response),
|
|
3168
|
+
)
|
|
3169
|
+
|
|
3170
|
+
def for_non_stream():
|
|
3171
|
+
for _ in for_stream():
|
|
3172
|
+
pass
|
|
3173
|
+
return self.last_response
|
|
3174
|
+
|
|
3175
|
+
return for_stream() if stream else for_non_stream()
|
|
3176
|
+
|
|
3177
|
+
def chat(
|
|
3178
|
+
self,
|
|
3179
|
+
prompt: str,
|
|
3180
|
+
stream: bool = False,
|
|
3181
|
+
optimizer: str = None,
|
|
3182
|
+
conversationally: bool = False,
|
|
3183
|
+
) -> str:
|
|
3184
|
+
"""Generate response `str`
|
|
3185
|
+
Args:
|
|
3186
|
+
prompt (str): Prompt to be send.
|
|
3187
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3188
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3189
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3190
|
+
Returns:
|
|
3191
|
+
str: Response generated
|
|
3192
|
+
"""
|
|
3193
|
+
|
|
3194
|
+
def for_stream():
|
|
3195
|
+
for response in self.ask(
|
|
3196
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
3197
|
+
):
|
|
3198
|
+
yield self.get_message(response)
|
|
3199
|
+
|
|
3200
|
+
def for_non_stream():
|
|
3201
|
+
return self.get_message(
|
|
3202
|
+
self.ask(
|
|
3203
|
+
prompt,
|
|
3204
|
+
False,
|
|
3205
|
+
optimizer=optimizer,
|
|
3206
|
+
conversationally=conversationally,
|
|
3207
|
+
)
|
|
3208
|
+
)
|
|
3209
|
+
|
|
3210
|
+
return for_stream() if stream else for_non_stream()
|
|
3211
|
+
|
|
3212
|
+
def get_message(self, response: dict) -> str:
|
|
3213
|
+
"""Retrieves message only from response
|
|
3214
|
+
|
|
3215
|
+
Args:
|
|
3216
|
+
response (dict): Response generated by `self.ask`
|
|
3217
|
+
|
|
3218
|
+
Returns:
|
|
3219
|
+
str: Message extracted
|
|
3220
|
+
"""
|
|
3221
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
3222
|
+
text_str: str = response.get("answer", "")
|
|
3223
|
+
|
|
3224
|
+
def update_web_results(web_results: list) -> None:
|
|
3225
|
+
for index, results in enumerate(web_results, start=1):
|
|
3226
|
+
self.web_results[str(index) + ". " + results["name"]] = dict(
|
|
3227
|
+
url=results.get("url"), snippet=results.get("snippet")
|
|
3228
|
+
)
|
|
3229
|
+
|
|
3230
|
+
if response.get("text"):
|
|
3231
|
+
# last chunk
|
|
3232
|
+
target: dict[str, Any] = json.loads(response.get("text"))
|
|
3233
|
+
text_str = target.get("answer")
|
|
3234
|
+
web_results: list[dict] = target.get("web_results")
|
|
3235
|
+
self.web_results.clear()
|
|
3236
|
+
update_web_results(web_results)
|
|
3237
|
+
|
|
3238
|
+
return (
|
|
3239
|
+
text_str
|
|
3240
|
+
if self.quiet or not self.web_results
|
|
3241
|
+
else text_str + "\n\n# WEB-RESULTS\n\n" + yaml.dump(self.web_results)
|
|
3242
|
+
)
|
|
3243
|
+
|
|
3244
|
+
else:
|
|
3245
|
+
if str(response.get("expect_search_results")).lower() == "true":
|
|
3246
|
+
return (
|
|
3247
|
+
text_str
|
|
3248
|
+
if self.quiet
|
|
3249
|
+
else text_str
|
|
3250
|
+
+ "\n\n# WEB-RESULTS\n\n"
|
|
3251
|
+
+ yaml.dump(response.get("web_results"))
|
|
3252
|
+
)
|
|
3253
|
+
else:
|
|
3254
|
+
return text_str
|
|
3255
|
+
#------------------------------------------------------BLACKBOXAI--------------------------------------------------------
|
|
3256
|
+
class BLACKBOXAI:
|
|
3257
|
+
def __init__(
|
|
3258
|
+
self,
|
|
3259
|
+
is_conversation: bool = True,
|
|
3260
|
+
max_tokens: int = 8000,
|
|
3261
|
+
timeout: int = 30,
|
|
3262
|
+
intro: str = None,
|
|
3263
|
+
filepath: str = None,
|
|
3264
|
+
update_file: bool = True,
|
|
3265
|
+
proxies: dict = {},
|
|
3266
|
+
history_offset: int = 10250,
|
|
3267
|
+
act: str = None,
|
|
3268
|
+
model: str = None,
|
|
3269
|
+
):
|
|
3270
|
+
"""Instantiates BLACKBOXAI
|
|
3271
|
+
|
|
3272
|
+
Args:
|
|
3273
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
3274
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
3275
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
3276
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
3277
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
3278
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
3279
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
3280
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
3281
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
3282
|
+
model (str, optional): Model name. Defaults to "Phind Model".
|
|
3283
|
+
"""
|
|
3284
|
+
self.session = requests.Session()
|
|
3285
|
+
self.max_tokens_to_sample = max_tokens
|
|
3286
|
+
self.is_conversation = is_conversation
|
|
3287
|
+
self.chat_endpoint = "https://www.blackbox.ai/api/chat"
|
|
3288
|
+
self.stream_chunk_size = 64
|
|
3289
|
+
self.timeout = timeout
|
|
3290
|
+
self.last_response = {}
|
|
3291
|
+
self.model = model
|
|
3292
|
+
self.previewToken: str = None
|
|
3293
|
+
self.userId: str = ""
|
|
3294
|
+
self.codeModelMode: bool = True
|
|
3295
|
+
self.id: str = ""
|
|
3296
|
+
self.agentMode: dict = {}
|
|
3297
|
+
self.trendingAgentMode: dict = {}
|
|
3298
|
+
self.isMicMode: bool = False
|
|
3299
|
+
|
|
3300
|
+
self.headers = {
|
|
3301
|
+
"Content-Type": "application/json",
|
|
3302
|
+
"User-Agent": "",
|
|
3303
|
+
"Accept": "*/*",
|
|
3304
|
+
"Accept-Encoding": "Identity",
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
self.__available_optimizers = (
|
|
3308
|
+
method
|
|
3309
|
+
for method in dir(Optimizers)
|
|
3310
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
3311
|
+
)
|
|
3312
|
+
self.session.headers.update(self.headers)
|
|
3313
|
+
Conversation.intro = (
|
|
3314
|
+
AwesomePrompts().get_act(
|
|
3315
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
3316
|
+
)
|
|
3317
|
+
if act
|
|
3318
|
+
else intro or Conversation.intro
|
|
3319
|
+
)
|
|
3320
|
+
self.conversation = Conversation(
|
|
3321
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
3322
|
+
)
|
|
3323
|
+
self.conversation.history_offset = history_offset
|
|
3324
|
+
self.session.proxies = proxies
|
|
3325
|
+
|
|
3326
|
+
def ask(
|
|
3327
|
+
self,
|
|
3328
|
+
prompt: str,
|
|
3329
|
+
stream: bool = False,
|
|
3330
|
+
raw: bool = False,
|
|
3331
|
+
optimizer: str = None,
|
|
3332
|
+
conversationally: bool = False,
|
|
3333
|
+
) -> dict:
|
|
3334
|
+
"""Chat with AI
|
|
3335
|
+
|
|
3336
|
+
Args:
|
|
3337
|
+
prompt (str): Prompt to be send.
|
|
3338
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3339
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
3340
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3341
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3342
|
+
Returns:
|
|
3343
|
+
dict : {}
|
|
3344
|
+
```json
|
|
3345
|
+
{
|
|
3346
|
+
"text" : "print('How may I help you today?')"
|
|
3347
|
+
}
|
|
3348
|
+
```
|
|
3349
|
+
"""
|
|
3350
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
3351
|
+
if optimizer:
|
|
3352
|
+
if optimizer in self.__available_optimizers:
|
|
3353
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
3354
|
+
conversation_prompt if conversationally else prompt
|
|
3355
|
+
)
|
|
3356
|
+
else:
|
|
3357
|
+
raise Exception(
|
|
3358
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
3359
|
+
)
|
|
3360
|
+
|
|
3361
|
+
self.session.headers.update(self.headers)
|
|
3362
|
+
payload = {
|
|
3363
|
+
"messages": [
|
|
3364
|
+
# json.loads(prev_messages),
|
|
3365
|
+
{"content": conversation_prompt, "role": "user"}
|
|
3366
|
+
],
|
|
3367
|
+
"id": self.id,
|
|
3368
|
+
"previewToken": self.previewToken,
|
|
3369
|
+
"userId": self.userId,
|
|
3370
|
+
"codeModelMode": self.codeModelMode,
|
|
3371
|
+
"agentMode": self.agentMode,
|
|
3372
|
+
"trendingAgentMode": self.trendingAgentMode,
|
|
3373
|
+
"isMicMode": self.isMicMode,
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3376
|
+
def for_stream():
|
|
3377
|
+
response = self.session.post(
|
|
3378
|
+
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
3379
|
+
)
|
|
3380
|
+
if (
|
|
3381
|
+
not response.ok
|
|
3382
|
+
or not response.headers.get("Content-Type")
|
|
3383
|
+
== "text/plain; charset=utf-8"
|
|
3384
|
+
):
|
|
3385
|
+
raise Exception(
|
|
3386
|
+
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
3387
|
+
)
|
|
3388
|
+
streaming_text = ""
|
|
3389
|
+
for value in response.iter_lines(
|
|
3390
|
+
decode_unicode=True,
|
|
3391
|
+
chunk_size=self.stream_chunk_size,
|
|
3392
|
+
delimiter="\n",
|
|
3393
|
+
):
|
|
3394
|
+
try:
|
|
3395
|
+
if bool(value):
|
|
3396
|
+
streaming_text += value + ("\n" if stream else "")
|
|
3397
|
+
|
|
3398
|
+
resp = dict(text=streaming_text)
|
|
3399
|
+
self.last_response.update(resp)
|
|
3400
|
+
yield value if raw else resp
|
|
3401
|
+
except json.decoder.JSONDecodeError:
|
|
3402
|
+
pass
|
|
3403
|
+
self.conversation.update_chat_history(
|
|
3404
|
+
prompt, self.get_message(self.last_response)
|
|
3405
|
+
)
|
|
3406
|
+
|
|
3407
|
+
def for_non_stream():
|
|
3408
|
+
for _ in for_stream():
|
|
3409
|
+
pass
|
|
3410
|
+
return self.last_response
|
|
3411
|
+
|
|
3412
|
+
return for_stream() if stream else for_non_stream()
|
|
3413
|
+
|
|
3414
|
+
def chat(
|
|
3415
|
+
self,
|
|
3416
|
+
prompt: str,
|
|
3417
|
+
stream: bool = False,
|
|
3418
|
+
optimizer: str = None,
|
|
3419
|
+
conversationally: bool = False,
|
|
3420
|
+
) -> str:
|
|
3421
|
+
"""Generate response `str`
|
|
3422
|
+
Args:
|
|
3423
|
+
prompt (str): Prompt to be send.
|
|
3424
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3425
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3426
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3427
|
+
Returns:
|
|
3428
|
+
str: Response generated
|
|
3429
|
+
"""
|
|
3430
|
+
|
|
3431
|
+
def for_stream():
|
|
3432
|
+
for response in self.ask(
|
|
3433
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
3434
|
+
):
|
|
3435
|
+
yield self.get_message(response)
|
|
3436
|
+
|
|
3437
|
+
def for_non_stream():
|
|
3438
|
+
return self.get_message(
|
|
3439
|
+
self.ask(
|
|
3440
|
+
prompt,
|
|
3441
|
+
False,
|
|
3442
|
+
optimizer=optimizer,
|
|
3443
|
+
conversationally=conversationally,
|
|
3444
|
+
)
|
|
3445
|
+
)
|
|
3446
|
+
|
|
3447
|
+
return for_stream() if stream else for_non_stream()
|
|
3448
|
+
|
|
3449
|
+
def get_message(self, response: dict) -> str:
|
|
3450
|
+
"""Retrieves message only from response
|
|
3451
|
+
|
|
3452
|
+
Args:
|
|
3453
|
+
response (dict): Response generated by `self.ask`
|
|
3454
|
+
|
|
3455
|
+
Returns:
|
|
3456
|
+
str: Message extracted
|
|
3457
|
+
"""
|
|
3458
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
3459
|
+
return response["text"]
|
|
3460
|
+
@staticmethod
|
|
3461
|
+
def chat_cli(prompt):
|
|
3462
|
+
"""Sends a request to the BLACKBOXAI API and processes the response."""
|
|
3463
|
+
blackbox_ai = BLACKBOXAI() # Initialize a BLACKBOXAI instance
|
|
3464
|
+
response = blackbox_ai.ask(prompt) # Perform a chat with the given prompt
|
|
3465
|
+
processed_response = blackbox_ai.get_message(response) # Process the response
|
|
3466
|
+
print(processed_response)
|
|
3467
|
+
class AsyncBLACKBOXAI(AsyncProvider):
|
|
3468
|
+
def __init__(
|
|
3469
|
+
self,
|
|
3470
|
+
is_conversation: bool = True,
|
|
3471
|
+
max_tokens: int = 600,
|
|
3472
|
+
timeout: int = 30,
|
|
3473
|
+
intro: str = None,
|
|
3474
|
+
filepath: str = None,
|
|
3475
|
+
update_file: bool = True,
|
|
3476
|
+
proxies: dict = {},
|
|
3477
|
+
history_offset: int = 10250,
|
|
3478
|
+
act: str = None,
|
|
3479
|
+
model: str = None,
|
|
3480
|
+
):
|
|
3481
|
+
"""Instantiates BLACKBOXAI
|
|
3482
|
+
|
|
3483
|
+
Args:
|
|
3484
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
3485
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
3486
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
3487
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
3488
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
3489
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
3490
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
3491
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
3492
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
3493
|
+
model (str, optional): Model name. Defaults to "Phind Model".
|
|
3494
|
+
"""
|
|
3495
|
+
self.max_tokens_to_sample = max_tokens
|
|
3496
|
+
self.is_conversation = is_conversation
|
|
3497
|
+
self.chat_endpoint = "https://www.blackbox.ai/api/chat"
|
|
3498
|
+
self.stream_chunk_size = 64
|
|
3499
|
+
self.timeout = timeout
|
|
3500
|
+
self.last_response = {}
|
|
3501
|
+
self.model = model
|
|
3502
|
+
self.previewToken: str = None
|
|
3503
|
+
self.userId: str = ""
|
|
3504
|
+
self.codeModelMode: bool = True
|
|
3505
|
+
self.id: str = ""
|
|
3506
|
+
self.agentMode: dict = {}
|
|
3507
|
+
self.trendingAgentMode: dict = {}
|
|
3508
|
+
self.isMicMode: bool = False
|
|
3509
|
+
|
|
3510
|
+
self.headers = {
|
|
3511
|
+
"Content-Type": "application/json",
|
|
3512
|
+
"User-Agent": "",
|
|
3513
|
+
"Accept": "*/*",
|
|
3514
|
+
"Accept-Encoding": "Identity",
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3517
|
+
self.__available_optimizers = (
|
|
3518
|
+
method
|
|
3519
|
+
for method in dir(Optimizers)
|
|
3520
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
3521
|
+
)
|
|
3522
|
+
Conversation.intro = (
|
|
3523
|
+
AwesomePrompts().get_act(
|
|
3524
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
3525
|
+
)
|
|
3526
|
+
if act
|
|
3527
|
+
else intro or Conversation.intro
|
|
3528
|
+
)
|
|
3529
|
+
self.conversation = Conversation(
|
|
3530
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
3531
|
+
)
|
|
3532
|
+
self.conversation.history_offset = history_offset
|
|
3533
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
3534
|
+
|
|
3535
|
+
async def ask(
|
|
3536
|
+
self,
|
|
3537
|
+
prompt: str,
|
|
3538
|
+
stream: bool = False,
|
|
3539
|
+
raw: bool = False,
|
|
3540
|
+
optimizer: str = None,
|
|
3541
|
+
conversationally: bool = False,
|
|
3542
|
+
) -> dict | AsyncGenerator:
|
|
3543
|
+
"""Chat with AI asynchronously.
|
|
3544
|
+
|
|
3545
|
+
Args:
|
|
3546
|
+
prompt (str): Prompt to be send.
|
|
3547
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3548
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
3549
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3550
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3551
|
+
Returns:
|
|
3552
|
+
dict|AsyncGenerator : ai content
|
|
3553
|
+
```json
|
|
3554
|
+
{
|
|
3555
|
+
"text" : "print('How may I help you today?')"
|
|
3556
|
+
}
|
|
3557
|
+
```
|
|
3558
|
+
"""
|
|
3559
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
3560
|
+
if optimizer:
|
|
3561
|
+
if optimizer in self.__available_optimizers:
|
|
3562
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
3563
|
+
conversation_prompt if conversationally else prompt
|
|
3564
|
+
)
|
|
3565
|
+
else:
|
|
3566
|
+
raise Exception(
|
|
3567
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
3568
|
+
)
|
|
3569
|
+
|
|
3570
|
+
payload = {
|
|
3571
|
+
"messages": [
|
|
3572
|
+
# json.loads(prev_messages),
|
|
3573
|
+
{"content": conversation_prompt, "role": "user"}
|
|
3574
|
+
],
|
|
3575
|
+
"id": self.id,
|
|
3576
|
+
"previewToken": self.previewToken,
|
|
3577
|
+
"userId": self.userId,
|
|
3578
|
+
"codeModelMode": self.codeModelMode,
|
|
3579
|
+
"agentMode": self.agentMode,
|
|
3580
|
+
"trendingAgentMode": self.trendingAgentMode,
|
|
3581
|
+
"isMicMode": self.isMicMode,
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
async def for_stream():
|
|
3585
|
+
async with self.session.stream(
|
|
3586
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
3587
|
+
) as response:
|
|
3588
|
+
if (
|
|
3589
|
+
not response.is_success
|
|
3590
|
+
or not response.headers.get("Content-Type")
|
|
3591
|
+
== "text/plain; charset=utf-8"
|
|
3592
|
+
):
|
|
3593
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
3594
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
3595
|
+
)
|
|
3596
|
+
streaming_text = ""
|
|
3597
|
+
async for value in response.aiter_lines():
|
|
3598
|
+
try:
|
|
3599
|
+
if bool(value):
|
|
3600
|
+
streaming_text += value + ("\n" if stream else "")
|
|
3601
|
+
resp = dict(text=streaming_text)
|
|
3602
|
+
self.last_response.update(resp)
|
|
3603
|
+
yield value if raw else resp
|
|
3604
|
+
except json.decoder.JSONDecodeError:
|
|
3605
|
+
pass
|
|
3606
|
+
self.conversation.update_chat_history(
|
|
3607
|
+
prompt, await self.get_message(self.last_response)
|
|
3608
|
+
)
|
|
3609
|
+
|
|
3610
|
+
async def for_non_stream():
|
|
3611
|
+
async for _ in for_stream():
|
|
3612
|
+
pass
|
|
3613
|
+
return self.last_response
|
|
3614
|
+
|
|
3615
|
+
return for_stream() if stream else await for_non_stream()
|
|
3616
|
+
|
|
3617
|
+
async def chat(
|
|
3618
|
+
self,
|
|
3619
|
+
prompt: str,
|
|
3620
|
+
stream: bool = False,
|
|
3621
|
+
optimizer: str = None,
|
|
3622
|
+
conversationally: bool = False,
|
|
3623
|
+
) -> str | AsyncGenerator:
|
|
3624
|
+
"""Generate response `str` asynchronously.
|
|
3625
|
+
Args:
|
|
3626
|
+
prompt (str): Prompt to be send.
|
|
3627
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3628
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3629
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3630
|
+
Returns:
|
|
3631
|
+
str|AsyncGenerator: Response generated
|
|
3632
|
+
"""
|
|
3633
|
+
|
|
3634
|
+
async def for_stream():
|
|
3635
|
+
async_ask = await self.ask(
|
|
3636
|
+
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
3637
|
+
)
|
|
3638
|
+
async for response in async_ask:
|
|
3639
|
+
yield await self.get_message(response)
|
|
3640
|
+
|
|
3641
|
+
async def for_non_stream():
|
|
3642
|
+
return await self.get_message(
|
|
3643
|
+
await self.ask(
|
|
3644
|
+
prompt,
|
|
3645
|
+
False,
|
|
3646
|
+
optimizer=optimizer,
|
|
3647
|
+
conversationally=conversationally,
|
|
3648
|
+
)
|
|
3649
|
+
)
|
|
3650
|
+
|
|
3651
|
+
return for_stream() if stream else await for_non_stream()
|
|
3652
|
+
|
|
3653
|
+
async def get_message(self, response: dict) -> str:
|
|
3654
|
+
"""Retrieves message only from response
|
|
3655
|
+
|
|
3656
|
+
Args:
|
|
3657
|
+
response (dict): Response generated by `self.ask`
|
|
3658
|
+
|
|
3659
|
+
Returns:
|
|
3660
|
+
str: Message extracted
|
|
3661
|
+
"""
|
|
3662
|
+
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
3663
|
+
return response["text"]
|
|
3664
|
+
#------------------------------------------------------phind-------------------------------------------------------------
|
|
3665
|
+
class PhindSearch:
|
|
3666
|
+
# default_model = "Phind Model"
|
|
3667
|
+
def __init__(
|
|
3668
|
+
self,
|
|
3669
|
+
is_conversation: bool = True,
|
|
3670
|
+
max_tokens: int = 8000,
|
|
3671
|
+
timeout: int = 30,
|
|
3672
|
+
intro: str = None,
|
|
3673
|
+
filepath: str = None,
|
|
3674
|
+
update_file: bool = True,
|
|
3675
|
+
proxies: dict = {},
|
|
3676
|
+
history_offset: int = 10250,
|
|
3677
|
+
act: str = None,
|
|
3678
|
+
model: str = "Phind Model",
|
|
3679
|
+
quiet: bool = False,
|
|
3680
|
+
):
|
|
3681
|
+
"""Instantiates PHIND
|
|
3682
|
+
|
|
3683
|
+
Args:
|
|
3684
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
3685
|
+
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
3686
|
+
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
3687
|
+
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
3688
|
+
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
3689
|
+
update_file (bool, optional): Add new prompts and responses to the file. Defaults to True.
|
|
3690
|
+
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
3691
|
+
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
3692
|
+
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
3693
|
+
model (str, optional): Model name. Defaults to "Phind Model".
|
|
3694
|
+
quiet (bool, optional): Ignore web search-results and yield final response only. Defaults to False.
|
|
3695
|
+
"""
|
|
3696
|
+
self.session = requests.Session()
|
|
3697
|
+
self.max_tokens_to_sample = max_tokens
|
|
3698
|
+
self.is_conversation = is_conversation
|
|
3699
|
+
self.chat_endpoint = "https://https.extension.phind.com/agent/"
|
|
3700
|
+
self.stream_chunk_size = 64
|
|
3701
|
+
self.timeout = timeout
|
|
3702
|
+
self.last_response = {}
|
|
3703
|
+
self.model = model
|
|
3704
|
+
self.quiet = quiet
|
|
3705
|
+
|
|
3706
|
+
self.headers = {
|
|
3707
|
+
"Content-Type": "application/json",
|
|
3708
|
+
"User-Agent": "",
|
|
3709
|
+
"Accept": "*/*",
|
|
3710
|
+
"Accept-Encoding": "Identity",
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
self.__available_optimizers = (
|
|
3714
|
+
method
|
|
3715
|
+
for method in dir(Optimizers)
|
|
3716
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
3717
|
+
)
|
|
3718
|
+
self.session.headers.update(self.headers)
|
|
3719
|
+
Conversation.intro = (
|
|
3720
|
+
AwesomePrompts().get_act(
|
|
3721
|
+
act, raise_not_found=True, default=None, case_insensitive=True
|
|
3722
|
+
)
|
|
3723
|
+
if act
|
|
3724
|
+
else intro or Conversation.intro
|
|
3725
|
+
)
|
|
3726
|
+
self.conversation = Conversation(
|
|
3727
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
3728
|
+
)
|
|
3729
|
+
self.conversation.history_offset = history_offset
|
|
3730
|
+
self.session.proxies = proxies
|
|
3731
|
+
|
|
3732
|
+
def ask(
|
|
3733
|
+
self,
|
|
3734
|
+
prompt: str,
|
|
3735
|
+
stream: bool = False,
|
|
3736
|
+
raw: bool = False,
|
|
3737
|
+
optimizer: str = None,
|
|
3738
|
+
conversationally: bool = False,
|
|
3739
|
+
) -> dict:
|
|
3740
|
+
"""Chat with AI
|
|
3741
|
+
|
|
3742
|
+
Args:
|
|
3743
|
+
prompt (str): Prompt to be send.
|
|
3744
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3745
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
3746
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3747
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3748
|
+
Returns:
|
|
3749
|
+
dict : {}
|
|
3750
|
+
```json
|
|
3751
|
+
{
|
|
3752
|
+
"id": "chatcmpl-r0wujizf2i2xb60mjiwt",
|
|
3753
|
+
"object": "chat.completion.chunk",
|
|
3754
|
+
"created": 1706775384,
|
|
3755
|
+
"model": "trt-llm-phind-model-serving",
|
|
3756
|
+
"choices": [
|
|
3757
|
+
{
|
|
3758
|
+
"index": 0,
|
|
3759
|
+
"delta": {
|
|
3760
|
+
"content": "Hello! How can I assist you with your programming today?"
|
|
3761
|
+
},
|
|
3762
|
+
"finish_reason": null
|
|
3763
|
+
}
|
|
3764
|
+
]
|
|
3765
|
+
}
|
|
3766
|
+
```
|
|
3767
|
+
"""
|
|
3768
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
3769
|
+
if optimizer:
|
|
3770
|
+
if optimizer in self.__available_optimizers:
|
|
3771
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
3772
|
+
conversation_prompt if conversationally else prompt
|
|
3773
|
+
)
|
|
3774
|
+
else:
|
|
3775
|
+
raise Exception(
|
|
3776
|
+
f"Optimizer is not one of {self.__available_optimizers}"
|
|
3777
|
+
)
|
|
3778
|
+
|
|
3779
|
+
self.session.headers.update(self.headers)
|
|
3780
|
+
payload = {
|
|
3781
|
+
"additional_extension_context": "",
|
|
3782
|
+
"allow_magic_buttons": True,
|
|
3783
|
+
"is_vscode_extension": True,
|
|
3784
|
+
"message_history": [
|
|
3785
|
+
{"content": conversation_prompt, "metadata": {}, "role": "user"}
|
|
1466
3786
|
],
|
|
1467
|
-
"
|
|
1468
|
-
"
|
|
3787
|
+
"requested_model": self.model,
|
|
3788
|
+
"user_input": prompt,
|
|
1469
3789
|
}
|
|
1470
3790
|
|
|
1471
3791
|
def for_stream():
|
|
@@ -1477,21 +3797,26 @@ class OPENGPT:
|
|
|
1477
3797
|
or not response.headers.get("Content-Type")
|
|
1478
3798
|
== "text/event-stream; charset=utf-8"
|
|
1479
3799
|
):
|
|
1480
|
-
raise
|
|
3800
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
1481
3801
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1482
3802
|
)
|
|
1483
|
-
|
|
3803
|
+
streaming_text = ""
|
|
1484
3804
|
for value in response.iter_lines(
|
|
1485
3805
|
decode_unicode=True,
|
|
1486
3806
|
chunk_size=self.stream_chunk_size,
|
|
1487
3807
|
):
|
|
1488
3808
|
try:
|
|
1489
3809
|
modified_value = re.sub("data:", "", value)
|
|
1490
|
-
|
|
1491
|
-
|
|
3810
|
+
json_modified_value = json.loads(modified_value)
|
|
3811
|
+
retrieved_text = self.get_message(json_modified_value)
|
|
3812
|
+
if not retrieved_text:
|
|
1492
3813
|
continue
|
|
1493
|
-
|
|
1494
|
-
|
|
3814
|
+
streaming_text += retrieved_text
|
|
3815
|
+
json_modified_value["choices"][0]["delta"][
|
|
3816
|
+
"content"
|
|
3817
|
+
] = streaming_text
|
|
3818
|
+
self.last_response.update(json_modified_value)
|
|
3819
|
+
yield value if raw else json_modified_value
|
|
1495
3820
|
except json.decoder.JSONDecodeError:
|
|
1496
3821
|
pass
|
|
1497
3822
|
self.conversation.update_chat_history(
|
|
@@ -1550,13 +3875,40 @@ class OPENGPT:
|
|
|
1550
3875
|
str: Message extracted
|
|
1551
3876
|
"""
|
|
1552
3877
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
3878
|
+
if response.get("type", "") == "metadata":
|
|
3879
|
+
return
|
|
3880
|
+
|
|
3881
|
+
delta: dict = response["choices"][0]["delta"]
|
|
3882
|
+
|
|
3883
|
+
if not delta:
|
|
3884
|
+
return ""
|
|
3885
|
+
|
|
3886
|
+
elif delta.get("function_call"):
|
|
3887
|
+
if self.quiet:
|
|
3888
|
+
return ""
|
|
3889
|
+
|
|
3890
|
+
function_call: dict = delta["function_call"]
|
|
3891
|
+
if function_call.get("name"):
|
|
3892
|
+
return function_call["name"]
|
|
3893
|
+
elif function_call.get("arguments"):
|
|
3894
|
+
return function_call.get("arguments")
|
|
3895
|
+
|
|
3896
|
+
elif delta.get("metadata"):
|
|
3897
|
+
if self.quiet:
|
|
3898
|
+
return ""
|
|
3899
|
+
return yaml.dump(delta["metadata"])
|
|
3900
|
+
|
|
3901
|
+
else:
|
|
3902
|
+
return (
|
|
3903
|
+
response["choices"][0]["delta"].get("content")
|
|
3904
|
+
if response["choices"][0].get("finish_reason") is None
|
|
3905
|
+
else ""
|
|
3906
|
+
)
|
|
3907
|
+
class AsyncPhindSearch(AsyncProvider):
|
|
1556
3908
|
def __init__(
|
|
1557
3909
|
self,
|
|
1558
3910
|
is_conversation: bool = True,
|
|
1559
|
-
max_tokens: int =
|
|
3911
|
+
max_tokens: int = 600,
|
|
1560
3912
|
timeout: int = 30,
|
|
1561
3913
|
intro: str = None,
|
|
1562
3914
|
filepath: str = None,
|
|
@@ -1564,9 +3916,10 @@ class PERPLEXITY:
|
|
|
1564
3916
|
proxies: dict = {},
|
|
1565
3917
|
history_offset: int = 10250,
|
|
1566
3918
|
act: str = None,
|
|
3919
|
+
model: str = "Phind Model",
|
|
1567
3920
|
quiet: bool = False,
|
|
1568
3921
|
):
|
|
1569
|
-
"""Instantiates
|
|
3922
|
+
"""Instantiates PHIND
|
|
1570
3923
|
|
|
1571
3924
|
Args:
|
|
1572
3925
|
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
@@ -1578,16 +3931,25 @@ class PERPLEXITY:
|
|
|
1578
3931
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
1579
3932
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1580
3933
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
3934
|
+
model (str, optional): Model name. Defaults to "Phind Model".
|
|
1581
3935
|
quiet (bool, optional): Ignore web search-results and yield final response only. Defaults to False.
|
|
1582
3936
|
"""
|
|
1583
|
-
logging.getLogger("websocket").setLevel(logging.ERROR)
|
|
1584
|
-
self.session = requests.Session()
|
|
1585
3937
|
self.max_tokens_to_sample = max_tokens
|
|
1586
3938
|
self.is_conversation = is_conversation
|
|
3939
|
+
self.chat_endpoint = "https://https.extension.phind.com/agent/"
|
|
3940
|
+
self.stream_chunk_size = 64
|
|
3941
|
+
self.timeout = timeout
|
|
1587
3942
|
self.last_response = {}
|
|
1588
|
-
self.
|
|
3943
|
+
self.model = model
|
|
1589
3944
|
self.quiet = quiet
|
|
1590
3945
|
|
|
3946
|
+
self.headers = {
|
|
3947
|
+
"Content-Type": "application/json",
|
|
3948
|
+
"User-Agent": "",
|
|
3949
|
+
"Accept": "*/*",
|
|
3950
|
+
"Accept-Encoding": "Identity",
|
|
3951
|
+
}
|
|
3952
|
+
|
|
1591
3953
|
self.__available_optimizers = (
|
|
1592
3954
|
method
|
|
1593
3955
|
for method in dir(Optimizers)
|
|
@@ -1604,48 +3966,44 @@ class PERPLEXITY:
|
|
|
1604
3966
|
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
1605
3967
|
)
|
|
1606
3968
|
self.conversation.history_offset = history_offset
|
|
3969
|
+
self.session = httpx.AsyncClient(headers=self.headers, proxies=proxies)
|
|
1607
3970
|
|
|
1608
|
-
def ask(
|
|
3971
|
+
async def ask(
|
|
1609
3972
|
self,
|
|
1610
3973
|
prompt: str,
|
|
1611
3974
|
stream: bool = False,
|
|
1612
3975
|
raw: bool = False,
|
|
1613
3976
|
optimizer: str = None,
|
|
1614
3977
|
conversationally: bool = False,
|
|
1615
|
-
|
|
1616
|
-
|
|
3978
|
+
synchronous_generator=False,
|
|
3979
|
+
) -> dict | AsyncGenerator:
|
|
3980
|
+
"""Asynchronously Chat with AI
|
|
1617
3981
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
3982
|
+
Args:
|
|
3983
|
+
prompt (str): Prompt to be send.
|
|
3984
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
3985
|
+
raw (bool, optional): Stream back raw response as received. Defaults to False.
|
|
3986
|
+
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
3987
|
+
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
3988
|
+
Returns:
|
|
3989
|
+
dict|AsyncGenerator : ai content.
|
|
3990
|
+
```json
|
|
1627
3991
|
{
|
|
1628
|
-
"
|
|
1629
|
-
"
|
|
1630
|
-
"
|
|
1631
|
-
"
|
|
1632
|
-
"
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
"display_model": "turbo",
|
|
1642
|
-
"attachments": null,
|
|
1643
|
-
"answer": "",
|
|
1644
|
-
"web_results": [],
|
|
1645
|
-
"chunks": [],
|
|
1646
|
-
"extra_web_results": []
|
|
3992
|
+
"id": "chatcmpl-r0wujizf2i2xb60mjiwt",
|
|
3993
|
+
"object": "chat.completion.chunk",
|
|
3994
|
+
"created": 1706775384,
|
|
3995
|
+
"model": "trt-llm-phind-model-serving",
|
|
3996
|
+
"choices": [
|
|
3997
|
+
{
|
|
3998
|
+
"index": 0,
|
|
3999
|
+
"delta": {
|
|
4000
|
+
"content": "Hello! How can I assist you with your programming today?"
|
|
4001
|
+
},
|
|
4002
|
+
"finish_reason": null
|
|
4003
|
+
}
|
|
4004
|
+
]
|
|
1647
4005
|
}
|
|
1648
|
-
|
|
4006
|
+
```
|
|
1649
4007
|
"""
|
|
1650
4008
|
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
1651
4009
|
if optimizer:
|
|
@@ -1658,30 +4016,70 @@ class PERPLEXITY:
|
|
|
1658
4016
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1659
4017
|
)
|
|
1660
4018
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
4019
|
+
payload = {
|
|
4020
|
+
"additional_extension_context": "",
|
|
4021
|
+
"allow_magic_buttons": True,
|
|
4022
|
+
"is_vscode_extension": True,
|
|
4023
|
+
"message_history": [
|
|
4024
|
+
{"content": conversation_prompt, "metadata": {}, "role": "user"}
|
|
4025
|
+
],
|
|
4026
|
+
"requested_model": self.model,
|
|
4027
|
+
"user_input": prompt,
|
|
4028
|
+
}
|
|
1665
4029
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
4030
|
+
async def for_stream():
|
|
4031
|
+
async with self.session.stream(
|
|
4032
|
+
"POST",
|
|
4033
|
+
self.chat_endpoint,
|
|
4034
|
+
json=payload,
|
|
4035
|
+
timeout=self.timeout,
|
|
4036
|
+
) as response:
|
|
4037
|
+
if (
|
|
4038
|
+
not response.is_success
|
|
4039
|
+
or not response.headers.get("Content-Type")
|
|
4040
|
+
== "text/event-stream; charset=utf-8"
|
|
4041
|
+
):
|
|
4042
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
4043
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase})"
|
|
4044
|
+
)
|
|
4045
|
+
streaming_text = ""
|
|
4046
|
+
async for value in response.aiter_lines():
|
|
4047
|
+
try:
|
|
4048
|
+
modified_value = re.sub("data:", "", value)
|
|
4049
|
+
json_modified_value = json.loads(modified_value)
|
|
4050
|
+
retrieved_text = await self.get_message(json_modified_value)
|
|
4051
|
+
if not retrieved_text:
|
|
4052
|
+
continue
|
|
4053
|
+
streaming_text += retrieved_text
|
|
4054
|
+
json_modified_value["choices"][0]["delta"][
|
|
4055
|
+
"content"
|
|
4056
|
+
] = streaming_text
|
|
4057
|
+
self.last_response.update(json_modified_value)
|
|
4058
|
+
yield value if raw else json_modified_value
|
|
4059
|
+
except json.decoder.JSONDecodeError:
|
|
4060
|
+
pass
|
|
4061
|
+
self.conversation.update_chat_history(
|
|
4062
|
+
prompt, await self.get_message(self.last_response)
|
|
4063
|
+
)
|
|
1670
4064
|
|
|
1671
|
-
def for_non_stream():
|
|
1672
|
-
for _ in for_stream():
|
|
4065
|
+
async def for_non_stream():
|
|
4066
|
+
async for _ in for_stream():
|
|
1673
4067
|
pass
|
|
1674
4068
|
return self.last_response
|
|
1675
4069
|
|
|
1676
|
-
return
|
|
4070
|
+
return (
|
|
4071
|
+
for_stream()
|
|
4072
|
+
if stream and not synchronous_generator
|
|
4073
|
+
else await for_non_stream()
|
|
4074
|
+
)
|
|
1677
4075
|
|
|
1678
|
-
def chat(
|
|
4076
|
+
async def chat(
|
|
1679
4077
|
self,
|
|
1680
4078
|
prompt: str,
|
|
1681
4079
|
stream: bool = False,
|
|
1682
4080
|
optimizer: str = None,
|
|
1683
4081
|
conversationally: bool = False,
|
|
1684
|
-
) -> str:
|
|
4082
|
+
) -> str | AsyncGenerator:
|
|
1685
4083
|
"""Generate response `str`
|
|
1686
4084
|
Args:
|
|
1687
4085
|
prompt (str): Prompt to be send.
|
|
@@ -1689,18 +4087,19 @@ class PERPLEXITY:
|
|
|
1689
4087
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
1690
4088
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
1691
4089
|
Returns:
|
|
1692
|
-
str: Response generated
|
|
4090
|
+
str|AsyncGenerator: Response generated
|
|
1693
4091
|
"""
|
|
1694
4092
|
|
|
1695
|
-
def for_stream():
|
|
1696
|
-
|
|
4093
|
+
async def for_stream():
|
|
4094
|
+
ask_resp = await self.ask(
|
|
1697
4095
|
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
1698
|
-
)
|
|
1699
|
-
|
|
4096
|
+
)
|
|
4097
|
+
async for response in ask_resp:
|
|
4098
|
+
yield await self.get_message(response)
|
|
1700
4099
|
|
|
1701
|
-
def for_non_stream():
|
|
1702
|
-
return self.get_message(
|
|
1703
|
-
self.ask(
|
|
4100
|
+
async def for_non_stream():
|
|
4101
|
+
return await self.get_message(
|
|
4102
|
+
await self.ask(
|
|
1704
4103
|
prompt,
|
|
1705
4104
|
False,
|
|
1706
4105
|
optimizer=optimizer,
|
|
@@ -1708,9 +4107,9 @@ class PERPLEXITY:
|
|
|
1708
4107
|
)
|
|
1709
4108
|
)
|
|
1710
4109
|
|
|
1711
|
-
return for_stream() if stream else for_non_stream()
|
|
4110
|
+
return for_stream() if stream else await for_non_stream()
|
|
1712
4111
|
|
|
1713
|
-
def get_message(self, response: dict) -> str:
|
|
4112
|
+
async def get_message(self, response: dict) -> str:
|
|
1714
4113
|
"""Retrieves message only from response
|
|
1715
4114
|
|
|
1716
4115
|
Args:
|
|
@@ -1720,45 +4119,46 @@ class PERPLEXITY:
|
|
|
1720
4119
|
str: Message extracted
|
|
1721
4120
|
"""
|
|
1722
4121
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1723
|
-
|
|
4122
|
+
if response.get("type", "") == "metadata":
|
|
4123
|
+
return
|
|
1724
4124
|
|
|
1725
|
-
|
|
1726
|
-
for index, results in enumerate(web_results, start=1):
|
|
1727
|
-
self.web_results[str(index) + ". " + results["name"]] = dict(
|
|
1728
|
-
url=results.get("url"), snippet=results.get("snippet")
|
|
1729
|
-
)
|
|
4125
|
+
delta: dict = response["choices"][0]["delta"]
|
|
1730
4126
|
|
|
1731
|
-
if
|
|
1732
|
-
|
|
1733
|
-
target: dict[str, Any] = json.loads(response.get("text"))
|
|
1734
|
-
text_str = target.get("answer")
|
|
1735
|
-
web_results: list[dict] = target.get("web_results")
|
|
1736
|
-
self.web_results.clear()
|
|
1737
|
-
update_web_results(web_results)
|
|
4127
|
+
if not delta:
|
|
4128
|
+
return ""
|
|
1738
4129
|
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
4130
|
+
elif delta.get("function_call"):
|
|
4131
|
+
if self.quiet:
|
|
4132
|
+
return ""
|
|
4133
|
+
|
|
4134
|
+
function_call: dict = delta["function_call"]
|
|
4135
|
+
if function_call.get("name"):
|
|
4136
|
+
return function_call["name"]
|
|
4137
|
+
elif function_call.get("arguments"):
|
|
4138
|
+
return function_call.get("arguments")
|
|
4139
|
+
|
|
4140
|
+
elif delta.get("metadata"):
|
|
4141
|
+
if self.quiet:
|
|
4142
|
+
return ""
|
|
4143
|
+
return yaml.dump(delta["metadata"])
|
|
1744
4144
|
|
|
1745
4145
|
else:
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
)
|
|
1754
|
-
else:
|
|
1755
|
-
return text_str
|
|
1756
|
-
#------------------------------------------------------BLACKBOXAI--------------------------------------------------------
|
|
1757
|
-
class BLACKBOXAI:
|
|
4146
|
+
return (
|
|
4147
|
+
response["choices"][0]["delta"].get("content")
|
|
4148
|
+
if response["choices"][0].get("finish_reason") is None
|
|
4149
|
+
else ""
|
|
4150
|
+
)
|
|
4151
|
+
#-------------------------------------------------------yep.com--------------------------------------------------------
|
|
4152
|
+
class YEPCHAT(Provider):
|
|
1758
4153
|
def __init__(
|
|
1759
4154
|
self,
|
|
1760
4155
|
is_conversation: bool = True,
|
|
1761
|
-
max_tokens: int =
|
|
4156
|
+
max_tokens: int = 600,
|
|
4157
|
+
temperature: float = 0.6,
|
|
4158
|
+
presence_penalty: int = 0,
|
|
4159
|
+
frequency_penalty: int = 0,
|
|
4160
|
+
top_p: float = 0.7,
|
|
4161
|
+
model: str ="Mixtral-8x7B-Instruct-v0.1",
|
|
1762
4162
|
timeout: int = 30,
|
|
1763
4163
|
intro: str = None,
|
|
1764
4164
|
filepath: str = None,
|
|
@@ -1766,13 +4166,17 @@ class BLACKBOXAI:
|
|
|
1766
4166
|
proxies: dict = {},
|
|
1767
4167
|
history_offset: int = 10250,
|
|
1768
4168
|
act: str = None,
|
|
1769
|
-
model: str = None,
|
|
1770
4169
|
):
|
|
1771
|
-
"""Instantiates
|
|
4170
|
+
"""Instantiates YEPCHAT
|
|
1772
4171
|
|
|
1773
4172
|
Args:
|
|
1774
|
-
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
4173
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
1775
4174
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
4175
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.6.
|
|
4176
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
4177
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
4178
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.7.
|
|
4179
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
1776
4180
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
1777
4181
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
1778
4182
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -1780,29 +4184,26 @@ class BLACKBOXAI:
|
|
|
1780
4184
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
1781
4185
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1782
4186
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1783
|
-
model (str, optional): Model name. Defaults to "Phind Model".
|
|
1784
4187
|
"""
|
|
1785
|
-
self.session = requests.Session()
|
|
1786
|
-
self.max_tokens_to_sample = max_tokens
|
|
1787
4188
|
self.is_conversation = is_conversation
|
|
1788
|
-
self.
|
|
4189
|
+
self.max_tokens_to_sample = max_tokens
|
|
4190
|
+
self.model = model
|
|
4191
|
+
self.temperature = temperature
|
|
4192
|
+
self.presence_penalty = presence_penalty
|
|
4193
|
+
self.frequency_penalty = frequency_penalty
|
|
4194
|
+
self.top_p = top_p
|
|
4195
|
+
self.chat_endpoint = "https://api.yep.com/v1/chat/completions"
|
|
1789
4196
|
self.stream_chunk_size = 64
|
|
1790
4197
|
self.timeout = timeout
|
|
1791
4198
|
self.last_response = {}
|
|
1792
|
-
self.model = model
|
|
1793
|
-
self.previewToken: str = None
|
|
1794
|
-
self.userId: str = ""
|
|
1795
|
-
self.codeModelMode: bool = True
|
|
1796
|
-
self.id: str = ""
|
|
1797
|
-
self.agentMode: dict = {}
|
|
1798
|
-
self.trendingAgentMode: dict = {}
|
|
1799
|
-
self.isMicMode: bool = False
|
|
1800
|
-
|
|
1801
4199
|
self.headers = {
|
|
1802
|
-
"Content-Type": "application/json",
|
|
1803
|
-
"User-Agent": "",
|
|
1804
4200
|
"Accept": "*/*",
|
|
1805
|
-
"Accept-Encoding": "
|
|
4201
|
+
"Accept-Encoding": "gzip, deflate",
|
|
4202
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
4203
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
4204
|
+
"Origin": "https://yep.com",
|
|
4205
|
+
"Referer": "https://yep.com/",
|
|
4206
|
+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
1806
4207
|
}
|
|
1807
4208
|
|
|
1808
4209
|
self.__available_optimizers = (
|
|
@@ -1844,7 +4245,20 @@ class BLACKBOXAI:
|
|
|
1844
4245
|
dict : {}
|
|
1845
4246
|
```json
|
|
1846
4247
|
{
|
|
1847
|
-
|
|
4248
|
+
"id": "cmpl-c61c1c88de4e4ad3a79134775d17ea0c",
|
|
4249
|
+
"object": "chat.completion.chunk",
|
|
4250
|
+
"created": 1713876886,
|
|
4251
|
+
"model": "Mixtral-8x7B-Instruct-v0.1",
|
|
4252
|
+
"choices": [
|
|
4253
|
+
{
|
|
4254
|
+
"index": 0,
|
|
4255
|
+
"delta": {
|
|
4256
|
+
"role": null,
|
|
4257
|
+
"content": " Sure, I can help with that. Are you looking for information on how to start coding, or do you need help with a specific coding problem? We can discuss various programming languages like Python, JavaScript, Java, C++, or others. Please provide more details so I can assist you better."
|
|
4258
|
+
},
|
|
4259
|
+
"finish_reason": null
|
|
4260
|
+
}
|
|
4261
|
+
]
|
|
1848
4262
|
}
|
|
1849
4263
|
```
|
|
1850
4264
|
"""
|
|
@@ -1858,47 +4272,41 @@ class BLACKBOXAI:
|
|
|
1858
4272
|
raise Exception(
|
|
1859
4273
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
1860
4274
|
)
|
|
1861
|
-
|
|
1862
4275
|
self.session.headers.update(self.headers)
|
|
1863
4276
|
payload = {
|
|
1864
|
-
"
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
"
|
|
1869
|
-
"
|
|
1870
|
-
"userId": self.userId,
|
|
1871
|
-
"codeModelMode": self.codeModelMode,
|
|
1872
|
-
"agentMode": self.agentMode,
|
|
1873
|
-
"trendingAgentMode": self.trendingAgentMode,
|
|
1874
|
-
"isMicMode": self.isMicMode,
|
|
4277
|
+
"stream": True,
|
|
4278
|
+
"max_tokens": 1280,
|
|
4279
|
+
"top_p": self.top_p,
|
|
4280
|
+
"temperature": self.temperature,
|
|
4281
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
4282
|
+
"model": self.model,
|
|
1875
4283
|
}
|
|
1876
4284
|
|
|
1877
4285
|
def for_stream():
|
|
1878
4286
|
response = self.session.post(
|
|
1879
4287
|
self.chat_endpoint, json=payload, stream=True, timeout=self.timeout
|
|
1880
4288
|
)
|
|
1881
|
-
if
|
|
1882
|
-
|
|
1883
|
-
or not response.headers.get("Content-Type")
|
|
1884
|
-
== "text/plain; charset=utf-8"
|
|
1885
|
-
):
|
|
1886
|
-
raise Exception(
|
|
4289
|
+
if not response.ok:
|
|
4290
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
1887
4291
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
1888
4292
|
)
|
|
1889
|
-
|
|
4293
|
+
|
|
4294
|
+
message_load = ""
|
|
1890
4295
|
for value in response.iter_lines(
|
|
1891
4296
|
decode_unicode=True,
|
|
4297
|
+
delimiter="" if raw else "data:",
|
|
1892
4298
|
chunk_size=self.stream_chunk_size,
|
|
1893
|
-
delimiter="\n",
|
|
1894
4299
|
):
|
|
1895
4300
|
try:
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
4301
|
+
resp = json.loads(value)
|
|
4302
|
+
incomplete_message = self.get_message(resp)
|
|
4303
|
+
if incomplete_message:
|
|
4304
|
+
message_load += incomplete_message
|
|
4305
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
1900
4306
|
self.last_response.update(resp)
|
|
1901
4307
|
yield value if raw else resp
|
|
4308
|
+
elif raw:
|
|
4309
|
+
yield value
|
|
1902
4310
|
except json.decoder.JSONDecodeError:
|
|
1903
4311
|
pass
|
|
1904
4312
|
self.conversation.update_chat_history(
|
|
@@ -1957,21 +4365,22 @@ class BLACKBOXAI:
|
|
|
1957
4365
|
str: Message extracted
|
|
1958
4366
|
"""
|
|
1959
4367
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
print(processed_response)
|
|
1968
|
-
#------------------------------------------------------phind-------------------------------------------------------------
|
|
1969
|
-
class PhindSearch:
|
|
1970
|
-
# default_model = "Phind Model"
|
|
4368
|
+
try:
|
|
4369
|
+
if response["choices"][0].get("delta"):
|
|
4370
|
+
return response["choices"][0]["delta"]["content"]
|
|
4371
|
+
return response["choices"][0]["message"]["content"]
|
|
4372
|
+
except KeyError:
|
|
4373
|
+
return ""
|
|
4374
|
+
class AsyncYEPCHAT(AsyncProvider):
|
|
1971
4375
|
def __init__(
|
|
1972
4376
|
self,
|
|
1973
4377
|
is_conversation: bool = True,
|
|
1974
|
-
max_tokens: int =
|
|
4378
|
+
max_tokens: int = 600,
|
|
4379
|
+
temperature: float = 0.6,
|
|
4380
|
+
presence_penalty: int = 0,
|
|
4381
|
+
frequency_penalty: int = 0,
|
|
4382
|
+
top_p: float = 0.7,
|
|
4383
|
+
model: str = "Mixtral-8x7B-Instruct-v0.1",
|
|
1975
4384
|
timeout: int = 30,
|
|
1976
4385
|
intro: str = None,
|
|
1977
4386
|
filepath: str = None,
|
|
@@ -1979,14 +4388,17 @@ class PhindSearch:
|
|
|
1979
4388
|
proxies: dict = {},
|
|
1980
4389
|
history_offset: int = 10250,
|
|
1981
4390
|
act: str = None,
|
|
1982
|
-
model: str = "Phind Model",
|
|
1983
|
-
quiet: bool = False,
|
|
1984
4391
|
):
|
|
1985
|
-
"""Instantiates
|
|
4392
|
+
"""Instantiates YEPCHAT
|
|
1986
4393
|
|
|
1987
4394
|
Args:
|
|
1988
|
-
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True
|
|
4395
|
+
is_conversation (bool, optional): Flag for chatting conversationally. Defaults to True.
|
|
1989
4396
|
max_tokens (int, optional): Maximum number of tokens to be generated upon completion. Defaults to 600.
|
|
4397
|
+
temperature (float, optional): Charge of the generated text's randomness. Defaults to 0.6.
|
|
4398
|
+
presence_penalty (int, optional): Chances of topic being repeated. Defaults to 0.
|
|
4399
|
+
frequency_penalty (int, optional): Chances of word being repeated. Defaults to 0.
|
|
4400
|
+
top_p (float, optional): Sampling threshold during inference time. Defaults to 0.7.
|
|
4401
|
+
model (str, optional): LLM model name. Defaults to "gpt-3.5-turbo".
|
|
1990
4402
|
timeout (int, optional): Http request timeout. Defaults to 30.
|
|
1991
4403
|
intro (str, optional): Conversation introductory prompt. Defaults to None.
|
|
1992
4404
|
filepath (str, optional): Path to file containing conversation history. Defaults to None.
|
|
@@ -1994,24 +4406,26 @@ class PhindSearch:
|
|
|
1994
4406
|
proxies (dict, optional): Http request proxies. Defaults to {}.
|
|
1995
4407
|
history_offset (int, optional): Limit conversation history to this number of last texts. Defaults to 10250.
|
|
1996
4408
|
act (str|int, optional): Awesome prompt key or index. (Used as intro). Defaults to None.
|
|
1997
|
-
model (str, optional): Model name. Defaults to "Phind Model".
|
|
1998
|
-
quiet (bool, optional): Ignore web search-results and yield final response only. Defaults to False.
|
|
1999
4409
|
"""
|
|
2000
|
-
self.session = requests.Session()
|
|
2001
|
-
self.max_tokens_to_sample = max_tokens
|
|
2002
4410
|
self.is_conversation = is_conversation
|
|
2003
|
-
self.
|
|
4411
|
+
self.max_tokens_to_sample = max_tokens
|
|
4412
|
+
self.model = model
|
|
4413
|
+
self.temperature = temperature
|
|
4414
|
+
self.presence_penalty = presence_penalty
|
|
4415
|
+
self.frequency_penalty = frequency_penalty
|
|
4416
|
+
self.top_p = top_p
|
|
4417
|
+
self.chat_endpoint = "https://api.yep.com/v1/chat/completions"
|
|
2004
4418
|
self.stream_chunk_size = 64
|
|
2005
4419
|
self.timeout = timeout
|
|
2006
4420
|
self.last_response = {}
|
|
2007
|
-
self.model = model
|
|
2008
|
-
self.quiet = quiet
|
|
2009
|
-
|
|
2010
4421
|
self.headers = {
|
|
2011
|
-
"Content-Type": "application/json",
|
|
2012
|
-
"User-Agent": "",
|
|
2013
4422
|
"Accept": "*/*",
|
|
2014
|
-
"Accept-Encoding": "
|
|
4423
|
+
"Accept-Encoding": "gzip, deflate",
|
|
4424
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
4425
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
4426
|
+
"Origin": "https://yep.com",
|
|
4427
|
+
"Referer": "https://yep.com/",
|
|
4428
|
+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
2015
4429
|
}
|
|
2016
4430
|
|
|
2017
4431
|
self.__available_optimizers = (
|
|
@@ -2019,7 +4433,6 @@ class PhindSearch:
|
|
|
2019
4433
|
for method in dir(Optimizers)
|
|
2020
4434
|
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
2021
4435
|
)
|
|
2022
|
-
self.session.headers.update(self.headers)
|
|
2023
4436
|
Conversation.intro = (
|
|
2024
4437
|
AwesomePrompts().get_act(
|
|
2025
4438
|
act, raise_not_found=True, default=None, case_insensitive=True
|
|
@@ -2031,9 +4444,12 @@ class PhindSearch:
|
|
|
2031
4444
|
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
2032
4445
|
)
|
|
2033
4446
|
self.conversation.history_offset = history_offset
|
|
2034
|
-
self.session
|
|
4447
|
+
self.session = httpx.AsyncClient(
|
|
4448
|
+
headers=self.headers,
|
|
4449
|
+
proxies=proxies,
|
|
4450
|
+
)
|
|
2035
4451
|
|
|
2036
|
-
def ask(
|
|
4452
|
+
async def ask(
|
|
2037
4453
|
self,
|
|
2038
4454
|
prompt: str,
|
|
2039
4455
|
stream: bool = False,
|
|
@@ -2041,7 +4457,7 @@ class PhindSearch:
|
|
|
2041
4457
|
optimizer: str = None,
|
|
2042
4458
|
conversationally: bool = False,
|
|
2043
4459
|
) -> dict:
|
|
2044
|
-
"""Chat with AI
|
|
4460
|
+
"""Chat with AI asynchronously.
|
|
2045
4461
|
|
|
2046
4462
|
Args:
|
|
2047
4463
|
prompt (str): Prompt to be send.
|
|
@@ -2053,15 +4469,16 @@ class PhindSearch:
|
|
|
2053
4469
|
dict : {}
|
|
2054
4470
|
```json
|
|
2055
4471
|
{
|
|
2056
|
-
"id": "
|
|
4472
|
+
"id": "cmpl-c61c1c88de4e4ad3a79134775d17ea0c",
|
|
2057
4473
|
"object": "chat.completion.chunk",
|
|
2058
|
-
"created":
|
|
2059
|
-
"model": "
|
|
4474
|
+
"created": 1713876886,
|
|
4475
|
+
"model": "Mixtral-8x7B-Instruct-v0.1",
|
|
2060
4476
|
"choices": [
|
|
2061
4477
|
{
|
|
2062
4478
|
"index": 0,
|
|
2063
4479
|
"delta": {
|
|
2064
|
-
"
|
|
4480
|
+
"role": null,
|
|
4481
|
+
"content": " Sure, I can help with that. Are you looking for information on how to start coding, or do you need help with a specific coding problem? We can discuss various programming languages like Python, JavaScript, Java, C++, or others. Please provide more details so I can assist you better."
|
|
2065
4482
|
},
|
|
2066
4483
|
"finish_reason": null
|
|
2067
4484
|
}
|
|
@@ -2079,69 +4496,58 @@ class PhindSearch:
|
|
|
2079
4496
|
raise Exception(
|
|
2080
4497
|
f"Optimizer is not one of {self.__available_optimizers}"
|
|
2081
4498
|
)
|
|
2082
|
-
|
|
2083
|
-
self.session.headers.update(self.headers)
|
|
2084
4499
|
payload = {
|
|
2085
|
-
"
|
|
2086
|
-
"
|
|
2087
|
-
"
|
|
2088
|
-
"
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
"requested_model": self.model,
|
|
2092
|
-
"user_input": prompt,
|
|
4500
|
+
"stream": True,
|
|
4501
|
+
"max_tokens": 1280,
|
|
4502
|
+
"top_p": self.top_p,
|
|
4503
|
+
"temperature": self.temperature,
|
|
4504
|
+
"messages": [{"content": conversation_prompt, "role": "user"}],
|
|
4505
|
+
"model": self.model,
|
|
2093
4506
|
}
|
|
2094
4507
|
|
|
2095
|
-
def for_stream():
|
|
2096
|
-
|
|
2097
|
-
self.chat_endpoint, json=payload,
|
|
2098
|
-
)
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
json_modified_value["choices"][0]["delta"][
|
|
2120
|
-
"content"
|
|
2121
|
-
] = streaming_text
|
|
2122
|
-
self.last_response.update(json_modified_value)
|
|
2123
|
-
yield value if raw else json_modified_value
|
|
2124
|
-
except json.decoder.JSONDecodeError:
|
|
2125
|
-
pass
|
|
4508
|
+
async def for_stream():
|
|
4509
|
+
async with self.session.stream(
|
|
4510
|
+
"POST", self.chat_endpoint, json=payload, timeout=self.timeout
|
|
4511
|
+
) as response:
|
|
4512
|
+
if not response.is_success:
|
|
4513
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
4514
|
+
f"Failed to generate response - ({response.status_code}, {response.reason_phrase}) - {response.text}"
|
|
4515
|
+
)
|
|
4516
|
+
|
|
4517
|
+
message_load = ""
|
|
4518
|
+
async for value in response.aiter_lines():
|
|
4519
|
+
try:
|
|
4520
|
+
resp = sanitize_stream(value)
|
|
4521
|
+
incomplete_message = await self.get_message(resp)
|
|
4522
|
+
if incomplete_message:
|
|
4523
|
+
message_load += incomplete_message
|
|
4524
|
+
resp["choices"][0]["delta"]["content"] = message_load
|
|
4525
|
+
self.last_response.update(resp)
|
|
4526
|
+
yield value if raw else resp
|
|
4527
|
+
elif raw:
|
|
4528
|
+
yield value
|
|
4529
|
+
except json.decoder.JSONDecodeError:
|
|
4530
|
+
pass
|
|
4531
|
+
|
|
2126
4532
|
self.conversation.update_chat_history(
|
|
2127
|
-
prompt, self.get_message(self.last_response)
|
|
4533
|
+
prompt, await self.get_message(self.last_response)
|
|
2128
4534
|
)
|
|
2129
4535
|
|
|
2130
|
-
def for_non_stream():
|
|
2131
|
-
for _ in for_stream():
|
|
4536
|
+
async def for_non_stream():
|
|
4537
|
+
async for _ in for_stream():
|
|
2132
4538
|
pass
|
|
2133
4539
|
return self.last_response
|
|
2134
4540
|
|
|
2135
|
-
return for_stream() if stream else for_non_stream()
|
|
4541
|
+
return for_stream() if stream else await for_non_stream()
|
|
2136
4542
|
|
|
2137
|
-
def chat(
|
|
4543
|
+
async def chat(
|
|
2138
4544
|
self,
|
|
2139
4545
|
prompt: str,
|
|
2140
4546
|
stream: bool = False,
|
|
2141
4547
|
optimizer: str = None,
|
|
2142
4548
|
conversationally: bool = False,
|
|
2143
4549
|
) -> str:
|
|
2144
|
-
"""Generate response `str`
|
|
4550
|
+
"""Generate response `str` asynchronously.
|
|
2145
4551
|
Args:
|
|
2146
4552
|
prompt (str): Prompt to be send.
|
|
2147
4553
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
@@ -2151,15 +4557,17 @@ class PhindSearch:
|
|
|
2151
4557
|
str: Response generated
|
|
2152
4558
|
"""
|
|
2153
4559
|
|
|
2154
|
-
def for_stream():
|
|
2155
|
-
|
|
4560
|
+
async def for_stream():
|
|
4561
|
+
async_ask = await self.ask(
|
|
2156
4562
|
prompt, True, optimizer=optimizer, conversationally=conversationally
|
|
2157
|
-
)
|
|
2158
|
-
yield self.get_message(response)
|
|
4563
|
+
)
|
|
2159
4564
|
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
4565
|
+
async for response in async_ask:
|
|
4566
|
+
yield await self.get_message(response)
|
|
4567
|
+
|
|
4568
|
+
async def for_non_stream():
|
|
4569
|
+
return await self.get_message(
|
|
4570
|
+
await self.ask(
|
|
2163
4571
|
prompt,
|
|
2164
4572
|
False,
|
|
2165
4573
|
optimizer=optimizer,
|
|
@@ -2167,9 +4575,9 @@ class PhindSearch:
|
|
|
2167
4575
|
)
|
|
2168
4576
|
)
|
|
2169
4577
|
|
|
2170
|
-
return for_stream() if stream else for_non_stream()
|
|
4578
|
+
return for_stream() if stream else await for_non_stream()
|
|
2171
4579
|
|
|
2172
|
-
def get_message(self, response: dict) -> str:
|
|
4580
|
+
async def get_message(self, response: dict) -> str:
|
|
2173
4581
|
"""Retrieves message only from response
|
|
2174
4582
|
|
|
2175
4583
|
Args:
|
|
@@ -2179,99 +4587,12 @@ class PhindSearch:
|
|
|
2179
4587
|
str: Message extracted
|
|
2180
4588
|
"""
|
|
2181
4589
|
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
if not delta:
|
|
4590
|
+
try:
|
|
4591
|
+
if response["choices"][0].get("delta"):
|
|
4592
|
+
return response["choices"][0]["delta"]["content"]
|
|
4593
|
+
return response["choices"][0]["message"]["content"]
|
|
4594
|
+
except KeyError:
|
|
2188
4595
|
return ""
|
|
2189
|
-
|
|
2190
|
-
elif delta.get("function_call"):
|
|
2191
|
-
if self.quiet:
|
|
2192
|
-
return ""
|
|
2193
|
-
|
|
2194
|
-
function_call: dict = delta["function_call"]
|
|
2195
|
-
if function_call.get("name"):
|
|
2196
|
-
return function_call["name"]
|
|
2197
|
-
elif function_call.get("arguments"):
|
|
2198
|
-
return function_call.get("arguments")
|
|
2199
|
-
|
|
2200
|
-
elif delta.get("metadata"):
|
|
2201
|
-
if self.quiet:
|
|
2202
|
-
return ""
|
|
2203
|
-
return yaml.dump(delta["metadata"])
|
|
2204
|
-
|
|
2205
|
-
else:
|
|
2206
|
-
return (
|
|
2207
|
-
response["choices"][0]["delta"].get("content")
|
|
2208
|
-
if response["choices"][0].get("finish_reason") is None
|
|
2209
|
-
else ""
|
|
2210
|
-
)
|
|
2211
|
-
@staticmethod
|
|
2212
|
-
def chat_cli(prompt):
|
|
2213
|
-
"""Sends a request to the Phind API and processes the response."""
|
|
2214
|
-
phind_search = PhindSearch() # Initialize a PhindSearch instance
|
|
2215
|
-
response = phind_search.ask(prompt) # Perform a search with the given prompt
|
|
2216
|
-
processed_response = phind_search.get_message(response) # Process the response
|
|
2217
|
-
print(processed_response)
|
|
2218
|
-
#-------------------------------------------------------yep.com--------------------------------------------------------
|
|
2219
|
-
class YepChat:
|
|
2220
|
-
def __init__(self, message="hello"):
|
|
2221
|
-
self.url = "https://api.yep.com/v1/chat/completions"
|
|
2222
|
-
self.headers = {
|
|
2223
|
-
"Accept": "*/*",
|
|
2224
|
-
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
2225
|
-
"Accept-Language": "en-US,en;q=0.9",
|
|
2226
|
-
"Cache-Control": "max-age=0",
|
|
2227
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
2228
|
-
"Origin": "https://yep.com",
|
|
2229
|
-
"Referer": "https://yep.com/",
|
|
2230
|
-
"Sec-Ch-Ua": '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
|
2231
|
-
"Sec-Ch-Ua-Mobile": "?0",
|
|
2232
|
-
"Sec-Ch-Ua-Platform": '"Windows"',
|
|
2233
|
-
"Sec-Fetch-Dest": "empty",
|
|
2234
|
-
"Sec-Fetch-Mode": "cors",
|
|
2235
|
-
"Sec-Fetch-Site": "same-site",
|
|
2236
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0.0.0 Safari/537.36"
|
|
2237
|
-
}
|
|
2238
|
-
self.payload = {
|
|
2239
|
-
"stream": True,
|
|
2240
|
-
"max_tokens": 1280,
|
|
2241
|
-
"top_p": 0.7,
|
|
2242
|
-
"temperature": 0.6,
|
|
2243
|
-
"messages": [{
|
|
2244
|
-
"content": message,
|
|
2245
|
-
"role": "user"
|
|
2246
|
-
}],
|
|
2247
|
-
"model": "Mixtral-8x7B-Instruct-v0.1"
|
|
2248
|
-
}
|
|
2249
|
-
|
|
2250
|
-
def send_request(self):
|
|
2251
|
-
response = requests.post(self.url, headers=self.headers, data=json.dumps(self.payload), stream=True)
|
|
2252
|
-
print(response.status_code)
|
|
2253
|
-
return response
|
|
2254
|
-
|
|
2255
|
-
def process_response(self, response):
|
|
2256
|
-
myset = ""
|
|
2257
|
-
for line in response.iter_lines():
|
|
2258
|
-
if line:
|
|
2259
|
-
myline = line.decode('utf-8').removeprefix("data: ").replace(" null", "False")
|
|
2260
|
-
try:
|
|
2261
|
-
myval = eval(myline)
|
|
2262
|
-
if "choices" in myval and "delta" in myval["choices"][0] and "content" in myval["choices"][0]["delta"]:
|
|
2263
|
-
myset += myval["choices"][0]["delta"]["content"]
|
|
2264
|
-
except:
|
|
2265
|
-
continue
|
|
2266
|
-
return myset
|
|
2267
|
-
|
|
2268
|
-
@staticmethod
|
|
2269
|
-
def chat_cli(message):
|
|
2270
|
-
"""Sends a request to the Yep API and processes the response."""
|
|
2271
|
-
yep_chat = YepChat(message=message)
|
|
2272
|
-
response = yep_chat.send_request()
|
|
2273
|
-
processed_response = yep_chat.process_response(response)
|
|
2274
|
-
print(processed_response)
|
|
2275
4596
|
#-------------------------------------------------------youchat--------------------------------------------------------
|
|
2276
4597
|
class youChat:
|
|
2277
4598
|
"""
|
|
@@ -2623,88 +4944,3 @@ class Pollinations:
|
|
|
2623
4944
|
image.show()
|
|
2624
4945
|
except Exception as e:
|
|
2625
4946
|
print(f"An error occurred: {e}")
|
|
2626
|
-
|
|
2627
|
-
@click.group()
|
|
2628
|
-
def cli():
|
|
2629
|
-
"""Webscout AI command-line interface."""
|
|
2630
|
-
pass
|
|
2631
|
-
|
|
2632
|
-
@cli.command()
|
|
2633
|
-
@click.option('--prompt', prompt='Enter your search prompt', help='The prompt to send.')
|
|
2634
|
-
def phindsearch(prompt):
|
|
2635
|
-
"""Perform a search with the given prompt using PhindSearch."""
|
|
2636
|
-
phind_search = PhindSearch() # Initialize a PhindSearch instance
|
|
2637
|
-
response = phind_search.ask(prompt) # Perform a search with the given prompt
|
|
2638
|
-
processed_response = phind_search.get_message(response) # Process the response
|
|
2639
|
-
print(processed_response)
|
|
2640
|
-
|
|
2641
|
-
@cli.command()
|
|
2642
|
-
@click.option('--message', prompt='Enter your message', help='The message to send.')
|
|
2643
|
-
def yepchat(message):
|
|
2644
|
-
YepChat.chat_cli(message)
|
|
2645
|
-
|
|
2646
|
-
@cli.command()
|
|
2647
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt to generate a completion from.')
|
|
2648
|
-
def youchat(prompt):
|
|
2649
|
-
youChat.chat_cli(prompt)
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
@cli.command()
|
|
2653
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt for generating the image.')
|
|
2654
|
-
def prodia(prompt):
|
|
2655
|
-
"""Generate an image based on the provided prompt."""
|
|
2656
|
-
Prodia.prodia_cli(prompt)
|
|
2657
|
-
|
|
2658
|
-
@cli.command()
|
|
2659
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt for generating the image.')
|
|
2660
|
-
def pollinations(prompt):
|
|
2661
|
-
"""Generate an image based on the provided prompt."""
|
|
2662
|
-
Pollinations.pollinations_cli(prompt)
|
|
2663
|
-
|
|
2664
|
-
@cli.command()
|
|
2665
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt to send.')
|
|
2666
|
-
def blackboxai(prompt):
|
|
2667
|
-
"""Chat with BLACKBOXAI using the provided prompt."""
|
|
2668
|
-
BLACKBOXAI.chat_cli(prompt)
|
|
2669
|
-
|
|
2670
|
-
@cli.command()
|
|
2671
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt to send.')
|
|
2672
|
-
@click.option('--stream', is_flag=True, help='Flag for streaming response.')
|
|
2673
|
-
@click.option('--raw', is_flag=True, help='Stream back raw response as received.')
|
|
2674
|
-
@click.option('--optimizer', type=str, help='Prompt optimizer name.')
|
|
2675
|
-
@click.option('--conversationally', is_flag=True, help='Chat conversationally when using optimizer.')
|
|
2676
|
-
def perplexity(prompt, stream, raw, optimizer, conversationally):
|
|
2677
|
-
"""Chat with PERPLEXITY using the provided prompt."""
|
|
2678
|
-
perplexity_instance = PERPLEXITY() # Initialize a PERPLEXITY instance
|
|
2679
|
-
response = perplexity_instance.ask(prompt, stream, raw, optimizer, conversationally)
|
|
2680
|
-
processed_response = perplexity_instance.get_message(response) # Process the response
|
|
2681
|
-
print(processed_response)
|
|
2682
|
-
|
|
2683
|
-
@cli.command()
|
|
2684
|
-
@click.option('--prompt', prompt='Enter your search prompt', help='The prompt to send.')
|
|
2685
|
-
@click.option('--stream', is_flag=True, help='Flag for streaming response.')
|
|
2686
|
-
def opengpt(prompt, stream):
|
|
2687
|
-
"""Chat with OPENGPT using the provided prompt."""
|
|
2688
|
-
opengpt = OPENGPT(is_conversation=True, max_tokens=8000, timeout=30)
|
|
2689
|
-
if stream:
|
|
2690
|
-
for response in opengpt.chat(prompt, stream=True):
|
|
2691
|
-
print(response)
|
|
2692
|
-
else:
|
|
2693
|
-
response_str = opengpt.chat(prompt)
|
|
2694
|
-
print(response_str)
|
|
2695
|
-
|
|
2696
|
-
@cli.command()
|
|
2697
|
-
@click.option('--prompt', prompt='Enter your prompt', help='The prompt to send.')
|
|
2698
|
-
@click.option('--stream', is_flag=True, help='Flag for streaming response.')
|
|
2699
|
-
@click.option('--raw', is_flag=True, help='Stream back raw response as received.')
|
|
2700
|
-
@click.option('--optimizer', type=str, help='Prompt optimizer name.')
|
|
2701
|
-
@click.option('--conversationally', is_flag=True, help='Chat conversationally when using optimizer.')
|
|
2702
|
-
def koboldai_cli(prompt, stream, raw, optimizer, conversationally):
|
|
2703
|
-
"""Chat with KOBOLDAI using the provided prompt."""
|
|
2704
|
-
koboldai_instance = KOBOLDAI() # Initialize a KOBOLDAI instance
|
|
2705
|
-
response = koboldai_instance.ask(prompt, stream, raw, optimizer, conversationally)
|
|
2706
|
-
processed_response = koboldai_instance.get_message(response) # Process the response
|
|
2707
|
-
print(processed_response)
|
|
2708
|
-
|
|
2709
|
-
if __name__ == '__main__':
|
|
2710
|
-
cli()
|