waldiez 0.5.9__py3-none-any.whl → 0.6.0__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 +113 -24
- waldiez/exporting/agent/exporter.py +9 -6
- waldiez/exporting/agent/extras/captain_agent_extras.py +44 -7
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +6 -1
- waldiez/exporting/agent/extras/handoffs/after_work.py +1 -0
- waldiez/exporting/agent/extras/handoffs/available.py +1 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +3 -1
- waldiez/exporting/agent/extras/handoffs/handoff.py +1 -0
- waldiez/exporting/agent/extras/handoffs/target.py +1 -0
- waldiez/exporting/agent/termination.py +1 -0
- waldiez/exporting/chats/utils/common.py +25 -23
- waldiez/exporting/core/__init__.py +0 -2
- waldiez/exporting/core/constants.py +3 -1
- waldiez/exporting/core/context.py +13 -13
- waldiez/exporting/core/extras/serializer.py +12 -10
- waldiez/exporting/core/protocols.py +0 -141
- waldiez/exporting/core/result.py +5 -5
- waldiez/exporting/core/types.py +1 -0
- waldiez/exporting/core/utils/llm_config.py +2 -2
- waldiez/exporting/flow/execution_generator.py +1 -0
- waldiez/exporting/flow/merger.py +2 -2
- waldiez/exporting/flow/orchestrator.py +1 -0
- waldiez/exporting/flow/utils/common.py +3 -3
- waldiez/exporting/flow/utils/importing.py +1 -0
- waldiez/exporting/flow/utils/logging.py +7 -80
- waldiez/exporting/tools/exporter.py +5 -0
- waldiez/exporting/tools/factory.py +4 -0
- waldiez/exporting/tools/processor.py +5 -1
- waldiez/io/__init__.py +3 -1
- waldiez/io/_ws.py +15 -5
- waldiez/io/models/content/image.py +1 -0
- waldiez/io/models/user_input.py +4 -4
- waldiez/io/models/user_response.py +1 -0
- waldiez/io/mqtt.py +1 -1
- waldiez/io/structured.py +98 -45
- waldiez/io/utils.py +17 -11
- waldiez/io/ws.py +10 -12
- waldiez/logger.py +180 -63
- waldiez/models/agents/agent/agent.py +2 -1
- waldiez/models/agents/agent/update_system_message.py +0 -2
- waldiez/models/agents/doc_agent/doc_agent.py +8 -1
- waldiez/models/chat/chat.py +1 -0
- waldiez/models/chat/chat_data.py +0 -2
- waldiez/models/common/base.py +2 -0
- waldiez/models/common/dict_utils.py +169 -40
- waldiez/models/common/handoff.py +2 -0
- waldiez/models/common/method_utils.py +2 -0
- waldiez/models/flow/flow.py +6 -6
- waldiez/models/flow/info.py +5 -1
- waldiez/models/model/_llm.py +31 -14
- waldiez/models/model/model.py +4 -1
- waldiez/models/model/model_data.py +18 -5
- waldiez/models/tool/predefined/_config.py +5 -1
- waldiez/models/tool/predefined/_duckduckgo.py +4 -0
- waldiez/models/tool/predefined/_email.py +477 -0
- waldiez/models/tool/predefined/_google.py +4 -1
- waldiez/models/tool/predefined/_perplexity.py +4 -1
- waldiez/models/tool/predefined/_searxng.py +4 -1
- waldiez/models/tool/predefined/_tavily.py +4 -1
- waldiez/models/tool/predefined/_wikipedia.py +5 -2
- waldiez/models/tool/predefined/_youtube.py +4 -1
- waldiez/models/tool/predefined/protocol.py +3 -0
- waldiez/models/tool/tool.py +22 -4
- waldiez/models/waldiez.py +12 -0
- waldiez/runner.py +37 -54
- waldiez/running/__init__.py +6 -0
- waldiez/running/base_runner.py +381 -363
- waldiez/running/environment.py +1 -0
- waldiez/running/exceptions.py +9 -0
- waldiez/running/post_run.py +10 -4
- waldiez/running/pre_run.py +199 -66
- waldiez/running/protocol.py +21 -101
- waldiez/running/run_results.py +1 -1
- waldiez/running/standard_runner.py +83 -276
- waldiez/running/step_by_step/__init__.py +46 -0
- waldiez/running/step_by_step/breakpoints_mixin.py +512 -0
- waldiez/running/step_by_step/command_handler.py +151 -0
- waldiez/running/step_by_step/events_processor.py +199 -0
- waldiez/running/step_by_step/step_by_step_models.py +541 -0
- waldiez/running/step_by_step/step_by_step_runner.py +750 -0
- waldiez/running/subprocess_runner/__base__.py +279 -0
- waldiez/running/subprocess_runner/__init__.py +16 -0
- waldiez/running/subprocess_runner/_async_runner.py +362 -0
- waldiez/running/subprocess_runner/_sync_runner.py +456 -0
- waldiez/running/subprocess_runner/runner.py +570 -0
- waldiez/running/timeline_processor.py +1 -1
- waldiez/running/utils.py +492 -3
- waldiez/utils/version.py +2 -6
- waldiez/ws/__init__.py +71 -0
- waldiez/ws/__main__.py +15 -0
- waldiez/ws/_file_handler.py +199 -0
- waldiez/ws/_mock.py +74 -0
- waldiez/ws/cli.py +235 -0
- waldiez/ws/client_manager.py +851 -0
- waldiez/ws/errors.py +416 -0
- waldiez/ws/models.py +988 -0
- waldiez/ws/reloader.py +363 -0
- waldiez/ws/server.py +508 -0
- waldiez/ws/session_manager.py +393 -0
- waldiez/ws/session_stats.py +83 -0
- waldiez/ws/utils.py +410 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/METADATA +105 -96
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/RECORD +108 -83
- waldiez/running/patch_io_stream.py +0 -210
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/WHEEL +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/entry_points.txt +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.5.9.dist-info → waldiez-0.6.0.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -2,63 +2,192 @@
|
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
"""Dictionary related utilities."""
|
|
4
4
|
|
|
5
|
+
import ast
|
|
6
|
+
import json
|
|
5
7
|
import re
|
|
6
|
-
from typing import Any
|
|
8
|
+
from typing import Any, Union
|
|
7
9
|
|
|
8
10
|
BOOL_VALUES = {"true", "false"}
|
|
9
11
|
NULL_VALUES = {"none", "null", "nil", "undefined"}
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
def _strip_outer_quotes(value: str) -> str:
|
|
15
|
+
"""Remove outer quotes from a string if present."""
|
|
16
|
+
value_stripped = value.strip()
|
|
17
|
+
if (value_stripped.startswith('"') and value_stripped.endswith('"')) or (
|
|
18
|
+
value_stripped.startswith("'") and value_stripped.endswith("'")
|
|
19
|
+
):
|
|
20
|
+
return value_stripped[1:-1]
|
|
21
|
+
return value_stripped
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _detect_null_or_boolean(value: str) -> Union[None, bool, str]:
|
|
25
|
+
"""
|
|
26
|
+
Detect null values or booleans.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
value : str
|
|
31
|
+
The string value to check.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
Union[None, bool, str]
|
|
36
|
+
None for null values, bool for booleans, or original string if neither.
|
|
37
|
+
"""
|
|
38
|
+
value_lower = value.lower()
|
|
39
|
+
|
|
40
|
+
if value_lower in NULL_VALUES:
|
|
41
|
+
return None
|
|
42
|
+
if value_lower in BOOL_VALUES:
|
|
43
|
+
return value_lower == "true"
|
|
44
|
+
|
|
45
|
+
return value
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _detect_numeric_type(value: str) -> Union[int, float, str]:
|
|
49
|
+
"""
|
|
50
|
+
Detect if string represents an integer or float.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
value : str
|
|
55
|
+
The string value to check.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
Union[int, float, str]
|
|
60
|
+
int for integers, float for floats, or original string if neither.
|
|
61
|
+
"""
|
|
62
|
+
# Check for integer first (more specific)
|
|
63
|
+
if re.fullmatch(r"[-+]?\d+", value):
|
|
64
|
+
return int(value)
|
|
65
|
+
|
|
66
|
+
# Try float conversion
|
|
67
|
+
try:
|
|
68
|
+
return float(value)
|
|
69
|
+
except ValueError:
|
|
70
|
+
return value
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _detect_container_type(
|
|
74
|
+
value: str,
|
|
75
|
+
) -> Union[dict[str, Any], list[Any], tuple[Any], set[Any], str]:
|
|
76
|
+
"""
|
|
77
|
+
Detect if string represents a container type (dict, list, tuple, set).
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
value : str
|
|
82
|
+
The string value to check.
|
|
83
|
+
|
|
84
|
+
Returns
|
|
85
|
+
-------
|
|
86
|
+
Union[dict[str, Any], list[Any], tuple[Any], set[Any], str]
|
|
87
|
+
Parsed container or original string if not a container.
|
|
88
|
+
"""
|
|
89
|
+
if not (value[0] in "{[(" and value[-1] in "}])"):
|
|
90
|
+
return value
|
|
91
|
+
|
|
92
|
+
# Handle empty containers
|
|
93
|
+
if value in ("()", "[]", "{}"):
|
|
94
|
+
return ast.literal_eval(value)
|
|
95
|
+
|
|
96
|
+
# Try JSON first (expects double quotes)
|
|
97
|
+
try:
|
|
98
|
+
parsed = json.loads(value)
|
|
99
|
+
if isinstance(parsed, (dict, list)):
|
|
100
|
+
return parsed # pyright: ignore
|
|
101
|
+
except (json.JSONDecodeError, TypeError):
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
# Fallback: Python literal (handles single quotes, tuples, sets)
|
|
105
|
+
try:
|
|
106
|
+
parsed = ast.literal_eval(value)
|
|
107
|
+
if isinstance(parsed, (dict, list, tuple, set)):
|
|
108
|
+
return parsed # pyright: ignore
|
|
109
|
+
except (ValueError, SyntaxError):
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
return value
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _convert_string_value(value: str) -> Any:
|
|
116
|
+
"""
|
|
117
|
+
Convert a string value to its detected type.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
value : str
|
|
122
|
+
The string value to convert.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
Any
|
|
127
|
+
The converted value or original string if no conversion possible.
|
|
128
|
+
"""
|
|
129
|
+
# Strip outer quotes if present
|
|
130
|
+
cleaned_value = _strip_outer_quotes(value)
|
|
131
|
+
|
|
132
|
+
# Skip conversion for empty strings
|
|
133
|
+
if not cleaned_value:
|
|
134
|
+
return value
|
|
135
|
+
|
|
136
|
+
# Try conversions in order of specificity
|
|
137
|
+
|
|
138
|
+
# 1. Container types (most specific structure)
|
|
139
|
+
container_result = _detect_container_type(cleaned_value)
|
|
140
|
+
if container_result != cleaned_value:
|
|
141
|
+
return container_result
|
|
142
|
+
|
|
143
|
+
# 2. Null and boolean values
|
|
144
|
+
null_bool_result = _detect_null_or_boolean(cleaned_value)
|
|
145
|
+
if null_bool_result != cleaned_value:
|
|
146
|
+
return null_bool_result
|
|
147
|
+
|
|
148
|
+
# 3. Numeric types
|
|
149
|
+
numeric_result = _detect_numeric_type(cleaned_value)
|
|
150
|
+
if numeric_result != cleaned_value:
|
|
151
|
+
return numeric_result
|
|
152
|
+
|
|
153
|
+
# 4. Keep as string if no conversion succeeded
|
|
154
|
+
return cleaned_value
|
|
155
|
+
|
|
156
|
+
|
|
12
157
|
def update_dict(original: dict[str, Any]) -> dict[str, Any]:
|
|
13
158
|
"""
|
|
14
|
-
|
|
159
|
+
Convert string values in a dictionary to their detected types.
|
|
160
|
+
|
|
161
|
+
Automatically detects and converts strings that represent:
|
|
162
|
+
- Boolean values (true/false)
|
|
163
|
+
- Null values (none/null/nil/undefined)
|
|
164
|
+
- Integers and floats
|
|
165
|
+
- Container types (lists, dicts, tuples, sets)
|
|
15
166
|
|
|
16
167
|
Parameters
|
|
17
168
|
----------
|
|
18
169
|
original : dict[str, Any]
|
|
19
|
-
The original dictionary.
|
|
170
|
+
The original dictionary with potentially string-encoded values.
|
|
20
171
|
|
|
21
172
|
Returns
|
|
22
173
|
-------
|
|
23
174
|
dict[str, Any]
|
|
24
|
-
|
|
175
|
+
A new dictionary with string values converted to their detected types.
|
|
176
|
+
Non-string values are preserved unchanged.
|
|
177
|
+
|
|
178
|
+
Examples
|
|
179
|
+
--------
|
|
180
|
+
>>> data = {"count": "42", "active": "true", "tags": "['a', 'b']"}
|
|
181
|
+
>>> update_dict(data)
|
|
182
|
+
{"count": 42, "active": True, "tags": ['a', 'b']}
|
|
25
183
|
"""
|
|
26
|
-
|
|
184
|
+
converted_dict: dict[str, Any] = {}
|
|
27
185
|
|
|
28
186
|
for key, value in original.items():
|
|
29
|
-
#
|
|
30
|
-
if
|
|
31
|
-
|
|
32
|
-
continue
|
|
33
|
-
|
|
34
|
-
value_stripped = value.strip()
|
|
35
|
-
if (
|
|
36
|
-
value_stripped.startswith('"') and value_stripped.endswith('"')
|
|
37
|
-
) or (value_stripped.startswith("'") and value_stripped.endswith("'")):
|
|
38
|
-
value_stripped = value_stripped[1:-1]
|
|
39
|
-
if not value_stripped: # Empty or whitespace-only
|
|
40
|
-
new_dict[key] = value
|
|
41
|
-
continue
|
|
42
|
-
|
|
43
|
-
value_lower = value_stripped.lower()
|
|
44
|
-
|
|
45
|
-
# Check for None/null
|
|
46
|
-
if value_lower in NULL_VALUES:
|
|
47
|
-
new_dict[key] = None
|
|
48
|
-
# Check for boolean
|
|
49
|
-
elif value_lower in BOOL_VALUES:
|
|
50
|
-
new_dict[key] = value_lower == "true"
|
|
51
|
-
# Check for integer
|
|
52
|
-
elif re.fullmatch(r"[-+]?\d+", value_stripped):
|
|
53
|
-
new_dict[key] = int(value_stripped)
|
|
54
|
-
# Check for float
|
|
187
|
+
# Only process string values
|
|
188
|
+
if isinstance(value, str):
|
|
189
|
+
converted_dict[key] = _convert_string_value(value)
|
|
55
190
|
else:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
new_dict[key] = float_val
|
|
60
|
-
except ValueError:
|
|
61
|
-
# Keep as string if conversion fails
|
|
62
|
-
new_dict[key] = value_stripped
|
|
63
|
-
|
|
64
|
-
return new_dict
|
|
191
|
+
converted_dict[key] = value
|
|
192
|
+
|
|
193
|
+
return converted_dict
|
waldiez/models/common/handoff.py
CHANGED
|
@@ -343,6 +343,7 @@ class WaldiezTransitionAvailability(WaldiezBase):
|
|
|
343
343
|
value: str = ""
|
|
344
344
|
|
|
345
345
|
|
|
346
|
+
# noinspection PyTypeHints
|
|
346
347
|
class WaldiezLLMBasedTransition(WaldiezBase):
|
|
347
348
|
"""Condition wrapper for LLM conditions."""
|
|
348
349
|
|
|
@@ -351,6 +352,7 @@ class WaldiezLLMBasedTransition(WaldiezBase):
|
|
|
351
352
|
available: WaldiezTransitionAvailability
|
|
352
353
|
|
|
353
354
|
|
|
355
|
+
# noinspection PyTypeHints
|
|
354
356
|
class WaldiezContextBasedTransition(WaldiezBase):
|
|
355
357
|
"""Condition wrapper for context conditions."""
|
|
356
358
|
|
|
@@ -123,11 +123,13 @@ def _extract_imports_from_ast(code_string: str) -> tuple[list[str], list[str]]:
|
|
|
123
123
|
|
|
124
124
|
for node in ast.walk(tree):
|
|
125
125
|
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
126
|
+
# noinspection PyTypeChecker
|
|
126
127
|
full_import_statement = ast.get_source_segment(code_string, node)
|
|
127
128
|
if not full_import_statement: # pragma: no cover
|
|
128
129
|
continue
|
|
129
130
|
full_import_statement = full_import_statement.strip()
|
|
130
131
|
|
|
132
|
+
# noinspection PyTypeChecker
|
|
131
133
|
module_name = _extract_module_name(node)
|
|
132
134
|
if not module_name: # pragma: no cover
|
|
133
135
|
continue
|
waldiez/models/flow/flow.py
CHANGED
|
@@ -397,7 +397,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
397
397
|
If no group manager is found.
|
|
398
398
|
"""
|
|
399
399
|
for agent in self.data.agents.groupManagerAgents:
|
|
400
|
-
if agent.data.parent_id is None:
|
|
400
|
+
if agent.data.parent_id is None: # pragma: no branch
|
|
401
401
|
return agent
|
|
402
402
|
raise ValueError("No group manager found.")
|
|
403
403
|
|
|
@@ -431,16 +431,16 @@ class WaldiezFlow(WaldiezBase):
|
|
|
431
431
|
to_root_manager: WaldiezChat | None = None
|
|
432
432
|
root_manager: WaldiezGroupManager = self.get_root_group_manager()
|
|
433
433
|
for chat in self.data.chats:
|
|
434
|
-
if chat.target == root_manager.id:
|
|
434
|
+
if chat.target == root_manager.id: # pragma: no branch
|
|
435
435
|
# check if the source is a user agent
|
|
436
436
|
source = self.get_agent_by_id(chat.source)
|
|
437
|
-
if source.is_user:
|
|
437
|
+
if source.is_user: # pragma: no branch
|
|
438
438
|
user_agent = source
|
|
439
439
|
to_root_manager = chat
|
|
440
440
|
break
|
|
441
|
-
if not to_root_manager:
|
|
441
|
+
if not to_root_manager: # pragma: no cover
|
|
442
442
|
return []
|
|
443
|
-
if not user_agent:
|
|
443
|
+
if not user_agent: # pragma: no cover
|
|
444
444
|
return []
|
|
445
445
|
return [
|
|
446
446
|
{
|
|
@@ -572,7 +572,7 @@ class WaldiezFlow(WaldiezBase):
|
|
|
572
572
|
- If the model IDs are not unique.
|
|
573
573
|
- If the tool IDs are not unique.
|
|
574
574
|
"""
|
|
575
|
-
if member.is_group_manager:
|
|
575
|
+
if member.is_group_manager: # pragma: no cover
|
|
576
576
|
raise ValueError(
|
|
577
577
|
"In single agent mode, the agent must not be a group manager."
|
|
578
578
|
)
|
waldiez/models/flow/info.py
CHANGED
|
@@ -18,6 +18,8 @@ class WaldiezAgentInfo(WaldiezBase):
|
|
|
18
18
|
|
|
19
19
|
Attributes
|
|
20
20
|
----------
|
|
21
|
+
id : str
|
|
22
|
+
The ID of the agent.
|
|
21
23
|
name : str
|
|
22
24
|
The name of the agent.
|
|
23
25
|
human_input_mode : WaldiezAgentHumanInputMode
|
|
@@ -27,6 +29,7 @@ class WaldiezAgentInfo(WaldiezBase):
|
|
|
27
29
|
The type of the agent (e.g., "user", "assistant").
|
|
28
30
|
"""
|
|
29
31
|
|
|
32
|
+
id: Annotated[str, Field(description="ID of the agent")]
|
|
30
33
|
name: Annotated[str, Field(description="Name of the agent")]
|
|
31
34
|
human_input_mode: Annotated[
|
|
32
35
|
WaldiezAgentHumanInputMode,
|
|
@@ -53,7 +56,7 @@ class WaldiezFlowInfo(WaldiezBase):
|
|
|
53
56
|
description="List of chat participants with their info",
|
|
54
57
|
default_factory=list[WaldiezAgentInfo],
|
|
55
58
|
),
|
|
56
|
-
]
|
|
59
|
+
] = []
|
|
57
60
|
|
|
58
61
|
@classmethod
|
|
59
62
|
def create(
|
|
@@ -77,6 +80,7 @@ class WaldiezFlowInfo(WaldiezBase):
|
|
|
77
80
|
for agent in agents:
|
|
78
81
|
participants.append(
|
|
79
82
|
WaldiezAgentInfo(
|
|
83
|
+
id=agent.id,
|
|
80
84
|
name=agent_names.get(agent.id, agent.name),
|
|
81
85
|
human_input_mode=agent.data.human_input_mode,
|
|
82
86
|
agent_type=agent.agent_type,
|
waldiez/models/model/_llm.py
CHANGED
|
@@ -31,9 +31,10 @@ if TYPE_CHECKING:
|
|
|
31
31
|
from .model import WaldiezModel
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
# noinspection PyUnusedLocal
|
|
34
35
|
def get_llm_requirements(
|
|
35
36
|
model: "WaldiezModel",
|
|
36
|
-
ag2_version: str,
|
|
37
|
+
ag2_version: str, # pylint: disable=unused-argument
|
|
37
38
|
) -> set[str]:
|
|
38
39
|
"""Get the LLM requirements for the model.
|
|
39
40
|
|
|
@@ -50,9 +51,16 @@ def get_llm_requirements(
|
|
|
50
51
|
The set of LLM requirements for the model.
|
|
51
52
|
"""
|
|
52
53
|
requirements: set[str] = {
|
|
54
|
+
# f"ag2[rag]=={ag2_version}",
|
|
55
|
+
"chromadb>=0.5,<2",
|
|
56
|
+
"docling>=2.15.1,<3",
|
|
57
|
+
"selenium>=4.28.1,<5",
|
|
58
|
+
"webdriver-manager==4.0.2",
|
|
53
59
|
"llama-index",
|
|
54
60
|
"llama-index-core",
|
|
55
|
-
|
|
61
|
+
"llama-index-embeddings-huggingface",
|
|
62
|
+
"llama-index-llms-langchain",
|
|
63
|
+
"llama-index-vector-stores-chroma",
|
|
56
64
|
}
|
|
57
65
|
match model.data.api_type:
|
|
58
66
|
case "openai":
|
|
@@ -87,7 +95,7 @@ def get_llm_requirements(
|
|
|
87
95
|
)
|
|
88
96
|
case "together":
|
|
89
97
|
requirements.add("llama-index-llms-together")
|
|
90
|
-
case "other":
|
|
98
|
+
case "other": # pragma: no cover
|
|
91
99
|
# openai compatible LLMs
|
|
92
100
|
requirements.add("llama-index-llms-openai-like")
|
|
93
101
|
|
|
@@ -147,6 +155,7 @@ def get_llm_imports(model: "WaldiezModel") -> set[str]:
|
|
|
147
155
|
case "other":
|
|
148
156
|
return {"from llama_index.llms.openai_like import OpenAILike"}
|
|
149
157
|
case _: # pragma: no cover
|
|
158
|
+
# noinspection PyUnreachableCode
|
|
150
159
|
raise ValueError(f"Unsupported API type: {model.data.api_type}")
|
|
151
160
|
|
|
152
161
|
|
|
@@ -194,6 +203,7 @@ def get_llm_arg(model: "WaldiezModel") -> tuple[str, str]:
|
|
|
194
203
|
case "other":
|
|
195
204
|
return do_other_llm(model)
|
|
196
205
|
case _: # pragma: no cover
|
|
206
|
+
# noinspection PyUnreachableCode
|
|
197
207
|
raise ValueError(f"Unsupported API type: {model.data.api_type}")
|
|
198
208
|
|
|
199
209
|
|
|
@@ -279,9 +289,9 @@ def do_azure_llm(model: "WaldiezModel") -> tuple[str, str]:
|
|
|
279
289
|
f' model="{model.name}",\n'
|
|
280
290
|
f" temperature={temperature},\n"
|
|
281
291
|
)
|
|
282
|
-
if model.data.base_url:
|
|
292
|
+
if model.data.base_url: # pragma: no branch
|
|
283
293
|
arg += f' azure_endpoint="{model.data.base_url}",\n'
|
|
284
|
-
if model.data.api_version:
|
|
294
|
+
if model.data.api_version: # pragma: no branch
|
|
285
295
|
arg += f' api_version="{model.data.api_version}",\n'
|
|
286
296
|
arg += ")"
|
|
287
297
|
before = ""
|
|
@@ -322,11 +332,11 @@ def do_bedrock_llm(model: "WaldiezModel") -> tuple[str, str]:
|
|
|
322
332
|
aws_access_key_id = model.data.aws.access_key or ""
|
|
323
333
|
aws_region = model.data.aws.region or ""
|
|
324
334
|
arg = f'BedrockConverse(\n model="{model.name}",\n'
|
|
325
|
-
if profile_name:
|
|
335
|
+
if profile_name: # pragma: no branch
|
|
326
336
|
arg += f' profile_name="{profile_name}",\n'
|
|
327
|
-
if aws_access_key_id:
|
|
337
|
+
if aws_access_key_id: # pragma: no branch
|
|
328
338
|
arg += f' aws_access_key_id="{aws_access_key_id}",\n'
|
|
329
|
-
if aws_region:
|
|
339
|
+
if aws_region: # pragma: no branch
|
|
330
340
|
arg += f' region_name="{aws_region}",\n'
|
|
331
341
|
arg += ")"
|
|
332
342
|
before = ""
|
|
@@ -347,11 +357,11 @@ def do_cohere_llm(model: "WaldiezModel") -> tuple[str, str]:
|
|
|
347
357
|
A tuple containing the LLM argument string and any content before it.
|
|
348
358
|
"""
|
|
349
359
|
arg = f'Cohere(\n model="{model.name}",\n'
|
|
350
|
-
if model.data.api_key:
|
|
360
|
+
if model.data.api_key: # pragma: no branch
|
|
351
361
|
arg += f' api_key="{model.data.api_key}",\n'
|
|
352
|
-
if model.data.base_url:
|
|
362
|
+
if model.data.base_url: # pragma: no branch
|
|
353
363
|
arg += f' base_url="{model.data.base_url}",\n'
|
|
354
|
-
if model.data.temperature is not None:
|
|
364
|
+
if model.data.temperature is not None: # pragma: no branch
|
|
355
365
|
arg += f" temperature={model.data.temperature},\n"
|
|
356
366
|
arg += ")"
|
|
357
367
|
before = ""
|
|
@@ -507,11 +517,18 @@ def do_other_llm(model: "WaldiezModel") -> tuple[str, str]:
|
|
|
507
517
|
f' model="{model.name}",\n'
|
|
508
518
|
f' api_base="{model.data.base_url}",\n'
|
|
509
519
|
)
|
|
510
|
-
if not model.data.api_key:
|
|
520
|
+
if not model.data.api_key: # pragma: no cover
|
|
511
521
|
arg += ' api_key="na",\n'
|
|
512
|
-
|
|
522
|
+
else:
|
|
523
|
+
arg += f' api_key="{model.data.api_key}",\n'
|
|
524
|
+
if model.data.temperature is not None: # pragma: no branch
|
|
525
|
+
arg += f" temperature={model.data.temperature},\n"
|
|
526
|
+
if model.data.extras: # pragma: no branch
|
|
513
527
|
for key, value in model.data.extras.items():
|
|
514
|
-
|
|
528
|
+
if isinstance(value, str):
|
|
529
|
+
arg += f' {key}="{value}",\n'
|
|
530
|
+
else:
|
|
531
|
+
arg += f" {key}={value},\n"
|
|
515
532
|
arg += ")"
|
|
516
533
|
# if model.data.price:
|
|
517
534
|
before = ""
|
waldiez/models/model/model.py
CHANGED
|
@@ -213,7 +213,7 @@ class WaldiezModel(WaldiezBase):
|
|
|
213
213
|
optionals: list[tuple[str, type]] = [
|
|
214
214
|
("base_url", str),
|
|
215
215
|
("max_tokens", int),
|
|
216
|
-
|
|
216
|
+
("temperature", float),
|
|
217
217
|
("top_p", float),
|
|
218
218
|
("api_version", str),
|
|
219
219
|
("default_headers", dict),
|
|
@@ -229,6 +229,9 @@ class WaldiezModel(WaldiezBase):
|
|
|
229
229
|
value = getattr(self, attr)
|
|
230
230
|
if value:
|
|
231
231
|
_llm_config[attr] = value
|
|
232
|
+
if "top_p" in _llm_config and "temperature" in _llm_config:
|
|
233
|
+
# only keep one
|
|
234
|
+
_llm_config.pop("top_p", None)
|
|
232
235
|
if self.data.api_type == "bedrock":
|
|
233
236
|
_llm_config.pop("base_url", None)
|
|
234
237
|
return set_bedrock_aws_config(_llm_config, self.data.aws)
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
# flake8: noqa: E501
|
|
4
4
|
"""Waldiez Model Data."""
|
|
5
5
|
|
|
6
|
-
from typing import Optional
|
|
6
|
+
from typing import Any, Optional
|
|
7
7
|
|
|
8
|
-
from pydantic import Field
|
|
9
|
-
from typing_extensions import Annotated, Literal
|
|
8
|
+
from pydantic import Field, model_validator
|
|
9
|
+
from typing_extensions import Annotated, Literal, Self
|
|
10
10
|
|
|
11
|
-
from ..common import WaldiezBase
|
|
11
|
+
from ..common import WaldiezBase, update_dict
|
|
12
12
|
from ._aws import WaldiezModelAWS
|
|
13
13
|
from ._price import WaldiezModelPrice
|
|
14
14
|
|
|
@@ -131,7 +131,7 @@ class WaldiezModelData(WaldiezBase):
|
|
|
131
131
|
),
|
|
132
132
|
] = None
|
|
133
133
|
extras: Annotated[
|
|
134
|
-
dict[str,
|
|
134
|
+
dict[str, Any],
|
|
135
135
|
Field(
|
|
136
136
|
alias="extras",
|
|
137
137
|
default_factory=dict,
|
|
@@ -154,3 +154,16 @@ class WaldiezModelData(WaldiezBase):
|
|
|
154
154
|
default=None, title="Price", description="The price of the model"
|
|
155
155
|
),
|
|
156
156
|
] = None
|
|
157
|
+
|
|
158
|
+
@model_validator(mode="after")
|
|
159
|
+
def validate_model_data(self) -> Self:
|
|
160
|
+
"""Validate model data.
|
|
161
|
+
|
|
162
|
+
Returns
|
|
163
|
+
-------
|
|
164
|
+
WaldiezModelData
|
|
165
|
+
The validated model data.
|
|
166
|
+
"""
|
|
167
|
+
if self.extras:
|
|
168
|
+
self.extras = update_dict(self.extras)
|
|
169
|
+
return self
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""Predefined tool configuration for Waldiez."""
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
8
|
from .protocol import PredefinedTool
|
|
8
9
|
|
|
@@ -52,6 +53,7 @@ class PredefinedToolConfig:
|
|
|
52
53
|
def get_content(
|
|
53
54
|
self,
|
|
54
55
|
secrets: dict[str, str],
|
|
56
|
+
runtime_kwargs: dict[str, Any] | None = None,
|
|
55
57
|
) -> str:
|
|
56
58
|
"""Get the content of the tool.
|
|
57
59
|
|
|
@@ -59,10 +61,12 @@ class PredefinedToolConfig:
|
|
|
59
61
|
----------
|
|
60
62
|
secrets : dict[str, str]
|
|
61
63
|
Dictionary of secrets/environment variables.
|
|
64
|
+
runtime_kwargs : dict[str, Any] | None, optional
|
|
65
|
+
Runtime keyword arguments to customize the content generation.
|
|
62
66
|
|
|
63
67
|
Returns
|
|
64
68
|
-------
|
|
65
69
|
str
|
|
66
70
|
Content of the tool.
|
|
67
71
|
"""
|
|
68
|
-
return self.implementation.get_content(secrets)
|
|
72
|
+
return self.implementation.get_content(secrets, runtime_kwargs)
|
|
@@ -81,6 +81,7 @@ class DuckDuckGoSearchToolImpl(PredefinedTool):
|
|
|
81
81
|
def get_content(
|
|
82
82
|
self,
|
|
83
83
|
secrets: dict[str, str],
|
|
84
|
+
runtime_kwargs: dict[str, Any] | None = None,
|
|
84
85
|
) -> str:
|
|
85
86
|
"""Get content for the tool.
|
|
86
87
|
|
|
@@ -89,6 +90,9 @@ class DuckDuckGoSearchToolImpl(PredefinedTool):
|
|
|
89
90
|
secrets : dict[str, str]
|
|
90
91
|
Dictionary of secrets/environment variables.
|
|
91
92
|
|
|
93
|
+
runtime_kwargs : dict[str, Any] | None, optional
|
|
94
|
+
Runtime keyword arguments to customize the content generation.
|
|
95
|
+
|
|
92
96
|
Returns
|
|
93
97
|
-------
|
|
94
98
|
str
|