waldiez 0.5.3__py3-none-any.whl → 0.5.5__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 waldiez might be problematic. Click here for more details.
- waldiez/_version.py +1 -1
- waldiez/cli.py +3 -27
- waldiez/exporter.py +0 -13
- waldiez/exporting/agent/exporter.py +38 -0
- waldiez/exporting/agent/extras/__init__.py +2 -0
- waldiez/exporting/agent/extras/doc_agent_extras.py +366 -0
- waldiez/exporting/agent/extras/group_member_extras.py +3 -2
- waldiez/exporting/agent/processor.py +113 -15
- waldiez/exporting/chats/processor.py +2 -21
- waldiez/exporting/chats/utils/common.py +66 -1
- waldiez/exporting/chats/utils/group.py +6 -3
- waldiez/exporting/chats/utils/nested.py +1 -1
- waldiez/exporting/chats/utils/sequential.py +25 -9
- waldiez/exporting/chats/utils/single.py +8 -6
- waldiez/exporting/core/context.py +0 -12
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -1
- waldiez/exporting/core/extras/base.py +20 -17
- waldiez/exporting/core/extras/path_resolver.py +39 -41
- waldiez/exporting/core/extras/serializer.py +16 -1
- waldiez/exporting/core/protocols.py +17 -0
- waldiez/exporting/core/types.py +6 -9
- waldiez/exporting/flow/execution_generator.py +56 -21
- waldiez/exporting/flow/exporter.py +1 -4
- waldiez/exporting/flow/factory.py +0 -9
- waldiez/exporting/flow/file_generator.py +6 -0
- waldiez/exporting/flow/orchestrator.py +27 -21
- waldiez/exporting/flow/utils/__init__.py +0 -2
- waldiez/exporting/flow/utils/common.py +15 -96
- waldiez/exporting/flow/utils/importing.py +4 -0
- waldiez/io/mqtt.py +33 -14
- waldiez/io/redis.py +18 -13
- waldiez/io/structured.py +9 -4
- waldiez/io/utils.py +32 -0
- waldiez/io/ws.py +8 -2
- waldiez/models/__init__.py +6 -0
- waldiez/models/agents/__init__.py +8 -0
- waldiez/models/agents/agent/agent.py +136 -38
- waldiez/models/agents/agent/agent_type.py +3 -2
- waldiez/models/agents/agents.py +10 -0
- waldiez/models/agents/doc_agent/__init__.py +13 -0
- waldiez/models/agents/doc_agent/doc_agent.py +126 -0
- waldiez/models/agents/doc_agent/doc_agent_data.py +149 -0
- waldiez/models/agents/doc_agent/rag_query_engine.py +127 -0
- waldiez/models/flow/flow.py +13 -2
- waldiez/models/model/__init__.py +2 -2
- waldiez/models/model/_aws.py +75 -0
- waldiez/models/model/_llm.py +516 -0
- waldiez/models/model/_price.py +30 -0
- waldiez/models/model/model.py +45 -2
- waldiez/models/model/model_data.py +2 -83
- waldiez/models/tool/predefined/_duckduckgo.py +123 -0
- waldiez/models/tool/predefined/_google.py +31 -9
- waldiez/models/tool/predefined/_perplexity.py +161 -0
- waldiez/models/tool/predefined/_searxng.py +152 -0
- waldiez/models/tool/predefined/_tavily.py +46 -9
- waldiez/models/tool/predefined/_wikipedia.py +26 -6
- waldiez/models/tool/predefined/_youtube.py +36 -8
- waldiez/models/tool/predefined/registry.py +6 -0
- waldiez/models/waldiez.py +12 -0
- waldiez/runner.py +177 -408
- waldiez/running/__init__.py +2 -4
- waldiez/running/base_runner.py +100 -112
- waldiez/running/environment.py +29 -4
- waldiez/running/post_run.py +0 -1
- waldiez/running/protocol.py +36 -48
- waldiez/running/run_results.py +5 -5
- waldiez/running/standard_runner.py +429 -0
- waldiez/running/timeline_processor.py +0 -82
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/METADATA +59 -62
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/RECORD +74 -64
- waldiez/running/import_runner.py +0 -437
- waldiez/running/subprocess_runner.py +0 -104
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/WHEEL +0 -0
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/NOTICE.md +0 -0
waldiez/models/model/model.py
CHANGED
|
@@ -9,7 +9,9 @@ from pydantic import Field
|
|
|
9
9
|
from typing_extensions import Annotated, Literal
|
|
10
10
|
|
|
11
11
|
from ..common import WaldiezBase, now
|
|
12
|
-
from .
|
|
12
|
+
from ._aws import WaldiezModelAWS
|
|
13
|
+
from ._llm import get_llm_arg, get_llm_imports, get_llm_requirements
|
|
14
|
+
from .model_data import WaldiezModelAPIType, WaldiezModelData
|
|
13
15
|
|
|
14
16
|
DEFAULT_BASE_URLS: dict[WaldiezModelAPIType, str] = {
|
|
15
17
|
"deepseek": "https://api.deepseek.com/v1",
|
|
@@ -26,7 +28,7 @@ DEFAULT_BASE_URLS: dict[WaldiezModelAPIType, str] = {
|
|
|
26
28
|
# we can omit the base_url for these models
|
|
27
29
|
MODEL_NEEDS_BASE_URL: dict[WaldiezModelAPIType, bool] = {
|
|
28
30
|
"openai": False,
|
|
29
|
-
"azure":
|
|
31
|
+
"azure": True,
|
|
30
32
|
"google": False,
|
|
31
33
|
"anthropic": False,
|
|
32
34
|
"cohere": False,
|
|
@@ -172,6 +174,10 @@ class WaldiezModel(WaldiezBase):
|
|
|
172
174
|
)
|
|
173
175
|
if api_key and api_key != "REPLACE_ME":
|
|
174
176
|
os.environ[env_key] = api_key
|
|
177
|
+
if api_key == "GOOGLE_GEMINI_API_KEY":
|
|
178
|
+
# llama-index expects GOOGLE_API_KEY
|
|
179
|
+
# https://docs.llamaindex.ai/en/stable/examples/llm/gemini/
|
|
180
|
+
os.environ["GOOGLE_API_KEY"] = api_key
|
|
175
181
|
return api_key or "REPLACE_ME"
|
|
176
182
|
|
|
177
183
|
@property
|
|
@@ -228,6 +234,43 @@ class WaldiezModel(WaldiezBase):
|
|
|
228
234
|
return set_bedrock_aws_config(_llm_config, self.data.aws)
|
|
229
235
|
return set_default_base_url(_llm_config, self.data.api_type)
|
|
230
236
|
|
|
237
|
+
def get_llm_requirements(self, ag2_version: str) -> set[str]:
|
|
238
|
+
"""Get the LLM requirements for the model.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
ag2_version : str
|
|
243
|
+
The version of AG2 to use for the requirements.
|
|
244
|
+
|
|
245
|
+
Returns
|
|
246
|
+
-------
|
|
247
|
+
set[str]
|
|
248
|
+
The set of LLM requirements for the model.
|
|
249
|
+
"""
|
|
250
|
+
return get_llm_requirements(self, ag2_version=ag2_version)
|
|
251
|
+
|
|
252
|
+
def get_llm_imports(self) -> set[str]:
|
|
253
|
+
"""Get the LLM import statements for the model.
|
|
254
|
+
|
|
255
|
+
Returns
|
|
256
|
+
-------
|
|
257
|
+
set[str]
|
|
258
|
+
The set of LLM import statements for the model.
|
|
259
|
+
"""
|
|
260
|
+
return get_llm_imports(self)
|
|
261
|
+
|
|
262
|
+
def get_llm_arg(
|
|
263
|
+
self,
|
|
264
|
+
) -> tuple[str, str]:
|
|
265
|
+
"""Get the LLM argument and any content before it.
|
|
266
|
+
|
|
267
|
+
Returns
|
|
268
|
+
-------
|
|
269
|
+
tuple[str, str]
|
|
270
|
+
The LLM argument string for the model and any content before it.
|
|
271
|
+
"""
|
|
272
|
+
return get_llm_arg(self)
|
|
273
|
+
|
|
231
274
|
|
|
232
275
|
def set_default_base_url(
|
|
233
276
|
llm_config: dict[str, Any], api_type: WaldiezModelAPIType
|
|
@@ -9,6 +9,8 @@ from pydantic import Field
|
|
|
9
9
|
from typing_extensions import Annotated, Literal
|
|
10
10
|
|
|
11
11
|
from ..common import WaldiezBase
|
|
12
|
+
from ._aws import WaldiezModelAWS
|
|
13
|
+
from ._price import WaldiezModelPrice
|
|
12
14
|
|
|
13
15
|
WaldiezModelAPIType = Literal[
|
|
14
16
|
"openai",
|
|
@@ -27,89 +29,6 @@ WaldiezModelAPIType = Literal[
|
|
|
27
29
|
"""Possible API types for the model."""
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
class WaldiezModelAWS(WaldiezBase):
|
|
31
|
-
"""AWS related parameters.
|
|
32
|
-
|
|
33
|
-
Attributes
|
|
34
|
-
----------
|
|
35
|
-
region : Optional[str]
|
|
36
|
-
The AWS region, by default None.
|
|
37
|
-
access_key : Optional[str]
|
|
38
|
-
The AWS access key, by default None.
|
|
39
|
-
secret_key : Optional[str]
|
|
40
|
-
The AWS secret access key, by default None.
|
|
41
|
-
session_token : Optional[str]
|
|
42
|
-
The AWS session token, by default None.
|
|
43
|
-
profile_name : Optional[str]
|
|
44
|
-
The AWS profile name, by default Nonde.
|
|
45
|
-
"""
|
|
46
|
-
|
|
47
|
-
region: Annotated[
|
|
48
|
-
Optional[str],
|
|
49
|
-
Field(
|
|
50
|
-
None,
|
|
51
|
-
alias="region",
|
|
52
|
-
title="Region",
|
|
53
|
-
description="The AWS region",
|
|
54
|
-
),
|
|
55
|
-
] = None
|
|
56
|
-
access_key: Annotated[
|
|
57
|
-
Optional[str],
|
|
58
|
-
Field(
|
|
59
|
-
None,
|
|
60
|
-
alias="accessKey",
|
|
61
|
-
title="Access Ke",
|
|
62
|
-
description="The AWS access key",
|
|
63
|
-
),
|
|
64
|
-
] = None
|
|
65
|
-
secret_key: Annotated[
|
|
66
|
-
Optional[str],
|
|
67
|
-
Field(
|
|
68
|
-
None,
|
|
69
|
-
alias="secretKey",
|
|
70
|
-
title="Secret Key",
|
|
71
|
-
description="The AWS secret key",
|
|
72
|
-
),
|
|
73
|
-
] = None
|
|
74
|
-
session_token: Annotated[
|
|
75
|
-
Optional[str],
|
|
76
|
-
Field(
|
|
77
|
-
None,
|
|
78
|
-
alias="sessionToken",
|
|
79
|
-
title="Session Token",
|
|
80
|
-
description="The AWS session token",
|
|
81
|
-
),
|
|
82
|
-
] = None
|
|
83
|
-
profile_name: Annotated[
|
|
84
|
-
Optional[str],
|
|
85
|
-
Field(
|
|
86
|
-
None,
|
|
87
|
-
alias="profileName",
|
|
88
|
-
title="Profile Name",
|
|
89
|
-
description="The AWS Profile name to use",
|
|
90
|
-
),
|
|
91
|
-
] = None
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class WaldiezModelPrice(WaldiezBase):
|
|
95
|
-
"""Model Price.
|
|
96
|
-
|
|
97
|
-
Attributes
|
|
98
|
-
----------
|
|
99
|
-
prompt_price_per_1k : float
|
|
100
|
-
The prompt price per 1k tokens.
|
|
101
|
-
completion_token_price_per_1k : float
|
|
102
|
-
The completion token price per 1k tokens.
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
prompt_price_per_1k: Annotated[
|
|
106
|
-
Optional[float], Field(None, alias="promptPricePer1k")
|
|
107
|
-
]
|
|
108
|
-
completion_token_price_per_1k: Annotated[
|
|
109
|
-
Optional[float], Field(None, alias="completionTokenPricePer1k")
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
|
|
113
32
|
# pylint: disable=line-too-long
|
|
114
33
|
class WaldiezModelData(WaldiezBase):
|
|
115
34
|
"""Waldiez Model Data.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Predefined DuckDuckGo search tool for Waldiez."""
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ._config import PredefinedToolConfig
|
|
8
|
+
from .protocol import PredefinedTool
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DuckDuckGoSearchToolImpl(PredefinedTool):
|
|
12
|
+
"""DuckDuckGo search tool for Waldiez."""
|
|
13
|
+
|
|
14
|
+
required_secrets: list[str] = []
|
|
15
|
+
required_kwargs: dict[str, type] = {}
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def name(self) -> str:
|
|
19
|
+
"""Tool name."""
|
|
20
|
+
return "duckduckgo_search"
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def description(self) -> str:
|
|
24
|
+
"""Tool description."""
|
|
25
|
+
return "Search DuckDuckGo for a given query."
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def kwargs(self) -> dict[str, Any]:
|
|
29
|
+
"""Keyword arguments for the tool, used for initialization."""
|
|
30
|
+
return {}
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def requirements(self) -> list[str]:
|
|
34
|
+
"""Python requirements for the tool."""
|
|
35
|
+
return ["ag2[duckduckgo]", "ddgs"]
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def tags(self) -> list[str]:
|
|
39
|
+
"""Tags for the tool, used for categorization."""
|
|
40
|
+
return ["duckduckgo", "search", "web"]
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def tool_imports(self) -> list[str]:
|
|
44
|
+
"""Imports required for the tool implementation."""
|
|
45
|
+
return [
|
|
46
|
+
"from autogen.tools.experimental import DuckDuckGoSearchTool",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
|
|
50
|
+
"""Validate secrets and return list of missing required ones.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
secrets : dict[str, str]
|
|
55
|
+
Dictionary of secrets/environment variables.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
list[str]
|
|
60
|
+
List of missing required secrets.
|
|
61
|
+
"""
|
|
62
|
+
# no secrets required for DuckDuckGo search tool
|
|
63
|
+
return []
|
|
64
|
+
|
|
65
|
+
def validate_kwargs(self, kwargs: dict[str, str]) -> list[str]:
|
|
66
|
+
"""Validate keyword arguments and return list of missing required ones.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
kwargs : dict[str, str]
|
|
71
|
+
Dictionary of keyword arguments.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
list[str]
|
|
76
|
+
List of missing required keyword arguments.
|
|
77
|
+
"""
|
|
78
|
+
# no keyword arguments required for DuckDuckGo search tool
|
|
79
|
+
return []
|
|
80
|
+
|
|
81
|
+
def get_content(
|
|
82
|
+
self,
|
|
83
|
+
secrets: dict[str, str],
|
|
84
|
+
) -> str:
|
|
85
|
+
"""Get content for the tool.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
secrets : dict[str, str]
|
|
90
|
+
Dictionary of secrets/environment variables.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
str
|
|
95
|
+
The content for the tool.
|
|
96
|
+
"""
|
|
97
|
+
content = f'''
|
|
98
|
+
def {self.name}(query: str, num_results: int = 5) -> list[dict[str, Any]]:
|
|
99
|
+
"""Perform a DuckDuckGo search and return formatted results.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
query: The search query string.
|
|
103
|
+
num_results: The maximum number of results to return. Defaults to 5.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
A list of dictionaries of the search results.
|
|
107
|
+
"""
|
|
108
|
+
tool = DuckDuckGoSearchTool()
|
|
109
|
+
return tool(query=query, num_results=num_results)
|
|
110
|
+
'''
|
|
111
|
+
return content
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
DuckDuckGoSearchTool = DuckDuckGoSearchToolImpl()
|
|
115
|
+
DuckDuckGoSearchConfig = PredefinedToolConfig(
|
|
116
|
+
name=DuckDuckGoSearchTool.name,
|
|
117
|
+
description=DuckDuckGoSearchTool.description,
|
|
118
|
+
required_secrets=DuckDuckGoSearchTool.required_secrets,
|
|
119
|
+
required_kwargs=DuckDuckGoSearchTool.required_kwargs,
|
|
120
|
+
requirements=DuckDuckGoSearchTool.requirements,
|
|
121
|
+
tags=DuckDuckGoSearchTool.tags,
|
|
122
|
+
implementation=DuckDuckGoSearchTool,
|
|
123
|
+
)
|
|
@@ -142,15 +142,37 @@ class GoogleSearchToolImpl(PredefinedTool):
|
|
|
142
142
|
google_search_engine_id = self.google_search_engine_id
|
|
143
143
|
if not google_search_engine_id:
|
|
144
144
|
google_search_engine_id = secrets.get("GOOGLE_SEARCH_ENGINE_ID", "")
|
|
145
|
-
content = f
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
145
|
+
content = f'''
|
|
146
|
+
def {self.name}(
|
|
147
|
+
query: str,
|
|
148
|
+
search_api_key: str,
|
|
149
|
+
search_engine_id: str,
|
|
150
|
+
num_results: int = 10,
|
|
151
|
+
) -> list[dict[str, Any]]:
|
|
152
|
+
"""Perform a Google search and return formatted results.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
query: The search query string.
|
|
156
|
+
search_api_key: The API key for the Google Search API.
|
|
157
|
+
search_engine_id: The search engine ID for the Google Search API.
|
|
158
|
+
num_results: The maximum number of results to return. Defaults to 10.
|
|
159
|
+
Returns:
|
|
160
|
+
A list of dictionaries of the search results.
|
|
161
|
+
"""
|
|
162
|
+
google_search_api_key = os.environ.get("GOOGLE_SEARCH_API_KEY", "")
|
|
163
|
+
if not google_search_api_key:
|
|
164
|
+
raise ValueError("GOOGLE_SEARCH_API_KEY is required for Google search tool.")
|
|
165
|
+
{self.name}_tool = GoogleSearchTool(
|
|
166
|
+
search_api_key=google_search_api_key,
|
|
167
|
+
search_engine_id="{google_search_engine_id}",
|
|
168
|
+
)
|
|
169
|
+
return {self.name}_tool(
|
|
170
|
+
query=query,
|
|
171
|
+
search_api_key=search_api_key,
|
|
172
|
+
search_engine_id=search_engine_id,
|
|
173
|
+
num_results=num_results
|
|
174
|
+
)
|
|
175
|
+
'''
|
|
154
176
|
return content
|
|
155
177
|
|
|
156
178
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pylint: disable=line-too-long
|
|
4
|
+
# flake8: noqa: E501
|
|
5
|
+
"""Predefined Perplexity AI search tool for Waldiez."""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ._config import PredefinedToolConfig
|
|
11
|
+
from .protocol import PredefinedTool
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PerplexitySearchToolImpl(PredefinedTool):
|
|
15
|
+
"""Perplexity AI search tool for Waldiez."""
|
|
16
|
+
|
|
17
|
+
required_secrets: list[str] = ["PERPLEXITY_API_KEY"]
|
|
18
|
+
required_kwargs: dict[str, type] = {}
|
|
19
|
+
kwarg_types: dict[str, type] = {
|
|
20
|
+
"model": str,
|
|
21
|
+
"max_tokens": int,
|
|
22
|
+
"search_domain_filters": list,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def name(self) -> str:
|
|
27
|
+
"""Tool name."""
|
|
28
|
+
return "perplexity_search"
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def description(self) -> str:
|
|
32
|
+
"""Tool description."""
|
|
33
|
+
return "Search Perplexity AI for a given query."
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def kwargs(self) -> dict[str, Any]:
|
|
37
|
+
"""Keyword arguments for the tool, used for initialization."""
|
|
38
|
+
return {
|
|
39
|
+
"model": "sonar",
|
|
40
|
+
"max_tokens": 1000,
|
|
41
|
+
"search_domain_filter": None,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def requirements(self) -> list[str]:
|
|
46
|
+
"""Python requirements for the tool."""
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def tags(self) -> list[str]:
|
|
51
|
+
"""Tags for the tool, used for categorization."""
|
|
52
|
+
return ["perplexity", "search", "web"]
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def tool_imports(self) -> list[str]:
|
|
56
|
+
"""Imports required for the tool implementation."""
|
|
57
|
+
return [
|
|
58
|
+
"from autogen.tools.experimental import PerplexitySearchTool",
|
|
59
|
+
"from autogen.tools.experimental.perplexity.perplexity_search import SearchResponse",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
|
|
63
|
+
"""Validate secrets and return list of missing required ones.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
secrets : dict[str, str]
|
|
68
|
+
Dictionary of secrets/environment variables.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
list[str]
|
|
73
|
+
List of missing required secrets.
|
|
74
|
+
"""
|
|
75
|
+
missing_secrets: list[str] = []
|
|
76
|
+
if not secrets.get("PERPLEXITY_API_KEY"):
|
|
77
|
+
missing_secrets.append("PERPLEXITY_API_KEY")
|
|
78
|
+
return missing_secrets
|
|
79
|
+
|
|
80
|
+
def validate_kwargs(self, kwargs: dict[str, Any]) -> list[str]:
|
|
81
|
+
"""Validate keyword arguments and return list of missing required ones.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
kwargs : dict[str, Any]
|
|
86
|
+
Dictionary of keyword arguments.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
list[str]
|
|
91
|
+
List of missing required keyword arguments.
|
|
92
|
+
"""
|
|
93
|
+
for key, value in self.kwargs.items():
|
|
94
|
+
if key in kwargs: # pragma: no branch
|
|
95
|
+
type_of = self.kwarg_types.get(key, str)
|
|
96
|
+
try:
|
|
97
|
+
casted = type_of(value)
|
|
98
|
+
if key in self.kwargs: # pragma: no branch
|
|
99
|
+
self.kwargs[key] = casted
|
|
100
|
+
except Exception: # pylint: disable=broad-except
|
|
101
|
+
pass
|
|
102
|
+
return []
|
|
103
|
+
|
|
104
|
+
def get_content(
|
|
105
|
+
self,
|
|
106
|
+
secrets: dict[str, str],
|
|
107
|
+
) -> str:
|
|
108
|
+
"""Get content for the tool.
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
secrets : dict[str, str]
|
|
113
|
+
Dictionary of secrets/environment variables.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
str
|
|
118
|
+
Content retrieved by the tool.
|
|
119
|
+
"""
|
|
120
|
+
os.environ["PERPLEXITY_API_KEY"] = secrets.get("PERPLEXITY_API_KEY", "")
|
|
121
|
+
content = f'''
|
|
122
|
+
def {self.name}(
|
|
123
|
+
query: str,
|
|
124
|
+
model: str = "{self.kwargs["model"]}",
|
|
125
|
+
max_tokens: int = {self.kwargs["max_tokens"]},
|
|
126
|
+
search_domain_filter: Optional[list[str]] = {self.kwargs["search_domain_filter"]},
|
|
127
|
+
) -> "SearchResponse":
|
|
128
|
+
"""Perform a Perplexity AI search and return formatted results.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
query: The search query string.
|
|
132
|
+
model: The model to use for the search. Defaults to "{self.kwargs["model"]}".
|
|
133
|
+
max_tokens: The maximum number of tokens to return. Defaults to {self.kwargs["max_tokens"]}.
|
|
134
|
+
search_domain_filter: List of domain filters for the search. Defaults to {self.kwargs["search_domain_filter"]}.
|
|
135
|
+
Returns:
|
|
136
|
+
A list of dictionaries of the search results.
|
|
137
|
+
"""
|
|
138
|
+
perplexity_api_key = os.environ.get("PERPLEXITY_API_KEY", "")
|
|
139
|
+
if not perplexity_api_key:
|
|
140
|
+
raise ValueError("PERPLEXITY_API_KEY is required for Perplexity search tool.")
|
|
141
|
+
perplexity_search_tool = PerplexitySearchTool(
|
|
142
|
+
api_key=perplexity_api_key,
|
|
143
|
+
model=model,
|
|
144
|
+
max_tokens=max_tokens,
|
|
145
|
+
search_domain_filter=search_domain_filter,
|
|
146
|
+
)
|
|
147
|
+
return perplexity_search_tool(query=query)
|
|
148
|
+
'''
|
|
149
|
+
return content
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
PerplexitySearchTool = PerplexitySearchToolImpl()
|
|
153
|
+
PerplexitySearchConfig = PredefinedToolConfig(
|
|
154
|
+
name=PerplexitySearchTool.name,
|
|
155
|
+
description=PerplexitySearchTool.description,
|
|
156
|
+
required_secrets=PerplexitySearchTool.required_secrets,
|
|
157
|
+
required_kwargs=PerplexitySearchTool.required_kwargs,
|
|
158
|
+
requirements=PerplexitySearchTool.requirements,
|
|
159
|
+
tags=PerplexitySearchTool.tags,
|
|
160
|
+
implementation=PerplexitySearchTool,
|
|
161
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pylint: disable=line-too-long
|
|
4
|
+
# flake8: noqa: E501
|
|
5
|
+
"""Predefined SearxNG search tool for Waldiez."""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from ._config import PredefinedToolConfig
|
|
10
|
+
from .protocol import PredefinedTool
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SearxNGSearchToolImpl(PredefinedTool):
|
|
14
|
+
"""SearxNG search tool for Waldiez."""
|
|
15
|
+
|
|
16
|
+
required_secrets: list[str] = []
|
|
17
|
+
required_kwargs: dict[str, type] = {}
|
|
18
|
+
kwarg_types: dict[str, type] = {
|
|
19
|
+
"base_url": str,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def name(self) -> str:
|
|
24
|
+
"""Tool name."""
|
|
25
|
+
return "searxng_search"
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def description(self) -> str:
|
|
29
|
+
"""Tool description."""
|
|
30
|
+
return "Search SearxNG for a given query."
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def kwargs(self) -> dict[str, Any]:
|
|
34
|
+
"""Keyword arguments for the tool, used for initialization."""
|
|
35
|
+
return {
|
|
36
|
+
"base_url": "https://searxng.site/search",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def requirements(self) -> list[str]:
|
|
41
|
+
"""Python requirements for the tool."""
|
|
42
|
+
return []
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def tags(self) -> list[str]:
|
|
46
|
+
"""Tags for the tool, used for categorization."""
|
|
47
|
+
return ["searxng", "search", "web"]
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def tool_imports(self) -> list[str]:
|
|
51
|
+
"""Imports required for the tool implementation."""
|
|
52
|
+
return [
|
|
53
|
+
"from autogen.tools.experimental import SearxngSearchTool",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
def validate_secrets(self, secrets: dict[str, str]) -> list[str]:
|
|
57
|
+
"""Validate secrets and return list of missing required ones.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
secrets : dict[str, str]
|
|
62
|
+
Dictionary of secrets to validate.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
list[str]
|
|
67
|
+
List of missing required secrets.
|
|
68
|
+
"""
|
|
69
|
+
return [] # No secrets required for this tool.
|
|
70
|
+
|
|
71
|
+
def validate_kwargs(self, kwargs: dict[str, Any]) -> list[str]:
|
|
72
|
+
"""Validate keyword arguments and return list of missing required ones.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
kwargs : dict[str, Any]
|
|
77
|
+
Dictionary of keyword arguments to validate.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
list[str]
|
|
82
|
+
List of missing required keyword arguments.
|
|
83
|
+
"""
|
|
84
|
+
for key, value in self.kwargs.items():
|
|
85
|
+
if key in kwargs: # pragma: no branch
|
|
86
|
+
type_of = self.kwarg_types.get(key, str)
|
|
87
|
+
try:
|
|
88
|
+
casted = type_of(value)
|
|
89
|
+
if key in self.kwargs: # pragma: no branch
|
|
90
|
+
self.kwargs[key] = casted
|
|
91
|
+
except Exception: # pylint: disable=broad-except
|
|
92
|
+
pass
|
|
93
|
+
return []
|
|
94
|
+
|
|
95
|
+
def get_content(
|
|
96
|
+
self,
|
|
97
|
+
secrets: dict[str, str],
|
|
98
|
+
) -> str:
|
|
99
|
+
"""Get content for the tool.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
secrets : dict[str, str]
|
|
104
|
+
Dictionary of secrets/environment variables.
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
str
|
|
109
|
+
Content retrieved by the tool.
|
|
110
|
+
"""
|
|
111
|
+
content = f'''
|
|
112
|
+
def {self.name}(
|
|
113
|
+
query: str,
|
|
114
|
+
max_results: int = 5,
|
|
115
|
+
categories: list[str] | None = None,
|
|
116
|
+
language: str | None = None,
|
|
117
|
+
) -> list[dict[str, Any]]:
|
|
118
|
+
"""Perform a SearxNG search and return formatted results.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
query: The search query string.
|
|
122
|
+
max_results: The maximum number of results to return. Defaults to 5.
|
|
123
|
+
categories: List of categories to search in.
|
|
124
|
+
language: Language code (e.g., 'en-US').
|
|
125
|
+
base_url: SearxNG instance URL.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
A list of dictionaries, each containing 'title', 'link', and 'snippet' of a search result.
|
|
129
|
+
"""
|
|
130
|
+
tool = SearxngSearchTool(
|
|
131
|
+
base_url="{self.kwargs["base_url"]}",
|
|
132
|
+
)
|
|
133
|
+
return tool(
|
|
134
|
+
query=query,
|
|
135
|
+
max_results=max_results,
|
|
136
|
+
categories=categories,
|
|
137
|
+
language=language,
|
|
138
|
+
)
|
|
139
|
+
'''
|
|
140
|
+
return content
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
SearxNGSearchTool = SearxNGSearchToolImpl()
|
|
144
|
+
SearxNGSearchConfig = PredefinedToolConfig(
|
|
145
|
+
name=SearxNGSearchTool.name,
|
|
146
|
+
description=SearxNGSearchTool.description,
|
|
147
|
+
tags=SearxNGSearchTool.tags,
|
|
148
|
+
requirements=SearxNGSearchTool.requirements,
|
|
149
|
+
required_kwargs=SearxNGSearchTool.required_kwargs,
|
|
150
|
+
required_secrets=SearxNGSearchTool.required_secrets,
|
|
151
|
+
implementation=SearxNGSearchTool,
|
|
152
|
+
)
|