webscout 8.3.1__py3-none-any.whl → 8.3.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIutel.py +180 -78
- webscout/Bing_search.py +417 -0
- webscout/Extra/gguf.py +706 -177
- webscout/Provider/AISEARCH/__init__.py +1 -0
- webscout/Provider/AISEARCH/genspark_search.py +7 -7
- webscout/Provider/AISEARCH/stellar_search.py +132 -0
- webscout/Provider/ExaChat.py +84 -58
- webscout/Provider/GeminiProxy.py +140 -0
- webscout/Provider/HeckAI.py +85 -80
- webscout/Provider/Jadve.py +56 -50
- webscout/Provider/MCPCore.py +78 -75
- webscout/Provider/MiniMax.py +207 -0
- webscout/Provider/Nemotron.py +41 -13
- webscout/Provider/Netwrck.py +34 -51
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -4
- webscout/Provider/OPENAI/GeminiProxy.py +328 -0
- webscout/Provider/OPENAI/MiniMax.py +298 -0
- webscout/Provider/OPENAI/README.md +32 -29
- webscout/Provider/OPENAI/README_AUTOPROXY.md +238 -0
- webscout/Provider/OPENAI/TogetherAI.py +4 -17
- webscout/Provider/OPENAI/__init__.py +17 -1
- webscout/Provider/OPENAI/autoproxy.py +1067 -39
- webscout/Provider/OPENAI/base.py +17 -76
- webscout/Provider/OPENAI/deepinfra.py +42 -108
- webscout/Provider/OPENAI/e2b.py +0 -1
- webscout/Provider/OPENAI/flowith.py +179 -166
- webscout/Provider/OPENAI/friendli.py +233 -0
- webscout/Provider/OPENAI/mcpcore.py +109 -70
- webscout/Provider/OPENAI/monochat.py +329 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -172
- webscout/Provider/OPENAI/scirachat.py +59 -51
- webscout/Provider/OPENAI/toolbaz.py +3 -9
- webscout/Provider/OPENAI/typegpt.py +1 -1
- webscout/Provider/OPENAI/utils.py +19 -42
- webscout/Provider/OPENAI/x0gpt.py +14 -2
- webscout/Provider/OPENAI/xenai.py +514 -0
- webscout/Provider/OPENAI/yep.py +8 -2
- webscout/Provider/OpenGPT.py +54 -32
- webscout/Provider/PI.py +58 -84
- webscout/Provider/StandardInput.py +32 -13
- webscout/Provider/TTI/README.md +9 -9
- webscout/Provider/TTI/__init__.py +3 -1
- webscout/Provider/TTI/aiarta.py +92 -78
- webscout/Provider/TTI/bing.py +231 -0
- webscout/Provider/TTI/infip.py +212 -0
- webscout/Provider/TTI/monochat.py +220 -0
- webscout/Provider/TTS/speechma.py +45 -39
- webscout/Provider/TeachAnything.py +11 -3
- webscout/Provider/TextPollinationsAI.py +78 -70
- webscout/Provider/TogetherAI.py +350 -0
- webscout/Provider/Venice.py +37 -46
- webscout/Provider/VercelAI.py +27 -24
- webscout/Provider/WiseCat.py +35 -35
- webscout/Provider/WrDoChat.py +22 -26
- webscout/Provider/WritingMate.py +26 -22
- webscout/Provider/XenAI.py +324 -0
- webscout/Provider/__init__.py +10 -5
- webscout/Provider/deepseek_assistant.py +378 -0
- webscout/Provider/granite.py +48 -57
- webscout/Provider/koala.py +51 -39
- webscout/Provider/learnfastai.py +49 -64
- webscout/Provider/llmchat.py +79 -93
- webscout/Provider/llmchatco.py +63 -78
- webscout/Provider/multichat.py +51 -40
- webscout/Provider/oivscode.py +1 -1
- webscout/Provider/scira_chat.py +159 -96
- webscout/Provider/scnet.py +13 -13
- webscout/Provider/searchchat.py +13 -13
- webscout/Provider/sonus.py +12 -11
- webscout/Provider/toolbaz.py +25 -8
- webscout/Provider/turboseek.py +41 -42
- webscout/Provider/typefully.py +27 -12
- webscout/Provider/typegpt.py +41 -46
- webscout/Provider/uncovr.py +55 -90
- webscout/Provider/x0gpt.py +33 -17
- webscout/Provider/yep.py +79 -96
- webscout/auth/__init__.py +55 -0
- webscout/auth/api_key_manager.py +189 -0
- webscout/auth/auth_system.py +100 -0
- webscout/auth/config.py +76 -0
- webscout/auth/database.py +400 -0
- webscout/auth/exceptions.py +67 -0
- webscout/auth/middleware.py +248 -0
- webscout/auth/models.py +130 -0
- webscout/auth/providers.py +279 -0
- webscout/auth/rate_limiter.py +254 -0
- webscout/auth/request_models.py +127 -0
- webscout/auth/request_processing.py +226 -0
- webscout/auth/routes.py +550 -0
- webscout/auth/schemas.py +103 -0
- webscout/auth/server.py +367 -0
- webscout/client.py +121 -70
- webscout/litagent/Readme.md +68 -55
- webscout/litagent/agent.py +99 -9
- webscout/scout/core/scout.py +104 -26
- webscout/scout/element.py +139 -18
- webscout/swiftcli/core/cli.py +14 -3
- webscout/swiftcli/decorators/output.py +59 -9
- webscout/update_checker.py +31 -49
- webscout/version.py +1 -1
- webscout/webscout_search.py +4 -12
- webscout/webscout_search_async.py +3 -10
- webscout/yep_search.py +2 -11
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/METADATA +141 -99
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/RECORD +109 -83
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/entry_points.txt +1 -1
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/OPENAI/api.py +0 -1320
- webscout/Provider/TTI/fastflux.py +0 -233
- webscout/Provider/Writecream.py +0 -246
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/WHEEL +0 -0
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.1.dist-info → webscout-8.3.3.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
##################################################################################
|
|
2
2
|
## Modified version of code written by t.me/infip1217 ##
|
|
3
3
|
##################################################################################
|
|
4
|
-
import time
|
|
5
4
|
import requests
|
|
6
5
|
import pathlib
|
|
7
6
|
import tempfile
|
|
8
|
-
from io import BytesIO
|
|
9
7
|
from webscout import exceptions
|
|
10
8
|
from webscout.litagent import LitAgent
|
|
11
|
-
from
|
|
12
|
-
from webscout.Provider.TTS import utils
|
|
9
|
+
from webscout.Litlogger import Logger, LogLevel
|
|
13
10
|
from webscout.Provider.TTS.base import BaseTTSProvider
|
|
14
11
|
|
|
15
12
|
class SpeechMaTTS(BaseTTSProvider):
|
|
@@ -18,12 +15,11 @@ class SpeechMaTTS(BaseTTSProvider):
|
|
|
18
15
|
"""
|
|
19
16
|
# Request headers
|
|
20
17
|
headers = {
|
|
21
|
-
"
|
|
22
|
-
"accept-language": "en-IN,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,en-AU;q=0.6",
|
|
23
|
-
"content-type": "application/json",
|
|
18
|
+
"authority": "speechma.com",
|
|
24
19
|
"origin": "https://speechma.com",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
20
|
+
"referer": "https://speechma.com/",
|
|
21
|
+
"content-type": "application/json",
|
|
22
|
+
**LitAgent().generate_fingerprint()
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
# Available voices with their IDs
|
|
@@ -496,8 +492,9 @@ class SpeechMaTTS(BaseTTSProvider):
|
|
|
496
492
|
if proxies:
|
|
497
493
|
self.session.proxies.update(proxies)
|
|
498
494
|
self.timeout = timeout
|
|
495
|
+
self.logger = Logger(name="SpeechMaTTS", level=LogLevel.INFO)
|
|
499
496
|
|
|
500
|
-
def tts(self, text: str, voice: str = "Emma", pitch: int = 0, rate: int = 0) -> str:
|
|
497
|
+
def tts(self, text: str, voice: str = "Emma", pitch: int = 0, rate: int = 0, verbose: bool = False) -> str:
|
|
501
498
|
"""
|
|
502
499
|
Converts text to speech using the SpeechMa API and saves it to a file.
|
|
503
500
|
|
|
@@ -506,6 +503,7 @@ class SpeechMaTTS(BaseTTSProvider):
|
|
|
506
503
|
voice (str): The voice to use for TTS (default: "Emma")
|
|
507
504
|
pitch (int): Voice pitch adjustment (-10 to 10, default: 0)
|
|
508
505
|
rate (int): Voice rate/speed adjustment (-10 to 10, default: 0)
|
|
506
|
+
verbose (bool): Whether to print debug information (default: False)
|
|
509
507
|
|
|
510
508
|
Returns:
|
|
511
509
|
str: Path to the generated audio file
|
|
@@ -517,10 +515,13 @@ class SpeechMaTTS(BaseTTSProvider):
|
|
|
517
515
|
voice in self.all_voices
|
|
518
516
|
), f"Voice '{voice}' not one of [{', '.join(self.all_voices.keys())}]"
|
|
519
517
|
|
|
518
|
+
if not text or text.strip() == '':
|
|
519
|
+
raise exceptions.FailedToGenerateResponseError("Text is empty")
|
|
520
|
+
|
|
520
521
|
filename = pathlib.Path(tempfile.mktemp(suffix=".mp3", dir=self.temp_dir))
|
|
521
522
|
voice_id = self.all_voices[voice]
|
|
522
523
|
|
|
523
|
-
# Prepare payload for the
|
|
524
|
+
# Prepare payload for the API
|
|
524
525
|
payload = {
|
|
525
526
|
"text": text,
|
|
526
527
|
"voice": voice_id,
|
|
@@ -530,44 +531,49 @@ class SpeechMaTTS(BaseTTSProvider):
|
|
|
530
531
|
}
|
|
531
532
|
|
|
532
533
|
try:
|
|
534
|
+
# Set logger level based on verbose flag
|
|
535
|
+
if verbose:
|
|
536
|
+
self.logger.level = LogLevel.DEBUG
|
|
537
|
+
self.logger.debug(f"Generating audio for voice: {voice} ({voice_id})")
|
|
538
|
+
self.logger.debug(f"Text length: {len(text)} characters")
|
|
539
|
+
else:
|
|
540
|
+
self.logger.level = LogLevel.INFO
|
|
541
|
+
|
|
542
|
+
# Make the request to the SpeechMa API
|
|
533
543
|
response = self.session.post(
|
|
534
544
|
self.api_url,
|
|
535
545
|
headers=self.headers,
|
|
536
546
|
json=payload,
|
|
537
547
|
timeout=self.timeout
|
|
538
548
|
)
|
|
539
|
-
response.raise_for_status()
|
|
540
|
-
resp_json = response.json()
|
|
541
|
-
if not resp_json.get("success") or "data" not in resp_json or "job_id" not in resp_json["data"]:
|
|
542
|
-
raise exceptions.FailedToGenerateResponseError(f"SpeechMa API error: {resp_json}")
|
|
543
|
-
job_id = resp_json["data"]["job_id"]
|
|
544
549
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
status_url,
|
|
550
|
-
headers=self.headers,
|
|
551
|
-
timeout=self.timeout
|
|
552
|
-
)
|
|
553
|
-
status_resp.raise_for_status()
|
|
554
|
-
status_json = status_resp.json()
|
|
555
|
-
if status_json.get("success") and status_json.get("data", {}).get("status") == "completed":
|
|
556
|
-
break
|
|
557
|
-
time.sleep(1)
|
|
558
|
-
else:
|
|
559
|
-
raise exceptions.FailedToGenerateResponseError("TTS job did not complete in time.")
|
|
550
|
+
if response.status_code != 200:
|
|
551
|
+
if verbose:
|
|
552
|
+
self.logger.error(f"API error: Status {response.status_code}")
|
|
553
|
+
raise exceptions.FailedToGenerateResponseError(f"API returned status {response.status_code}: {response.text[:500]}")
|
|
560
554
|
|
|
561
|
-
#
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
555
|
+
# Check if response is audio data (content-type should be audio/mpeg)
|
|
556
|
+
content_type = response.headers.get('content-type', '').lower()
|
|
557
|
+
if verbose:
|
|
558
|
+
self.logger.debug(f"Response content type: {content_type}")
|
|
559
|
+
self.logger.debug(f"Response size: {len(response.content)} bytes")
|
|
560
|
+
|
|
561
|
+
if 'audio' in content_type or response.content.startswith(b'\xff\xfb') or response.content.startswith(b'ID3') or b'LAME' in response.content[:100]:
|
|
562
|
+
# This is audio data, save it directly
|
|
563
|
+
with open(filename, 'wb') as f:
|
|
564
|
+
f.write(response.content)
|
|
565
|
+
if verbose:
|
|
566
|
+
self.logger.debug(f"Audio saved to: {filename}")
|
|
567
|
+
return filename.as_posix()
|
|
568
|
+
else:
|
|
569
|
+
# Unexpected response format
|
|
570
|
+
if verbose:
|
|
571
|
+
self.logger.error(f"Unexpected response format: {content_type}")
|
|
572
|
+
raise exceptions.FailedToGenerateResponseError(f"Unexpected response format. Content-Type: {content_type}, Content: {response.text[:200]}")
|
|
569
573
|
|
|
570
574
|
except requests.exceptions.RequestException as e:
|
|
575
|
+
if verbose:
|
|
576
|
+
self.logger.error(f"Request failed: {e}")
|
|
571
577
|
raise exceptions.FailedToGenerateResponseError(
|
|
572
578
|
f"Failed to perform the operation: {e}"
|
|
573
579
|
)
|
|
@@ -163,6 +163,7 @@ class TeachAnything(Provider):
|
|
|
163
163
|
stream: bool = False, # Keep stream param for interface consistency
|
|
164
164
|
optimizer: str = None,
|
|
165
165
|
conversationally: bool = False,
|
|
166
|
+
raw: bool = False, # Added raw parameter
|
|
166
167
|
) -> Union[str, Any]:
|
|
167
168
|
"""Generate response `str` or yield for streaming compatibility
|
|
168
169
|
Args:
|
|
@@ -170,22 +171,29 @@ class TeachAnything(Provider):
|
|
|
170
171
|
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
171
172
|
optimizer (str, optional): Prompt optimizer name - `[code, shell_command]`. Defaults to None.
|
|
172
173
|
conversationally (bool, optional): Chat conversationally when using optimizer. Defaults to False.
|
|
174
|
+
raw (bool, optional): If True, return raw string output.
|
|
173
175
|
Returns:
|
|
174
176
|
str or generator: Response generated
|
|
175
177
|
"""
|
|
176
178
|
response_data = self.ask(
|
|
177
179
|
prompt,
|
|
178
180
|
stream=False, # Call ask in non-stream mode internally
|
|
179
|
-
raw=
|
|
181
|
+
raw=raw, # Pass raw flag
|
|
180
182
|
optimizer=optimizer,
|
|
181
183
|
conversationally=conversationally
|
|
182
184
|
)
|
|
183
185
|
if stream:
|
|
184
186
|
def stream_wrapper():
|
|
185
|
-
|
|
187
|
+
if raw:
|
|
188
|
+
yield response_data if isinstance(response_data, str) else self.get_message(response_data)
|
|
189
|
+
else:
|
|
190
|
+
yield self.get_message(response_data)
|
|
186
191
|
return stream_wrapper()
|
|
187
192
|
else:
|
|
188
|
-
|
|
193
|
+
if raw:
|
|
194
|
+
return response_data if isinstance(response_data, str) else self.get_message(response_data)
|
|
195
|
+
else:
|
|
196
|
+
return self.get_message(response_data)
|
|
189
197
|
|
|
190
198
|
def get_message(self, response: Union[dict, str]) -> str:
|
|
191
199
|
"""Retrieves message only from response
|
|
@@ -135,95 +135,98 @@ class TextPollinationsAI(Provider):
|
|
|
135
135
|
payload["tool_choice"] = tool_choice
|
|
136
136
|
|
|
137
137
|
def for_stream():
|
|
138
|
-
try:
|
|
139
|
-
# Use curl_cffi session post with impersonate
|
|
138
|
+
try:
|
|
140
139
|
response = self.session.post(
|
|
141
140
|
self.api_endpoint,
|
|
142
|
-
# headers are set on the session
|
|
143
141
|
json=payload,
|
|
144
142
|
stream=True,
|
|
145
143
|
timeout=self.timeout,
|
|
146
|
-
impersonate="chrome120"
|
|
144
|
+
impersonate="chrome120"
|
|
147
145
|
)
|
|
148
|
-
|
|
149
146
|
if not response.ok:
|
|
150
147
|
raise exceptions.FailedToGenerateResponseError(
|
|
151
148
|
f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
|
|
152
149
|
)
|
|
153
|
-
|
|
154
150
|
streaming_text = ""
|
|
155
|
-
# Use sanitize_stream
|
|
156
151
|
processed_stream = sanitize_stream(
|
|
157
|
-
data=response.iter_content(chunk_size=None),
|
|
152
|
+
data=response.iter_content(chunk_size=None),
|
|
158
153
|
intro_value="data:",
|
|
159
|
-
to_json=True,
|
|
154
|
+
to_json=True,
|
|
160
155
|
skip_markers=["[DONE]"],
|
|
161
|
-
# Extractor handles both content and tool_calls
|
|
162
156
|
content_extractor=lambda chunk: chunk.get('choices', [{}])[0].get('delta') if isinstance(chunk, dict) else None,
|
|
163
|
-
yield_raw_on_error=False
|
|
157
|
+
yield_raw_on_error=False,
|
|
158
|
+
raw=raw
|
|
164
159
|
)
|
|
165
|
-
|
|
166
160
|
for delta in processed_stream:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
161
|
+
if isinstance(delta, bytes):
|
|
162
|
+
delta = delta.decode('utf-8', errors='ignore')
|
|
163
|
+
if delta is None:
|
|
164
|
+
continue
|
|
165
|
+
if raw:
|
|
166
|
+
# Only yield content or tool_calls as string
|
|
167
|
+
if isinstance(delta, dict):
|
|
168
|
+
if 'content' in delta and delta['content'] is not None:
|
|
169
|
+
content = delta['content']
|
|
170
|
+
streaming_text += content
|
|
171
|
+
yield content
|
|
172
|
+
elif 'tool_calls' in delta:
|
|
173
|
+
tool_calls = delta['tool_calls']
|
|
174
|
+
yield json.dumps(tool_calls)
|
|
175
|
+
elif isinstance(delta, str):
|
|
176
|
+
streaming_text += delta
|
|
177
|
+
yield delta
|
|
178
|
+
else:
|
|
179
|
+
if isinstance(delta, dict):
|
|
180
|
+
if 'content' in delta and delta['content'] is not None:
|
|
181
|
+
content = delta['content']
|
|
182
|
+
streaming_text += content
|
|
183
|
+
yield dict(text=content)
|
|
184
|
+
elif 'tool_calls' in delta:
|
|
185
|
+
tool_calls = delta['tool_calls']
|
|
186
|
+
yield dict(tool_calls=tool_calls)
|
|
187
|
+
self.last_response.update(dict(text=streaming_text))
|
|
188
|
+
if streaming_text:
|
|
180
189
|
self.conversation.update_chat_history(
|
|
181
|
-
prompt, streaming_text
|
|
190
|
+
prompt, streaming_text
|
|
182
191
|
)
|
|
183
|
-
except CurlError as e:
|
|
192
|
+
except CurlError as e:
|
|
184
193
|
raise exceptions.FailedToGenerateResponseError(f"Request failed (CurlError): {e}") from e
|
|
185
|
-
except Exception as e:
|
|
194
|
+
except Exception as e:
|
|
186
195
|
raise exceptions.FailedToGenerateResponseError(f"An unexpected error occurred ({type(e).__name__}): {e}") from e
|
|
187
|
-
|
|
188
|
-
|
|
189
196
|
def for_non_stream():
|
|
190
|
-
# Aggregate the stream using the updated for_stream logic
|
|
191
197
|
final_content = ""
|
|
192
|
-
tool_calls_aggregated = None
|
|
193
|
-
try:
|
|
198
|
+
tool_calls_aggregated = None
|
|
199
|
+
try:
|
|
194
200
|
for chunk_data in for_stream():
|
|
195
|
-
if
|
|
196
|
-
if
|
|
197
|
-
final_content += chunk_data
|
|
198
|
-
elif
|
|
199
|
-
|
|
201
|
+
if raw:
|
|
202
|
+
if isinstance(chunk_data, str):
|
|
203
|
+
final_content += chunk_data
|
|
204
|
+
elif isinstance(chunk_data, bytes):
|
|
205
|
+
final_content += chunk_data.decode('utf-8', errors='ignore')
|
|
206
|
+
elif isinstance(chunk_data, list):
|
|
200
207
|
if tool_calls_aggregated is None:
|
|
201
208
|
tool_calls_aggregated = []
|
|
202
|
-
tool_calls_aggregated.extend(chunk_data
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
tool_calls_aggregated.extend(chunk_data)
|
|
210
|
+
else:
|
|
211
|
+
if isinstance(chunk_data, dict):
|
|
212
|
+
if "text" in chunk_data:
|
|
213
|
+
final_content += chunk_data["text"]
|
|
214
|
+
elif "tool_calls" in chunk_data:
|
|
215
|
+
if tool_calls_aggregated is None:
|
|
216
|
+
tool_calls_aggregated = []
|
|
217
|
+
tool_calls_aggregated.extend(chunk_data["tool_calls"])
|
|
218
|
+
elif isinstance(chunk_data, str):
|
|
219
|
+
final_content += chunk_data
|
|
210
220
|
except Exception as e:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
raise exceptions.FailedToGenerateResponseError(f"Failed to get non-stream response: {str(e)}") from e
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
# last_response and history are updated within for_stream (for text)
|
|
217
|
-
# Return a dict containing text and/or tool_calls
|
|
221
|
+
if not final_content and not tool_calls_aggregated:
|
|
222
|
+
raise exceptions.FailedToGenerateResponseError(f"Failed to get non-stream response: {str(e)}") from e
|
|
218
223
|
result = {}
|
|
219
224
|
if final_content:
|
|
220
225
|
result["text"] = final_content
|
|
221
226
|
if tool_calls_aggregated:
|
|
222
227
|
result["tool_calls"] = tool_calls_aggregated
|
|
223
|
-
self.last_response = result
|
|
224
|
-
return self.last_response
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
self.last_response = result
|
|
229
|
+
return self.last_response if not raw else (final_content if final_content else json.dumps(tool_calls_aggregated) if tool_calls_aggregated else "")
|
|
227
230
|
return for_stream() if stream else for_non_stream()
|
|
228
231
|
|
|
229
232
|
def chat(
|
|
@@ -234,27 +237,32 @@ class TextPollinationsAI(Provider):
|
|
|
234
237
|
conversationally: bool = False,
|
|
235
238
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
236
239
|
tool_choice: Optional[Dict[str, Any]] = None,
|
|
240
|
+
raw: bool = False, # Added raw parameter
|
|
237
241
|
) -> Union[str, Generator[str, None, None]]:
|
|
238
242
|
"""Generate response as a string"""
|
|
239
243
|
def for_stream():
|
|
240
244
|
for response in self.ask(
|
|
241
|
-
prompt, True, optimizer=optimizer, conversationally=conversationally,
|
|
245
|
+
prompt, True, raw=raw, optimizer=optimizer, conversationally=conversationally,
|
|
242
246
|
tools=tools, tool_choice=tool_choice
|
|
243
247
|
):
|
|
244
|
-
|
|
245
|
-
|
|
248
|
+
if raw:
|
|
249
|
+
yield response
|
|
250
|
+
else:
|
|
251
|
+
yield self.get_message(response)
|
|
246
252
|
def for_non_stream():
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
)
|
|
253
|
+
result = self.ask(
|
|
254
|
+
prompt,
|
|
255
|
+
False,
|
|
256
|
+
raw=raw,
|
|
257
|
+
optimizer=optimizer,
|
|
258
|
+
conversationally=conversationally,
|
|
259
|
+
tools=tools,
|
|
260
|
+
tool_choice=tool_choice,
|
|
256
261
|
)
|
|
257
|
-
|
|
262
|
+
if raw:
|
|
263
|
+
return result if isinstance(result, str) else (result.get("text", "") if isinstance(result, dict) else str(result))
|
|
264
|
+
else:
|
|
265
|
+
return self.get_message(result)
|
|
258
266
|
return for_stream() if stream else for_non_stream()
|
|
259
267
|
|
|
260
268
|
def get_message(self, response: dict) -> str:
|