waldiez 0.2.2__py3-none-any.whl → 0.3.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/__init__.py +2 -0
- waldiez/__main__.py +2 -0
- waldiez/_version.py +3 -1
- waldiez/cli.py +13 -3
- waldiez/cli_extras.py +4 -3
- waldiez/conflict_checker.py +4 -3
- waldiez/exporter.py +28 -105
- waldiez/exporting/__init__.py +8 -9
- waldiez/exporting/agent/__init__.py +7 -0
- waldiez/exporting/agent/agent_exporter.py +279 -0
- waldiez/exporting/agent/utils/__init__.py +23 -0
- waldiez/exporting/agent/utils/agent_class_name.py +34 -0
- waldiez/exporting/agent/utils/agent_imports.py +50 -0
- waldiez/exporting/{agents → agent/utils}/code_execution.py +9 -11
- waldiez/exporting/{agents → agent/utils}/group_manager.py +47 -35
- waldiez/exporting/{agents → agent/utils}/rag_user/__init__.py +2 -0
- waldiez/exporting/{agents → agent/utils}/rag_user/chroma_utils.py +22 -17
- waldiez/exporting/{agents → agent/utils}/rag_user/mongo_utils.py +14 -10
- waldiez/exporting/{agents → agent/utils}/rag_user/pgvector_utils.py +12 -8
- waldiez/exporting/{agents → agent/utils}/rag_user/qdrant_utils.py +11 -8
- waldiez/exporting/{agents → agent/utils}/rag_user/rag_user.py +78 -55
- waldiez/exporting/{agents → agent/utils}/rag_user/vector_db.py +10 -8
- waldiez/exporting/agent/utils/swarm_agent.py +463 -0
- waldiez/exporting/{agents → agent/utils}/teachability.py +10 -6
- waldiez/exporting/{agents → agent/utils}/termination_message.py +7 -8
- waldiez/exporting/base/__init__.py +25 -0
- waldiez/exporting/base/agent_position.py +75 -0
- waldiez/exporting/base/base_exporter.py +118 -0
- waldiez/exporting/base/export_position.py +48 -0
- waldiez/exporting/base/import_position.py +23 -0
- waldiez/exporting/base/mixin.py +134 -0
- waldiez/exporting/base/utils/__init__.py +18 -0
- waldiez/exporting/{utils → base/utils}/comments.py +12 -55
- waldiez/exporting/{utils → base/utils}/naming.py +14 -4
- waldiez/exporting/base/utils/path_check.py +68 -0
- waldiez/exporting/{utils/object_string.py → base/utils/to_string.py} +21 -20
- waldiez/exporting/chats/__init__.py +5 -12
- waldiez/exporting/chats/chats_exporter.py +240 -0
- waldiez/exporting/chats/utils/__init__.py +15 -0
- waldiez/exporting/chats/utils/common.py +81 -0
- waldiez/exporting/chats/{nested.py → utils/nested.py} +125 -86
- waldiez/exporting/chats/utils/sequential.py +244 -0
- waldiez/exporting/chats/utils/single_chat.py +313 -0
- waldiez/exporting/chats/utils/swarm.py +207 -0
- waldiez/exporting/flow/__init__.py +5 -3
- waldiez/exporting/flow/flow_exporter.py +503 -0
- waldiez/exporting/flow/utils/__init__.py +47 -0
- waldiez/exporting/flow/utils/agent_utils.py +204 -0
- waldiez/exporting/flow/utils/chat_utils.py +71 -0
- waldiez/exporting/flow/utils/def_main.py +62 -0
- waldiez/exporting/flow/utils/flow_content.py +112 -0
- waldiez/exporting/flow/utils/flow_names.py +115 -0
- waldiez/exporting/flow/utils/importing_utils.py +179 -0
- waldiez/exporting/{utils → flow/utils}/logging_utils.py +34 -31
- waldiez/exporting/models/__init__.py +7 -242
- waldiez/exporting/models/models_exporter.py +192 -0
- waldiez/exporting/models/utils.py +166 -0
- waldiez/exporting/skills/__init__.py +7 -161
- waldiez/exporting/skills/skills_exporter.py +169 -0
- waldiez/exporting/skills/utils.py +281 -0
- waldiez/models/__init__.py +25 -7
- waldiez/models/agents/__init__.py +70 -0
- waldiez/models/agents/agent/__init__.py +11 -1
- waldiez/models/agents/agent/agent.py +9 -4
- waldiez/models/agents/agent/agent_data.py +3 -1
- waldiez/models/agents/agent/code_execution.py +2 -0
- waldiez/models/agents/agent/linked_skill.py +2 -0
- waldiez/models/agents/agent/nested_chat.py +2 -0
- waldiez/models/agents/agent/teachability.py +2 -0
- waldiez/models/agents/agent/termination_message.py +49 -13
- waldiez/models/agents/agents.py +15 -3
- waldiez/models/agents/assistant/__init__.py +2 -0
- waldiez/models/agents/assistant/assistant.py +2 -0
- waldiez/models/agents/assistant/assistant_data.py +2 -0
- waldiez/models/agents/group_manager/__init__.py +9 -1
- waldiez/models/agents/group_manager/group_manager.py +2 -0
- waldiez/models/agents/group_manager/group_manager_data.py +2 -0
- waldiez/models/agents/group_manager/speakers.py +49 -13
- waldiez/models/agents/rag_user/__init__.py +21 -4
- waldiez/models/agents/rag_user/rag_user.py +3 -1
- waldiez/models/agents/rag_user/rag_user_data.py +2 -0
- waldiez/models/agents/rag_user/retrieve_config.py +268 -17
- waldiez/models/agents/rag_user/vector_db_config.py +5 -3
- waldiez/models/agents/swarm_agent/__init__.py +49 -0
- waldiez/models/agents/swarm_agent/after_work.py +178 -0
- waldiez/models/agents/swarm_agent/on_condition.py +103 -0
- waldiez/models/agents/swarm_agent/on_condition_available.py +140 -0
- waldiez/models/agents/swarm_agent/on_condition_target.py +40 -0
- waldiez/models/agents/swarm_agent/swarm_agent.py +107 -0
- waldiez/models/agents/swarm_agent/swarm_agent_data.py +125 -0
- waldiez/models/agents/swarm_agent/update_system_message.py +144 -0
- waldiez/models/agents/user_proxy/__init__.py +2 -0
- waldiez/models/agents/user_proxy/user_proxy.py +2 -0
- waldiez/models/agents/user_proxy/user_proxy_data.py +2 -0
- waldiez/models/chat/__init__.py +21 -3
- waldiez/models/chat/chat.py +241 -7
- waldiez/models/chat/chat_data.py +192 -48
- waldiez/models/chat/chat_message.py +153 -144
- waldiez/models/chat/chat_nested.py +33 -53
- waldiez/models/chat/chat_summary.py +2 -0
- waldiez/models/common/__init__.py +6 -6
- waldiez/models/common/base.py +4 -1
- waldiez/models/common/method_utils.py +163 -83
- waldiez/models/flow/__init__.py +2 -0
- waldiez/models/flow/flow.py +176 -40
- waldiez/models/flow/flow_data.py +63 -2
- waldiez/models/flow/utils.py +172 -0
- waldiez/models/model/__init__.py +2 -0
- waldiez/models/model/model.py +25 -6
- waldiez/models/model/model_data.py +3 -1
- waldiez/models/skill/__init__.py +4 -1
- waldiez/models/skill/skill.py +30 -2
- waldiez/models/skill/skill_data.py +2 -0
- waldiez/models/waldiez.py +28 -4
- waldiez/runner.py +142 -228
- waldiez/running/__init__.py +33 -0
- waldiez/running/environment.py +83 -0
- waldiez/running/gen_seq_diagram.py +185 -0
- waldiez/running/running.py +300 -0
- {waldiez-0.2.2.dist-info → waldiez-0.3.0.dist-info}/METADATA +32 -26
- waldiez-0.3.0.dist-info/RECORD +125 -0
- waldiez-0.3.0.dist-info/licenses/LICENSE +201 -0
- waldiez/exporting/agents/__init__.py +0 -5
- waldiez/exporting/agents/agent.py +0 -236
- waldiez/exporting/agents/agent_skills.py +0 -67
- waldiez/exporting/agents/llm_config.py +0 -53
- waldiez/exporting/chats/chats.py +0 -46
- waldiez/exporting/chats/helpers.py +0 -420
- waldiez/exporting/flow/def_main.py +0 -32
- waldiez/exporting/flow/flow.py +0 -189
- waldiez/exporting/utils/__init__.py +0 -36
- waldiez/exporting/utils/importing.py +0 -265
- waldiez/exporting/utils/method_utils.py +0 -35
- waldiez/exporting/utils/path_check.py +0 -51
- waldiez-0.2.2.dist-info/RECORD +0 -92
- waldiez-0.2.2.dist-info/licenses/LICENSE +0 -21
- {waldiez-0.2.2.dist-info → waldiez-0.3.0.dist-info}/WHEEL +0 -0
- {waldiez-0.2.2.dist-info → waldiez-0.3.0.dist-info}/entry_points.txt +0 -0
waldiez/__init__.py
CHANGED
waldiez/__main__.py
CHANGED
waldiez/_version.py
CHANGED
waldiez/cli.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pylint: disable=missing-function-docstring,missing-param-doc,missing-raises-doc # noqa: E501
|
|
1
4
|
"""Command line interface to convert or run a waldiez file."""
|
|
2
5
|
|
|
3
|
-
# pylint: disable=missing-function-docstring,missing-param-doc,missing-raises-doc # noqa: E501
|
|
4
6
|
import json
|
|
5
7
|
import logging
|
|
6
8
|
import os
|
|
@@ -9,6 +11,7 @@ import warnings
|
|
|
9
11
|
from pathlib import Path
|
|
10
12
|
from typing import TYPE_CHECKING, Optional
|
|
11
13
|
|
|
14
|
+
import anyio
|
|
12
15
|
import typer
|
|
13
16
|
from typing_extensions import Annotated
|
|
14
17
|
|
|
@@ -87,6 +90,10 @@ def run(
|
|
|
87
90
|
),
|
|
88
91
|
) -> None:
|
|
89
92
|
"""Run a Waldiez flow."""
|
|
93
|
+
# swarm without a user,
|
|
94
|
+
# creates a new user (this has a default code execution with docker)
|
|
95
|
+
# temp (until we handle/detect docker setup)
|
|
96
|
+
os.environ["AUTOGEN_USE_DOCKER"] = "0"
|
|
90
97
|
output_path = _get_output_path(output, force)
|
|
91
98
|
with file.open("r", encoding="utf-8") as _file:
|
|
92
99
|
try:
|
|
@@ -96,14 +103,17 @@ def run(
|
|
|
96
103
|
raise typer.Exit(code=1) from error
|
|
97
104
|
waldiez = Waldiez.from_dict(data)
|
|
98
105
|
runner = WaldiezRunner(waldiez)
|
|
99
|
-
|
|
106
|
+
if waldiez.is_async:
|
|
107
|
+
results = anyio.run(runner.a_run, output_path)
|
|
108
|
+
else:
|
|
109
|
+
results = runner.run(output_path=output_path)
|
|
100
110
|
logger = _get_logger()
|
|
101
111
|
if isinstance(results, list):
|
|
102
112
|
logger.info("Results:")
|
|
103
113
|
for result in results:
|
|
104
114
|
_log_result(result, logger)
|
|
105
115
|
sep = "-" * 80
|
|
106
|
-
print(
|
|
116
|
+
print("\n" + f"{sep}" + "\n")
|
|
107
117
|
else:
|
|
108
118
|
_log_result(results, logger)
|
|
109
119
|
|
waldiez/cli_extras.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
# pylint: skip-file
|
|
4
|
+
# type: ignore
|
|
4
5
|
# isort: skip_file
|
|
5
6
|
"""Extra typer commands for CLI."""
|
|
6
7
|
|
|
@@ -20,7 +21,7 @@ except BaseException:
|
|
|
20
21
|
pass
|
|
21
22
|
|
|
22
23
|
try:
|
|
23
|
-
import waldiez_jupyter
|
|
24
|
+
import waldiez_jupyter # noqa: F401
|
|
24
25
|
|
|
25
26
|
HAVE_JUPYTER = True
|
|
26
27
|
except BaseException:
|
waldiez/conflict_checker.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
# pylint: disable=line-too-long
|
|
4
|
+
"""Check for conflicts with 'autogen-agentchat' package."""
|
|
4
5
|
|
|
5
6
|
import sys
|
|
6
7
|
from importlib.metadata import PackageNotFoundError, version
|
|
@@ -16,7 +17,7 @@ def check_conflicts() -> None: # pragma: no cover
|
|
|
16
17
|
"in the current environment, \n"
|
|
17
18
|
"which conflicts with 'ag2' / 'pyautogen'.\n"
|
|
18
19
|
"Please uninstall 'autogen-agentchat': \n"
|
|
19
|
-
f"{sys.executable} -m pip uninstall -y autogen-agentchat \n"
|
|
20
|
+
f"{sys.executable} -m pip uninstall -y autogen-agentchat" + "\n"
|
|
20
21
|
"And install 'pyautogen' (and/or 'waldiez') again: \n"
|
|
21
22
|
f"{sys.executable} -m pip install --force pyautogen waldiez"
|
|
22
23
|
)
|
waldiez/exporter.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""
|
|
3
4
|
The role of the exporter is to export the model's data
|
|
4
5
|
to an autogen's flow with one or more chats.
|
|
5
6
|
|
|
@@ -8,8 +9,8 @@ to trigger the chat(s).
|
|
|
8
9
|
If additional tools/skills are used,
|
|
9
10
|
they are exported as their `skill_name` in the same directory with
|
|
10
11
|
the `flow.py` file. So the `flow.py` could have entries like:
|
|
11
|
-
`form {skill1_name} import {skill1_name}`
|
|
12
|
-
`form {skill2_name} import {skill2_name}`
|
|
12
|
+
`form {flow_name}_{skill1_name} import {skill1_name}`
|
|
13
|
+
`form {flow_name}_{skill2_name} import {skill2_name}`
|
|
13
14
|
"""
|
|
14
15
|
|
|
15
16
|
# pylint: disable=inconsistent-quotes
|
|
@@ -19,16 +20,10 @@ import shutil
|
|
|
19
20
|
import subprocess
|
|
20
21
|
import sys
|
|
21
22
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
23
|
+
from typing import List, Optional, Union
|
|
23
24
|
|
|
24
|
-
from .exporting import
|
|
25
|
-
from .models import
|
|
26
|
-
Waldiez,
|
|
27
|
-
WaldiezAgent,
|
|
28
|
-
WaldiezChat,
|
|
29
|
-
WaldiezModel,
|
|
30
|
-
WaldiezSkill,
|
|
31
|
-
)
|
|
25
|
+
from .exporting import FlowExporter
|
|
26
|
+
from .models import Waldiez
|
|
32
27
|
|
|
33
28
|
|
|
34
29
|
class WaldiezExporter:
|
|
@@ -38,15 +33,6 @@ class WaldiezExporter:
|
|
|
38
33
|
waldiez (Waldiez): The Waldiez instance.
|
|
39
34
|
"""
|
|
40
35
|
|
|
41
|
-
_agent_names: Dict[str, str]
|
|
42
|
-
_model_names: Dict[str, str]
|
|
43
|
-
_skill_names: Dict[str, str]
|
|
44
|
-
_chat_names: Dict[str, str]
|
|
45
|
-
_chats: List[WaldiezChat]
|
|
46
|
-
_skills: List[WaldiezSkill]
|
|
47
|
-
_models: List[WaldiezModel]
|
|
48
|
-
_agents: List[WaldiezAgent]
|
|
49
|
-
|
|
50
36
|
def __init__(self, waldiez: Waldiez) -> None:
|
|
51
37
|
"""Initialize the Waldiez exporter.
|
|
52
38
|
|
|
@@ -54,7 +40,7 @@ class WaldiezExporter:
|
|
|
54
40
|
waldiez (Waldiez): The Waldiez instance.
|
|
55
41
|
"""
|
|
56
42
|
self.waldiez = waldiez
|
|
57
|
-
self._initialize()
|
|
43
|
+
# self._initialize()
|
|
58
44
|
|
|
59
45
|
@classmethod
|
|
60
46
|
def load(cls, file_path: Path) -> "WaldiezExporter":
|
|
@@ -73,56 +59,6 @@ class WaldiezExporter:
|
|
|
73
59
|
waldiez = Waldiez.load(file_path)
|
|
74
60
|
return cls(waldiez)
|
|
75
61
|
|
|
76
|
-
def _initialize(
|
|
77
|
-
self,
|
|
78
|
-
) -> None:
|
|
79
|
-
"""Get all the names in the flow.
|
|
80
|
-
|
|
81
|
-
We need to make sure that no duplicate names are used,
|
|
82
|
-
and that the names can be used as python variables.
|
|
83
|
-
"""
|
|
84
|
-
all_names: Dict[str, str] = {}
|
|
85
|
-
agent_names: Dict[str, str] = {}
|
|
86
|
-
model_names: Dict[str, str] = {}
|
|
87
|
-
skill_names: Dict[str, str] = {}
|
|
88
|
-
chat_names: Dict[str, str] = {}
|
|
89
|
-
chats: List[WaldiezChat] = []
|
|
90
|
-
skills: List[WaldiezSkill] = []
|
|
91
|
-
models: List[WaldiezModel] = []
|
|
92
|
-
agents: List[WaldiezAgent] = []
|
|
93
|
-
for agent in self.waldiez.agents:
|
|
94
|
-
all_names = get_valid_instance_name(
|
|
95
|
-
(agent.id, agent.name), all_names, prefix="wa"
|
|
96
|
-
)
|
|
97
|
-
agent_names[agent.id] = all_names[agent.id]
|
|
98
|
-
agents.append(agent)
|
|
99
|
-
for model in self.waldiez.models:
|
|
100
|
-
all_names = get_valid_instance_name(
|
|
101
|
-
(model.id, model.name), all_names, prefix="wm"
|
|
102
|
-
)
|
|
103
|
-
model_names[model.id] = all_names[model.id]
|
|
104
|
-
models.append(model)
|
|
105
|
-
for skill in self.waldiez.skills:
|
|
106
|
-
all_names = get_valid_instance_name(
|
|
107
|
-
(skill.id, skill.name), all_names, prefix="ws"
|
|
108
|
-
)
|
|
109
|
-
skill_names[skill.id] = all_names[skill.id]
|
|
110
|
-
skills.append(skill)
|
|
111
|
-
for chat in self.waldiez.flow.data.chats:
|
|
112
|
-
all_names = get_valid_instance_name(
|
|
113
|
-
(chat.id, chat.name), all_names, prefix="wc"
|
|
114
|
-
)
|
|
115
|
-
chat_names[chat.id] = all_names[chat.id]
|
|
116
|
-
chats.append(chat)
|
|
117
|
-
self._agent_names = agent_names
|
|
118
|
-
self._model_names = model_names
|
|
119
|
-
self._skill_names = skill_names
|
|
120
|
-
self._chat_names = chat_names
|
|
121
|
-
self._chats = chats
|
|
122
|
-
self._skills = skills
|
|
123
|
-
self._models = models
|
|
124
|
-
self._agents = agents
|
|
125
|
-
|
|
126
62
|
def export(self, path: Union[str, Path], force: bool = False) -> None:
|
|
127
63
|
"""Export the Waldiez instance.
|
|
128
64
|
|
|
@@ -175,25 +111,17 @@ class WaldiezExporter:
|
|
|
175
111
|
RuntimeError
|
|
176
112
|
If the notebook could not be generated.
|
|
177
113
|
"""
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
requirements = " ".join(self.waldiez.requirements)
|
|
182
|
-
if requirements:
|
|
183
|
-
content += (
|
|
184
|
-
f"# !{{sys.executable}} -m pip install -q {requirements}" + "\n"
|
|
185
|
-
)
|
|
186
|
-
content += export_flow(
|
|
114
|
+
# we first create a .py file with the content
|
|
115
|
+
# and then convert it to a notebook using jupytext
|
|
116
|
+
exporter = FlowExporter(
|
|
187
117
|
waldiez=self.waldiez,
|
|
188
|
-
agents=(self._agents, self._agent_names),
|
|
189
|
-
chats=(self._chats, self._chat_names),
|
|
190
|
-
models=(self._models, self._model_names),
|
|
191
|
-
skills=(self._skills, self._skill_names),
|
|
192
118
|
output_dir=path.parent,
|
|
193
|
-
|
|
119
|
+
for_notebook=True,
|
|
194
120
|
)
|
|
195
|
-
|
|
196
|
-
|
|
121
|
+
output = exporter.export()
|
|
122
|
+
content = output["content"]
|
|
123
|
+
if not content:
|
|
124
|
+
raise RuntimeError("Could not generate notebook")
|
|
197
125
|
py_path = path.with_suffix(".tmp.py")
|
|
198
126
|
with open(py_path, "w", encoding="utf-8", newline="\n") as f:
|
|
199
127
|
f.write(content)
|
|
@@ -226,26 +154,21 @@ class WaldiezExporter:
|
|
|
226
154
|
----------
|
|
227
155
|
path : Path
|
|
228
156
|
The path to export to.
|
|
157
|
+
|
|
158
|
+
Raises
|
|
159
|
+
------
|
|
160
|
+
RuntimeError
|
|
161
|
+
If the python script could not be generated.
|
|
229
162
|
"""
|
|
230
|
-
|
|
231
|
-
content += f'"""{self.waldiez.name}\n\n'
|
|
232
|
-
content += f"{self.waldiez.description}\n\n"
|
|
233
|
-
content += f"Tags: {', '.join(self.waldiez.tags)}\n\n"
|
|
234
|
-
content += f"Requirements: {', '.join(self.waldiez.requirements)}\n\n"
|
|
235
|
-
content += '"""\n\n'
|
|
236
|
-
content += "# cspell: disable\n"
|
|
237
|
-
content += "# flake8: noqa\n\n"
|
|
238
|
-
content += export_flow(
|
|
163
|
+
exporter = FlowExporter(
|
|
239
164
|
waldiez=self.waldiez,
|
|
240
|
-
agents=(self._agents, self._agent_names),
|
|
241
|
-
chats=(self._chats, self._chat_names),
|
|
242
|
-
models=(self._models, self._model_names),
|
|
243
|
-
skills=(self._skills, self._skill_names),
|
|
244
165
|
output_dir=path.parent,
|
|
245
|
-
|
|
166
|
+
for_notebook=False,
|
|
246
167
|
)
|
|
247
|
-
|
|
248
|
-
content
|
|
168
|
+
output = exporter.export()
|
|
169
|
+
content = output["content"]
|
|
170
|
+
if not content:
|
|
171
|
+
raise RuntimeError("Could not generate python script")
|
|
249
172
|
with open(path, "w", encoding="utf-8", newline="\n") as file:
|
|
250
173
|
file.write(content)
|
|
251
174
|
|
waldiez/exporting/__init__.py
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
1
3
|
"""Tools for exporting agents, models, skills and chats to strings."""
|
|
2
4
|
|
|
3
|
-
from .flow import
|
|
4
|
-
from .models import
|
|
5
|
-
from .skills import
|
|
6
|
-
from .utils import comment, get_valid_instance_name
|
|
5
|
+
from .flow import FlowExporter
|
|
6
|
+
from .models import ModelsExporter
|
|
7
|
+
from .skills import SkillsExporter
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"export_models",
|
|
13
|
-
"export_skills",
|
|
10
|
+
"FlowExporter",
|
|
11
|
+
"ModelsExporter",
|
|
12
|
+
"SkillsExporter",
|
|
14
13
|
]
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pylint: disable=too-many-return-statements,too-many-instance-attributes
|
|
4
|
+
"""Export agents."""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Callable, Dict, List, Optional, Tuple, Union
|
|
8
|
+
|
|
9
|
+
from waldiez.models import WaldiezAgent, WaldiezChat
|
|
10
|
+
|
|
11
|
+
from ..base import (
|
|
12
|
+
AgentPosition,
|
|
13
|
+
AgentPositions,
|
|
14
|
+
BaseExporter,
|
|
15
|
+
ExporterMixin,
|
|
16
|
+
ExporterReturnType,
|
|
17
|
+
ExportPosition,
|
|
18
|
+
ImportPosition,
|
|
19
|
+
)
|
|
20
|
+
from .utils import (
|
|
21
|
+
get_agent_class_name,
|
|
22
|
+
get_agent_code_execution_config,
|
|
23
|
+
get_agent_imports,
|
|
24
|
+
get_group_manager_extras,
|
|
25
|
+
get_is_termination_message,
|
|
26
|
+
get_rag_user_extras,
|
|
27
|
+
get_swarm_extras,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentExporter(BaseExporter, ExporterMixin):
|
|
32
|
+
"""Agents exporter."""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
agent: WaldiezAgent,
|
|
37
|
+
agent_names: Dict[str, str],
|
|
38
|
+
model_names: Dict[str, str],
|
|
39
|
+
skill_names: Dict[str, str],
|
|
40
|
+
chats: Tuple[List[WaldiezChat], Dict[str, str]],
|
|
41
|
+
is_async: bool,
|
|
42
|
+
group_chat_members: List[WaldiezAgent],
|
|
43
|
+
for_notebook: bool,
|
|
44
|
+
arguments_resolver: Callable[[WaldiezAgent], List[str]],
|
|
45
|
+
output_dir: Optional[Union[str, Path]] = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Initialize the agents exporter.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
agent : WaldiezAgent
|
|
52
|
+
The agent to export.
|
|
53
|
+
agent_names : Dict[str, str]
|
|
54
|
+
The agent ids to names mapping.
|
|
55
|
+
model_names : Dict[str, str]
|
|
56
|
+
The model ids to names mapping.
|
|
57
|
+
skill_names : Dict[str, str]
|
|
58
|
+
The skill ids to names mapping.
|
|
59
|
+
all_chats : List[WaldiezChat]
|
|
60
|
+
All the chats in the flow.
|
|
61
|
+
chat_names : Dict[str, str]
|
|
62
|
+
The chat ids to names mapping.
|
|
63
|
+
is_async : bool
|
|
64
|
+
Whether the whole flow is async.
|
|
65
|
+
for_notebook : bool
|
|
66
|
+
Whether the exporter is for a notebook.
|
|
67
|
+
output_dir : Optional[Union[str, Path]], optional
|
|
68
|
+
The output directory, by default None
|
|
69
|
+
"""
|
|
70
|
+
self.for_notebook = for_notebook
|
|
71
|
+
self.agent = agent
|
|
72
|
+
self.agent_names = agent_names
|
|
73
|
+
if output_dir is not None and not isinstance(output_dir, Path):
|
|
74
|
+
output_dir = Path(output_dir)
|
|
75
|
+
self.output_dir = output_dir
|
|
76
|
+
self.model_names = model_names
|
|
77
|
+
self.skill_names = skill_names
|
|
78
|
+
self.arguments_resolver = arguments_resolver
|
|
79
|
+
self.group_chat_members = group_chat_members
|
|
80
|
+
self.chats = chats
|
|
81
|
+
self.is_async = is_async
|
|
82
|
+
self._agent_name = agent_names[agent.id]
|
|
83
|
+
self._agent_class = get_agent_class_name(self.agent)
|
|
84
|
+
# content, argument, import
|
|
85
|
+
self._code_execution = get_agent_code_execution_config(
|
|
86
|
+
agent=self.agent,
|
|
87
|
+
agent_name=self._agent_name,
|
|
88
|
+
skill_names=self.skill_names,
|
|
89
|
+
)
|
|
90
|
+
# before_rag, retrieve_arg, rag_imports
|
|
91
|
+
self._rag = get_rag_user_extras(
|
|
92
|
+
agent=self.agent,
|
|
93
|
+
agent_name=self._agent_name,
|
|
94
|
+
model_names=self.model_names,
|
|
95
|
+
path_resolver=self.path_resolver,
|
|
96
|
+
serializer=self.serializer,
|
|
97
|
+
)
|
|
98
|
+
# before_manager, group_chat_arg
|
|
99
|
+
self._group_chat = get_group_manager_extras(
|
|
100
|
+
agent=self.agent,
|
|
101
|
+
agent_names=self.agent_names,
|
|
102
|
+
group_chat_members=self.group_chat_members,
|
|
103
|
+
serializer=self.serializer,
|
|
104
|
+
)
|
|
105
|
+
# before_agent, extra args, handoff_registrations
|
|
106
|
+
self._swarm = get_swarm_extras(
|
|
107
|
+
agent=self.agent,
|
|
108
|
+
agent_names=self.agent_names,
|
|
109
|
+
skill_names=self.skill_names,
|
|
110
|
+
chats=self.chats,
|
|
111
|
+
is_async=self.is_async,
|
|
112
|
+
serializer=self.serializer,
|
|
113
|
+
string_escape=self.string_escape,
|
|
114
|
+
)
|
|
115
|
+
# before_agent, termination_arg
|
|
116
|
+
self._termination = get_is_termination_message(
|
|
117
|
+
agent=self.agent, agent_name=self._agent_name
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def get_imports(self) -> Optional[List[Tuple[str, ImportPosition]]]:
|
|
121
|
+
"""Get the imports.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
Optional[Tuple[str, ImportPosition]]
|
|
126
|
+
The imports.
|
|
127
|
+
"""
|
|
128
|
+
position = ImportPosition.THIRD_PARTY
|
|
129
|
+
# default imports based on the agent class.
|
|
130
|
+
agent_imports = get_agent_imports(self._agent_class)
|
|
131
|
+
# if code execution is enabled, update the imports.
|
|
132
|
+
if self._code_execution[2]:
|
|
133
|
+
agent_imports.add(self._code_execution[2])
|
|
134
|
+
# if RAG is enabled, update the imports.
|
|
135
|
+
if self._rag[2]:
|
|
136
|
+
agent_imports.update(self._rag[2])
|
|
137
|
+
# if the agent has skills, add the register_function import.
|
|
138
|
+
if self.agent.data.skills:
|
|
139
|
+
agent_imports.add("from autogen import register_function")
|
|
140
|
+
return [(import_string, position) for import_string in agent_imports]
|
|
141
|
+
|
|
142
|
+
def get_system_message_arg(self) -> str:
|
|
143
|
+
"""Get the system message argument.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
str
|
|
148
|
+
The system message argument.
|
|
149
|
+
"""
|
|
150
|
+
if not self.agent.data.system_message:
|
|
151
|
+
return ""
|
|
152
|
+
system_message = self.string_escape(self.agent.data.system_message)
|
|
153
|
+
return ",\n system_message=" + f'"{system_message}"'
|
|
154
|
+
|
|
155
|
+
def get_before_export(
|
|
156
|
+
self,
|
|
157
|
+
) -> Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]:
|
|
158
|
+
"""Generate the content before the main export.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]
|
|
163
|
+
The exported content before the main export and its position.
|
|
164
|
+
"""
|
|
165
|
+
before_agent_string = ""
|
|
166
|
+
if self._code_execution[0] and self._code_execution[2]:
|
|
167
|
+
before_agent_string += self._code_execution[0]
|
|
168
|
+
if self._termination[1]:
|
|
169
|
+
before_agent_string += self._termination[1]
|
|
170
|
+
if self._group_chat[0]:
|
|
171
|
+
before_agent_string += self._group_chat[0]
|
|
172
|
+
if self._rag[0]:
|
|
173
|
+
before_agent_string += self._rag[0]
|
|
174
|
+
if self._swarm[0]:
|
|
175
|
+
before_agent_string += self._swarm[0]
|
|
176
|
+
if before_agent_string:
|
|
177
|
+
return [
|
|
178
|
+
(
|
|
179
|
+
before_agent_string,
|
|
180
|
+
AgentPosition(self.agent, AgentPositions.BEFORE),
|
|
181
|
+
)
|
|
182
|
+
]
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
def get_after_export(
|
|
186
|
+
self,
|
|
187
|
+
) -> Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]:
|
|
188
|
+
"""Generate the content after the main export.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
Optional[List[Tuple[str, Union[ExportPosition, AgentPosition]]]]
|
|
193
|
+
The exported content after the main export and its position.
|
|
194
|
+
"""
|
|
195
|
+
after_agent_string = ""
|
|
196
|
+
if self._swarm[2]:
|
|
197
|
+
after_agent_string += self._swarm[2]
|
|
198
|
+
if after_agent_string:
|
|
199
|
+
return [
|
|
200
|
+
(
|
|
201
|
+
after_agent_string,
|
|
202
|
+
AgentPosition(self.agent, AgentPositions.AFTER_ALL),
|
|
203
|
+
)
|
|
204
|
+
]
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
def generate(self) -> Optional[str]:
|
|
208
|
+
"""Generate the exported agent.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
Optional[str]
|
|
213
|
+
The exported agent.
|
|
214
|
+
"""
|
|
215
|
+
agent = self.agent
|
|
216
|
+
agent_name = self._agent_name
|
|
217
|
+
agent_class = self._agent_class
|
|
218
|
+
retrieve_arg = self._rag[1]
|
|
219
|
+
group_chat_arg = self._group_chat[1]
|
|
220
|
+
is_termination = self._termination[0]
|
|
221
|
+
code_execution_arg = self._code_execution[1]
|
|
222
|
+
system_message_arg = self.get_system_message_arg()
|
|
223
|
+
default_auto_reply: str = "None"
|
|
224
|
+
if agent.data.agent_default_auto_reply:
|
|
225
|
+
default_auto_reply = (
|
|
226
|
+
f'"{self.string_escape(agent.data.agent_default_auto_reply)}"'
|
|
227
|
+
)
|
|
228
|
+
agent_str = f"""{agent_name} = {agent_class}(
|
|
229
|
+
name="{agent_name}",
|
|
230
|
+
description="{agent.description}"{system_message_arg},
|
|
231
|
+
human_input_mode="{agent.data.human_input_mode}",
|
|
232
|
+
max_consecutive_auto_reply={agent.data.max_consecutive_auto_reply},
|
|
233
|
+
default_auto_reply={default_auto_reply},
|
|
234
|
+
code_execution_config={code_execution_arg},
|
|
235
|
+
is_termination_msg={is_termination},{group_chat_arg}{retrieve_arg}
|
|
236
|
+
"""
|
|
237
|
+
if self._swarm[1]:
|
|
238
|
+
agent_str += self._swarm[1]
|
|
239
|
+
# e.g. llm_config=...
|
|
240
|
+
other_args = self.arguments_resolver(agent)
|
|
241
|
+
if other_args:
|
|
242
|
+
agent_str += ",\n".join(other_args)
|
|
243
|
+
if not agent_str.endswith("\n"):
|
|
244
|
+
agent_str += "\n"
|
|
245
|
+
agent_str += ")"
|
|
246
|
+
return agent_str
|
|
247
|
+
|
|
248
|
+
def export(self) -> ExporterReturnType:
|
|
249
|
+
"""Export the agent.
|
|
250
|
+
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
ExporterReturnType
|
|
254
|
+
The exported agent.
|
|
255
|
+
"""
|
|
256
|
+
agent_string = self.generate() or ""
|
|
257
|
+
is_group_manager = self.agent.agent_type == "group_manager"
|
|
258
|
+
after_export = self.get_after_export() or []
|
|
259
|
+
content: Optional[str] = agent_string
|
|
260
|
+
if is_group_manager and agent_string:
|
|
261
|
+
content = None
|
|
262
|
+
# make sure the group manager is defined
|
|
263
|
+
# after the rest of the agents.
|
|
264
|
+
# to avoid issues with (for example):
|
|
265
|
+
# 'group_manager_group_chat = GroupChat(
|
|
266
|
+
# # assistant and rag_user should be defined first
|
|
267
|
+
# ' agents=[assistant, rag_user],
|
|
268
|
+
# ' enable_clear_history=True,
|
|
269
|
+
# ...
|
|
270
|
+
after_export.append(
|
|
271
|
+
(agent_string, AgentPosition(None, AgentPositions.AFTER_ALL, 0))
|
|
272
|
+
)
|
|
273
|
+
return {
|
|
274
|
+
"content": content,
|
|
275
|
+
"imports": self.get_imports(),
|
|
276
|
+
"environment_variables": [],
|
|
277
|
+
"before_export": self.get_before_export(),
|
|
278
|
+
"after_export": after_export,
|
|
279
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Utility functions for generating agent related strings."""
|
|
4
|
+
|
|
5
|
+
from .agent_class_name import get_agent_class_name
|
|
6
|
+
from .agent_imports import get_agent_imports
|
|
7
|
+
from .code_execution import get_agent_code_execution_config
|
|
8
|
+
from .group_manager import get_group_manager_extras
|
|
9
|
+
from .rag_user import get_rag_user_extras
|
|
10
|
+
from .swarm_agent import get_swarm_extras
|
|
11
|
+
from .teachability import get_agent_teachability_string
|
|
12
|
+
from .termination_message import get_is_termination_message
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"get_agent_class_name",
|
|
16
|
+
"get_agent_imports",
|
|
17
|
+
"get_agent_code_execution_config",
|
|
18
|
+
"get_agent_teachability_string",
|
|
19
|
+
"get_group_manager_extras",
|
|
20
|
+
"get_is_termination_message",
|
|
21
|
+
"get_rag_user_extras",
|
|
22
|
+
"get_swarm_extras",
|
|
23
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Get the agent class name."""
|
|
4
|
+
|
|
5
|
+
from waldiez.models import WaldiezAgent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# pylint: disable=too-many-return-statements
|
|
9
|
+
def get_agent_class_name(agent: WaldiezAgent) -> str:
|
|
10
|
+
"""Get the agent class name.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
agent : WaldiezAgent
|
|
15
|
+
The agent.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
str
|
|
20
|
+
The agent class name.
|
|
21
|
+
"""
|
|
22
|
+
if agent.data.is_multimodal:
|
|
23
|
+
return "MultimodalConversableAgent"
|
|
24
|
+
if agent.agent_type == "assistant":
|
|
25
|
+
return "AssistantAgent"
|
|
26
|
+
if agent.agent_type == "user":
|
|
27
|
+
return "UserProxyAgent"
|
|
28
|
+
if agent.agent_type == "manager":
|
|
29
|
+
return "GroupChatManager"
|
|
30
|
+
if agent.agent_type == "rag_user":
|
|
31
|
+
return "RetrieveUserProxyAgent"
|
|
32
|
+
if agent.agent_type == "swarm":
|
|
33
|
+
return "SwarmAgent"
|
|
34
|
+
return "ConversableAgent" # pragma: no cover
|