waldiez 0.4.6__py3-none-any.whl → 0.4.8__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 +5 -5
- waldiez/_version.py +1 -1
- waldiez/cli.py +112 -73
- waldiez/exporter.py +61 -19
- waldiez/exporting/__init__.py +25 -6
- waldiez/exporting/agent/__init__.py +7 -3
- waldiez/exporting/agent/code_execution.py +114 -0
- waldiez/exporting/agent/exporter.py +354 -0
- waldiez/exporting/agent/extras/__init__.py +15 -0
- waldiez/exporting/agent/extras/captain_agent_extras.py +315 -0
- waldiez/exporting/agent/extras/group/target.py +178 -0
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +500 -0
- waldiez/exporting/agent/extras/group_member_extras.py +181 -0
- waldiez/exporting/agent/extras/handoffs/__init__.py +19 -0
- waldiez/exporting/agent/extras/handoffs/after_work.py +78 -0
- waldiez/exporting/agent/extras/handoffs/available.py +74 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +158 -0
- waldiez/exporting/agent/extras/handoffs/handoff.py +171 -0
- waldiez/exporting/agent/extras/handoffs/target.py +189 -0
- waldiez/exporting/agent/extras/rag/__init__.py +10 -0
- waldiez/exporting/agent/{utils/rag_user/chroma_utils.py → extras/rag/chroma_extras.py} +16 -15
- waldiez/exporting/agent/{utils/rag_user/mongo_utils.py → extras/rag/mongo_extras.py} +10 -10
- waldiez/exporting/agent/{utils/rag_user/pgvector_utils.py → extras/rag/pgvector_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/qdrant_utils.py → extras/rag/qdrant_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/vector_db.py → extras/rag/vector_db_extras.py} +59 -46
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +245 -0
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +88 -0
- waldiez/exporting/agent/factory.py +95 -0
- waldiez/exporting/agent/processor.py +150 -0
- waldiez/exporting/agent/system_message.py +36 -0
- waldiez/exporting/agent/termination.py +50 -0
- waldiez/exporting/chats/__init__.py +7 -3
- waldiez/exporting/chats/exporter.py +97 -0
- waldiez/exporting/chats/factory.py +65 -0
- waldiez/exporting/chats/processor.py +226 -0
- waldiez/exporting/chats/utils/__init__.py +6 -5
- waldiez/exporting/chats/utils/common.py +11 -45
- waldiez/exporting/chats/utils/group.py +55 -0
- waldiez/exporting/chats/utils/nested.py +37 -52
- waldiez/exporting/chats/utils/sequential.py +72 -61
- waldiez/exporting/chats/utils/{single_chat.py → single.py} +48 -50
- waldiez/exporting/core/__init__.py +196 -0
- waldiez/exporting/core/constants.py +17 -0
- waldiez/exporting/core/content.py +69 -0
- waldiez/exporting/core/context.py +244 -0
- waldiez/exporting/core/enums.py +89 -0
- waldiez/exporting/core/errors.py +19 -0
- waldiez/exporting/core/exporter.py +390 -0
- waldiez/exporting/core/exporters.py +67 -0
- waldiez/exporting/core/extras/__init__.py +39 -0
- waldiez/exporting/core/extras/agent_extras/__init__.py +27 -0
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +57 -0
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +102 -0
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +53 -0
- waldiez/exporting/core/extras/agent_extras/reasoning_extras.py +68 -0
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +263 -0
- waldiez/exporting/core/extras/base.py +241 -0
- waldiez/exporting/core/extras/chat_extras.py +118 -0
- waldiez/exporting/core/extras/flow_extras.py +70 -0
- waldiez/exporting/core/extras/model_extras.py +73 -0
- waldiez/exporting/core/extras/path_resolver.py +93 -0
- waldiez/exporting/core/extras/serializer.py +138 -0
- waldiez/exporting/core/extras/tool_extras.py +82 -0
- waldiez/exporting/core/protocols.py +259 -0
- waldiez/exporting/core/result.py +705 -0
- waldiez/exporting/core/types.py +329 -0
- waldiez/exporting/core/utils/__init__.py +11 -0
- waldiez/exporting/core/utils/comment.py +33 -0
- waldiez/exporting/core/utils/llm_config.py +117 -0
- waldiez/exporting/core/validation.py +96 -0
- waldiez/exporting/flow/__init__.py +6 -2
- waldiez/exporting/flow/execution_generator.py +193 -0
- waldiez/exporting/flow/exporter.py +107 -0
- waldiez/exporting/flow/factory.py +94 -0
- waldiez/exporting/flow/file_generator.py +214 -0
- waldiez/exporting/flow/merger.py +387 -0
- waldiez/exporting/flow/orchestrator.py +411 -0
- waldiez/exporting/flow/utils/__init__.py +9 -36
- waldiez/exporting/flow/utils/common.py +206 -0
- waldiez/exporting/flow/utils/importing.py +373 -0
- waldiez/exporting/flow/utils/linting.py +200 -0
- waldiez/exporting/flow/utils/{logging_utils.py → logging.py} +23 -9
- waldiez/exporting/models/__init__.py +3 -1
- waldiez/exporting/models/exporter.py +233 -0
- waldiez/exporting/models/factory.py +66 -0
- waldiez/exporting/models/processor.py +139 -0
- waldiez/exporting/tools/__init__.py +11 -0
- waldiez/exporting/tools/exporter.py +207 -0
- waldiez/exporting/tools/factory.py +57 -0
- waldiez/exporting/tools/processor.py +248 -0
- waldiez/exporting/tools/registration.py +133 -0
- waldiez/io/__init__.py +128 -0
- waldiez/io/_ws.py +199 -0
- waldiez/io/models/__init__.py +60 -0
- waldiez/io/models/base.py +66 -0
- waldiez/io/models/constants.py +78 -0
- waldiez/io/models/content/__init__.py +23 -0
- waldiez/io/models/content/audio.py +43 -0
- waldiez/io/models/content/base.py +45 -0
- waldiez/io/models/content/file.py +43 -0
- waldiez/io/models/content/image.py +96 -0
- waldiez/io/models/content/text.py +37 -0
- waldiez/io/models/content/video.py +43 -0
- waldiez/io/models/user_input.py +269 -0
- waldiez/io/models/user_response.py +215 -0
- waldiez/io/mqtt.py +681 -0
- waldiez/io/redis.py +782 -0
- waldiez/io/structured.py +419 -0
- waldiez/io/utils.py +184 -0
- waldiez/io/ws.py +298 -0
- waldiez/logger.py +481 -0
- waldiez/models/__init__.py +108 -51
- waldiez/models/agents/__init__.py +34 -70
- waldiez/models/agents/agent/__init__.py +10 -4
- waldiez/models/agents/agent/agent.py +466 -65
- waldiez/models/agents/agent/agent_data.py +119 -47
- waldiez/models/agents/agent/agent_type.py +13 -2
- waldiez/models/agents/agent/code_execution.py +12 -12
- waldiez/models/agents/agent/human_input_mode.py +8 -0
- waldiez/models/agents/agent/{linked_skill.py → linked_tool.py} +7 -7
- waldiez/models/agents/agent/nested_chat.py +35 -7
- waldiez/models/agents/agent/termination_message.py +30 -22
- waldiez/models/agents/{swarm_agent → agent}/update_system_message.py +22 -22
- waldiez/models/agents/agents.py +58 -63
- waldiez/models/agents/assistant/assistant.py +4 -4
- waldiez/models/agents/assistant/assistant_data.py +13 -1
- waldiez/models/agents/{captain_agent → captain}/captain_agent.py +5 -5
- waldiez/models/agents/{captain_agent → captain}/captain_agent_data.py +5 -5
- waldiez/models/agents/extra_requirements.py +11 -16
- waldiez/models/agents/group_manager/group_manager.py +103 -13
- waldiez/models/agents/group_manager/group_manager_data.py +36 -14
- waldiez/models/agents/group_manager/speakers.py +77 -24
- waldiez/models/agents/{rag_user → rag_user_proxy}/__init__.py +16 -16
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +64 -0
- waldiez/models/agents/{rag_user/rag_user_data.py → rag_user_proxy/rag_user_proxy_data.py} +6 -5
- waldiez/models/agents/{rag_user → rag_user_proxy}/retrieve_config.py +182 -114
- waldiez/models/agents/{rag_user → rag_user_proxy}/vector_db_config.py +13 -13
- waldiez/models/agents/reasoning/reasoning_agent.py +6 -6
- waldiez/models/agents/reasoning/reasoning_agent_data.py +110 -63
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +38 -10
- waldiez/models/agents/user_proxy/user_proxy.py +11 -7
- waldiez/models/agents/user_proxy/user_proxy_data.py +2 -2
- waldiez/models/chat/__init__.py +2 -1
- waldiez/models/chat/chat.py +166 -87
- waldiez/models/chat/chat_data.py +99 -136
- waldiez/models/chat/chat_message.py +33 -23
- waldiez/models/chat/chat_nested.py +31 -30
- waldiez/models/chat/chat_summary.py +10 -8
- waldiez/models/common/__init__.py +52 -2
- waldiez/models/common/ag2_version.py +1 -1
- waldiez/models/common/base.py +38 -7
- waldiez/models/common/dict_utils.py +42 -17
- waldiez/models/common/handoff.py +459 -0
- waldiez/models/common/id_generator.py +19 -0
- waldiez/models/common/method_utils.py +130 -68
- waldiez/{exporting/base/utils → models/common}/naming.py +38 -61
- waldiez/models/common/waldiez_version.py +37 -0
- waldiez/models/flow/__init__.py +9 -2
- waldiez/models/flow/connection.py +18 -0
- waldiez/models/flow/flow.py +311 -215
- waldiez/models/flow/flow_data.py +207 -40
- waldiez/models/flow/info.py +85 -0
- waldiez/models/flow/naming.py +131 -0
- waldiez/models/model/__init__.py +7 -1
- waldiez/models/model/extra_requirements.py +3 -12
- waldiez/models/model/model.py +76 -21
- waldiez/models/model/model_data.py +108 -20
- waldiez/models/tool/__init__.py +16 -0
- waldiez/models/tool/extra_requirements.py +36 -0
- waldiez/models/{skill/skill.py → tool/tool.py} +88 -88
- waldiez/models/tool/tool_data.py +51 -0
- waldiez/models/tool/tool_type.py +8 -0
- waldiez/models/waldiez.py +97 -80
- waldiez/runner.py +114 -49
- waldiez/running/__init__.py +1 -1
- waldiez/running/environment.py +49 -68
- waldiez/running/gen_seq_diagram.py +16 -14
- waldiez/running/running.py +53 -34
- waldiez/utils/__init__.py +0 -4
- waldiez/utils/cli_extras/jupyter.py +5 -3
- waldiez/utils/cli_extras/runner.py +6 -4
- waldiez/utils/cli_extras/studio.py +6 -4
- waldiez/utils/conflict_checker.py +15 -9
- waldiez/utils/flaml_warnings.py +5 -5
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/METADATA +235 -91
- waldiez-0.4.8.dist-info/RECORD +200 -0
- waldiez/exporting/agent/agent_exporter.py +0 -297
- waldiez/exporting/agent/utils/__init__.py +0 -23
- waldiez/exporting/agent/utils/captain_agent.py +0 -263
- waldiez/exporting/agent/utils/code_execution.py +0 -65
- waldiez/exporting/agent/utils/group_manager.py +0 -220
- waldiez/exporting/agent/utils/rag_user/__init__.py +0 -7
- waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -209
- waldiez/exporting/agent/utils/reasoning.py +0 -36
- waldiez/exporting/agent/utils/swarm_agent.py +0 -469
- waldiez/exporting/agent/utils/teachability.py +0 -41
- waldiez/exporting/agent/utils/termination_message.py +0 -44
- waldiez/exporting/base/__init__.py +0 -25
- waldiez/exporting/base/agent_position.py +0 -75
- waldiez/exporting/base/base_exporter.py +0 -118
- waldiez/exporting/base/export_position.py +0 -48
- waldiez/exporting/base/import_position.py +0 -23
- waldiez/exporting/base/mixin.py +0 -137
- waldiez/exporting/base/utils/__init__.py +0 -18
- waldiez/exporting/base/utils/comments.py +0 -96
- waldiez/exporting/base/utils/path_check.py +0 -68
- waldiez/exporting/base/utils/to_string.py +0 -84
- waldiez/exporting/chats/chats_exporter.py +0 -240
- waldiez/exporting/chats/utils/swarm.py +0 -210
- waldiez/exporting/flow/flow_exporter.py +0 -528
- waldiez/exporting/flow/utils/agent_utils.py +0 -204
- waldiez/exporting/flow/utils/chat_utils.py +0 -71
- waldiez/exporting/flow/utils/def_main.py +0 -77
- waldiez/exporting/flow/utils/flow_content.py +0 -202
- waldiez/exporting/flow/utils/flow_names.py +0 -116
- waldiez/exporting/flow/utils/importing_utils.py +0 -227
- waldiez/exporting/models/models_exporter.py +0 -199
- waldiez/exporting/models/utils.py +0 -174
- waldiez/exporting/skills/__init__.py +0 -9
- waldiez/exporting/skills/skills_exporter.py +0 -176
- waldiez/exporting/skills/utils.py +0 -369
- waldiez/models/agents/agent/teachability.py +0 -70
- waldiez/models/agents/rag_user/rag_user.py +0 -60
- waldiez/models/agents/swarm_agent/__init__.py +0 -50
- waldiez/models/agents/swarm_agent/after_work.py +0 -179
- waldiez/models/agents/swarm_agent/on_condition.py +0 -105
- waldiez/models/agents/swarm_agent/on_condition_available.py +0 -142
- waldiez/models/agents/swarm_agent/on_condition_target.py +0 -40
- waldiez/models/agents/swarm_agent/swarm_agent.py +0 -107
- waldiez/models/agents/swarm_agent/swarm_agent_data.py +0 -124
- waldiez/models/flow/utils.py +0 -232
- waldiez/models/skill/__init__.py +0 -16
- waldiez/models/skill/extra_requirements.py +0 -36
- waldiez/models/skill/skill_data.py +0 -53
- waldiez/models/skill/skill_type.py +0 -8
- waldiez/utils/pysqlite3_checker.py +0 -308
- waldiez/utils/rdps_checker.py +0 -122
- waldiez-0.4.6.dist-info/RECORD +0 -149
- /waldiez/models/agents/{captain_agent → captain}/__init__.py +0 -0
- /waldiez/models/agents/{captain_agent → captain}/captain_agent_lib_entry.py +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/WHEEL +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/entry_points.txt +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Models exporter module."""
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Optional, Union
|
|
7
|
+
|
|
8
|
+
from waldiez.models import WaldiezAgent, WaldiezModel
|
|
9
|
+
|
|
10
|
+
from ..core import (
|
|
11
|
+
AgentPosition,
|
|
12
|
+
ContentOrder,
|
|
13
|
+
DefaultSerializer,
|
|
14
|
+
Exporter,
|
|
15
|
+
ExporterContext,
|
|
16
|
+
ExportPosition,
|
|
17
|
+
ModelExtras,
|
|
18
|
+
get_comment,
|
|
19
|
+
)
|
|
20
|
+
from .processor import ModelProcessor
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ModelsExporter(Exporter[ModelExtras]):
|
|
24
|
+
"""Mdels exporter with structured extras."""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
flow_name: str,
|
|
29
|
+
agents: list[WaldiezAgent],
|
|
30
|
+
agent_names: dict[str, str],
|
|
31
|
+
models: list[WaldiezModel],
|
|
32
|
+
model_names: dict[str, str],
|
|
33
|
+
for_notebook: bool = False,
|
|
34
|
+
cache_seed: Optional[int] = None,
|
|
35
|
+
output_dir: Optional[Union[str, Path]] = None,
|
|
36
|
+
context: Optional[ExporterContext] = None,
|
|
37
|
+
**kwargs: Any,
|
|
38
|
+
):
|
|
39
|
+
"""Initialize the models exporter."""
|
|
40
|
+
super().__init__(context, **kwargs)
|
|
41
|
+
|
|
42
|
+
self.flow_name = flow_name
|
|
43
|
+
self.agents = agents
|
|
44
|
+
self.agent_names = agent_names
|
|
45
|
+
self.models = models
|
|
46
|
+
self.model_names = model_names
|
|
47
|
+
self.for_notebook = for_notebook
|
|
48
|
+
self.cache_seed = cache_seed
|
|
49
|
+
self.output_dir = Path(output_dir) if output_dir else None
|
|
50
|
+
|
|
51
|
+
# Initialize extras with processed model content
|
|
52
|
+
self._extras = self._create_model_extras()
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def extras(self) -> ModelExtras:
|
|
56
|
+
"""Get the model extras."""
|
|
57
|
+
return self._extras
|
|
58
|
+
|
|
59
|
+
def _create_model_extras(self) -> ModelExtras:
|
|
60
|
+
"""Create and populate model extras."""
|
|
61
|
+
extras = ModelExtras("models")
|
|
62
|
+
|
|
63
|
+
# Process models to generate LLM configs
|
|
64
|
+
model_processor = ModelProcessor(
|
|
65
|
+
flow_name=self.flow_name,
|
|
66
|
+
models=self.models,
|
|
67
|
+
model_names=self.model_names,
|
|
68
|
+
serializer=(
|
|
69
|
+
self.context.serializer
|
|
70
|
+
if self.context.serializer
|
|
71
|
+
else DefaultSerializer()
|
|
72
|
+
),
|
|
73
|
+
output_dir=self.output_dir,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
llm_configs_content = model_processor.process()
|
|
77
|
+
|
|
78
|
+
# Set LLM config content
|
|
79
|
+
if llm_configs_content:
|
|
80
|
+
extras.set_llm_config({"content": llm_configs_content})
|
|
81
|
+
self.add_content(
|
|
82
|
+
llm_configs_content,
|
|
83
|
+
ExportPosition.MODELS,
|
|
84
|
+
order=ContentOrder.MAIN_CONTENT,
|
|
85
|
+
)
|
|
86
|
+
# Add environment variables for API keys
|
|
87
|
+
for model in self.models:
|
|
88
|
+
if model.api_key:
|
|
89
|
+
self.add_env_var(
|
|
90
|
+
model.api_key_env_key,
|
|
91
|
+
model.api_key,
|
|
92
|
+
f"API key for {self.model_names[model.id]} model",
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return extras
|
|
96
|
+
|
|
97
|
+
def generate_main_content(self) -> Optional[str]:
|
|
98
|
+
"""Generate the main models content (LLM configs).
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
Optional[str]
|
|
103
|
+
The main content string, or None if no content is available.
|
|
104
|
+
"""
|
|
105
|
+
# handled in extras._contribute_specific_content(...)
|
|
106
|
+
# also here for direct access
|
|
107
|
+
if self.extras.has_specific_content():
|
|
108
|
+
return self.extras.get_content()
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
def _add_additional_content(self) -> None:
|
|
112
|
+
"""Add model related additional content."""
|
|
113
|
+
if self.output_dir is not None:
|
|
114
|
+
# Add API key loader script if output directory is set
|
|
115
|
+
api_key_loader_script = self.get_api_key_loader_script()
|
|
116
|
+
self.add_content(
|
|
117
|
+
api_key_loader_script,
|
|
118
|
+
ExportPosition.IMPORTS,
|
|
119
|
+
order=ContentOrder.LATE_CLEANUP,
|
|
120
|
+
skip_strip=True,
|
|
121
|
+
)
|
|
122
|
+
for agent in self.agents:
|
|
123
|
+
llm_config_arg = self.get_agent_llm_config_arg(agent)
|
|
124
|
+
if llm_config_arg:
|
|
125
|
+
# Position as agent argument
|
|
126
|
+
self.add_content(
|
|
127
|
+
llm_config_arg,
|
|
128
|
+
ExportPosition.AGENTS,
|
|
129
|
+
order=ContentOrder.MAIN_CONTENT,
|
|
130
|
+
agent_id=agent.id,
|
|
131
|
+
agent_position=AgentPosition.AS_ARGUMENT,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def get_agent_llm_config_arg(self, agent: WaldiezAgent) -> str:
|
|
135
|
+
"""Get LLM config argument for agent.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
agent : WaldiezAgent
|
|
140
|
+
The agent for which to get the LLM config argument.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
str
|
|
145
|
+
The LLM config argument string for the agent,
|
|
146
|
+
or "llm_config=False" if no models are configured.
|
|
147
|
+
"""
|
|
148
|
+
if not agent.data.model_ids:
|
|
149
|
+
return " llm_config=False, # pyright: ignore\n"
|
|
150
|
+
|
|
151
|
+
# Get model configs for this agent
|
|
152
|
+
model_configs: list[str] = []
|
|
153
|
+
for model_id in agent.data.model_ids:
|
|
154
|
+
model_name = self.model_names.get(model_id)
|
|
155
|
+
if model_name:
|
|
156
|
+
model_configs.append(f"{model_name}_llm_config")
|
|
157
|
+
tab = " " * 4
|
|
158
|
+
if not model_configs:
|
|
159
|
+
return f"{tab}llm_config=False, # pyright: ignore\n"
|
|
160
|
+
|
|
161
|
+
config_list = f",\n{tab}{tab}{tab}".join(model_configs)
|
|
162
|
+
llm_config = f"""{tab}llm_config=autogen.LLMConfig(
|
|
163
|
+
config_list=[
|
|
164
|
+
{config_list},
|
|
165
|
+
]"""
|
|
166
|
+
#
|
|
167
|
+
# Add cache seed if provided
|
|
168
|
+
if self.cache_seed is not None:
|
|
169
|
+
llm_config += f",\n{tab}{tab}cache_seed={self.cache_seed},\n"
|
|
170
|
+
else:
|
|
171
|
+
llm_config += f",\n{tab}{tab}cache_seed=None,\n"
|
|
172
|
+
llm_config += f"{tab}),\n"
|
|
173
|
+
|
|
174
|
+
return llm_config
|
|
175
|
+
|
|
176
|
+
def get_api_key_loader_script(self) -> str:
|
|
177
|
+
"""Get the api key loader script.
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
str
|
|
182
|
+
The api key loader script.
|
|
183
|
+
"""
|
|
184
|
+
comment = get_comment(
|
|
185
|
+
"Load model API keys",
|
|
186
|
+
for_notebook=self.config.for_notebook,
|
|
187
|
+
)
|
|
188
|
+
loader_script = f'''{comment}# NOTE:
|
|
189
|
+
# This section assumes that a file named "{self.flow_name}_api_keys"
|
|
190
|
+
# exists in the same directory as this file.
|
|
191
|
+
# This file contains the API keys for the models used in this flow.
|
|
192
|
+
# It should be .gitignored and not shared publicly.
|
|
193
|
+
# If this file is not present, you can either create it manually
|
|
194
|
+
# or change the way API keys are loaded in the flow.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def load_api_key_module(flow_name: str) -> ModuleType:
|
|
198
|
+
"""Load the api key module.
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
flow_name : str
|
|
203
|
+
The flow name.
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
ModuleType
|
|
208
|
+
The api keys loading module.
|
|
209
|
+
"""
|
|
210
|
+
module_name = f"{{flow_name}}_api_keys"
|
|
211
|
+
if module_name in sys.modules:
|
|
212
|
+
return importlib.reload(sys.modules[module_name])
|
|
213
|
+
return importlib.import_module(module_name)
|
|
214
|
+
|
|
215
|
+
__MODELS_MODULE__ = load_api_key_module("{self.flow_name}")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def get_{self.flow_name}_model_api_key(model_name: str) -> str:
|
|
219
|
+
"""Get the model api key.
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
model_name : str
|
|
223
|
+
The model name.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
str
|
|
228
|
+
The model api key.
|
|
229
|
+
"""
|
|
230
|
+
return __MODELS_MODULE__.get_{self.flow_name}_model_api_key(model_name)
|
|
231
|
+
|
|
232
|
+
'''
|
|
233
|
+
return loader_script
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Factory function for creating a ModelsExporter instance."""
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
|
|
8
|
+
from waldiez.models import WaldiezAgent, WaldiezModel
|
|
9
|
+
|
|
10
|
+
from ..core import ExporterContext, get_default_exporter_context
|
|
11
|
+
from .exporter import ModelsExporter
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_models_exporter(
|
|
15
|
+
# Factory function for models exporter creation
|
|
16
|
+
flow_name: str,
|
|
17
|
+
agents: list[WaldiezAgent],
|
|
18
|
+
agent_names: dict[str, str],
|
|
19
|
+
models: list[WaldiezModel],
|
|
20
|
+
model_names: dict[str, str],
|
|
21
|
+
for_notebook: bool = False,
|
|
22
|
+
cache_seed: Optional[int] = None,
|
|
23
|
+
output_dir: Optional[Union[str, Path]] = None,
|
|
24
|
+
context: Optional[ExporterContext] = None,
|
|
25
|
+
) -> ModelsExporter:
|
|
26
|
+
"""Create a models exporter.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
flow_name : str
|
|
31
|
+
The name of the flow.
|
|
32
|
+
agents : list[WaldiezAgent]
|
|
33
|
+
The agents that use models.
|
|
34
|
+
agent_names : dict[str, str]
|
|
35
|
+
Mapping of agent IDs to names.
|
|
36
|
+
models : list[WaldiezModel]
|
|
37
|
+
The models to export.
|
|
38
|
+
model_names : dict[str, str]
|
|
39
|
+
Mapping of model IDs to names.
|
|
40
|
+
for_notebook : bool, optional
|
|
41
|
+
Whether the export is for a notebook, by default False
|
|
42
|
+
cache_seed : Optional[int], optional
|
|
43
|
+
The cache seed if any, by default None
|
|
44
|
+
output_dir : Optional[Union[str, Path]], optional
|
|
45
|
+
Output directory for generated files, by default None
|
|
46
|
+
context : Optional[ExporterContext], optional
|
|
47
|
+
Exporter context with dependencies, by default None
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
ModelsExporter
|
|
52
|
+
The created models exporter.
|
|
53
|
+
"""
|
|
54
|
+
if context is None:
|
|
55
|
+
context = get_default_exporter_context()
|
|
56
|
+
return ModelsExporter(
|
|
57
|
+
flow_name=flow_name,
|
|
58
|
+
agents=agents,
|
|
59
|
+
agent_names=agent_names,
|
|
60
|
+
models=models,
|
|
61
|
+
model_names=model_names,
|
|
62
|
+
for_notebook=for_notebook,
|
|
63
|
+
cache_seed=cache_seed,
|
|
64
|
+
output_dir=output_dir,
|
|
65
|
+
context=context,
|
|
66
|
+
)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
# pylint: disable=too-few-public-methods,unused-argument
|
|
4
|
+
"""Model exporting utilities for Waldiez."""
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from waldiez.models import WaldiezModel
|
|
11
|
+
|
|
12
|
+
from ..core.constants import FILE_HEADER
|
|
13
|
+
from ..core.errors import ExporterContentError
|
|
14
|
+
from ..core.extras.serializer import DefaultSerializer
|
|
15
|
+
from ..core.protocols import Serializer
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class ModelProcessingResult:
|
|
20
|
+
"""Result from processing models."""
|
|
21
|
+
|
|
22
|
+
llm_configs_content: str = ""
|
|
23
|
+
api_keys_file: Optional[Path] = None
|
|
24
|
+
needs_api_key_loader: bool = False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ModelProcessor:
|
|
28
|
+
"""Model processor for generating LLM configs and API key loading."""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
flow_name: str,
|
|
33
|
+
models: list[WaldiezModel],
|
|
34
|
+
model_names: dict[str, str],
|
|
35
|
+
serializer: Optional[Serializer] = None,
|
|
36
|
+
output_dir: Optional[Path] = None,
|
|
37
|
+
):
|
|
38
|
+
self.flow_name = flow_name
|
|
39
|
+
self.models = models
|
|
40
|
+
self.model_names = model_names
|
|
41
|
+
self.serializer = serializer or DefaultSerializer()
|
|
42
|
+
self.output_dir = output_dir
|
|
43
|
+
|
|
44
|
+
def process(self) -> str:
|
|
45
|
+
"""Process the flow models.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
str
|
|
50
|
+
The string representation of all models' LLM configs.
|
|
51
|
+
"""
|
|
52
|
+
content = ""
|
|
53
|
+
for model in self.models:
|
|
54
|
+
model_name = self.model_names[model.id]
|
|
55
|
+
model_config = model.get_llm_config()
|
|
56
|
+
|
|
57
|
+
# Remove api_key if present
|
|
58
|
+
api_key = model_config.pop("api_key", None)
|
|
59
|
+
model_dict_str = self.serializer.serialize(model_config, tabs=0)
|
|
60
|
+
# and use the getter function to get it when needed
|
|
61
|
+
if api_key: # pragma: no branch
|
|
62
|
+
extra_arg = (
|
|
63
|
+
f'get_{self.flow_name}_model_api_key("{model_name}")'
|
|
64
|
+
)
|
|
65
|
+
# remove the \n}, from the end of the dict string
|
|
66
|
+
model_dict_str = model_dict_str.rstrip("\n},")
|
|
67
|
+
model_dict_str += f',\n "api_key": {extra_arg}\n}}'
|
|
68
|
+
content += (
|
|
69
|
+
f"\n{model_name}_llm_config: dict[str, Any] = "
|
|
70
|
+
f"{model_dict_str}\n"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Write API keys file if output directory provided
|
|
74
|
+
if self.output_dir:
|
|
75
|
+
self.output_dir = Path(self.output_dir)
|
|
76
|
+
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
77
|
+
self._write_api_keys()
|
|
78
|
+
|
|
79
|
+
return content
|
|
80
|
+
|
|
81
|
+
def _write_api_keys(self) -> None:
|
|
82
|
+
"""Write API keys file."""
|
|
83
|
+
flow_name_upper = self.flow_name.upper()
|
|
84
|
+
api_keys_content = f'''{FILE_HEADER}
|
|
85
|
+
# flake8: noqa: E501
|
|
86
|
+
# pylint: disable=line-too-long
|
|
87
|
+
"""API keys for the {self.flow_name} models."""
|
|
88
|
+
|
|
89
|
+
import os
|
|
90
|
+
|
|
91
|
+
__{flow_name_upper}_MODEL_API_KEYS__ = {{'''
|
|
92
|
+
|
|
93
|
+
for model in self.models:
|
|
94
|
+
model_name = self.model_names[model.id]
|
|
95
|
+
key_env = model.api_key_env_key
|
|
96
|
+
api_keys_content += (
|
|
97
|
+
"\n" + f' "{model_name}": '
|
|
98
|
+
f'{{"key": "{model.api_key}", "env_key": "{key_env}"}},'
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
api_keys_content += "\n}\n"
|
|
102
|
+
api_keys_content += f'''
|
|
103
|
+
|
|
104
|
+
def get_{self.flow_name}_model_api_key(model_name: str) -> str:
|
|
105
|
+
"""Get the api key for the model.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
model_name : str
|
|
110
|
+
The name of the model.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
str
|
|
115
|
+
The api key for the model.
|
|
116
|
+
"""
|
|
117
|
+
entry = __{flow_name_upper}_MODEL_API_KEYS__.get(model_name, {{}})
|
|
118
|
+
if not entry:
|
|
119
|
+
return ""
|
|
120
|
+
env_key = entry.get("env_key", "")
|
|
121
|
+
if env_key:
|
|
122
|
+
from_env = os.environ.get(env_key, "")
|
|
123
|
+
if from_env:
|
|
124
|
+
return from_env
|
|
125
|
+
return entry.get("key", "")
|
|
126
|
+
'''
|
|
127
|
+
|
|
128
|
+
# Write the file
|
|
129
|
+
file_name = f"{self.flow_name}_api_keys.py"
|
|
130
|
+
output_path = (
|
|
131
|
+
self.output_dir / file_name if self.output_dir else Path(file_name)
|
|
132
|
+
)
|
|
133
|
+
try:
|
|
134
|
+
with open(output_path, "w", encoding="utf-8", newline="\n") as f:
|
|
135
|
+
f.write(api_keys_content)
|
|
136
|
+
except Exception as e: # pragma: no cover
|
|
137
|
+
raise ExporterContentError(
|
|
138
|
+
f"Failed to write API keys file: {e}"
|
|
139
|
+
) from e
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Export tool."""
|
|
4
|
+
|
|
5
|
+
from .exporter import ToolsExporter
|
|
6
|
+
from .factory import create_tools_exporter
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ToolsExporter",
|
|
10
|
+
"create_tools_exporter",
|
|
11
|
+
]
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
|
|
4
|
+
"""Tools exporter."""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Optional, Union
|
|
8
|
+
|
|
9
|
+
from waldiez.models import WaldiezAgent, WaldiezTool
|
|
10
|
+
|
|
11
|
+
from ..core import (
|
|
12
|
+
ContentOrder,
|
|
13
|
+
Exporter,
|
|
14
|
+
ExporterContext,
|
|
15
|
+
ExportPosition,
|
|
16
|
+
ImportPosition,
|
|
17
|
+
ImportStatement,
|
|
18
|
+
ToolExtras,
|
|
19
|
+
get_comment,
|
|
20
|
+
)
|
|
21
|
+
from .processor import ToolProcessor
|
|
22
|
+
from .registration import ToolRegistrationProcessor
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ToolsExporter(Exporter[ToolExtras]):
|
|
26
|
+
"""Rools exporter with structured extras."""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
flow_name: str,
|
|
31
|
+
agents: list[WaldiezAgent],
|
|
32
|
+
agent_names: dict[str, str],
|
|
33
|
+
tools: list[WaldiezTool],
|
|
34
|
+
tool_names: dict[str, str],
|
|
35
|
+
output_dir: Optional[Union[str, Path]] = None,
|
|
36
|
+
context: Optional[ExporterContext] = None,
|
|
37
|
+
**kwargs: Any,
|
|
38
|
+
):
|
|
39
|
+
"""Initialize the tools exporter.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
flow_name : str
|
|
44
|
+
The name of the flow.
|
|
45
|
+
agents : list[WaldiezAgent]
|
|
46
|
+
The agents that use tools.
|
|
47
|
+
agent_names : dict[str, str]
|
|
48
|
+
Mapping of agent IDs to names.
|
|
49
|
+
tools : list[WaldiezTool]
|
|
50
|
+
The tools to export.
|
|
51
|
+
tool_names : dict[str, str]
|
|
52
|
+
Mapping of tool IDs to names.
|
|
53
|
+
output_dir : Optional[Union[str, Path]], optional
|
|
54
|
+
Output directory for generated files, by default None
|
|
55
|
+
context : Optional[ExporterContext], optional
|
|
56
|
+
Exporter context with dependencies, by default None
|
|
57
|
+
**kwargs
|
|
58
|
+
Additional keyword arguments.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(context, **kwargs)
|
|
61
|
+
|
|
62
|
+
self.flow_name = flow_name
|
|
63
|
+
self.agents = agents
|
|
64
|
+
self.agent_names = agent_names
|
|
65
|
+
self.tools = tools
|
|
66
|
+
self.tool_names = tool_names
|
|
67
|
+
self.output_dir = Path(output_dir) if output_dir else None
|
|
68
|
+
|
|
69
|
+
# Initialize extras with processed tool content
|
|
70
|
+
self._extras = self._create_tool_extras()
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def extras(self) -> ToolExtras:
|
|
74
|
+
"""Get the tool extras."""
|
|
75
|
+
return self._extras
|
|
76
|
+
|
|
77
|
+
def _create_tool_extras(self) -> ToolExtras:
|
|
78
|
+
"""Create and populate tool extras."""
|
|
79
|
+
extras = ToolExtras("tools")
|
|
80
|
+
|
|
81
|
+
# Process tools to generate content
|
|
82
|
+
tool_processor = ToolProcessor(
|
|
83
|
+
flow_name=self.flow_name,
|
|
84
|
+
tools=self.tools,
|
|
85
|
+
tool_names=self.tool_names,
|
|
86
|
+
output_dir=self.output_dir,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
tool_result = tool_processor.process()
|
|
90
|
+
|
|
91
|
+
# Add tool content
|
|
92
|
+
if tool_result.content:
|
|
93
|
+
extras.add_function_content(tool_result.content)
|
|
94
|
+
|
|
95
|
+
# Add imports
|
|
96
|
+
for import_stmt in tool_result.builtin_imports:
|
|
97
|
+
extras.add_import(
|
|
98
|
+
ImportStatement(import_stmt, ImportPosition.BUILTINS)
|
|
99
|
+
)
|
|
100
|
+
# Override import position for builtins
|
|
101
|
+
self.add_import(import_stmt, ImportPosition.BUILTINS)
|
|
102
|
+
|
|
103
|
+
for import_stmt in tool_result.third_party_imports:
|
|
104
|
+
extras.add_import(
|
|
105
|
+
ImportStatement(import_stmt, ImportPosition.THIRD_PARTY)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Add environment variables
|
|
109
|
+
for environment_variable in tool_result.environment_variables:
|
|
110
|
+
self.add_env_var(
|
|
111
|
+
name=environment_variable.name,
|
|
112
|
+
value=environment_variable.value,
|
|
113
|
+
description=environment_variable.description,
|
|
114
|
+
required=environment_variable.required,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Process tool registrations
|
|
118
|
+
|
|
119
|
+
registration_processor = ToolRegistrationProcessor(
|
|
120
|
+
agents=self.agents,
|
|
121
|
+
agent_names=self.agent_names,
|
|
122
|
+
tools=self.tools,
|
|
123
|
+
tool_names=self.tool_names,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
registration_content = registration_processor.process()
|
|
127
|
+
if registration_content:
|
|
128
|
+
extras.add_registration_content(registration_content)
|
|
129
|
+
|
|
130
|
+
if self.output_dir is not None:
|
|
131
|
+
# add the tool secrets loader script
|
|
132
|
+
for tool in self.tools:
|
|
133
|
+
if tool.secrets:
|
|
134
|
+
tool_name = self.tool_names.get(tool.id, tool.id)
|
|
135
|
+
tool_secrets_loader_script = (
|
|
136
|
+
self.get_tool_secrets_loader_script(tool_name=tool_name)
|
|
137
|
+
)
|
|
138
|
+
self.add_content(
|
|
139
|
+
tool_secrets_loader_script,
|
|
140
|
+
ExportPosition.TOOLS,
|
|
141
|
+
order=ContentOrder.EARLY_SETUP,
|
|
142
|
+
skip_strip=True,
|
|
143
|
+
)
|
|
144
|
+
return extras
|
|
145
|
+
|
|
146
|
+
def generate_main_content(self) -> Optional[str]:
|
|
147
|
+
"""Generate the main tools content."""
|
|
148
|
+
# handled as positioned content
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
def _add_default_imports(self) -> None:
|
|
152
|
+
"""Add default imports for tools."""
|
|
153
|
+
# Tools might need register_function import
|
|
154
|
+
if any(agent.data.tools for agent in self.agents): # pragma: no branch
|
|
155
|
+
self.add_import("from autogen import register_function")
|
|
156
|
+
|
|
157
|
+
# Add interop import if needed
|
|
158
|
+
if any(tool.is_interop for tool in self.tools):
|
|
159
|
+
self.add_import("from autogen.interop import Interoperability")
|
|
160
|
+
|
|
161
|
+
def get_tool_secrets_loader_script(self, tool_name: str) -> str:
|
|
162
|
+
"""Get the tool secrets loader script.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
tool_name : str
|
|
167
|
+
The name of the tool for which to generate the loader script.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
str
|
|
172
|
+
The tool secrets loader script.
|
|
173
|
+
"""
|
|
174
|
+
comment = get_comment(
|
|
175
|
+
"Load tool secrets module if needed",
|
|
176
|
+
for_notebook=self.config.for_notebook,
|
|
177
|
+
)
|
|
178
|
+
loader_script = f'''{comment}# NOTE:
|
|
179
|
+
# This section assumes that a file named "{self.flow_name}_{tool_name}_secrets"
|
|
180
|
+
# exists in the same directory as this file.
|
|
181
|
+
# This file contains the secrets for the tool used in this flow.
|
|
182
|
+
# It should be .gitignored and not shared publicly.
|
|
183
|
+
# If this file is not present, you can either create it manually
|
|
184
|
+
# or change the way secrets are loaded in the flow.
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def load_tool_secrets_module(flow_name: str, tool_name: str) -> ModuleType:
|
|
188
|
+
"""Load the tool secrets module for the given flow name and tool name.
|
|
189
|
+
|
|
190
|
+
Parameters
|
|
191
|
+
----------
|
|
192
|
+
flow_name : str
|
|
193
|
+
The flow name.
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
ModuleType
|
|
198
|
+
The loaded module.
|
|
199
|
+
"""
|
|
200
|
+
module_name = f"{{flow_name}}_{{tool_name}}_secrets"
|
|
201
|
+
if module_name in sys.modules:
|
|
202
|
+
return importlib.reload(sys.modules[module_name])
|
|
203
|
+
return importlib.import_module(module_name)
|
|
204
|
+
|
|
205
|
+
load_tool_secrets_module("{self.flow_name}", "{tool_name}")
|
|
206
|
+
'''
|
|
207
|
+
return loader_script
|