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.

Files changed (94) hide show
  1. waldiez/__init__.py +15 -0
  2. waldiez/__main__.py +6 -0
  3. waldiez/_version.py +3 -0
  4. waldiez/cli.py +162 -0
  5. waldiez/exporter.py +293 -0
  6. waldiez/exporting/__init__.py +14 -0
  7. waldiez/exporting/agents/__init__.py +5 -0
  8. waldiez/exporting/agents/agent.py +229 -0
  9. waldiez/exporting/agents/agent_skills.py +67 -0
  10. waldiez/exporting/agents/code_execution.py +67 -0
  11. waldiez/exporting/agents/group_manager.py +209 -0
  12. waldiez/exporting/agents/llm_config.py +53 -0
  13. waldiez/exporting/agents/rag_user/__init__.py +5 -0
  14. waldiez/exporting/agents/rag_user/chroma_utils.py +134 -0
  15. waldiez/exporting/agents/rag_user/mongo_utils.py +83 -0
  16. waldiez/exporting/agents/rag_user/pgvector_utils.py +93 -0
  17. waldiez/exporting/agents/rag_user/qdrant_utils.py +112 -0
  18. waldiez/exporting/agents/rag_user/rag_user.py +165 -0
  19. waldiez/exporting/agents/rag_user/vector_db.py +119 -0
  20. waldiez/exporting/agents/teachability.py +37 -0
  21. waldiez/exporting/agents/termination_message.py +45 -0
  22. waldiez/exporting/chats/__init__.py +14 -0
  23. waldiez/exporting/chats/chats.py +46 -0
  24. waldiez/exporting/chats/helpers.py +395 -0
  25. waldiez/exporting/chats/nested.py +264 -0
  26. waldiez/exporting/flow/__init__.py +5 -0
  27. waldiez/exporting/flow/def_main.py +37 -0
  28. waldiez/exporting/flow/flow.py +185 -0
  29. waldiez/exporting/models/__init__.py +193 -0
  30. waldiez/exporting/skills/__init__.py +128 -0
  31. waldiez/exporting/utils/__init__.py +34 -0
  32. waldiez/exporting/utils/comments.py +136 -0
  33. waldiez/exporting/utils/importing.py +267 -0
  34. waldiez/exporting/utils/logging_utils.py +203 -0
  35. waldiez/exporting/utils/method_utils.py +35 -0
  36. waldiez/exporting/utils/naming.py +127 -0
  37. waldiez/exporting/utils/object_string.py +81 -0
  38. waldiez/io_stream.py +181 -0
  39. waldiez/models/__init__.py +107 -0
  40. waldiez/models/agents/__init__.py +65 -0
  41. waldiez/models/agents/agent/__init__.py +21 -0
  42. waldiez/models/agents/agent/agent.py +190 -0
  43. waldiez/models/agents/agent/agent_data.py +162 -0
  44. waldiez/models/agents/agent/code_execution.py +71 -0
  45. waldiez/models/agents/agent/linked_skill.py +30 -0
  46. waldiez/models/agents/agent/nested_chat.py +73 -0
  47. waldiez/models/agents/agent/teachability.py +68 -0
  48. waldiez/models/agents/agent/termination_message.py +167 -0
  49. waldiez/models/agents/agents.py +129 -0
  50. waldiez/models/agents/assistant/__init__.py +6 -0
  51. waldiez/models/agents/assistant/assistant.py +41 -0
  52. waldiez/models/agents/assistant/assistant_data.py +29 -0
  53. waldiez/models/agents/group_manager/__init__.py +19 -0
  54. waldiez/models/agents/group_manager/group_manager.py +87 -0
  55. waldiez/models/agents/group_manager/group_manager_data.py +91 -0
  56. waldiez/models/agents/group_manager/speakers.py +211 -0
  57. waldiez/models/agents/rag_user/__init__.py +26 -0
  58. waldiez/models/agents/rag_user/rag_user.py +58 -0
  59. waldiez/models/agents/rag_user/rag_user_data.py +32 -0
  60. waldiez/models/agents/rag_user/retrieve_config.py +592 -0
  61. waldiez/models/agents/rag_user/vector_db_config.py +162 -0
  62. waldiez/models/agents/user_proxy/__init__.py +6 -0
  63. waldiez/models/agents/user_proxy/user_proxy.py +41 -0
  64. waldiez/models/agents/user_proxy/user_proxy_data.py +30 -0
  65. waldiez/models/chat/__init__.py +22 -0
  66. waldiez/models/chat/chat.py +129 -0
  67. waldiez/models/chat/chat_data.py +326 -0
  68. waldiez/models/chat/chat_message.py +304 -0
  69. waldiez/models/chat/chat_nested.py +160 -0
  70. waldiez/models/chat/chat_summary.py +110 -0
  71. waldiez/models/common/__init__.py +38 -0
  72. waldiez/models/common/base.py +63 -0
  73. waldiez/models/common/method_utils.py +165 -0
  74. waldiez/models/flow/__init__.py +9 -0
  75. waldiez/models/flow/flow.py +302 -0
  76. waldiez/models/flow/flow_data.py +87 -0
  77. waldiez/models/model/__init__.py +11 -0
  78. waldiez/models/model/model.py +169 -0
  79. waldiez/models/model/model_data.py +86 -0
  80. waldiez/models/skill/__init__.py +9 -0
  81. waldiez/models/skill/skill.py +129 -0
  82. waldiez/models/skill/skill_data.py +37 -0
  83. waldiez/models/waldiez.py +301 -0
  84. waldiez/py.typed +0 -0
  85. waldiez/runner.py +304 -0
  86. waldiez/stream/__init__.py +7 -0
  87. waldiez/stream/consumer.py +139 -0
  88. waldiez/stream/provider.py +339 -0
  89. waldiez/stream/server.py +412 -0
  90. waldiez-0.1.0.dist-info/METADATA +181 -0
  91. waldiez-0.1.0.dist-info/RECORD +94 -0
  92. waldiez-0.1.0.dist-info/WHEEL +4 -0
  93. waldiez-0.1.0.dist-info/entry_points.txt +2 -0
  94. waldiez-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,160 @@
1
+ """Nested chat model."""
2
+
3
+ from typing import Any, Optional
4
+
5
+ from pydantic import (
6
+ ConfigDict,
7
+ Field,
8
+ ValidationInfo,
9
+ field_validator,
10
+ model_validator,
11
+ )
12
+ from pydantic.alias_generators import to_camel
13
+ from typing_extensions import Annotated, Self
14
+
15
+ from ..common import WaldiezBase, WaldiezMethodName
16
+ from .chat_message import WaldiezChatMessage, validate_message_dict
17
+
18
+
19
+ class WaldiezChatNested(WaldiezBase):
20
+ """Nested chat class.
21
+
22
+ Attributes
23
+ ----------
24
+ message : WaldiezChatMessage
25
+ The message in a nested chat (sender -> recipient).
26
+ reply : WaldiezChatMessage
27
+ The reply in a nested chat (recipient -> sender).
28
+ """
29
+
30
+ model_config = ConfigDict(
31
+ extra="forbid",
32
+ alias_generator=to_camel,
33
+ populate_by_name=True,
34
+ frozen=False,
35
+ )
36
+
37
+ message: Annotated[
38
+ Optional[WaldiezChatMessage],
39
+ Field(
40
+ None,
41
+ title="Message",
42
+ description="The message in a nested chat (sender -> recipient).",
43
+ ),
44
+ ]
45
+ reply: Annotated[
46
+ Optional[WaldiezChatMessage],
47
+ Field(
48
+ None,
49
+ title="Reply",
50
+ description="The reply in a nested chat (recipient -> sender).",
51
+ ),
52
+ ]
53
+
54
+ _message_content: Optional[str] = None
55
+ _reply_content: Optional[str] = None
56
+
57
+ @property
58
+ def message_content(self) -> Optional[str]:
59
+ """Get the message content."""
60
+ return self._message_content
61
+
62
+ @property
63
+ def reply_content(self) -> Optional[str]:
64
+ """Get the reply content."""
65
+ return self._reply_content
66
+
67
+ @field_validator("message", "reply", mode="before")
68
+ @classmethod
69
+ def validate_message(
70
+ cls, value: Any, info: ValidationInfo
71
+ ) -> WaldiezChatMessage:
72
+ """Validate the message.
73
+
74
+ Parameters
75
+ ----------
76
+ value : Any
77
+ The value.
78
+ info : ValidationInfo
79
+ The validation info.
80
+
81
+ Returns
82
+ -------
83
+ WaldiezChatMessage
84
+ The validated message.
85
+
86
+ Raises
87
+ ------
88
+ ValueError
89
+ If the validation fails.
90
+ """
91
+ function_name: WaldiezMethodName = (
92
+ "nested_chat_message"
93
+ if info.field_name == "message"
94
+ else "nested_chat_reply"
95
+ )
96
+ if not value:
97
+ return WaldiezChatMessage(
98
+ type="none", use_carryover=False, content=None, context={}
99
+ )
100
+ if isinstance(value, str):
101
+ return WaldiezChatMessage(
102
+ type="string", use_carryover=False, content=value, context={}
103
+ )
104
+ if isinstance(value, dict):
105
+ return validate_message_dict(value, function_name=function_name)
106
+ if isinstance(value, WaldiezChatMessage):
107
+ return validate_message_dict(
108
+ {
109
+ "type": value.type,
110
+ "use_carryover": False,
111
+ "content": value.content,
112
+ "context": value.context,
113
+ },
114
+ function_name=function_name,
115
+ )
116
+ raise ValueError(f"Invalid message type: {type(value)}")
117
+
118
+ @model_validator(mode="after")
119
+ def validate_nested_chat(self) -> Self:
120
+ """Validate the nested chat.
121
+
122
+ Returns
123
+ -------
124
+ WaldiezChatNested
125
+ The validated nested chat.
126
+
127
+ Raises
128
+ ------
129
+ ValueError
130
+ If the validation fails.
131
+ """
132
+ if self.message is not None:
133
+ if self.message.type == "none":
134
+ self._message_content = ""
135
+ elif self.message.type == "string":
136
+ self._message_content = self.message.content
137
+ else:
138
+ self._message_content = validate_message_dict(
139
+ value={
140
+ "type": "method",
141
+ "content": self.message.content,
142
+ },
143
+ function_name="nested_chat_message",
144
+ skip_definition=True,
145
+ ).content
146
+ if self.reply is not None:
147
+ if self.reply.type == "none":
148
+ self._reply_content = ""
149
+ elif self.reply.type == "string":
150
+ self._reply_content = self.reply.content
151
+ else:
152
+ self._reply_content = validate_message_dict(
153
+ value={
154
+ "type": "method",
155
+ "content": self.reply.content,
156
+ },
157
+ function_name="nested_chat_reply",
158
+ skip_definition=True,
159
+ ).content
160
+ return self
@@ -0,0 +1,110 @@
1
+ """Waldiez chat summary options."""
2
+
3
+ from typing import Any, Dict, Optional
4
+
5
+ from pydantic import (
6
+ Field,
7
+ FieldSerializationInfo,
8
+ field_serializer,
9
+ field_validator,
10
+ )
11
+ from typing_extensions import Annotated, Literal
12
+
13
+ from ..common import WaldiezBase
14
+
15
+ WaldiezChatSummaryMethod = Literal[
16
+ "reflectionWithLlm",
17
+ "lastMsg",
18
+ "reflection_with_llm",
19
+ "last_msg",
20
+ ]
21
+
22
+
23
+ class WaldiezChatSummary(WaldiezBase):
24
+ """Llm summary method options.
25
+
26
+ Attributes
27
+ ----------
28
+ method : Optional[WaldiezChatSummaryMethod]
29
+ The method to use for the LLM summary. Defaults to "last_msg".
30
+ prompt : str
31
+ The prompt for the LLM summary method.
32
+ args : Optional[Dict[str, Any]]
33
+ The additional arguments for the LLM summary method, by default None.
34
+ """
35
+
36
+ method: Annotated[
37
+ Optional[WaldiezChatSummaryMethod],
38
+ Field(
39
+ "last_msg",
40
+ title="Method",
41
+ description="The method to use for the LLM summary.",
42
+ ),
43
+ ]
44
+ prompt: Annotated[
45
+ str,
46
+ Field(
47
+ "",
48
+ title="Prompt",
49
+ description="The prompt for the LLM summary method.",
50
+ ),
51
+ ]
52
+ args: Annotated[
53
+ Dict[str, str],
54
+ Field(
55
+ title="Arguments",
56
+ description="The additional arguments for the LLM summary method.",
57
+ default_factory=dict,
58
+ ),
59
+ ]
60
+
61
+ @field_validator("method", mode="before")
62
+ @classmethod
63
+ def validate_summary_method(
64
+ cls, value: Optional[WaldiezChatSummaryMethod]
65
+ ) -> Optional[WaldiezChatSummaryMethod]:
66
+ """Validate the summary method.
67
+
68
+ Parameters
69
+ ----------
70
+ value : Optional[WaldiezChatSummaryMethod]
71
+ The passed WaldiezChatSummaryMethod
72
+
73
+ Returns
74
+ -------
75
+ Optional[WaldiezChatSummaryMethod]
76
+ The validated message summary method
77
+ """
78
+ if str(value).lower() == "none":
79
+ return None
80
+ if value == "lastMsg":
81
+ return "last_msg"
82
+ if value == "reflectionWithLlm":
83
+ return "reflection_with_llm"
84
+ return value
85
+
86
+ @field_serializer("method")
87
+ @classmethod
88
+ def serialize_summary_method(
89
+ cls, value: Any, info: FieldSerializationInfo
90
+ ) -> Any:
91
+ """Serialize summary method.
92
+
93
+ Parameters
94
+ ----------
95
+ value : Any
96
+ The value to serialize.
97
+ info : FieldSerializationInfo
98
+ The serialization info.
99
+
100
+ Returns
101
+ -------
102
+ Any
103
+ The serialized value.
104
+ """
105
+ if info.by_alias is True:
106
+ if value == "reflection_with_llm":
107
+ return "reflectionWithLlm"
108
+ if value == "last_msg":
109
+ return "lastMsg"
110
+ return value
@@ -0,0 +1,38 @@
1
+ """Common utils for all models."""
2
+
3
+ from datetime import datetime, timezone
4
+
5
+ from .base import WaldiezBase
6
+ from .method_utils import (
7
+ METHOD_ARGS,
8
+ METHOD_TYPE_HINTS,
9
+ WaldiezMethodName,
10
+ check_function,
11
+ parse_code_string,
12
+ )
13
+
14
+
15
+ def now() -> str:
16
+ """Get the current date and time in UTC.
17
+
18
+ Returns
19
+ -------
20
+ str
21
+ The current date and time in UTC.
22
+ """
23
+ return (
24
+ datetime.now(tz=timezone.utc)
25
+ .isoformat(timespec="milliseconds")
26
+ .replace("+00:00", "Z")
27
+ )
28
+
29
+
30
+ __all__ = [
31
+ "WaldiezBase",
32
+ "METHOD_ARGS",
33
+ "METHOD_TYPE_HINTS",
34
+ "WaldiezMethodName",
35
+ "now",
36
+ "check_function",
37
+ "parse_code_string",
38
+ ]
@@ -0,0 +1,63 @@
1
+ """Base class to inherit from."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from pydantic import BaseModel, ConfigDict
6
+ from pydantic.alias_generators import to_camel
7
+
8
+
9
+ class WaldiezBase(BaseModel):
10
+ """Base model class to inherit from.
11
+
12
+ It contains the default configuration for all models.
13
+ It also `model_dumps` by alias by default.
14
+ """
15
+
16
+ model_config = ConfigDict(
17
+ extra="forbid",
18
+ # treat `skillId` as `skill_id`
19
+ alias_generator=to_camel,
20
+ # allow passing either `skill_id` or `skillId`
21
+ populate_by_name=True,
22
+ frozen=True,
23
+ )
24
+
25
+ def model_dump(self, **kwargs: Any) -> Dict[str, Any]:
26
+ """Dump the model to a dictionary.
27
+
28
+ Parameters
29
+ ----------
30
+ **kwargs : Any
31
+ Additional keyword arguments.
32
+
33
+ Returns
34
+ -------
35
+ Dict[str, Any]
36
+ The dictionary representation of the model.
37
+ """
38
+ by_alias = kwargs.pop("by_alias", None)
39
+ if by_alias is None:
40
+ by_alias = True
41
+ if not isinstance(by_alias, bool):
42
+ by_alias = True
43
+ return super().model_dump(by_alias=by_alias, **kwargs)
44
+
45
+ def model_dump_json(self, **kwargs: Any) -> str:
46
+ """Dump the model to a JSON string.
47
+
48
+ Parameters
49
+ ----------
50
+ **kwargs : Any
51
+ Additional keyword arguments.
52
+
53
+ Returns
54
+ -------
55
+ str
56
+ The JSON string.
57
+ """
58
+ by_alias = kwargs.pop("by_alias", None)
59
+ if by_alias is None:
60
+ by_alias = True
61
+ if not isinstance(by_alias, bool):
62
+ by_alias = True
63
+ return super().model_dump_json(by_alias=by_alias, **kwargs)
@@ -0,0 +1,165 @@
1
+ """Function related utilities."""
2
+
3
+ import ast
4
+ from typing import Dict, List, Literal, Optional, Tuple
5
+
6
+ WaldiezMethodName = Literal[
7
+ "callable_message", # Chat
8
+ "is_termination_message", # Agent
9
+ "nested_chat_message", # Agents' NestedChat
10
+ "nested_chat_reply", # Agents' NestedChat
11
+ "custom_speaker_selection", # GroupChat
12
+ "custom_embedding_function", # RAG
13
+ "custom_token_count_function", # RAG
14
+ "custom_text_split_function", # RAG
15
+ ]
16
+
17
+ METHOD_ARGS: Dict[WaldiezMethodName, List[str]] = {
18
+ "callable_message": ["sender", "recipient", "context"],
19
+ "is_termination_message": ["message"],
20
+ "nested_chat_message": ["recipient", "messages", "sender", "config"],
21
+ "nested_chat_reply": ["recipient", "messages", "sender", "config"],
22
+ "custom_speaker_selection": ["last_speaker", "groupchat"],
23
+ "custom_embedding_function": [],
24
+ "custom_token_count_function": ["text", "model"],
25
+ "custom_text_split_function": [
26
+ "text",
27
+ "max_tokens",
28
+ "chunk_mode",
29
+ "must_break_at_empty_line",
30
+ "overlap",
31
+ ],
32
+ }
33
+
34
+ # pylint: disable=line-too-long
35
+ METHOD_TYPE_HINTS: Dict[WaldiezMethodName, str] = {
36
+ "callable_message": "# type: (ConversableAgent, ConversableAgent, dict) -> Union[dict, str]",
37
+ "is_termination_message": "# type: (dict) -> bool",
38
+ "nested_chat_message": "# type: (ConversableAgent, list[dict], ConversableAgent, dict) -> Union[dict, str]",
39
+ "nested_chat_reply": "# type: (ConversableAgent, list[dict], ConversableAgent, dict) -> Union[dict, str]",
40
+ "custom_speaker_selection": "# type: (ConversableAgent, GroupChat) -> Union[Agent, str, None]",
41
+ "custom_embedding_function": "# type: () -> Callable[..., Any]",
42
+ "custom_token_count_function": "# type: (str, str) -> int",
43
+ "custom_text_split_function": "# type: (str, int, str, bool, int) -> List[str]",
44
+ }
45
+
46
+
47
+ def parse_code_string(
48
+ code_string: str,
49
+ ) -> Tuple[Optional[str], Optional[ast.Module]]:
50
+ """Parse the code string.
51
+
52
+ Parameters
53
+ ----------
54
+ code_string : str
55
+ The code string.
56
+
57
+ Returns
58
+ -------
59
+ Tuple[Optional[str], Optional[ast.Module]]
60
+ If valid, None and the ast module.
61
+ If invalid, the error message and None.
62
+ """
63
+ # pylint: disable=broad-except
64
+ try:
65
+ tree = ast.parse(code_string)
66
+ except SyntaxError as e:
67
+ return f"SyntaxError: {e}, in \n{code_string}", None
68
+ except BaseException as e: # pragma: no cover
69
+ return f"Invalid code: {e}, in \n{code_string}", None
70
+ return None, tree
71
+
72
+
73
+ def check_function(
74
+ code_string: str,
75
+ function_name: WaldiezMethodName,
76
+ skip_type_hints: bool = False,
77
+ ) -> Tuple[bool, str]:
78
+ """Check the function.
79
+
80
+ Parameters
81
+ ----------
82
+ code_string : str
83
+ The code string.
84
+ function_name : WaldiezMethodName
85
+ The expected function name.
86
+ skip_type_hints : bool, optional
87
+ Whether to skip type hints in the function body, by default False.
88
+
89
+ Returns
90
+ -------
91
+ Tuple[bool, str]
92
+ If valid, True and the function body (only), no extra lines.
93
+ If invalid, False and the error message.
94
+ """
95
+ error, tree = parse_code_string(code_string)
96
+ if error is not None or tree is None:
97
+ return False, error or "Invalid code"
98
+ if function_name not in METHOD_ARGS:
99
+ return False, f"Invalid function name: {function_name}"
100
+ expected_method_args = METHOD_ARGS[function_name]
101
+ return _get_function_body(
102
+ tree,
103
+ code_string,
104
+ function_name,
105
+ expected_method_args,
106
+ skip_type_hints=skip_type_hints,
107
+ )
108
+
109
+
110
+ def _get_function_body(
111
+ tree: ast.Module,
112
+ code_string: str,
113
+ function_name: WaldiezMethodName,
114
+ method_args: List[str],
115
+ skip_type_hints: bool = False,
116
+ ) -> Tuple[bool, str]:
117
+ """Get the function body.
118
+
119
+ Parameters
120
+ ----------
121
+ tree : ast.Module
122
+ The ast module.
123
+ code_string : str
124
+ The code string.
125
+ function_name : WaldiezMethodName
126
+ The expected function name.
127
+ method_args : List[str]
128
+ The expected method arguments.
129
+
130
+ Returns
131
+ -------
132
+ Tuple[bool, str]
133
+ If valid, True and the function body (only), no extra lines.
134
+ If invalid, False and the error message.
135
+ """
136
+ for node in ast.walk(tree):
137
+ if isinstance(node, ast.FunctionDef):
138
+ if node.name != function_name:
139
+ continue
140
+ if len(node.args.args) != len(method_args):
141
+ return (
142
+ False,
143
+ f"Invalid number of arguments in function {node.name}",
144
+ )
145
+ for arg, expected_arg in zip(node.args.args, method_args):
146
+ if arg.arg != expected_arg:
147
+ return (
148
+ False,
149
+ f"Invalid argument name in function {node.name}",
150
+ )
151
+ function_body_lines = code_string.splitlines()[
152
+ node.lineno - 1 : node.end_lineno
153
+ ]
154
+ function_body = "\n".join(function_body_lines[1:])
155
+ if not skip_type_hints:
156
+ # add type hints after the function definition
157
+ function_body = (
158
+ f" {METHOD_TYPE_HINTS[function_name]}\n{function_body}"
159
+ )
160
+ return True, function_body
161
+ error_msg = (
162
+ f"No function with name `{function_name}`"
163
+ f" and arguments `{method_args}` found"
164
+ )
165
+ return False, error_msg
@@ -0,0 +1,9 @@
1
+ """Waldiez flow related models."""
2
+
3
+ from .flow import WaldiezFlow
4
+ from .flow_data import WaldiezFlowData
5
+
6
+ __all__ = [
7
+ "WaldiezFlow",
8
+ "WaldiezFlowData",
9
+ ]