webscout 8.3.7__py3-none-any.whl → 2025.10.11__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 +250 -250
- webscout/AIbase.py +379 -379
- webscout/AIutel.py +60 -60
- webscout/Bard.py +1012 -1012
- webscout/Bing_search.py +417 -417
- webscout/DWEBS.py +529 -529
- webscout/Extra/Act.md +309 -309
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/README.md +110 -110
- webscout/Extra/GitToolkit/gitapi/__init__.py +11 -11
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -195
- webscout/Extra/GitToolkit/gitapi/user.py +96 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +61 -61
- webscout/Extra/YTToolkit/README.md +375 -375
- webscout/Extra/YTToolkit/YTdownloader.py +956 -956
- webscout/Extra/YTToolkit/__init__.py +2 -2
- webscout/Extra/YTToolkit/transcriber.py +475 -475
- webscout/Extra/YTToolkit/ytapi/README.md +44 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +118 -118
- webscout/Extra/YTToolkit/ytapi/https.py +88 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +58 -58
- webscout/Extra/YTToolkit/ytapi/pool.py +7 -7
- webscout/Extra/YTToolkit/ytapi/query.py +39 -39
- webscout/Extra/YTToolkit/ytapi/stream.py +62 -62
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -62
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Extra/autocoder/__init__.py +9 -9
- webscout/Extra/autocoder/autocoder.py +1105 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +332 -332
- webscout/Extra/gguf.md +429 -429
- webscout/Extra/gguf.py +1213 -1213
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +27 -27
- webscout/Extra/tempmail/async_utils.py +140 -140
- webscout/Extra/tempmail/base.py +160 -160
- webscout/Extra/tempmail/cli.py +186 -186
- webscout/Extra/tempmail/emailnator.py +84 -84
- webscout/Extra/tempmail/mail_tm.py +360 -360
- webscout/Extra/tempmail/temp_mail_io.py +291 -291
- webscout/Extra/weather.md +281 -281
- webscout/Extra/weather.py +193 -193
- webscout/Litlogger/README.md +10 -10
- webscout/Litlogger/__init__.py +15 -15
- webscout/Litlogger/formats.py +13 -13
- webscout/Litlogger/handlers.py +121 -121
- webscout/Litlogger/levels.py +13 -13
- webscout/Litlogger/logger.py +134 -134
- webscout/Provider/AISEARCH/Perplexity.py +332 -332
- webscout/Provider/AISEARCH/README.md +279 -279
- webscout/Provider/AISEARCH/__init__.py +16 -1
- webscout/Provider/AISEARCH/felo_search.py +206 -206
- webscout/Provider/AISEARCH/genspark_search.py +323 -323
- webscout/Provider/AISEARCH/hika_search.py +185 -185
- webscout/Provider/AISEARCH/iask_search.py +410 -410
- webscout/Provider/AISEARCH/monica_search.py +219 -219
- webscout/Provider/AISEARCH/scira_search.py +316 -316
- webscout/Provider/AISEARCH/stellar_search.py +177 -177
- webscout/Provider/AISEARCH/webpilotai_search.py +255 -255
- webscout/Provider/Aitopia.py +314 -314
- webscout/Provider/Apriel.py +306 -0
- webscout/Provider/ChatGPTClone.py +236 -236
- webscout/Provider/ChatSandbox.py +343 -343
- webscout/Provider/Cloudflare.py +324 -324
- webscout/Provider/Cohere.py +208 -208
- webscout/Provider/Deepinfra.py +370 -366
- webscout/Provider/ExaAI.py +260 -260
- webscout/Provider/ExaChat.py +308 -308
- webscout/Provider/Flowith.py +221 -221
- webscout/Provider/GMI.py +293 -0
- webscout/Provider/Gemini.py +164 -164
- webscout/Provider/GeminiProxy.py +167 -167
- webscout/Provider/GithubChat.py +371 -372
- webscout/Provider/Groq.py +800 -800
- webscout/Provider/HeckAI.py +383 -383
- webscout/Provider/Jadve.py +282 -282
- webscout/Provider/K2Think.py +307 -307
- webscout/Provider/Koboldai.py +205 -205
- webscout/Provider/LambdaChat.py +423 -423
- webscout/Provider/Nemotron.py +244 -244
- webscout/Provider/Netwrck.py +248 -248
- webscout/Provider/OLLAMA.py +395 -395
- webscout/Provider/OPENAI/Cloudflare.py +393 -393
- webscout/Provider/OPENAI/FalconH1.py +451 -451
- webscout/Provider/OPENAI/FreeGemini.py +296 -296
- webscout/Provider/OPENAI/K2Think.py +431 -431
- webscout/Provider/OPENAI/NEMOTRON.py +240 -240
- webscout/Provider/OPENAI/PI.py +427 -427
- webscout/Provider/OPENAI/README.md +959 -959
- webscout/Provider/OPENAI/TogetherAI.py +345 -345
- webscout/Provider/OPENAI/TwoAI.py +465 -465
- webscout/Provider/OPENAI/__init__.py +33 -18
- webscout/Provider/OPENAI/base.py +248 -248
- webscout/Provider/OPENAI/chatglm.py +528 -0
- webscout/Provider/OPENAI/chatgpt.py +592 -592
- webscout/Provider/OPENAI/chatgptclone.py +521 -521
- webscout/Provider/OPENAI/chatsandbox.py +202 -202
- webscout/Provider/OPENAI/deepinfra.py +318 -314
- webscout/Provider/OPENAI/e2b.py +1665 -1665
- webscout/Provider/OPENAI/exaai.py +420 -420
- webscout/Provider/OPENAI/exachat.py +452 -452
- webscout/Provider/OPENAI/friendli.py +232 -232
- webscout/Provider/OPENAI/{refact.py → gmi.py} +324 -274
- webscout/Provider/OPENAI/groq.py +364 -364
- webscout/Provider/OPENAI/heckai.py +314 -314
- webscout/Provider/OPENAI/llmchatco.py +337 -337
- webscout/Provider/OPENAI/netwrck.py +355 -355
- webscout/Provider/OPENAI/oivscode.py +290 -290
- webscout/Provider/OPENAI/opkfc.py +518 -518
- webscout/Provider/OPENAI/pydantic_imports.py +1 -1
- webscout/Provider/OPENAI/scirachat.py +535 -535
- webscout/Provider/OPENAI/sonus.py +308 -308
- webscout/Provider/OPENAI/standardinput.py +442 -442
- webscout/Provider/OPENAI/textpollinations.py +340 -340
- webscout/Provider/OPENAI/toolbaz.py +419 -416
- webscout/Provider/OPENAI/typefully.py +362 -362
- webscout/Provider/OPENAI/utils.py +295 -295
- webscout/Provider/OPENAI/venice.py +436 -436
- webscout/Provider/OPENAI/wisecat.py +387 -387
- webscout/Provider/OPENAI/writecream.py +166 -166
- webscout/Provider/OPENAI/x0gpt.py +378 -378
- webscout/Provider/OPENAI/yep.py +389 -389
- webscout/Provider/OpenGPT.py +230 -230
- webscout/Provider/Openai.py +243 -243
- webscout/Provider/PI.py +405 -405
- webscout/Provider/Perplexitylabs.py +430 -430
- webscout/Provider/QwenLM.py +272 -272
- webscout/Provider/STT/__init__.py +16 -1
- webscout/Provider/Sambanova.py +257 -257
- webscout/Provider/StandardInput.py +309 -309
- webscout/Provider/TTI/README.md +82 -82
- webscout/Provider/TTI/__init__.py +33 -18
- webscout/Provider/TTI/aiarta.py +413 -413
- webscout/Provider/TTI/base.py +136 -136
- webscout/Provider/TTI/bing.py +243 -243
- webscout/Provider/TTI/gpt1image.py +149 -149
- webscout/Provider/TTI/imagen.py +196 -196
- webscout/Provider/TTI/infip.py +211 -211
- webscout/Provider/TTI/magicstudio.py +232 -232
- webscout/Provider/TTI/monochat.py +219 -219
- webscout/Provider/TTI/piclumen.py +214 -214
- webscout/Provider/TTI/pixelmuse.py +232 -232
- webscout/Provider/TTI/pollinations.py +232 -232
- webscout/Provider/TTI/together.py +288 -288
- webscout/Provider/TTI/utils.py +12 -12
- webscout/Provider/TTI/venice.py +367 -367
- webscout/Provider/TTS/README.md +192 -192
- webscout/Provider/TTS/__init__.py +33 -18
- webscout/Provider/TTS/parler.py +110 -110
- webscout/Provider/TTS/streamElements.py +333 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TeachAnything.py +237 -237
- webscout/Provider/TextPollinationsAI.py +310 -310
- webscout/Provider/TogetherAI.py +356 -356
- webscout/Provider/TwoAI.py +312 -312
- webscout/Provider/TypliAI.py +311 -311
- webscout/Provider/UNFINISHED/ChatHub.py +208 -208
- webscout/Provider/UNFINISHED/ChutesAI.py +313 -313
- webscout/Provider/UNFINISHED/GizAI.py +294 -294
- webscout/Provider/UNFINISHED/Marcus.py +198 -198
- webscout/Provider/UNFINISHED/Qodo.py +477 -477
- webscout/Provider/UNFINISHED/VercelAIGateway.py +338 -338
- webscout/Provider/UNFINISHED/XenAI.py +324 -324
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/liner.py +334 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +262 -262
- webscout/Provider/UNFINISHED/puterjs.py +634 -634
- webscout/Provider/UNFINISHED/samurai.py +223 -223
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Venice.py +250 -250
- webscout/Provider/VercelAI.py +256 -256
- webscout/Provider/WiseCat.py +231 -231
- webscout/Provider/WrDoChat.py +366 -366
- webscout/Provider/__init__.py +33 -18
- webscout/Provider/ai4chat.py +174 -174
- webscout/Provider/akashgpt.py +331 -331
- webscout/Provider/cerebras.py +446 -446
- webscout/Provider/chatglm.py +394 -301
- webscout/Provider/cleeai.py +211 -211
- webscout/Provider/elmo.py +282 -282
- webscout/Provider/geminiapi.py +208 -208
- webscout/Provider/granite.py +261 -261
- webscout/Provider/hermes.py +263 -263
- webscout/Provider/julius.py +223 -223
- webscout/Provider/learnfastai.py +309 -309
- webscout/Provider/llama3mitril.py +214 -214
- webscout/Provider/llmchat.py +243 -243
- webscout/Provider/llmchatco.py +290 -290
- webscout/Provider/meta.py +801 -801
- webscout/Provider/oivscode.py +309 -309
- webscout/Provider/scira_chat.py +383 -383
- webscout/Provider/searchchat.py +292 -292
- webscout/Provider/sonus.py +258 -258
- webscout/Provider/toolbaz.py +370 -367
- webscout/Provider/turboseek.py +273 -273
- webscout/Provider/typefully.py +207 -207
- webscout/Provider/yep.py +372 -372
- webscout/__init__.py +30 -31
- webscout/__main__.py +5 -5
- webscout/auth/api_key_manager.py +189 -189
- webscout/auth/config.py +175 -175
- webscout/auth/models.py +185 -185
- webscout/auth/routes.py +664 -664
- webscout/auth/simple_logger.py +236 -236
- webscout/cli.py +523 -523
- webscout/conversation.py +438 -438
- webscout/exceptions.py +361 -361
- webscout/litagent/Readme.md +298 -298
- webscout/litagent/__init__.py +28 -28
- webscout/litagent/agent.py +581 -581
- webscout/litagent/constants.py +59 -59
- webscout/litprinter/__init__.py +58 -58
- webscout/models.py +181 -181
- webscout/optimizers.py +419 -419
- webscout/prompt_manager.py +288 -288
- webscout/sanitize.py +1078 -1078
- webscout/scout/README.md +401 -401
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +6 -6
- webscout/scout/core/crawler.py +297 -297
- webscout/scout/core/scout.py +706 -706
- webscout/scout/core/search_result.py +95 -95
- webscout/scout/core/text_analyzer.py +62 -62
- webscout/scout/core/text_utils.py +277 -277
- webscout/scout/core/web_analyzer.py +51 -51
- webscout/scout/element.py +599 -599
- webscout/scout/parsers/__init__.py +69 -69
- webscout/scout/parsers/html5lib_parser.py +172 -172
- webscout/scout/parsers/html_parser.py +236 -236
- webscout/scout/parsers/lxml_parser.py +178 -178
- webscout/scout/utils.py +37 -37
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/__init__.py +95 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +308 -308
- webscout/swiftcli/core/context.py +104 -104
- webscout/swiftcli/core/group.py +241 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +221 -221
- webscout/swiftcli/decorators/options.py +220 -220
- webscout/swiftcli/decorators/output.py +302 -302
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +135 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +59 -59
- webscout/swiftcli/utils/formatting.py +252 -252
- webscout/swiftcli/utils/parsing.py +267 -267
- webscout/update_checker.py +117 -117
- webscout/version.py +1 -1
- webscout/webscout_search.py +1183 -1183
- webscout/webscout_search_async.py +649 -649
- webscout/yep_search.py +346 -346
- webscout/zeroart/README.md +89 -89
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/base.py +66 -66
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/METADATA +937 -937
- webscout-2025.10.11.dist-info/RECORD +300 -0
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/OPENAI/Qwen3.py +0 -303
- webscout/Provider/OPENAI/qodo.py +0 -630
- webscout/Provider/OPENAI/xenai.py +0 -514
- webscout/tempid.py +0 -134
- webscout-8.3.7.dist-info/RECORD +0 -301
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/WHEEL +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/entry_points.txt +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.7.dist-info → webscout-2025.10.11.dist-info}/top_level.txt +0 -0
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import uuid
|
|
3
|
-
import requests
|
|
4
|
-
import json
|
|
5
|
-
from typing import List, Dict, Optional, Union, Generator, Any
|
|
6
|
-
|
|
7
|
-
# Import base classes and utility structures
|
|
8
|
-
from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
|
|
9
|
-
from .utils import (
|
|
10
|
-
ChatCompletionChunk, ChatCompletion, Choice, ChoiceDelta,
|
|
11
|
-
ChatCompletionMessage, CompletionUsage, count_tokens
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
# Attempt to import LitAgent, fallback if not available
|
|
15
|
-
try:
|
|
16
|
-
from webscout.litagent import LitAgent
|
|
17
|
-
except ImportError:
|
|
18
|
-
print("Warning: LitAgent not found. Using default user agent.")
|
|
19
|
-
|
|
20
|
-
class Completions(BaseCompletions):
|
|
21
|
-
def __init__(self, client: 'Writecream'):
|
|
22
|
-
self._client = client
|
|
23
|
-
|
|
24
|
-
def create(
|
|
25
|
-
self,
|
|
26
|
-
*,
|
|
27
|
-
model: str = None, # Not used by Writecream, for compatibility
|
|
28
|
-
messages: List[Dict[str, str]],
|
|
29
|
-
max_tokens: Optional[int] = None, # Not used by Writecream
|
|
30
|
-
stream: bool = False,
|
|
31
|
-
temperature: Optional[float] = None, # Not used by Writecream
|
|
32
|
-
top_p: Optional[float] = None, # Not used by Writecream
|
|
33
|
-
timeout: Optional[int] = None,
|
|
34
|
-
proxies: Optional[Dict[str, str]] = None,
|
|
35
|
-
**kwargs: Any
|
|
36
|
-
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
37
|
-
"""
|
|
38
|
-
Creates a model response for the given chat conversation.
|
|
39
|
-
Mimics openai.chat.completions.create
|
|
40
|
-
"""
|
|
41
|
-
payload = messages
|
|
42
|
-
request_id = f"chatcmpl-{uuid.uuid4()}"
|
|
43
|
-
created_time = int(time.time())
|
|
44
|
-
if stream:
|
|
45
|
-
return self._create_stream(request_id, created_time, payload, timeout, proxies)
|
|
46
|
-
else:
|
|
47
|
-
return self._create_non_stream(request_id, created_time, payload, timeout, proxies)
|
|
48
|
-
|
|
49
|
-
def _create_stream(
|
|
50
|
-
self, request_id: str, created_time: int, payload: List[Dict[str, str]], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
51
|
-
) -> Generator[ChatCompletionChunk, None, None]:
|
|
52
|
-
# Writecream does not support streaming, so yield the full response as a single chunk
|
|
53
|
-
completion = self._create_non_stream(request_id, created_time, payload, timeout, proxies)
|
|
54
|
-
content = completion.choices[0].message.content
|
|
55
|
-
# Yield as a single chunk
|
|
56
|
-
delta = ChoiceDelta(content=content)
|
|
57
|
-
choice = Choice(index=0, delta=delta, finish_reason=None)
|
|
58
|
-
chunk = ChatCompletionChunk(
|
|
59
|
-
id=request_id,
|
|
60
|
-
choices=[choice],
|
|
61
|
-
created=created_time,
|
|
62
|
-
model="writecream",
|
|
63
|
-
)
|
|
64
|
-
yield chunk
|
|
65
|
-
# Final chunk with finish_reason
|
|
66
|
-
delta = ChoiceDelta(content=None)
|
|
67
|
-
choice = Choice(index=0, delta=delta, finish_reason="stop")
|
|
68
|
-
chunk = ChatCompletionChunk(
|
|
69
|
-
id=request_id,
|
|
70
|
-
choices=[choice],
|
|
71
|
-
created=created_time,
|
|
72
|
-
model="writecream",
|
|
73
|
-
)
|
|
74
|
-
yield chunk
|
|
75
|
-
|
|
76
|
-
def _create_non_stream(
|
|
77
|
-
self, request_id: str, created_time: int, payload: List[Dict[str, str]], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
78
|
-
) -> ChatCompletion:
|
|
79
|
-
try:
|
|
80
|
-
params = {
|
|
81
|
-
"query": json.dumps(payload),
|
|
82
|
-
"link": "writecream.com"
|
|
83
|
-
}
|
|
84
|
-
response = self._client.session.get(
|
|
85
|
-
self._client.base_url,
|
|
86
|
-
params=params,
|
|
87
|
-
headers=self._client.headers,
|
|
88
|
-
timeout=timeout or self._client.timeout,
|
|
89
|
-
proxies=proxies or getattr(self._client, "proxies", None)
|
|
90
|
-
)
|
|
91
|
-
response.raise_for_status()
|
|
92
|
-
data = response.json()
|
|
93
|
-
# Extract the response content according to the new API format
|
|
94
|
-
content = data.get("response_content", "")
|
|
95
|
-
# Estimate tokens
|
|
96
|
-
prompt_tokens = sum(count_tokens(m.get("content", "")) for m in payload)
|
|
97
|
-
completion_tokens = count_tokens(content)
|
|
98
|
-
usage = CompletionUsage(
|
|
99
|
-
prompt_tokens=prompt_tokens,
|
|
100
|
-
completion_tokens=completion_tokens,
|
|
101
|
-
total_tokens=prompt_tokens + completion_tokens
|
|
102
|
-
)
|
|
103
|
-
message = ChatCompletionMessage(role="assistant", content=content)
|
|
104
|
-
choice = Choice(index=0, message=message, finish_reason="stop")
|
|
105
|
-
completion = ChatCompletion(
|
|
106
|
-
id=request_id,
|
|
107
|
-
choices=[choice],
|
|
108
|
-
created=created_time,
|
|
109
|
-
model="writecream",
|
|
110
|
-
usage=usage
|
|
111
|
-
)
|
|
112
|
-
return completion
|
|
113
|
-
except Exception as e:
|
|
114
|
-
print(f"Error during Writecream request: {e}")
|
|
115
|
-
raise IOError(f"Writecream request failed: {e}") from e
|
|
116
|
-
|
|
117
|
-
class Chat(BaseChat):
|
|
118
|
-
def __init__(self, client: 'Writecream'):
|
|
119
|
-
self.completions = Completions(client)
|
|
120
|
-
|
|
121
|
-
class Writecream(OpenAICompatibleProvider):
|
|
122
|
-
"""
|
|
123
|
-
OpenAI-compatible client for Writecream API.
|
|
124
|
-
|
|
125
|
-
Usage:
|
|
126
|
-
client = Writecream()
|
|
127
|
-
response = client.chat.completions.create(
|
|
128
|
-
messages=[{"role": "system", "content": "You are a helpful assistant."},
|
|
129
|
-
{"role": "user", "content": "What is the capital of France?"}]
|
|
130
|
-
)
|
|
131
|
-
print(response.choices[0].message.content)
|
|
132
|
-
"""
|
|
133
|
-
AVAILABLE_MODELS = ["writecream"]
|
|
134
|
-
|
|
135
|
-
def __init__(self, browser: str = "chrome"):
|
|
136
|
-
self.timeout = None
|
|
137
|
-
self.base_url = "https://8pe3nv3qha.execute-api.us-east-1.amazonaws.com/default/llm_chat"
|
|
138
|
-
self.session = requests.Session()
|
|
139
|
-
agent = LitAgent()
|
|
140
|
-
self.headers = {
|
|
141
|
-
"User-Agent": agent.random(),
|
|
142
|
-
"Referer": "https://www.writecream.com/chatgpt-chat/"
|
|
143
|
-
}
|
|
144
|
-
self.session.headers.update(self.headers)
|
|
145
|
-
self.chat = Chat(self)
|
|
146
|
-
|
|
147
|
-
def convert_model_name(self, model: str) -> str:
|
|
148
|
-
return "writecream"
|
|
149
|
-
|
|
150
|
-
@property
|
|
151
|
-
def models(self):
|
|
152
|
-
class _ModelList:
|
|
153
|
-
def list(inner_self):
|
|
154
|
-
return Writecream.AVAILABLE_MODELS
|
|
155
|
-
return _ModelList()
|
|
156
|
-
|
|
157
|
-
# Simple test if run directly
|
|
158
|
-
if __name__ == "__main__":
|
|
159
|
-
client = Writecream()
|
|
160
|
-
response = client.chat.completions.create(
|
|
161
|
-
messages=[
|
|
162
|
-
{"role": "system", "content": "You are a helpful assistant."},
|
|
163
|
-
{"role": "user", "content": "What is the capital of France?"}
|
|
164
|
-
]
|
|
165
|
-
)
|
|
166
|
-
print(response.choices[0].message.content)
|
|
1
|
+
import time
|
|
2
|
+
import uuid
|
|
3
|
+
import requests
|
|
4
|
+
import json
|
|
5
|
+
from typing import List, Dict, Optional, Union, Generator, Any
|
|
6
|
+
|
|
7
|
+
# Import base classes and utility structures
|
|
8
|
+
from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
|
|
9
|
+
from .utils import (
|
|
10
|
+
ChatCompletionChunk, ChatCompletion, Choice, ChoiceDelta,
|
|
11
|
+
ChatCompletionMessage, CompletionUsage, count_tokens
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Attempt to import LitAgent, fallback if not available
|
|
15
|
+
try:
|
|
16
|
+
from webscout.litagent import LitAgent
|
|
17
|
+
except ImportError:
|
|
18
|
+
print("Warning: LitAgent not found. Using default user agent.")
|
|
19
|
+
|
|
20
|
+
class Completions(BaseCompletions):
|
|
21
|
+
def __init__(self, client: 'Writecream'):
|
|
22
|
+
self._client = client
|
|
23
|
+
|
|
24
|
+
def create(
|
|
25
|
+
self,
|
|
26
|
+
*,
|
|
27
|
+
model: str = None, # Not used by Writecream, for compatibility
|
|
28
|
+
messages: List[Dict[str, str]],
|
|
29
|
+
max_tokens: Optional[int] = None, # Not used by Writecream
|
|
30
|
+
stream: bool = False,
|
|
31
|
+
temperature: Optional[float] = None, # Not used by Writecream
|
|
32
|
+
top_p: Optional[float] = None, # Not used by Writecream
|
|
33
|
+
timeout: Optional[int] = None,
|
|
34
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
35
|
+
**kwargs: Any
|
|
36
|
+
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
37
|
+
"""
|
|
38
|
+
Creates a model response for the given chat conversation.
|
|
39
|
+
Mimics openai.chat.completions.create
|
|
40
|
+
"""
|
|
41
|
+
payload = messages
|
|
42
|
+
request_id = f"chatcmpl-{uuid.uuid4()}"
|
|
43
|
+
created_time = int(time.time())
|
|
44
|
+
if stream:
|
|
45
|
+
return self._create_stream(request_id, created_time, payload, timeout, proxies)
|
|
46
|
+
else:
|
|
47
|
+
return self._create_non_stream(request_id, created_time, payload, timeout, proxies)
|
|
48
|
+
|
|
49
|
+
def _create_stream(
|
|
50
|
+
self, request_id: str, created_time: int, payload: List[Dict[str, str]], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
51
|
+
) -> Generator[ChatCompletionChunk, None, None]:
|
|
52
|
+
# Writecream does not support streaming, so yield the full response as a single chunk
|
|
53
|
+
completion = self._create_non_stream(request_id, created_time, payload, timeout, proxies)
|
|
54
|
+
content = completion.choices[0].message.content
|
|
55
|
+
# Yield as a single chunk
|
|
56
|
+
delta = ChoiceDelta(content=content)
|
|
57
|
+
choice = Choice(index=0, delta=delta, finish_reason=None)
|
|
58
|
+
chunk = ChatCompletionChunk(
|
|
59
|
+
id=request_id,
|
|
60
|
+
choices=[choice],
|
|
61
|
+
created=created_time,
|
|
62
|
+
model="writecream",
|
|
63
|
+
)
|
|
64
|
+
yield chunk
|
|
65
|
+
# Final chunk with finish_reason
|
|
66
|
+
delta = ChoiceDelta(content=None)
|
|
67
|
+
choice = Choice(index=0, delta=delta, finish_reason="stop")
|
|
68
|
+
chunk = ChatCompletionChunk(
|
|
69
|
+
id=request_id,
|
|
70
|
+
choices=[choice],
|
|
71
|
+
created=created_time,
|
|
72
|
+
model="writecream",
|
|
73
|
+
)
|
|
74
|
+
yield chunk
|
|
75
|
+
|
|
76
|
+
def _create_non_stream(
|
|
77
|
+
self, request_id: str, created_time: int, payload: List[Dict[str, str]], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
78
|
+
) -> ChatCompletion:
|
|
79
|
+
try:
|
|
80
|
+
params = {
|
|
81
|
+
"query": json.dumps(payload),
|
|
82
|
+
"link": "writecream.com"
|
|
83
|
+
}
|
|
84
|
+
response = self._client.session.get(
|
|
85
|
+
self._client.base_url,
|
|
86
|
+
params=params,
|
|
87
|
+
headers=self._client.headers,
|
|
88
|
+
timeout=timeout or self._client.timeout,
|
|
89
|
+
proxies=proxies or getattr(self._client, "proxies", None)
|
|
90
|
+
)
|
|
91
|
+
response.raise_for_status()
|
|
92
|
+
data = response.json()
|
|
93
|
+
# Extract the response content according to the new API format
|
|
94
|
+
content = data.get("response_content", "")
|
|
95
|
+
# Estimate tokens
|
|
96
|
+
prompt_tokens = sum(count_tokens(m.get("content", "")) for m in payload)
|
|
97
|
+
completion_tokens = count_tokens(content)
|
|
98
|
+
usage = CompletionUsage(
|
|
99
|
+
prompt_tokens=prompt_tokens,
|
|
100
|
+
completion_tokens=completion_tokens,
|
|
101
|
+
total_tokens=prompt_tokens + completion_tokens
|
|
102
|
+
)
|
|
103
|
+
message = ChatCompletionMessage(role="assistant", content=content)
|
|
104
|
+
choice = Choice(index=0, message=message, finish_reason="stop")
|
|
105
|
+
completion = ChatCompletion(
|
|
106
|
+
id=request_id,
|
|
107
|
+
choices=[choice],
|
|
108
|
+
created=created_time,
|
|
109
|
+
model="writecream",
|
|
110
|
+
usage=usage
|
|
111
|
+
)
|
|
112
|
+
return completion
|
|
113
|
+
except Exception as e:
|
|
114
|
+
print(f"Error during Writecream request: {e}")
|
|
115
|
+
raise IOError(f"Writecream request failed: {e}") from e
|
|
116
|
+
|
|
117
|
+
class Chat(BaseChat):
|
|
118
|
+
def __init__(self, client: 'Writecream'):
|
|
119
|
+
self.completions = Completions(client)
|
|
120
|
+
|
|
121
|
+
class Writecream(OpenAICompatibleProvider):
|
|
122
|
+
"""
|
|
123
|
+
OpenAI-compatible client for Writecream API.
|
|
124
|
+
|
|
125
|
+
Usage:
|
|
126
|
+
client = Writecream()
|
|
127
|
+
response = client.chat.completions.create(
|
|
128
|
+
messages=[{"role": "system", "content": "You are a helpful assistant."},
|
|
129
|
+
{"role": "user", "content": "What is the capital of France?"}]
|
|
130
|
+
)
|
|
131
|
+
print(response.choices[0].message.content)
|
|
132
|
+
"""
|
|
133
|
+
AVAILABLE_MODELS = ["writecream"]
|
|
134
|
+
|
|
135
|
+
def __init__(self, browser: str = "chrome"):
|
|
136
|
+
self.timeout = None
|
|
137
|
+
self.base_url = "https://8pe3nv3qha.execute-api.us-east-1.amazonaws.com/default/llm_chat"
|
|
138
|
+
self.session = requests.Session()
|
|
139
|
+
agent = LitAgent()
|
|
140
|
+
self.headers = {
|
|
141
|
+
"User-Agent": agent.random(),
|
|
142
|
+
"Referer": "https://www.writecream.com/chatgpt-chat/"
|
|
143
|
+
}
|
|
144
|
+
self.session.headers.update(self.headers)
|
|
145
|
+
self.chat = Chat(self)
|
|
146
|
+
|
|
147
|
+
def convert_model_name(self, model: str) -> str:
|
|
148
|
+
return "writecream"
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def models(self):
|
|
152
|
+
class _ModelList:
|
|
153
|
+
def list(inner_self):
|
|
154
|
+
return Writecream.AVAILABLE_MODELS
|
|
155
|
+
return _ModelList()
|
|
156
|
+
|
|
157
|
+
# Simple test if run directly
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
client = Writecream()
|
|
160
|
+
response = client.chat.completions.create(
|
|
161
|
+
messages=[
|
|
162
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
163
|
+
{"role": "user", "content": "What is the capital of France?"}
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
print(response.choices[0].message.content)
|