waldiez 0.1.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 +15 -0
- waldiez/__main__.py +6 -0
- waldiez/_version.py +3 -0
- waldiez/cli.py +162 -0
- waldiez/exporter.py +293 -0
- waldiez/exporting/__init__.py +14 -0
- waldiez/exporting/agents/__init__.py +5 -0
- waldiez/exporting/agents/agent.py +229 -0
- waldiez/exporting/agents/agent_skills.py +67 -0
- waldiez/exporting/agents/code_execution.py +67 -0
- waldiez/exporting/agents/group_manager.py +209 -0
- waldiez/exporting/agents/llm_config.py +53 -0
- waldiez/exporting/agents/rag_user/__init__.py +5 -0
- waldiez/exporting/agents/rag_user/chroma_utils.py +134 -0
- waldiez/exporting/agents/rag_user/mongo_utils.py +83 -0
- waldiez/exporting/agents/rag_user/pgvector_utils.py +93 -0
- waldiez/exporting/agents/rag_user/qdrant_utils.py +112 -0
- waldiez/exporting/agents/rag_user/rag_user.py +165 -0
- waldiez/exporting/agents/rag_user/vector_db.py +119 -0
- waldiez/exporting/agents/teachability.py +37 -0
- waldiez/exporting/agents/termination_message.py +45 -0
- waldiez/exporting/chats/__init__.py +14 -0
- waldiez/exporting/chats/chats.py +46 -0
- waldiez/exporting/chats/helpers.py +395 -0
- waldiez/exporting/chats/nested.py +264 -0
- waldiez/exporting/flow/__init__.py +5 -0
- waldiez/exporting/flow/def_main.py +37 -0
- waldiez/exporting/flow/flow.py +185 -0
- waldiez/exporting/models/__init__.py +193 -0
- waldiez/exporting/skills/__init__.py +128 -0
- waldiez/exporting/utils/__init__.py +34 -0
- waldiez/exporting/utils/comments.py +136 -0
- waldiez/exporting/utils/importing.py +267 -0
- waldiez/exporting/utils/logging_utils.py +203 -0
- waldiez/exporting/utils/method_utils.py +35 -0
- waldiez/exporting/utils/naming.py +127 -0
- waldiez/exporting/utils/object_string.py +81 -0
- waldiez/io_stream.py +181 -0
- waldiez/models/__init__.py +107 -0
- waldiez/models/agents/__init__.py +65 -0
- waldiez/models/agents/agent/__init__.py +21 -0
- waldiez/models/agents/agent/agent.py +190 -0
- waldiez/models/agents/agent/agent_data.py +162 -0
- waldiez/models/agents/agent/code_execution.py +71 -0
- waldiez/models/agents/agent/linked_skill.py +30 -0
- waldiez/models/agents/agent/nested_chat.py +73 -0
- waldiez/models/agents/agent/teachability.py +68 -0
- waldiez/models/agents/agent/termination_message.py +167 -0
- waldiez/models/agents/agents.py +129 -0
- waldiez/models/agents/assistant/__init__.py +6 -0
- waldiez/models/agents/assistant/assistant.py +41 -0
- waldiez/models/agents/assistant/assistant_data.py +29 -0
- waldiez/models/agents/group_manager/__init__.py +19 -0
- waldiez/models/agents/group_manager/group_manager.py +87 -0
- waldiez/models/agents/group_manager/group_manager_data.py +91 -0
- waldiez/models/agents/group_manager/speakers.py +211 -0
- waldiez/models/agents/rag_user/__init__.py +26 -0
- waldiez/models/agents/rag_user/rag_user.py +58 -0
- waldiez/models/agents/rag_user/rag_user_data.py +32 -0
- waldiez/models/agents/rag_user/retrieve_config.py +592 -0
- waldiez/models/agents/rag_user/vector_db_config.py +162 -0
- waldiez/models/agents/user_proxy/__init__.py +6 -0
- waldiez/models/agents/user_proxy/user_proxy.py +41 -0
- waldiez/models/agents/user_proxy/user_proxy_data.py +30 -0
- waldiez/models/chat/__init__.py +22 -0
- waldiez/models/chat/chat.py +129 -0
- waldiez/models/chat/chat_data.py +326 -0
- waldiez/models/chat/chat_message.py +304 -0
- waldiez/models/chat/chat_nested.py +160 -0
- waldiez/models/chat/chat_summary.py +110 -0
- waldiez/models/common/__init__.py +38 -0
- waldiez/models/common/base.py +63 -0
- waldiez/models/common/method_utils.py +165 -0
- waldiez/models/flow/__init__.py +9 -0
- waldiez/models/flow/flow.py +302 -0
- waldiez/models/flow/flow_data.py +87 -0
- waldiez/models/model/__init__.py +11 -0
- waldiez/models/model/model.py +169 -0
- waldiez/models/model/model_data.py +86 -0
- waldiez/models/skill/__init__.py +9 -0
- waldiez/models/skill/skill.py +129 -0
- waldiez/models/skill/skill_data.py +37 -0
- waldiez/models/waldiez.py +301 -0
- waldiez/py.typed +0 -0
- waldiez/runner.py +304 -0
- waldiez/stream/__init__.py +7 -0
- waldiez/stream/consumer.py +139 -0
- waldiez/stream/provider.py +339 -0
- waldiez/stream/server.py +412 -0
- waldiez-0.1.0.dist-info/METADATA +181 -0
- waldiez-0.1.0.dist-info/RECORD +94 -0
- waldiez-0.1.0.dist-info/WHEEL +4 -0
- waldiez-0.1.0.dist-info/entry_points.txt +2 -0
- waldiez-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"""Waldiez flow model."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
from pydantic import Field, model_validator
|
|
7
|
+
from typing_extensions import Annotated, Literal, Self
|
|
8
|
+
|
|
9
|
+
from ..agents import WaldiezAgent
|
|
10
|
+
from ..chat import WaldiezChat
|
|
11
|
+
from ..common import WaldiezBase, now
|
|
12
|
+
from .flow_data import WaldiezFlowData
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WaldiezFlow(WaldiezBase):
|
|
16
|
+
"""Flow data class.
|
|
17
|
+
|
|
18
|
+
Attributes
|
|
19
|
+
----------
|
|
20
|
+
id : str
|
|
21
|
+
The ID of the flow.
|
|
22
|
+
type : Literal["flow"], optional
|
|
23
|
+
The type of the "node" in a graph: "flow".
|
|
24
|
+
name : str
|
|
25
|
+
The name of the flow.
|
|
26
|
+
description : str
|
|
27
|
+
The description of the flow.
|
|
28
|
+
tags : List[str]
|
|
29
|
+
The tags of the flow.
|
|
30
|
+
requirements : List[str]
|
|
31
|
+
The requirements of the flow.
|
|
32
|
+
storage_id : str
|
|
33
|
+
The storage ID of the flow (ignored, UI related).
|
|
34
|
+
created_at : str
|
|
35
|
+
The date and time when the flow was created.
|
|
36
|
+
updated_at : str
|
|
37
|
+
The date and time when the flow was last updated.
|
|
38
|
+
data : WaldiezFlowData
|
|
39
|
+
The data of the flow. See `WaldiezFlowData`.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
id: Annotated[
|
|
43
|
+
str,
|
|
44
|
+
Field(
|
|
45
|
+
description="The ID of the flow",
|
|
46
|
+
title="ID",
|
|
47
|
+
default_factory=uuid.uuid4,
|
|
48
|
+
),
|
|
49
|
+
]
|
|
50
|
+
type: Annotated[
|
|
51
|
+
Literal["flow"],
|
|
52
|
+
Field(
|
|
53
|
+
"flow",
|
|
54
|
+
description="The type of the 'node' in a graph",
|
|
55
|
+
title="Type",
|
|
56
|
+
),
|
|
57
|
+
]
|
|
58
|
+
name: Annotated[
|
|
59
|
+
str,
|
|
60
|
+
Field(
|
|
61
|
+
...,
|
|
62
|
+
description="The name of the flow",
|
|
63
|
+
title="Name",
|
|
64
|
+
),
|
|
65
|
+
]
|
|
66
|
+
description: Annotated[
|
|
67
|
+
str,
|
|
68
|
+
Field(
|
|
69
|
+
...,
|
|
70
|
+
description="The description of the flow",
|
|
71
|
+
title="Description",
|
|
72
|
+
),
|
|
73
|
+
]
|
|
74
|
+
tags: Annotated[
|
|
75
|
+
List[str],
|
|
76
|
+
Field(
|
|
77
|
+
description="The tags of the flow",
|
|
78
|
+
title="Tags",
|
|
79
|
+
default_factory=list,
|
|
80
|
+
),
|
|
81
|
+
]
|
|
82
|
+
requirements: Annotated[
|
|
83
|
+
List[str],
|
|
84
|
+
Field(
|
|
85
|
+
description="The requirements of the flow",
|
|
86
|
+
title="Requirements",
|
|
87
|
+
default_factory=list,
|
|
88
|
+
),
|
|
89
|
+
]
|
|
90
|
+
data: Annotated[
|
|
91
|
+
WaldiezFlowData,
|
|
92
|
+
Field(
|
|
93
|
+
...,
|
|
94
|
+
description="The data of the flow",
|
|
95
|
+
title="Data",
|
|
96
|
+
),
|
|
97
|
+
]
|
|
98
|
+
storage_id: Annotated[
|
|
99
|
+
str,
|
|
100
|
+
Field(
|
|
101
|
+
uuid.uuid4(),
|
|
102
|
+
description="The storage ID of the flow (ignored, UI related)",
|
|
103
|
+
title="Storage ID",
|
|
104
|
+
alias="storageId",
|
|
105
|
+
),
|
|
106
|
+
]
|
|
107
|
+
created_at: Annotated[
|
|
108
|
+
str,
|
|
109
|
+
Field(
|
|
110
|
+
default_factory=now,
|
|
111
|
+
title="Created At",
|
|
112
|
+
description="The date and time when the flow was created.",
|
|
113
|
+
),
|
|
114
|
+
]
|
|
115
|
+
updated_at: Annotated[
|
|
116
|
+
str,
|
|
117
|
+
Field(
|
|
118
|
+
default_factory=now,
|
|
119
|
+
title="Updated At",
|
|
120
|
+
description="The date and time when the flow was last updated.",
|
|
121
|
+
),
|
|
122
|
+
]
|
|
123
|
+
_ordered_flow: Optional[
|
|
124
|
+
List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]
|
|
125
|
+
] = None
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def ordered_flow(
|
|
129
|
+
self,
|
|
130
|
+
) -> List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]:
|
|
131
|
+
"""Get the ordered flow."""
|
|
132
|
+
if not self._ordered_flow:
|
|
133
|
+
self._ordered_flow = self._get_flow_order()
|
|
134
|
+
return self._ordered_flow
|
|
135
|
+
|
|
136
|
+
def get_agent_by_id(self, agent_id: str) -> WaldiezAgent:
|
|
137
|
+
"""Get the agent by ID.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
agent_id : str
|
|
142
|
+
The ID of the agent.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
WaldiezAgent
|
|
147
|
+
The agent.
|
|
148
|
+
|
|
149
|
+
Raises
|
|
150
|
+
------
|
|
151
|
+
ValueError
|
|
152
|
+
If the agent with the given ID is not found.
|
|
153
|
+
"""
|
|
154
|
+
for user in self.data.agents.users:
|
|
155
|
+
if user.id == agent_id:
|
|
156
|
+
return user
|
|
157
|
+
for assistant in self.data.agents.assistants:
|
|
158
|
+
if assistant.id == agent_id:
|
|
159
|
+
return assistant
|
|
160
|
+
for manager in self.data.agents.managers:
|
|
161
|
+
if manager.id == agent_id:
|
|
162
|
+
return manager
|
|
163
|
+
for rag_user in self.data.agents.rag_users:
|
|
164
|
+
if rag_user.id == agent_id:
|
|
165
|
+
return rag_user
|
|
166
|
+
raise ValueError(f"Agent with ID {agent_id} not found.")
|
|
167
|
+
|
|
168
|
+
def _get_flow_order(
|
|
169
|
+
self,
|
|
170
|
+
) -> List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]]:
|
|
171
|
+
"""Get the ordered flow."""
|
|
172
|
+
# in the chats, there is the 'order' field, we use this,
|
|
173
|
+
# we only keep the ones with order >=0
|
|
174
|
+
# and sort them by this property
|
|
175
|
+
ordered_flow: List[Tuple[WaldiezChat, WaldiezAgent, WaldiezAgent]] = []
|
|
176
|
+
sorted_chats_by_order = sorted(
|
|
177
|
+
self.data.chats, key=lambda chat: chat.data.order
|
|
178
|
+
)
|
|
179
|
+
for chat in sorted_chats_by_order:
|
|
180
|
+
if chat.data.order < 0:
|
|
181
|
+
continue
|
|
182
|
+
source = self.get_agent_by_id(chat.source)
|
|
183
|
+
target = self.get_agent_by_id(chat.target)
|
|
184
|
+
ordered_flow.append((chat, source, target))
|
|
185
|
+
if not ordered_flow:
|
|
186
|
+
if len(self.data.chats) == 1:
|
|
187
|
+
chat = self.data.chats[0]
|
|
188
|
+
source = self.get_agent_by_id(chat.source)
|
|
189
|
+
target = self.get_agent_by_id(chat.target)
|
|
190
|
+
ordered_flow.append((chat, source, target))
|
|
191
|
+
return ordered_flow
|
|
192
|
+
|
|
193
|
+
def get_agent_connections(
|
|
194
|
+
self, agent_id: str, all_chats: bool = True
|
|
195
|
+
) -> List[str]:
|
|
196
|
+
"""Get the agent connections.
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
agent_id : str
|
|
201
|
+
The ID of the agent.
|
|
202
|
+
all_chats : bool, optional
|
|
203
|
+
If True, get the connections from all the chats, otherwise
|
|
204
|
+
get the connections from the ordered flow (main chat flow).
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
List[str]
|
|
209
|
+
The list of agent ids that the agent with the given ID connects to.
|
|
210
|
+
"""
|
|
211
|
+
connections = []
|
|
212
|
+
if all_chats:
|
|
213
|
+
for chat in self.data.chats:
|
|
214
|
+
if chat.source == agent_id:
|
|
215
|
+
connections.append(chat.target)
|
|
216
|
+
if chat.target == agent_id:
|
|
217
|
+
connections.append(chat.source)
|
|
218
|
+
else:
|
|
219
|
+
for _, source, target in self.ordered_flow:
|
|
220
|
+
if source.id == agent_id:
|
|
221
|
+
connections.append(target.id)
|
|
222
|
+
if target.id == agent_id:
|
|
223
|
+
connections.append(source.id)
|
|
224
|
+
return connections
|
|
225
|
+
|
|
226
|
+
def get_group_chat_members(
|
|
227
|
+
self, group_manager_id: str
|
|
228
|
+
) -> List[WaldiezAgent]:
|
|
229
|
+
"""Get the group chat members.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
group_manager_id : str
|
|
234
|
+
The ID of the group manager.
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
List[WaldiezAgent]
|
|
239
|
+
The list of group chat
|
|
240
|
+
"""
|
|
241
|
+
agent = self.get_agent_by_id(group_manager_id)
|
|
242
|
+
if agent.agent_type != "manager":
|
|
243
|
+
return []
|
|
244
|
+
connections = self.get_agent_connections(group_manager_id)
|
|
245
|
+
return [self.get_agent_by_id(member_id) for member_id in connections]
|
|
246
|
+
|
|
247
|
+
def _validate_agent_connections(self) -> None:
|
|
248
|
+
for agent in self.data.agents.members:
|
|
249
|
+
if not any(
|
|
250
|
+
agent.id in (chat.source, chat.target)
|
|
251
|
+
for chat in self.data.chats
|
|
252
|
+
):
|
|
253
|
+
raise ValueError(
|
|
254
|
+
f"Agent {agent.id} ({agent.name}) "
|
|
255
|
+
"does not connect to any other node."
|
|
256
|
+
)
|
|
257
|
+
# already covered above
|
|
258
|
+
# if agent.agent_type == "manager":
|
|
259
|
+
# chat_member_ids = self.get_agent_connections(agent.id)
|
|
260
|
+
# if not chat_member_ids:
|
|
261
|
+
# raise ValueError(
|
|
262
|
+
# f"Manager's {agent.id} group chat has no members."
|
|
263
|
+
# )
|
|
264
|
+
|
|
265
|
+
@model_validator(mode="after")
|
|
266
|
+
def validate_flow(self) -> Self:
|
|
267
|
+
"""Flow validation.
|
|
268
|
+
|
|
269
|
+
- unique node ids
|
|
270
|
+
- there are at least two agents
|
|
271
|
+
- all the agents connect to at least one other agent
|
|
272
|
+
- all the linked agent skills are found in the flow
|
|
273
|
+
- all the linked agent models are found in the flow
|
|
274
|
+
- all the managers have at least one member in the chat group
|
|
275
|
+
- the ordered flow (chats with position >=0) is not empty
|
|
276
|
+
- all agents' code execution config functions exist in the flow skills
|
|
277
|
+
|
|
278
|
+
Returns
|
|
279
|
+
-------
|
|
280
|
+
WaldiezFlow
|
|
281
|
+
The validated flow.
|
|
282
|
+
|
|
283
|
+
Raises
|
|
284
|
+
------
|
|
285
|
+
ValueError
|
|
286
|
+
If the ordered flow is empty.
|
|
287
|
+
If the model IDs are not unique.
|
|
288
|
+
If the skill IDs are not unique.
|
|
289
|
+
If the agents do not connect to any other node.
|
|
290
|
+
If the manager's group chat has no members.
|
|
291
|
+
"""
|
|
292
|
+
if not self.ordered_flow:
|
|
293
|
+
raise ValueError("The ordered flow is empty.")
|
|
294
|
+
model_ids = [model.id for model in self.data.models]
|
|
295
|
+
if len(model_ids) != len(set(model_ids)):
|
|
296
|
+
raise ValueError("Model IDs must be unique.")
|
|
297
|
+
skills_ids = [skill.id for skill in self.data.skills]
|
|
298
|
+
if len(skills_ids) != len(set(skills_ids)):
|
|
299
|
+
raise ValueError("Skill IDs must be unique.")
|
|
300
|
+
self.data.agents.validate_flow(model_ids, skills_ids)
|
|
301
|
+
self._validate_agent_connections()
|
|
302
|
+
return self
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Waldiez flow data."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from typing_extensions import Annotated
|
|
7
|
+
|
|
8
|
+
from ..agents import WaldiezAgents
|
|
9
|
+
from ..chat import WaldiezChat
|
|
10
|
+
from ..common import WaldiezBase
|
|
11
|
+
from ..model import WaldiezModel
|
|
12
|
+
from ..skill import WaldiezSkill
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WaldiezFlowData(WaldiezBase):
|
|
16
|
+
"""Flow data class.
|
|
17
|
+
|
|
18
|
+
Attributes
|
|
19
|
+
----------
|
|
20
|
+
nodes : List[Dict[str, Any]]
|
|
21
|
+
The nodes of the flow. We ignore this (UI-related)
|
|
22
|
+
edges : List[Dict[str, Any]]
|
|
23
|
+
The edges of the flow. We ignore this (UI-related)
|
|
24
|
+
viewport : Dict[str, Any]
|
|
25
|
+
The viewport of the flow. We ignore this (UI-related)
|
|
26
|
+
agents : WaldiezAgents
|
|
27
|
+
The agents of the flow:
|
|
28
|
+
users: List[WaldiezUserProxy]
|
|
29
|
+
assistants: List[WaldiezAssistant]
|
|
30
|
+
managers: List[WaldiezGroupManager]
|
|
31
|
+
rag_users : List[WaldiezRagUser]
|
|
32
|
+
See `WaldiezAgents` for more info.
|
|
33
|
+
models : List[WaldiezModel]
|
|
34
|
+
The models of the flow. See `WaldiezModel`.
|
|
35
|
+
skills : List[WaldiezSkill]
|
|
36
|
+
The skills of the flow. See `WaldiezSkill`.
|
|
37
|
+
chats : List[WaldiezChat]
|
|
38
|
+
The chats of the flow. See `WaldiezChat`.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# the ones below (nodes,edges, viewport) we ignore
|
|
42
|
+
# (they for graph connections, positions, etc.)
|
|
43
|
+
nodes: Annotated[
|
|
44
|
+
List[Dict[str, Any]],
|
|
45
|
+
Field(default_factory=list),
|
|
46
|
+
]
|
|
47
|
+
edges: Annotated[
|
|
48
|
+
List[Dict[str, Any]],
|
|
49
|
+
Field(default_factory=list),
|
|
50
|
+
]
|
|
51
|
+
viewport: Annotated[
|
|
52
|
+
Dict[str, Any],
|
|
53
|
+
Field(default_factory=dict),
|
|
54
|
+
]
|
|
55
|
+
# these are the ones we use.
|
|
56
|
+
agents: Annotated[
|
|
57
|
+
WaldiezAgents,
|
|
58
|
+
Field(
|
|
59
|
+
description="The agents of the flow",
|
|
60
|
+
title="Agents",
|
|
61
|
+
default_factory=WaldiezAgents,
|
|
62
|
+
),
|
|
63
|
+
]
|
|
64
|
+
models: Annotated[
|
|
65
|
+
List[WaldiezModel],
|
|
66
|
+
Field(
|
|
67
|
+
description="The models of the flow",
|
|
68
|
+
title="Models",
|
|
69
|
+
default_factory=list,
|
|
70
|
+
),
|
|
71
|
+
]
|
|
72
|
+
skills: Annotated[
|
|
73
|
+
List[WaldiezSkill],
|
|
74
|
+
Field(
|
|
75
|
+
description="The skills of the flow",
|
|
76
|
+
title="Skills",
|
|
77
|
+
default_factory=list,
|
|
78
|
+
),
|
|
79
|
+
]
|
|
80
|
+
chats: Annotated[
|
|
81
|
+
List[WaldiezChat],
|
|
82
|
+
Field(
|
|
83
|
+
description="The chats of the flow",
|
|
84
|
+
title="Chats",
|
|
85
|
+
default_factory=list,
|
|
86
|
+
),
|
|
87
|
+
]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Waldiez model(llm) model."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
from typing_extensions import Annotated, Literal
|
|
8
|
+
|
|
9
|
+
from ..common import WaldiezBase, now
|
|
10
|
+
from .model_data import WaldiezModelData
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WaldiezModel(WaldiezBase):
|
|
14
|
+
"""Waldiez Model class.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
id : str
|
|
19
|
+
The ID of the model.
|
|
20
|
+
name : str
|
|
21
|
+
The name of the model.
|
|
22
|
+
description : str
|
|
23
|
+
The description of the model.
|
|
24
|
+
tags : List[str]
|
|
25
|
+
The tags of the model.
|
|
26
|
+
requirements : List[str]
|
|
27
|
+
The requirements of the model.
|
|
28
|
+
created_at : str
|
|
29
|
+
The date and time when the model was created.
|
|
30
|
+
updated_at : str
|
|
31
|
+
The date and time when the model was last updated.
|
|
32
|
+
data : WaldiezModelData
|
|
33
|
+
The data of the model.
|
|
34
|
+
See `waldiez.models.model.WaldiezModelData` for more information.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
id: Annotated[
|
|
38
|
+
str, Field(..., title="ID", description="The ID of the model.")
|
|
39
|
+
]
|
|
40
|
+
type: Annotated[
|
|
41
|
+
Literal["model"],
|
|
42
|
+
Field(
|
|
43
|
+
default="model",
|
|
44
|
+
title="Type",
|
|
45
|
+
description="The type of the 'node' in a graph.",
|
|
46
|
+
),
|
|
47
|
+
]
|
|
48
|
+
name: Annotated[
|
|
49
|
+
str, Field(..., title="Name", description="The name of the model.")
|
|
50
|
+
]
|
|
51
|
+
description: Annotated[
|
|
52
|
+
str,
|
|
53
|
+
Field(
|
|
54
|
+
...,
|
|
55
|
+
title="Description",
|
|
56
|
+
description="The description of the model.",
|
|
57
|
+
),
|
|
58
|
+
]
|
|
59
|
+
tags: Annotated[
|
|
60
|
+
List[str],
|
|
61
|
+
Field(
|
|
62
|
+
default_factory=list,
|
|
63
|
+
title="Tags",
|
|
64
|
+
description="The tags of the model.",
|
|
65
|
+
),
|
|
66
|
+
]
|
|
67
|
+
requirements: Annotated[
|
|
68
|
+
List[str],
|
|
69
|
+
Field(
|
|
70
|
+
default_factory=list,
|
|
71
|
+
title="Requirements",
|
|
72
|
+
description="The requirements of the model.",
|
|
73
|
+
),
|
|
74
|
+
]
|
|
75
|
+
created_at: Annotated[
|
|
76
|
+
str,
|
|
77
|
+
Field(
|
|
78
|
+
default_factory=now,
|
|
79
|
+
title="Create At",
|
|
80
|
+
description="The date and time when the model was created.",
|
|
81
|
+
),
|
|
82
|
+
]
|
|
83
|
+
updated_at: Annotated[
|
|
84
|
+
str,
|
|
85
|
+
Field(
|
|
86
|
+
default_factory=now,
|
|
87
|
+
title="Updated At",
|
|
88
|
+
description="The date and time when the model was last updated.",
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
data: Annotated[
|
|
92
|
+
WaldiezModelData,
|
|
93
|
+
Field(..., title="Data", description="The data of the model."),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def api_key(self) -> str:
|
|
98
|
+
"""Get the model's api key.
|
|
99
|
+
|
|
100
|
+
Either from the model's data or from the environment variables:
|
|
101
|
+
|
|
102
|
+
- openai: 'OPENAI_API_KEY',
|
|
103
|
+
- azure: 'AZURE_API_KEY',
|
|
104
|
+
- google: 'GOOGLE_GEMINI_API_KEY',
|
|
105
|
+
- anthropic: 'ANTHROPIC_API_KEY',
|
|
106
|
+
- mistral: 'MISTRAL_API_KEY',
|
|
107
|
+
- groq: 'GROQ_API_KEY',
|
|
108
|
+
- together: 'TOGETHER_API_KEY',
|
|
109
|
+
- nim: 'NIM_API_KEY',
|
|
110
|
+
- other: 'OPENAI_API_KEY'
|
|
111
|
+
"""
|
|
112
|
+
if self.data.api_key:
|
|
113
|
+
return self.data.api_key
|
|
114
|
+
env_key = "OPENAI_API_KEY"
|
|
115
|
+
if self.data.api_type == "google":
|
|
116
|
+
env_key = "GOOGLE_GEMINI_API_KEY"
|
|
117
|
+
elif self.data.api_type not in ["openai", "other"]:
|
|
118
|
+
env_key = f"{self.data.api_type.upper()}_API_KEY"
|
|
119
|
+
api_key = os.environ.get(env_key, "")
|
|
120
|
+
return api_key
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def price(self) -> Optional[List[float]]:
|
|
124
|
+
"""Get the model's price."""
|
|
125
|
+
if self.data.price is None:
|
|
126
|
+
return None
|
|
127
|
+
if isinstance(
|
|
128
|
+
self.data.price.prompt_price_per_1k, float
|
|
129
|
+
) and isinstance(self.data.price.completion_token_price_per_1k, float):
|
|
130
|
+
return [
|
|
131
|
+
self.data.price.prompt_price_per_1k,
|
|
132
|
+
self.data.price.completion_token_price_per_1k,
|
|
133
|
+
]
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
def get_llm_config(self, skip_price: bool = False) -> Dict[str, Any]:
|
|
137
|
+
"""Get the model's llm config.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
skip_price : bool, optional
|
|
142
|
+
Whether to skip the price, by default False
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
Dict[str, Any]
|
|
147
|
+
The model's llm config dictionary.
|
|
148
|
+
"""
|
|
149
|
+
_llm_config: Dict[str, Any] = {}
|
|
150
|
+
_llm_config["model"] = self.name
|
|
151
|
+
for attr, atr_type in [
|
|
152
|
+
("base_url", str),
|
|
153
|
+
("max_tokens", int),
|
|
154
|
+
("temperature", float),
|
|
155
|
+
("top_p", float),
|
|
156
|
+
("api_version", str),
|
|
157
|
+
("default_headers", dict),
|
|
158
|
+
]:
|
|
159
|
+
value = getattr(self.data, attr)
|
|
160
|
+
if value and isinstance(value, atr_type):
|
|
161
|
+
_llm_config[attr] = value
|
|
162
|
+
if self.data.api_type not in ["nim", "other"]:
|
|
163
|
+
_llm_config["api_type"] = self.data.api_type
|
|
164
|
+
other_attrs = ["api_key"] if skip_price else ["api_key", "price"]
|
|
165
|
+
for attr in other_attrs:
|
|
166
|
+
value = getattr(self, attr)
|
|
167
|
+
if value:
|
|
168
|
+
_llm_config[attr] = value
|
|
169
|
+
return _llm_config
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Waldiez Model Data."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from typing_extensions import Annotated, Literal
|
|
7
|
+
|
|
8
|
+
from ..common import WaldiezBase
|
|
9
|
+
|
|
10
|
+
WaldiezModelAPIType = Literal[
|
|
11
|
+
"openai",
|
|
12
|
+
"azure",
|
|
13
|
+
"google",
|
|
14
|
+
"anthropic",
|
|
15
|
+
"mistral",
|
|
16
|
+
"groq",
|
|
17
|
+
"together",
|
|
18
|
+
"nim",
|
|
19
|
+
"other",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WaldiezModelPrice(WaldiezBase):
|
|
24
|
+
"""Model Price.
|
|
25
|
+
|
|
26
|
+
Attributes
|
|
27
|
+
----------
|
|
28
|
+
prompt_price_per_1k : float
|
|
29
|
+
The prompt price per 1k tokens.
|
|
30
|
+
completion_token_price_per_1k : float
|
|
31
|
+
The completion token price per 1k tokens.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
prompt_price_per_1k: Annotated[
|
|
35
|
+
Optional[float], Field(None, alias="promptPricePer1k")
|
|
36
|
+
]
|
|
37
|
+
completion_token_price_per_1k: Annotated[
|
|
38
|
+
Optional[float], Field(None, alias="completionTokenPricePer1k")
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# pylint: disable=line-too-long
|
|
43
|
+
class WaldiezModelData(WaldiezBase):
|
|
44
|
+
"""Waldiez Model Data.
|
|
45
|
+
|
|
46
|
+
Attributes
|
|
47
|
+
----------
|
|
48
|
+
base_url : Optional[str]
|
|
49
|
+
The base url of the model, by default None.
|
|
50
|
+
api_key : Optional[str]
|
|
51
|
+
The api key to use with the model, by default None.
|
|
52
|
+
api_type : Literal["openai","azure","google","anthropic","mistral","groq","together","nim","other"]
|
|
53
|
+
The api type of the model.
|
|
54
|
+
api_version : Optional[str]
|
|
55
|
+
The api version of the model, by default None.
|
|
56
|
+
temperature : Optional[float]
|
|
57
|
+
The temperature of the model, by default None.
|
|
58
|
+
top_p : Optional[float]
|
|
59
|
+
The top p of the model, by default None.
|
|
60
|
+
max_tokens : Optional[int]
|
|
61
|
+
The max tokens of the model, by default None.
|
|
62
|
+
default_headers : Dict[str, str]
|
|
63
|
+
The default headers of the model.
|
|
64
|
+
price : Optional[WaldiezModelPrice]
|
|
65
|
+
The price of the model, by default None.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
base_url: Annotated[
|
|
69
|
+
Optional[str],
|
|
70
|
+
Field(
|
|
71
|
+
None,
|
|
72
|
+
title="Base URL",
|
|
73
|
+
description="The base url of the model",
|
|
74
|
+
alias="baseUrl",
|
|
75
|
+
),
|
|
76
|
+
]
|
|
77
|
+
api_key: Annotated[Optional[str], Field(None, alias="apiKey")]
|
|
78
|
+
api_type: Annotated[WaldiezModelAPIType, Field("other", alias="apiType")]
|
|
79
|
+
api_version: Annotated[Optional[str], Field(None, alias="apiVersion")]
|
|
80
|
+
temperature: Annotated[Optional[float], Field(None, alias="temperature")]
|
|
81
|
+
top_p: Annotated[Optional[float], Field(None, alias="topP")]
|
|
82
|
+
max_tokens: Annotated[Optional[int], Field(None, alias="maxTokens")]
|
|
83
|
+
default_headers: Annotated[
|
|
84
|
+
Dict[str, str], Field(alias="defaultHeaders", default_factory=dict)
|
|
85
|
+
]
|
|
86
|
+
price: Annotated[Optional[WaldiezModelPrice], Field(None)]
|