webscout 8.2.2__py3-none-any.whl → 8.2.7__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/AIauto.py +112 -22
- webscout/AIbase.py +144 -7
- webscout/AIutel.py +249 -131
- webscout/Bard.py +579 -206
- webscout/DWEBS.py +78 -35
- webscout/__init__.py +0 -1
- webscout/cli.py +256 -0
- webscout/conversation.py +307 -436
- webscout/exceptions.py +23 -0
- webscout/prompt_manager.py +56 -42
- webscout/version.py +1 -1
- webscout/webscout_search.py +65 -47
- webscout/webscout_search_async.py +81 -126
- webscout/yep_search.py +93 -43
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info}/METADATA +172 -52
- webscout-8.2.7.dist-info/RECORD +26 -0
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info}/WHEEL +1 -1
- webscout-8.2.7.dist-info/entry_points.txt +3 -0
- webscout-8.2.7.dist-info/top_level.txt +1 -0
- inferno/__init__.py +0 -6
- inferno/__main__.py +0 -9
- inferno/cli.py +0 -6
- webscout/Extra/GitToolkit/__init__.py +0 -10
- webscout/Extra/GitToolkit/gitapi/__init__.py +0 -12
- webscout/Extra/GitToolkit/gitapi/repository.py +0 -195
- webscout/Extra/GitToolkit/gitapi/user.py +0 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +0 -62
- webscout/Extra/YTToolkit/YTdownloader.py +0 -957
- webscout/Extra/YTToolkit/__init__.py +0 -3
- webscout/Extra/YTToolkit/transcriber.py +0 -476
- webscout/Extra/YTToolkit/ytapi/__init__.py +0 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +0 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +0 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +0 -45
- webscout/Extra/YTToolkit/ytapi/https.py +0 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +0 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +0 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +0 -8
- webscout/Extra/YTToolkit/ytapi/query.py +0 -40
- webscout/Extra/YTToolkit/ytapi/stream.py +0 -63
- webscout/Extra/YTToolkit/ytapi/utils.py +0 -62
- webscout/Extra/YTToolkit/ytapi/video.py +0 -232
- webscout/Extra/__init__.py +0 -7
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -849
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/Extra/gguf.py +0 -682
- webscout/Extra/tempmail/__init__.py +0 -28
- webscout/Extra/tempmail/async_utils.py +0 -141
- webscout/Extra/tempmail/base.py +0 -161
- webscout/Extra/tempmail/cli.py +0 -187
- webscout/Extra/tempmail/emailnator.py +0 -84
- webscout/Extra/tempmail/mail_tm.py +0 -361
- webscout/Extra/tempmail/temp_mail_io.py +0 -292
- webscout/Extra/weather.py +0 -194
- webscout/Extra/weather_ascii.py +0 -76
- webscout/LLM.py +0 -442
- webscout/Litlogger/__init__.py +0 -67
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Local/__init__.py +0 -12
- webscout/Local/__main__.py +0 -9
- webscout/Local/api.py +0 -576
- webscout/Local/cli.py +0 -516
- webscout/Local/config.py +0 -75
- webscout/Local/llm.py +0 -287
- webscout/Local/model_manager.py +0 -253
- webscout/Local/server.py +0 -721
- webscout/Local/utils.py +0 -93
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -250
- webscout/Provider/AISEARCH/ISou.py +0 -256
- webscout/Provider/AISEARCH/Perplexity.py +0 -359
- webscout/Provider/AISEARCH/__init__.py +0 -10
- webscout/Provider/AISEARCH/felo_search.py +0 -228
- webscout/Provider/AISEARCH/genspark_search.py +0 -208
- webscout/Provider/AISEARCH/hika_search.py +0 -194
- webscout/Provider/AISEARCH/iask_search.py +0 -436
- webscout/Provider/AISEARCH/monica_search.py +0 -246
- webscout/Provider/AISEARCH/scira_search.py +0 -324
- webscout/Provider/AISEARCH/webpilotai_search.py +0 -281
- webscout/Provider/Aitopia.py +0 -292
- webscout/Provider/AllenAI.py +0 -413
- webscout/Provider/Andi.py +0 -228
- webscout/Provider/Blackboxai.py +0 -229
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTClone.py +0 -226
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Chatify.py +0 -175
- webscout/Provider/Cloudflare.py +0 -273
- webscout/Provider/Cohere.py +0 -208
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/Deepinfra.py +0 -297
- webscout/Provider/ElectronHub.py +0 -709
- webscout/Provider/ExaAI.py +0 -261
- webscout/Provider/ExaChat.py +0 -342
- webscout/Provider/Free2GPT.py +0 -241
- webscout/Provider/GPTWeb.py +0 -193
- webscout/Provider/Gemini.py +0 -169
- webscout/Provider/GithubChat.py +0 -367
- webscout/Provider/Glider.py +0 -211
- webscout/Provider/Groq.py +0 -670
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HeckAI.py +0 -233
- webscout/Provider/HuggingFaceChat.py +0 -462
- webscout/Provider/Hunyuan.py +0 -272
- webscout/Provider/Jadve.py +0 -266
- webscout/Provider/Koboldai.py +0 -381
- webscout/Provider/LambdaChat.py +0 -392
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Llama3.py +0 -204
- webscout/Provider/Marcus.py +0 -148
- webscout/Provider/Netwrck.py +0 -228
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/__init__.py +0 -25
- webscout/Provider/OPENAI/base.py +0 -46
- webscout/Provider/OPENAI/c4ai.py +0 -367
- webscout/Provider/OPENAI/chatgpt.py +0 -549
- webscout/Provider/OPENAI/chatgptclone.py +0 -460
- webscout/Provider/OPENAI/deepinfra.py +0 -272
- webscout/Provider/OPENAI/e2b.py +0 -1350
- webscout/Provider/OPENAI/exaai.py +0 -404
- webscout/Provider/OPENAI/exachat.py +0 -433
- webscout/Provider/OPENAI/freeaichat.py +0 -352
- webscout/Provider/OPENAI/glider.py +0 -316
- webscout/Provider/OPENAI/heckai.py +0 -337
- webscout/Provider/OPENAI/llmchatco.py +0 -327
- webscout/Provider/OPENAI/netwrck.py +0 -348
- webscout/Provider/OPENAI/opkfc.py +0 -488
- webscout/Provider/OPENAI/scirachat.py +0 -463
- webscout/Provider/OPENAI/sonus.py +0 -294
- webscout/Provider/OPENAI/standardinput.py +0 -425
- webscout/Provider/OPENAI/textpollinations.py +0 -285
- webscout/Provider/OPENAI/toolbaz.py +0 -405
- webscout/Provider/OPENAI/typegpt.py +0 -346
- webscout/Provider/OPENAI/uncovrAI.py +0 -455
- webscout/Provider/OPENAI/utils.py +0 -211
- webscout/Provider/OPENAI/venice.py +0 -413
- webscout/Provider/OPENAI/wisecat.py +0 -381
- webscout/Provider/OPENAI/writecream.py +0 -156
- webscout/Provider/OPENAI/x0gpt.py +0 -371
- webscout/Provider/OPENAI/yep.py +0 -327
- webscout/Provider/OpenGPT.py +0 -199
- webscout/Provider/Openai.py +0 -496
- webscout/Provider/PI.py +0 -344
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/PizzaGPT.py +0 -198
- webscout/Provider/QwenLM.py +0 -254
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -278
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/__init__.py +0 -12
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/TTS/__init__.py +0 -7
- webscout/Provider/TTS/deepgram.py +0 -156
- webscout/Provider/TTS/elevenlabs.py +0 -111
- webscout/Provider/TTS/gesserit.py +0 -127
- webscout/Provider/TTS/murfai.py +0 -113
- webscout/Provider/TTS/parler.py +0 -111
- webscout/Provider/TTS/speechma.py +0 -180
- webscout/Provider/TTS/streamElements.py +0 -333
- webscout/Provider/TTS/utils.py +0 -280
- webscout/Provider/TeachAnything.py +0 -187
- webscout/Provider/TextPollinationsAI.py +0 -231
- webscout/Provider/TwoAI.py +0 -199
- webscout/Provider/Venice.py +0 -219
- webscout/Provider/VercelAI.py +0 -234
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/WiseCat.py +0 -196
- webscout/Provider/Writecream.py +0 -211
- webscout/Provider/WritingMate.py +0 -197
- webscout/Provider/Youchat.py +0 -330
- webscout/Provider/__init__.py +0 -198
- webscout/Provider/ai4chat.py +0 -202
- webscout/Provider/aimathgpt.py +0 -189
- webscout/Provider/akashgpt.py +0 -342
- webscout/Provider/askmyai.py +0 -158
- webscout/Provider/asksteve.py +0 -203
- webscout/Provider/bagoodex.py +0 -145
- webscout/Provider/cerebras.py +0 -242
- webscout/Provider/chatglm.py +0 -205
- webscout/Provider/cleeai.py +0 -213
- webscout/Provider/copilot.py +0 -428
- webscout/Provider/elmo.py +0 -234
- webscout/Provider/freeaichat.py +0 -271
- webscout/Provider/gaurish.py +0 -244
- webscout/Provider/geminiapi.py +0 -208
- webscout/Provider/geminiprorealtime.py +0 -160
- webscout/Provider/granite.py +0 -187
- webscout/Provider/hermes.py +0 -219
- webscout/Provider/julius.py +0 -223
- webscout/Provider/koala.py +0 -268
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/learnfastai.py +0 -266
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llama3mitril.py +0 -180
- webscout/Provider/llamatutor.py +0 -192
- webscout/Provider/llmchat.py +0 -213
- webscout/Provider/llmchatco.py +0 -311
- webscout/Provider/meta.py +0 -794
- webscout/Provider/multichat.py +0 -325
- webscout/Provider/promptrefine.py +0 -193
- webscout/Provider/scira_chat.py +0 -277
- webscout/Provider/scnet.py +0 -187
- webscout/Provider/searchchat.py +0 -293
- webscout/Provider/sonus.py +0 -208
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/toolbaz.py +0 -320
- webscout/Provider/turboseek.py +0 -219
- webscout/Provider/tutorai.py +0 -252
- webscout/Provider/typefully.py +0 -280
- webscout/Provider/typegpt.py +0 -232
- webscout/Provider/uncovr.py +0 -312
- webscout/Provider/x0gpt.py +0 -256
- webscout/Provider/yep.py +0 -376
- webscout/litagent/__init__.py +0 -29
- webscout/litagent/agent.py +0 -455
- webscout/litagent/constants.py +0 -60
- webscout/litprinter/__init__.py +0 -59
- webscout/scout/__init__.py +0 -8
- webscout/scout/core/__init__.py +0 -7
- webscout/scout/core/crawler.py +0 -140
- webscout/scout/core/scout.py +0 -568
- webscout/scout/core/search_result.py +0 -96
- webscout/scout/core/text_analyzer.py +0 -63
- webscout/scout/core/text_utils.py +0 -277
- webscout/scout/core/web_analyzer.py +0 -52
- webscout/scout/core.py +0 -881
- webscout/scout/element.py +0 -460
- webscout/scout/parsers/__init__.py +0 -69
- webscout/scout/parsers/html5lib_parser.py +0 -172
- webscout/scout/parsers/html_parser.py +0 -236
- webscout/scout/parsers/lxml_parser.py +0 -178
- webscout/scout/utils.py +0 -37
- webscout/swiftcli/__init__.py +0 -809
- webscout/zeroart/__init__.py +0 -55
- webscout/zeroart/base.py +0 -60
- webscout/zeroart/effects.py +0 -99
- webscout/zeroart/fonts.py +0 -816
- webscout-8.2.2.dist-info/RECORD +0 -309
- webscout-8.2.2.dist-info/entry_points.txt +0 -5
- webscout-8.2.2.dist-info/top_level.txt +0 -3
- webstoken/__init__.py +0 -30
- webstoken/classifier.py +0 -189
- webstoken/keywords.py +0 -216
- webstoken/language.py +0 -128
- webstoken/ner.py +0 -164
- webstoken/normalizer.py +0 -35
- webstoken/processor.py +0 -77
- webstoken/sentiment.py +0 -206
- webstoken/stemmer.py +0 -73
- webstoken/tagger.py +0 -60
- webstoken/tokenizer.py +0 -158
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info/licenses}/LICENSE.md +0 -0
webscout/Provider/PI.py
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
from uuid import uuid4
|
|
2
|
-
import cloudscraper
|
|
3
|
-
import json
|
|
4
|
-
import re
|
|
5
|
-
import threading
|
|
6
|
-
import requests
|
|
7
|
-
from webscout.AIutel import Optimizers
|
|
8
|
-
from webscout.AIutel import Conversation
|
|
9
|
-
from webscout.AIutel import AwesomePrompts
|
|
10
|
-
from webscout.AIbase import Provider
|
|
11
|
-
from typing import Dict, Union, Any, Optional
|
|
12
|
-
from webscout.litagent import LitAgent
|
|
13
|
-
|
|
14
|
-
class PiAI(Provider):
|
|
15
|
-
"""
|
|
16
|
-
PiAI is a provider class for interacting with the Pi.ai chat API.
|
|
17
|
-
|
|
18
|
-
Attributes:
|
|
19
|
-
knowledge_cutoff (str): The knowledge cutoff date for the model
|
|
20
|
-
AVAILABLE_VOICES (Dict[str, int]): Available voice options for audio responses
|
|
21
|
-
AVAILABLE_MODELS (List[str]): Available model options for the API
|
|
22
|
-
"""
|
|
23
|
-
AVAILABLE_MODELS = ["inflection_3_pi"]
|
|
24
|
-
AVAILABLE_VOICES: Dict[str, int] = {
|
|
25
|
-
"voice1": 1,
|
|
26
|
-
"voice2": 2,
|
|
27
|
-
"voice3": 3,
|
|
28
|
-
"voice4": 4,
|
|
29
|
-
"voice5": 5,
|
|
30
|
-
"voice6": 6,
|
|
31
|
-
"voice7": 7,
|
|
32
|
-
"voice8": 8
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
def __init__(
|
|
36
|
-
self,
|
|
37
|
-
is_conversation: bool = True,
|
|
38
|
-
max_tokens: int = 2048,
|
|
39
|
-
timeout: int = 30,
|
|
40
|
-
intro: str = None,
|
|
41
|
-
filepath: str = None,
|
|
42
|
-
update_file: bool = True,
|
|
43
|
-
proxies: dict = {},
|
|
44
|
-
history_offset: int = 10250,
|
|
45
|
-
act: str = None,
|
|
46
|
-
voice: bool = False,
|
|
47
|
-
voice_name: str = "voice3",
|
|
48
|
-
output_file: str = "PiAI.mp3",
|
|
49
|
-
model: str = "inflection_3_pi",
|
|
50
|
-
):
|
|
51
|
-
"""
|
|
52
|
-
Initializes PiAI with voice support.
|
|
53
|
-
|
|
54
|
-
Args:
|
|
55
|
-
voice (bool): Enable/disable voice output
|
|
56
|
-
voice_name (str): Name of the voice to use (if None, uses default)
|
|
57
|
-
output_file (str): Path to save voice output (default: PiAI.mp3)
|
|
58
|
-
"""
|
|
59
|
-
# Voice settings
|
|
60
|
-
self.voice_enabled = voice
|
|
61
|
-
self.voice_name = voice_name
|
|
62
|
-
self.output_file = output_file
|
|
63
|
-
|
|
64
|
-
if voice and voice_name and voice_name not in self.AVAILABLE_VOICES:
|
|
65
|
-
raise ValueError(f"Voice '{voice_name}' not available. Choose from: {list(self.AVAILABLE_VOICES.keys())}")
|
|
66
|
-
|
|
67
|
-
# Initialize other attributes
|
|
68
|
-
self.scraper = cloudscraper.create_scraper()
|
|
69
|
-
self.primary_url = 'https://pi.ai/api/chat'
|
|
70
|
-
self.fallback_url = 'https://pi.ai/api/v2/chat'
|
|
71
|
-
self.url = self.primary_url
|
|
72
|
-
self.headers = {
|
|
73
|
-
'Accept': 'text/event-stream',
|
|
74
|
-
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
|
75
|
-
'Accept-Language': 'en-US,en;q=0.9,en-IN;q=0.8',
|
|
76
|
-
'Content-Type': 'application/json',
|
|
77
|
-
'DNT': '1',
|
|
78
|
-
'Origin': 'https://pi.ai',
|
|
79
|
-
'Referer': 'https://pi.ai/talk',
|
|
80
|
-
'Sec-CH-UA': '"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"',
|
|
81
|
-
'Sec-CH-UA-Mobile': '?0',
|
|
82
|
-
'Sec-CH-UA-Platform': '"Windows"',
|
|
83
|
-
'Sec-Fetch-Dest': 'empty',
|
|
84
|
-
'Sec-Fetch-Mode': 'cors',
|
|
85
|
-
'Sec-Fetch-Site': 'same-origin',
|
|
86
|
-
'User-Agent': LitAgent().random(),
|
|
87
|
-
'X-Api-Version': '3'
|
|
88
|
-
}
|
|
89
|
-
self.cookies = {
|
|
90
|
-
'__cf_bm': uuid4().hex
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
self.session = requests.Session()
|
|
94
|
-
self.session.headers.update(self.headers)
|
|
95
|
-
self.session.proxies = proxies
|
|
96
|
-
|
|
97
|
-
self.is_conversation = is_conversation
|
|
98
|
-
self.max_tokens_to_sample = max_tokens
|
|
99
|
-
self.timeout = timeout
|
|
100
|
-
self.last_response = {} if self.is_conversation else {'text': ""}
|
|
101
|
-
self.conversation_id = None
|
|
102
|
-
|
|
103
|
-
self.__available_optimizers = (
|
|
104
|
-
method
|
|
105
|
-
for method in dir(Optimizers)
|
|
106
|
-
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
# Setup conversation
|
|
110
|
-
Conversation.intro = (
|
|
111
|
-
AwesomePrompts().get_act(
|
|
112
|
-
act, raise_not_found=True, default=None, case_insensitive=True
|
|
113
|
-
) if act else intro or Conversation.intro
|
|
114
|
-
)
|
|
115
|
-
self.conversation = Conversation(
|
|
116
|
-
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
117
|
-
)
|
|
118
|
-
self.conversation.history_offset = history_offset
|
|
119
|
-
self.session.proxies = proxies
|
|
120
|
-
|
|
121
|
-
if self.is_conversation:
|
|
122
|
-
self.start_conversation()
|
|
123
|
-
|
|
124
|
-
def start_conversation(self) -> str:
|
|
125
|
-
"""
|
|
126
|
-
Initializes a new conversation and returns the conversation ID.
|
|
127
|
-
"""
|
|
128
|
-
response = self.scraper.post(
|
|
129
|
-
"https://pi.ai/api/chat/start",
|
|
130
|
-
headers=self.headers,
|
|
131
|
-
cookies=self.cookies,
|
|
132
|
-
json={},
|
|
133
|
-
timeout=self.timeout
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
if not response.ok:
|
|
137
|
-
raise Exception(f"Failed to start conversation: {response.status_code}")
|
|
138
|
-
|
|
139
|
-
data = response.json()
|
|
140
|
-
self.conversation_id = data['conversations'][0]['sid']
|
|
141
|
-
|
|
142
|
-
return self.conversation_id
|
|
143
|
-
|
|
144
|
-
def ask(
|
|
145
|
-
self,
|
|
146
|
-
prompt: str,
|
|
147
|
-
stream: bool = False,
|
|
148
|
-
raw: bool = False,
|
|
149
|
-
optimizer: str = None,
|
|
150
|
-
conversationally: bool = False,
|
|
151
|
-
voice: bool = None,
|
|
152
|
-
voice_name: str = None,
|
|
153
|
-
output_file: str = None
|
|
154
|
-
) -> dict:
|
|
155
|
-
"""
|
|
156
|
-
Interact with Pi.ai by sending a prompt and receiving a response.
|
|
157
|
-
|
|
158
|
-
Args:
|
|
159
|
-
prompt (str): The prompt to send
|
|
160
|
-
stream (bool): Whether to stream the response
|
|
161
|
-
raw (bool): Return raw response format
|
|
162
|
-
optimizer (str): Prompt optimizer to use
|
|
163
|
-
conversationally (bool): Use conversation context
|
|
164
|
-
voice (bool): Override default voice setting
|
|
165
|
-
voice_name (str): Override default voice name
|
|
166
|
-
output_file (str): Override default output file path
|
|
167
|
-
"""
|
|
168
|
-
# Voice configuration
|
|
169
|
-
voice = self.voice_enabled if voice is None else voice
|
|
170
|
-
voice_name = self.voice_name if voice_name is None else voice_name
|
|
171
|
-
output_file = self.output_file if output_file is None else output_file
|
|
172
|
-
|
|
173
|
-
if voice and voice_name and voice_name not in self.AVAILABLE_VOICES:
|
|
174
|
-
raise ValueError(f"Voice '{voice_name}' not available. Choose from: {list(self.AVAILABLE_VOICES.keys())}")
|
|
175
|
-
|
|
176
|
-
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
177
|
-
if optimizer:
|
|
178
|
-
if optimizer in self.__available_optimizers:
|
|
179
|
-
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
180
|
-
conversation_prompt if conversationally else prompt
|
|
181
|
-
)
|
|
182
|
-
else:
|
|
183
|
-
raise Exception(f"Optimizer is not one of {self.__available_optimizers}")
|
|
184
|
-
|
|
185
|
-
data = {
|
|
186
|
-
'text': conversation_prompt,
|
|
187
|
-
'conversation': self.conversation_id
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
def process_stream():
|
|
191
|
-
# Try primary URL first
|
|
192
|
-
response = self.scraper.post(
|
|
193
|
-
self.url,
|
|
194
|
-
headers=self.headers,
|
|
195
|
-
cookies=self.cookies,
|
|
196
|
-
json=data,
|
|
197
|
-
stream=True,
|
|
198
|
-
timeout=self.timeout
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
# If primary URL fails, try fallback URL
|
|
202
|
-
if not response.ok and self.url == self.primary_url:
|
|
203
|
-
self.url = self.fallback_url
|
|
204
|
-
response = self.scraper.post(
|
|
205
|
-
self.url,
|
|
206
|
-
headers=self.headers,
|
|
207
|
-
cookies=self.cookies,
|
|
208
|
-
json=data,
|
|
209
|
-
stream=True,
|
|
210
|
-
timeout=self.timeout
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
if not response.ok:
|
|
214
|
-
raise Exception(f"API request failed: {response.status_code}")
|
|
215
|
-
|
|
216
|
-
output_str = response.content.decode('utf-8')
|
|
217
|
-
sids = re.findall(r'"sid":"(.*?)"', output_str)
|
|
218
|
-
second_sid = sids[1] if len(sids) >= 2 else None
|
|
219
|
-
|
|
220
|
-
if voice and voice_name and second_sid:
|
|
221
|
-
threading.Thread(
|
|
222
|
-
target=self.download_audio_threaded,
|
|
223
|
-
args=(voice_name, second_sid, output_file)
|
|
224
|
-
).start()
|
|
225
|
-
|
|
226
|
-
streaming_text = ""
|
|
227
|
-
for line in response.iter_lines(decode_unicode=True):
|
|
228
|
-
if line.startswith("data: "):
|
|
229
|
-
try:
|
|
230
|
-
parsed_data = json.loads(line[6:])
|
|
231
|
-
if 'text' in parsed_data:
|
|
232
|
-
streaming_text += parsed_data['text']
|
|
233
|
-
resp = dict(text=streaming_text)
|
|
234
|
-
self.last_response.update(resp)
|
|
235
|
-
yield parsed_data if raw else resp
|
|
236
|
-
except json.JSONDecodeError:
|
|
237
|
-
continue
|
|
238
|
-
|
|
239
|
-
self.conversation.update_chat_history(
|
|
240
|
-
prompt, self.get_message(self.last_response)
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
if stream:
|
|
244
|
-
return process_stream()
|
|
245
|
-
else:
|
|
246
|
-
# For non-stream, collect all responses and return the final one
|
|
247
|
-
for res in process_stream():
|
|
248
|
-
pass
|
|
249
|
-
return self.last_response
|
|
250
|
-
|
|
251
|
-
def chat(
|
|
252
|
-
self,
|
|
253
|
-
prompt: str,
|
|
254
|
-
stream: bool = False,
|
|
255
|
-
optimizer: str = None,
|
|
256
|
-
conversationally: bool = False,
|
|
257
|
-
voice: bool = None,
|
|
258
|
-
voice_name: str = None,
|
|
259
|
-
output_file: str = None
|
|
260
|
-
) -> str:
|
|
261
|
-
"""
|
|
262
|
-
Generates a response based on the provided prompt.
|
|
263
|
-
|
|
264
|
-
Args:
|
|
265
|
-
prompt (str): The prompt to send
|
|
266
|
-
stream (bool): Whether to stream the response
|
|
267
|
-
optimizer (str): Prompt optimizer to use
|
|
268
|
-
conversationally (bool): Use conversation context
|
|
269
|
-
voice (bool): Override default voice setting
|
|
270
|
-
voice_name (str): Override default voice name
|
|
271
|
-
output_file (str): Override default output file path
|
|
272
|
-
"""
|
|
273
|
-
# Use instance defaults if not specified
|
|
274
|
-
voice = self.voice_enabled if voice is None else voice
|
|
275
|
-
voice_name = self.voice_name if voice_name is None else voice_name
|
|
276
|
-
output_file = self.output_file if output_file is None else output_file
|
|
277
|
-
|
|
278
|
-
if voice and voice_name and voice_name not in self.AVAILABLE_VOICES:
|
|
279
|
-
raise ValueError(f"Voice '{voice_name}' not available. Choose from: {list(self.AVAILABLE_VOICES.keys())}")
|
|
280
|
-
|
|
281
|
-
if stream:
|
|
282
|
-
def stream_generator():
|
|
283
|
-
for response in self.ask(
|
|
284
|
-
prompt,
|
|
285
|
-
stream=True,
|
|
286
|
-
optimizer=optimizer,
|
|
287
|
-
conversationally=conversationally,
|
|
288
|
-
voice=voice,
|
|
289
|
-
voice_name=voice_name,
|
|
290
|
-
output_file=output_file
|
|
291
|
-
):
|
|
292
|
-
yield self.get_message(response).encode('utf-8').decode('utf-8')
|
|
293
|
-
return stream_generator()
|
|
294
|
-
else:
|
|
295
|
-
response = self.ask(
|
|
296
|
-
prompt,
|
|
297
|
-
stream=False,
|
|
298
|
-
optimizer=optimizer,
|
|
299
|
-
conversationally=conversationally,
|
|
300
|
-
voice=voice,
|
|
301
|
-
voice_name=voice_name,
|
|
302
|
-
output_file=output_file
|
|
303
|
-
)
|
|
304
|
-
return self.get_message(response)
|
|
305
|
-
|
|
306
|
-
def get_message(self, response: dict) -> str:
|
|
307
|
-
"""Retrieves message only from response"""
|
|
308
|
-
assert isinstance(response, dict), "Response should be of dict data-type only"
|
|
309
|
-
return response["text"]
|
|
310
|
-
|
|
311
|
-
def download_audio_threaded(self, voice_name: str, second_sid: str, output_file: str) -> None:
|
|
312
|
-
"""Downloads audio in a separate thread."""
|
|
313
|
-
params = {
|
|
314
|
-
'mode': 'eager',
|
|
315
|
-
'voice': f'voice{self.AVAILABLE_VOICES[voice_name]}',
|
|
316
|
-
'messageSid': second_sid,
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
try:
|
|
320
|
-
audio_response = self.scraper.get(
|
|
321
|
-
'https://pi.ai/api/chat/voice',
|
|
322
|
-
params=params,
|
|
323
|
-
cookies=self.cookies,
|
|
324
|
-
headers=self.headers,
|
|
325
|
-
timeout=self.timeout
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
if not audio_response.ok:
|
|
329
|
-
return
|
|
330
|
-
|
|
331
|
-
audio_response.raise_for_status()
|
|
332
|
-
|
|
333
|
-
with open(output_file, "wb") as file:
|
|
334
|
-
file.write(audio_response.content)
|
|
335
|
-
|
|
336
|
-
except requests.exceptions.RequestException:
|
|
337
|
-
pass
|
|
338
|
-
|
|
339
|
-
if __name__ == '__main__':
|
|
340
|
-
from rich import print
|
|
341
|
-
ai = PiAI()
|
|
342
|
-
response = ai.chat(input(">>> "), stream=True)
|
|
343
|
-
for chunk in response:
|
|
344
|
-
print(chunk, end="", flush=True)
|