webscout 8.2.2__tar.gz → 8.2.3__tar.gz
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-8.2.2/webscout.egg-info → webscout-8.2.3}/PKG-INFO +1 -1
- webscout-8.2.3/webscout/AIbase.py +260 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Cloudflare.py +5 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/textpollinations.py +90 -44
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/toolbaz.py +4 -4
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/__init__.py +1 -0
- webscout-8.2.3/webscout/Provider/TTS/base.py +159 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/deepgram.py +16 -16
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/elevenlabs.py +5 -5
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/gesserit.py +6 -5
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/murfai.py +7 -7
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/parler.py +6 -6
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/speechma.py +22 -22
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/streamElements.py +7 -7
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TextPollinationsAI.py +56 -41
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/toolbaz.py +4 -4
- webscout-8.2.3/webscout/version.py +2 -0
- {webscout-8.2.2 → webscout-8.2.3/webscout.egg-info}/PKG-INFO +1 -1
- {webscout-8.2.2 → webscout-8.2.3}/webscout.egg-info/SOURCES.txt +1 -0
- webscout-8.2.2/webscout/AIbase.py +0 -123
- webscout-8.2.2/webscout/version.py +0 -2
- {webscout-8.2.2 → webscout-8.2.3}/LICENSE.md +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/README.md +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/inferno/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/inferno/__main__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/inferno/cli.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/setup.cfg +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/setup.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/AIauto.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/AIutel.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Bard.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/DWEBS.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/GitToolkit/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/repository.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/user.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/YTdownloader.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/transcriber.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/channel.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/errors.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/extras.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/https.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/patterns.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/playlist.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/pool.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/query.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/stream.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/video.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/autocoder/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/autocoder/autocoder.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/autocoder/autocoder_utiles.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/gguf.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/async_utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/base.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/cli.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/emailnator.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/mail_tm.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/tempmail/temp_mail_io.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/weather.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Extra/weather_ascii.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/LLM.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/core/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/core/level.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/core/logger.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/handlers/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/handlers/console.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/handlers/file.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/handlers/network.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/styles/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/styles/colors.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/styles/formats.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/styles/text.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/utils/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/utils/detectors.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Litlogger/utils/formatters.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/__main__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/api.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/cli.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/config.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/llm.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/model_manager.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/server.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Local/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AI21.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/DeepFind.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/ISou.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/Perplexity.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/felo_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/genspark_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/hika_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/iask_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/monica_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/scira_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AISEARCH/webpilotai_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Aitopia.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/AllenAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Andi.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Blackboxai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/C4ai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ChatGPTClone.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ChatGPTES.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ChatGPTGratis.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Chatify.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Cohere.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/DeepSeek.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Deepinfra.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ElectronHub.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ExaAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ExaChat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Free2GPT.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/GPTWeb.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Gemini.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/GithubChat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Glider.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Groq.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/HF_space/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/HF_space/qwen_qwen2.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/HeckAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/HuggingFaceChat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Hunyuan.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Jadve.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Koboldai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/LambdaChat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Llama.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Llama3.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Marcus.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Netwrck.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OLLAMA.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/base.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/c4ai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/chatgpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/chatgptclone.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/deepinfra.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/e2b.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/exaai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/exachat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/freeaichat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/glider.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/heckai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/llmchatco.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/netwrck.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/opkfc.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/scirachat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/sonus.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/standardinput.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/typegpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/uncovrAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/venice.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/wisecat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/writecream.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/x0gpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OPENAI/yep.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/OpenGPT.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Openai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/PI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Perplexitylabs.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Phind.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/PizzaGPT.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/QwenLM.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Reka.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/StandardInput.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/async_aiforce.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/async_nexra.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/sync_nexra.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/async_aiarta.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/artbit/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/artbit/async_artbit.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/artbit/sync_artbit.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/async_fastflux.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/async_huggingface.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/async_piclumen.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/talkai/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/talkai/async_talkai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTI/talkai/sync_talkai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TTS/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TeachAnything.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/TwoAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Venice.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/VercelAI.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/WebSim.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/WiseCat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Writecream.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/WritingMate.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/Youchat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/ai4chat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/aimathgpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/akashgpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/askmyai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/asksteve.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/bagoodex.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/cerebras.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/chatglm.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/cleeai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/copilot.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/elmo.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/freeaichat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/gaurish.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/geminiapi.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/geminiprorealtime.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/granite.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/hermes.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/julius.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/koala.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/labyrinth.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/learnfastai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/lepton.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/llama3mitril.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/llamatutor.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/llmchat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/llmchatco.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/meta.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/multichat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/promptrefine.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/scira_chat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/scnet.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/searchchat.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/sonus.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/talkai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/turboseek.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/tutorai.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/typefully.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/typegpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/uncovr.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/x0gpt.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/Provider/yep.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/__main__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/cli.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/conversation.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/exceptions.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/litagent/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/litagent/agent.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/litagent/constants.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/litprinter/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/models.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/optimizers.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/prompt_manager.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/crawler.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/scout.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/search_result.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/text_analyzer.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/text_utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core/web_analyzer.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/core.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/element.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/parsers/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/parsers/html5lib_parser.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/parsers/html_parser.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/parsers/lxml_parser.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/scout/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/swiftcli/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/tempid.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/update_checker.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/utils.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/webscout_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/webscout_search_async.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/yep_search.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/zeroart/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/zeroart/base.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/zeroart/effects.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout/zeroart/fonts.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout.egg-info/dependency_links.txt +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout.egg-info/entry_points.txt +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout.egg-info/requires.txt +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webscout.egg-info/top_level.txt +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/__init__.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/classifier.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/keywords.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/language.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/ner.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/normalizer.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/processor.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/sentiment.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/stemmer.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/tagger.py +0 -0
- {webscout-8.2.2 → webscout-8.2.3}/webstoken/tokenizer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: webscout
|
|
3
|
-
Version: 8.2.
|
|
3
|
+
Version: 8.2.3
|
|
4
4
|
Summary: Search for anything using Google, DuckDuckGo, phind.com, Contains AI models, can transcribe yt videos, temporary email and phone number generation, has TTS support, webai (terminal gpt and open interpreter) and offline LLMs and more
|
|
5
5
|
Author: OEvortex
|
|
6
6
|
Author-email: helpingai5@gmail.com
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import AsyncGenerator, List, Union, Generator, Optional
|
|
4
|
+
from typing_extensions import TypeAlias
|
|
5
|
+
|
|
6
|
+
# Type aliases for better readability
|
|
7
|
+
Response: TypeAlias = dict[str, Union[str, bool, None]]
|
|
8
|
+
ImageData: TypeAlias = Union[bytes, str, Generator[bytes, None, None]]
|
|
9
|
+
AsyncImageData: TypeAlias = Union[bytes, str, AsyncGenerator[bytes, None]]
|
|
10
|
+
|
|
11
|
+
class AIProviderError(Exception):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
class Provider(ABC):
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def ask(
|
|
18
|
+
self,
|
|
19
|
+
prompt: str,
|
|
20
|
+
stream: bool = False,
|
|
21
|
+
raw: bool = False,
|
|
22
|
+
optimizer: Optional[str] = None,
|
|
23
|
+
conversationally: bool = False,
|
|
24
|
+
) -> Response:
|
|
25
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def chat(
|
|
29
|
+
self,
|
|
30
|
+
prompt: str,
|
|
31
|
+
stream: bool = False,
|
|
32
|
+
optimizer: Optional[str] = None,
|
|
33
|
+
conversationally: bool = False,
|
|
34
|
+
) -> str:
|
|
35
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def get_message(self, response: Response) -> str:
|
|
39
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
40
|
+
|
|
41
|
+
class AsyncProvider(ABC):
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
async def ask(
|
|
45
|
+
self,
|
|
46
|
+
prompt: str,
|
|
47
|
+
stream: bool = False,
|
|
48
|
+
raw: bool = False,
|
|
49
|
+
optimizer: Optional[str] = None,
|
|
50
|
+
conversationally: bool = False,
|
|
51
|
+
) -> Response:
|
|
52
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
async def chat(
|
|
56
|
+
self,
|
|
57
|
+
prompt: str,
|
|
58
|
+
stream: bool = False,
|
|
59
|
+
optimizer: Optional[str] = None,
|
|
60
|
+
conversationally: bool = False,
|
|
61
|
+
) -> str:
|
|
62
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
async def get_message(self, response: Response) -> str:
|
|
66
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
67
|
+
|
|
68
|
+
class TTSProvider(ABC):
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
|
|
72
|
+
"""Convert text to speech and save to a temporary file.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
text (str): The text to convert to speech
|
|
76
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
77
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
str: Path to the generated audio file
|
|
81
|
+
"""
|
|
82
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
83
|
+
|
|
84
|
+
def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
85
|
+
"""Save audio to a specific destination.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
audio_file (str): Path to the source audio file
|
|
89
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
90
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
str: Path to the saved audio file
|
|
94
|
+
"""
|
|
95
|
+
import shutil
|
|
96
|
+
import os
|
|
97
|
+
from pathlib import Path
|
|
98
|
+
import time
|
|
99
|
+
|
|
100
|
+
source_path = Path(audio_file)
|
|
101
|
+
|
|
102
|
+
if not source_path.exists():
|
|
103
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
104
|
+
|
|
105
|
+
if destination is None:
|
|
106
|
+
# Create a default destination with timestamp in current directory
|
|
107
|
+
timestamp = int(time.time())
|
|
108
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
109
|
+
|
|
110
|
+
# Ensure the destination directory exists
|
|
111
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
112
|
+
|
|
113
|
+
# Copy the file
|
|
114
|
+
shutil.copy2(source_path, destination)
|
|
115
|
+
|
|
116
|
+
if verbose:
|
|
117
|
+
print(f"[debug] Audio saved to {destination}")
|
|
118
|
+
|
|
119
|
+
return destination
|
|
120
|
+
|
|
121
|
+
def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> Generator[bytes, None, None]:
|
|
122
|
+
"""Stream audio in chunks.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
text (str): The text to convert to speech
|
|
126
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
127
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
128
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
129
|
+
|
|
130
|
+
Yields:
|
|
131
|
+
Generator[bytes, None, None]: Audio data chunks
|
|
132
|
+
"""
|
|
133
|
+
# Generate the audio file
|
|
134
|
+
audio_file = self.tts(text, voice=voice, verbose=verbose)
|
|
135
|
+
|
|
136
|
+
# Stream the file in chunks
|
|
137
|
+
with open(audio_file, 'rb') as f:
|
|
138
|
+
while chunk := f.read(chunk_size):
|
|
139
|
+
yield chunk
|
|
140
|
+
|
|
141
|
+
class AsyncTTSProvider(ABC):
|
|
142
|
+
|
|
143
|
+
@abstractmethod
|
|
144
|
+
async def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
|
|
145
|
+
"""Convert text to speech and save to a temporary file asynchronously.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
text (str): The text to convert to speech
|
|
149
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
150
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: Path to the generated audio file
|
|
154
|
+
"""
|
|
155
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
156
|
+
|
|
157
|
+
async def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
158
|
+
"""Save audio to a specific destination asynchronously.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
audio_file (str): Path to the source audio file
|
|
162
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
163
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
str: Path to the saved audio file
|
|
167
|
+
"""
|
|
168
|
+
import shutil
|
|
169
|
+
import os
|
|
170
|
+
from pathlib import Path
|
|
171
|
+
import time
|
|
172
|
+
import asyncio
|
|
173
|
+
|
|
174
|
+
source_path = Path(audio_file)
|
|
175
|
+
|
|
176
|
+
if not source_path.exists():
|
|
177
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
178
|
+
|
|
179
|
+
if destination is None:
|
|
180
|
+
# Create a default destination with timestamp in current directory
|
|
181
|
+
timestamp = int(time.time())
|
|
182
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
183
|
+
|
|
184
|
+
# Ensure the destination directory exists
|
|
185
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
186
|
+
|
|
187
|
+
# Copy the file using asyncio to avoid blocking
|
|
188
|
+
await asyncio.to_thread(shutil.copy2, source_path, destination)
|
|
189
|
+
|
|
190
|
+
if verbose:
|
|
191
|
+
print(f"[debug] Audio saved to {destination}")
|
|
192
|
+
|
|
193
|
+
return destination
|
|
194
|
+
|
|
195
|
+
async def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> AsyncGenerator[bytes, None]:
|
|
196
|
+
"""Stream audio in chunks asynchronously.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
text (str): The text to convert to speech
|
|
200
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
201
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
202
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
203
|
+
|
|
204
|
+
Yields:
|
|
205
|
+
AsyncGenerator[bytes, None]: Audio data chunks
|
|
206
|
+
"""
|
|
207
|
+
import aiofiles
|
|
208
|
+
|
|
209
|
+
# Generate the audio file
|
|
210
|
+
audio_file = await self.tts(text, voice=voice, verbose=verbose)
|
|
211
|
+
|
|
212
|
+
# Stream the file in chunks
|
|
213
|
+
async with aiofiles.open(audio_file, 'rb') as f:
|
|
214
|
+
while chunk := await f.read(chunk_size):
|
|
215
|
+
yield chunk
|
|
216
|
+
|
|
217
|
+
class ImageProvider(ABC):
|
|
218
|
+
|
|
219
|
+
@abstractmethod
|
|
220
|
+
def generate(self, prompt: str, amount: int = 1) -> List[bytes]:
|
|
221
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
222
|
+
|
|
223
|
+
@abstractmethod
|
|
224
|
+
def save(
|
|
225
|
+
self,
|
|
226
|
+
response: List[bytes],
|
|
227
|
+
name: Optional[str] = None,
|
|
228
|
+
dir: Optional[Union[str, Path]] = None
|
|
229
|
+
) -> List[str]:
|
|
230
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
231
|
+
|
|
232
|
+
class AsyncImageProvider(ABC):
|
|
233
|
+
|
|
234
|
+
@abstractmethod
|
|
235
|
+
async def generate(
|
|
236
|
+
self,
|
|
237
|
+
prompt: str,
|
|
238
|
+
amount: int = 1
|
|
239
|
+
) -> Union[AsyncGenerator[bytes, None], List[bytes]]:
|
|
240
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
241
|
+
|
|
242
|
+
@abstractmethod
|
|
243
|
+
async def save(
|
|
244
|
+
self,
|
|
245
|
+
response: Union[AsyncGenerator[bytes, None], List[bytes]],
|
|
246
|
+
name: Optional[str] = None,
|
|
247
|
+
dir: Optional[Union[str, Path]] = None
|
|
248
|
+
) -> List[str]:
|
|
249
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
250
|
+
|
|
251
|
+
class AISearch(ABC):
|
|
252
|
+
|
|
253
|
+
@abstractmethod
|
|
254
|
+
def search(
|
|
255
|
+
self,
|
|
256
|
+
prompt: str,
|
|
257
|
+
stream: bool = False,
|
|
258
|
+
raw: bool = False,
|
|
259
|
+
) -> Response:
|
|
260
|
+
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
@@ -23,6 +23,7 @@ class Cloudflare(Provider):
|
|
|
23
23
|
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
24
24
|
"@cf/thebloke/discolm-german-7b-v1-awq",
|
|
25
25
|
"@cf/tiiuae/falcon-7b-instruct",
|
|
26
|
+
"@cf/google/gemma-3-12b-it",
|
|
26
27
|
"@hf/google/gemma-7b-it",
|
|
27
28
|
"@hf/nousresearch/hermes-2-pro-mistral-7b",
|
|
28
29
|
"@hf/thebloke/llama-2-13b-chat-awq",
|
|
@@ -37,12 +38,14 @@ class Cloudflare(Provider):
|
|
|
37
38
|
"@cf/meta/llama-3.2-1b-instruct",
|
|
38
39
|
"@cf/meta/llama-3.2-3b-instruct",
|
|
39
40
|
"@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
41
|
+
"@cf/meta/llama-4-scout-17b-16e-instruct",
|
|
40
42
|
"@cf/meta/llama-guard-3-8b",
|
|
41
43
|
"@hf/thebloke/llamaguard-7b-awq",
|
|
42
44
|
"@hf/meta-llama/meta-llama-3-8b-instruct",
|
|
43
45
|
"@cf/mistral/mistral-7b-instruct-v0.1",
|
|
44
46
|
"@hf/thebloke/mistral-7b-instruct-v0.1-awq",
|
|
45
47
|
"@hf/mistral/mistral-7b-instruct-v0.2",
|
|
48
|
+
"@cf/mistralai/mistral-small-3.1-24b-instruct",
|
|
46
49
|
"@hf/thebloke/neural-chat-7b-v3-1-awq",
|
|
47
50
|
"@cf/openchat/openchat-3.5-0106",
|
|
48
51
|
"@hf/thebloke/openhermes-2.5-mistral-7b-awq",
|
|
@@ -51,6 +54,8 @@ class Cloudflare(Provider):
|
|
|
51
54
|
"@cf/qwen/qwen1.5-1.8b-chat",
|
|
52
55
|
"@cf/qwen/qwen1.5-14b-chat-awq",
|
|
53
56
|
"@cf/qwen/qwen1.5-7b-chat-awq",
|
|
57
|
+
"@cf/qwen/qwen2.5-coder-32b-instruct",
|
|
58
|
+
"@cf/qwen/qwq-32b",
|
|
54
59
|
"@cf/defog/sqlcoder-7b-2",
|
|
55
60
|
"@hf/nexusflow/starling-lm-7b-beta",
|
|
56
61
|
"@cf/tinyllama/tinyllama-1.1b-chat-v1.0",
|
|
@@ -8,7 +8,7 @@ from typing import List, Dict, Optional, Union, Generator, Any
|
|
|
8
8
|
from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
|
|
9
9
|
from .utils import (
|
|
10
10
|
ChatCompletionChunk, ChatCompletion, Choice, ChoiceDelta,
|
|
11
|
-
ChatCompletionMessage, CompletionUsage
|
|
11
|
+
ChatCompletionMessage, CompletionUsage, ToolCall, ToolFunction
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
# Import LitAgent for browser fingerprinting
|
|
@@ -32,6 +32,8 @@ class Completions(BaseCompletions):
|
|
|
32
32
|
stream: bool = False,
|
|
33
33
|
temperature: Optional[float] = None,
|
|
34
34
|
top_p: Optional[float] = None,
|
|
35
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
36
|
+
tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
|
|
35
37
|
**kwargs: Any
|
|
36
38
|
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
37
39
|
"""
|
|
@@ -49,6 +51,10 @@ class Completions(BaseCompletions):
|
|
|
49
51
|
payload["temperature"] = temperature
|
|
50
52
|
if top_p is not None:
|
|
51
53
|
payload["top_p"] = top_p
|
|
54
|
+
if tools is not None:
|
|
55
|
+
payload["tools"] = tools
|
|
56
|
+
if tool_choice is not None:
|
|
57
|
+
payload["tool_choice"] = tool_choice
|
|
52
58
|
|
|
53
59
|
payload.update(kwargs)
|
|
54
60
|
|
|
@@ -95,16 +101,39 @@ class Completions(BaseCompletions):
|
|
|
95
101
|
json_data = json.loads(line[6:])
|
|
96
102
|
if 'choices' in json_data and len(json_data['choices']) > 0:
|
|
97
103
|
choice = json_data['choices'][0]
|
|
98
|
-
if 'delta' in choice
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
if 'delta' in choice:
|
|
105
|
+
delta_obj = ChoiceDelta()
|
|
106
|
+
|
|
107
|
+
# Handle content in delta
|
|
108
|
+
if 'content' in choice['delta']:
|
|
109
|
+
content = choice['delta']['content']
|
|
110
|
+
full_response += content
|
|
111
|
+
delta_obj.content = content
|
|
112
|
+
|
|
113
|
+
# Handle tool calls in delta
|
|
114
|
+
if 'tool_calls' in choice['delta']:
|
|
115
|
+
tool_calls = []
|
|
116
|
+
for tool_call_data in choice['delta']['tool_calls']:
|
|
117
|
+
if 'function' in tool_call_data:
|
|
118
|
+
function = ToolFunction(
|
|
119
|
+
name=tool_call_data['function'].get('name', ''),
|
|
120
|
+
arguments=tool_call_data['function'].get('arguments', '')
|
|
121
|
+
)
|
|
122
|
+
tool_call = ToolCall(
|
|
123
|
+
id=tool_call_data.get('id', str(uuid.uuid4())),
|
|
124
|
+
type=tool_call_data.get('type', 'function'),
|
|
125
|
+
function=function
|
|
126
|
+
)
|
|
127
|
+
tool_calls.append(tool_call)
|
|
128
|
+
|
|
129
|
+
if tool_calls:
|
|
130
|
+
delta_obj.tool_calls = tool_calls
|
|
101
131
|
|
|
102
132
|
# Create and yield a chunk
|
|
103
|
-
|
|
104
|
-
choice = Choice(index=0, delta=delta, finish_reason=None)
|
|
133
|
+
choice_obj = Choice(index=0, delta=delta_obj, finish_reason=None)
|
|
105
134
|
chunk = ChatCompletionChunk(
|
|
106
135
|
id=request_id,
|
|
107
|
-
choices=[
|
|
136
|
+
choices=[choice_obj],
|
|
108
137
|
created=created_time,
|
|
109
138
|
model=model
|
|
110
139
|
)
|
|
@@ -155,18 +184,40 @@ class Completions(BaseCompletions):
|
|
|
155
184
|
|
|
156
185
|
# Extract the content
|
|
157
186
|
if 'choices' in response_json and len(response_json['choices']) > 0:
|
|
158
|
-
|
|
159
|
-
|
|
187
|
+
choice_data = response_json['choices'][0]
|
|
188
|
+
if 'message' in choice_data:
|
|
189
|
+
message_data = choice_data['message']
|
|
190
|
+
|
|
191
|
+
# Extract content
|
|
192
|
+
full_content = message_data.get('content', '')
|
|
193
|
+
|
|
194
|
+
# Create the completion message with potential tool calls
|
|
195
|
+
message = ChatCompletionMessage(role="assistant", content=full_content)
|
|
196
|
+
|
|
197
|
+
# Handle tool calls if present
|
|
198
|
+
if 'tool_calls' in message_data:
|
|
199
|
+
tool_calls = []
|
|
200
|
+
for tool_call_data in message_data['tool_calls']:
|
|
201
|
+
if 'function' in tool_call_data:
|
|
202
|
+
function = ToolFunction(
|
|
203
|
+
name=tool_call_data['function'].get('name', ''),
|
|
204
|
+
arguments=tool_call_data['function'].get('arguments', '')
|
|
205
|
+
)
|
|
206
|
+
tool_call = ToolCall(
|
|
207
|
+
id=tool_call_data.get('id', str(uuid.uuid4())),
|
|
208
|
+
type=tool_call_data.get('type', 'function'),
|
|
209
|
+
function=function
|
|
210
|
+
)
|
|
211
|
+
tool_calls.append(tool_call)
|
|
212
|
+
|
|
213
|
+
if tool_calls:
|
|
214
|
+
message.tool_calls = tool_calls
|
|
160
215
|
else:
|
|
161
|
-
|
|
216
|
+
# Fallback if no message is present
|
|
217
|
+
message = ChatCompletionMessage(role="assistant", content="")
|
|
162
218
|
else:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# Create the completion message
|
|
166
|
-
message = ChatCompletionMessage(
|
|
167
|
-
role="assistant",
|
|
168
|
-
content=full_content
|
|
169
|
-
)
|
|
219
|
+
# Fallback if no choices are present
|
|
220
|
+
message = ChatCompletionMessage(role="assistant", content="")
|
|
170
221
|
|
|
171
222
|
# Create the choice
|
|
172
223
|
choice = Choice(
|
|
@@ -217,33 +268,28 @@ class TextPollinations(OpenAICompatibleProvider):
|
|
|
217
268
|
"""
|
|
218
269
|
|
|
219
270
|
AVAILABLE_MODELS = [
|
|
220
|
-
"openai",
|
|
221
|
-
"openai-large",
|
|
222
|
-
"openai-reasoning",
|
|
223
|
-
"qwen-coder",
|
|
224
|
-
"llama",
|
|
225
|
-
"llamascout",
|
|
226
|
-
"mistral",
|
|
227
|
-
"unity",
|
|
228
|
-
"midijourney",
|
|
229
|
-
"rtist",
|
|
230
|
-
"searchgpt",
|
|
231
|
-
"evil",
|
|
232
|
-
"deepseek-reasoning",
|
|
233
|
-
"deepseek-reasoning-large",
|
|
234
|
-
"
|
|
235
|
-
"
|
|
236
|
-
"
|
|
237
|
-
"
|
|
238
|
-
"
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"roblox-rp",
|
|
243
|
-
"deepseek",
|
|
244
|
-
"sur",
|
|
245
|
-
"llama-scaleway",
|
|
246
|
-
"openai-audio",
|
|
271
|
+
"openai", # OpenAI GPT-4.1-nano (Azure) - vision capable
|
|
272
|
+
"openai-large", # OpenAI GPT-4.1 mini (Azure) - vision capable
|
|
273
|
+
"openai-reasoning", # OpenAI o4-mini (Azure) - vision capable, reasoning
|
|
274
|
+
"qwen-coder", # Qwen 2.5 Coder 32B (Scaleway)
|
|
275
|
+
"llama", # Llama 3.3 70B (Cloudflare)
|
|
276
|
+
"llamascout", # Llama 4 Scout 17B (Cloudflare)
|
|
277
|
+
"mistral", # Mistral Small 3 (Scaleway) - vision capable
|
|
278
|
+
"unity", # Unity Mistral Large (Scaleway) - vision capable, uncensored
|
|
279
|
+
"midijourney", # Midijourney (Azure)
|
|
280
|
+
"rtist", # Rtist (Azure)
|
|
281
|
+
"searchgpt", # SearchGPT (Azure) - vision capable
|
|
282
|
+
"evil", # Evil (Scaleway) - vision capable, uncensored
|
|
283
|
+
"deepseek-reasoning", # DeepSeek-R1 Distill Qwen 32B (Cloudflare) - reasoning
|
|
284
|
+
"deepseek-reasoning-large", # DeepSeek R1 - Llama 70B (Scaleway) - reasoning
|
|
285
|
+
"phi", # Phi-4 Instruct (Cloudflare) - vision and audio capable
|
|
286
|
+
"llama-vision", # Llama 3.2 11B Vision (Cloudflare) - vision capable
|
|
287
|
+
"gemini", # gemini-2.5-flash-preview-04-17 (Azure) - vision and audio capable
|
|
288
|
+
"hormoz", # Hormoz 8b (Modal)
|
|
289
|
+
"hypnosis-tracy", # Hypnosis Tracy 7B (Azure) - audio capable
|
|
290
|
+
"deepseek", # DeepSeek-V3 (DeepSeek)
|
|
291
|
+
"sur", # Sur AI Assistant (Mistral) (Scaleway) - vision capable
|
|
292
|
+
"openai-audio", # OpenAI GPT-4o-audio-preview (Azure) - vision and audio capable
|
|
247
293
|
]
|
|
248
294
|
|
|
249
295
|
def __init__(
|
|
@@ -284,20 +284,20 @@ class Toolbaz(OpenAICompatibleProvider):
|
|
|
284
284
|
"""
|
|
285
285
|
|
|
286
286
|
AVAILABLE_MODELS = [
|
|
287
|
+
"gemini-2.5-flash",
|
|
287
288
|
"gemini-2.0-flash-thinking",
|
|
288
289
|
"gemini-2.0-flash",
|
|
289
290
|
"gemini-1.5-flash",
|
|
290
291
|
"gpt-4o-latest",
|
|
291
|
-
"gpt-4o-mini",
|
|
292
292
|
"gpt-4o",
|
|
293
293
|
"deepseek-r1",
|
|
294
|
+
"Llama-4-Maverick",
|
|
295
|
+
"Llama-4-Scout",
|
|
294
296
|
"Llama-3.3-70B",
|
|
295
|
-
"Llama-3.1-405B",
|
|
296
|
-
"Llama-3.1-70B",
|
|
297
297
|
"Qwen2.5-72B",
|
|
298
298
|
"Qwen2-72B",
|
|
299
299
|
"grok-2-1212",
|
|
300
|
-
"grok-beta",
|
|
300
|
+
"grok-3-beta",
|
|
301
301
|
"toolbaz_v3.5_pro",
|
|
302
302
|
"toolbaz_v3",
|
|
303
303
|
"mixtral_8x22b",
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for TTS providers with common functionality.
|
|
3
|
+
"""
|
|
4
|
+
import os
|
|
5
|
+
import tempfile
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Generator, Optional
|
|
8
|
+
from webscout.AIbase import TTSProvider
|
|
9
|
+
|
|
10
|
+
class BaseTTSProvider(TTSProvider):
|
|
11
|
+
"""
|
|
12
|
+
Base class for TTS providers with common functionality.
|
|
13
|
+
|
|
14
|
+
This class implements common methods like save_audio and stream_audio
|
|
15
|
+
that can be used by all TTS providers.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
"""Initialize the base TTS provider."""
|
|
20
|
+
self.temp_dir = tempfile.mkdtemp(prefix="webscout_tts_")
|
|
21
|
+
|
|
22
|
+
def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
23
|
+
"""
|
|
24
|
+
Save audio to a specific destination.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
audio_file (str): Path to the source audio file
|
|
28
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
29
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
str: Path to the saved audio file
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
FileNotFoundError: If the audio file doesn't exist
|
|
36
|
+
"""
|
|
37
|
+
import shutil
|
|
38
|
+
import time
|
|
39
|
+
|
|
40
|
+
source_path = Path(audio_file)
|
|
41
|
+
|
|
42
|
+
if not source_path.exists():
|
|
43
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
44
|
+
|
|
45
|
+
if destination is None:
|
|
46
|
+
# Create a default destination with timestamp in current directory
|
|
47
|
+
timestamp = int(time.time())
|
|
48
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
49
|
+
|
|
50
|
+
# Ensure the destination directory exists
|
|
51
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
52
|
+
|
|
53
|
+
# Copy the file
|
|
54
|
+
shutil.copy2(source_path, destination)
|
|
55
|
+
|
|
56
|
+
if verbose:
|
|
57
|
+
print(f"[debug] Audio saved to {destination}")
|
|
58
|
+
|
|
59
|
+
return destination
|
|
60
|
+
|
|
61
|
+
def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> Generator[bytes, None, None]:
|
|
62
|
+
"""
|
|
63
|
+
Stream audio in chunks.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
text (str): The text to convert to speech
|
|
67
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
68
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
69
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
70
|
+
|
|
71
|
+
Yields:
|
|
72
|
+
Generator[bytes, None, None]: Audio data chunks
|
|
73
|
+
"""
|
|
74
|
+
# Generate the audio file
|
|
75
|
+
audio_file = self.tts(text, voice=voice, verbose=verbose)
|
|
76
|
+
|
|
77
|
+
# Stream the file in chunks
|
|
78
|
+
with open(audio_file, 'rb') as f:
|
|
79
|
+
while chunk := f.read(chunk_size):
|
|
80
|
+
yield chunk
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class AsyncBaseTTSProvider:
|
|
84
|
+
"""
|
|
85
|
+
Base class for async TTS providers with common functionality.
|
|
86
|
+
|
|
87
|
+
This class implements common async methods like save_audio and stream_audio
|
|
88
|
+
that can be used by all async TTS providers.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(self):
|
|
92
|
+
"""Initialize the async base TTS provider."""
|
|
93
|
+
self.temp_dir = tempfile.mkdtemp(prefix="webscout_tts_")
|
|
94
|
+
|
|
95
|
+
async def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
96
|
+
"""
|
|
97
|
+
Save audio to a specific destination asynchronously.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
audio_file (str): Path to the source audio file
|
|
101
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
102
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
str: Path to the saved audio file
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
FileNotFoundError: If the audio file doesn't exist
|
|
109
|
+
"""
|
|
110
|
+
import shutil
|
|
111
|
+
import time
|
|
112
|
+
import asyncio
|
|
113
|
+
|
|
114
|
+
source_path = Path(audio_file)
|
|
115
|
+
|
|
116
|
+
if not source_path.exists():
|
|
117
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
118
|
+
|
|
119
|
+
if destination is None:
|
|
120
|
+
# Create a default destination with timestamp in current directory
|
|
121
|
+
timestamp = int(time.time())
|
|
122
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
123
|
+
|
|
124
|
+
# Ensure the destination directory exists
|
|
125
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
126
|
+
|
|
127
|
+
# Copy the file using asyncio to avoid blocking
|
|
128
|
+
await asyncio.to_thread(shutil.copy2, source_path, destination)
|
|
129
|
+
|
|
130
|
+
if verbose:
|
|
131
|
+
print(f"[debug] Audio saved to {destination}")
|
|
132
|
+
|
|
133
|
+
return destination
|
|
134
|
+
|
|
135
|
+
async def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False):
|
|
136
|
+
"""
|
|
137
|
+
Stream audio in chunks asynchronously.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
text (str): The text to convert to speech
|
|
141
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
142
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
143
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
144
|
+
|
|
145
|
+
Yields:
|
|
146
|
+
AsyncGenerator[bytes, None]: Audio data chunks
|
|
147
|
+
"""
|
|
148
|
+
try:
|
|
149
|
+
import aiofiles
|
|
150
|
+
except ImportError:
|
|
151
|
+
raise ImportError("The 'aiofiles' package is required for async streaming. Install it with 'pip install aiofiles'.")
|
|
152
|
+
|
|
153
|
+
# Generate the audio file
|
|
154
|
+
audio_file = await self.tts(text, voice=voice, verbose=verbose)
|
|
155
|
+
|
|
156
|
+
# Stream the file in chunks
|
|
157
|
+
async with aiofiles.open(audio_file, 'rb') as f:
|
|
158
|
+
while chunk := await f.read(chunk_size):
|
|
159
|
+
yield chunk
|