lionagi 0.1.1__py3-none-any.whl → 0.2.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. lionagi/__init__.py +60 -5
  2. lionagi/core/__init__.py +0 -25
  3. lionagi/core/_setting/_setting.py +59 -0
  4. lionagi/core/action/__init__.py +14 -0
  5. lionagi/core/action/function_calling.py +136 -0
  6. lionagi/core/action/manual.py +1 -0
  7. lionagi/core/action/node.py +109 -0
  8. lionagi/core/action/tool.py +114 -0
  9. lionagi/core/action/tool_manager.py +356 -0
  10. lionagi/core/agent/base_agent.py +27 -13
  11. lionagi/core/agent/eval/evaluator.py +1 -0
  12. lionagi/core/agent/eval/vote.py +40 -0
  13. lionagi/core/agent/learn/learner.py +59 -0
  14. lionagi/core/agent/plan/unit_template.py +1 -0
  15. lionagi/core/collections/__init__.py +17 -0
  16. lionagi/core/{generic/data_logger.py → collections/_logger.py} +69 -55
  17. lionagi/core/collections/abc/__init__.py +53 -0
  18. lionagi/core/collections/abc/component.py +615 -0
  19. lionagi/core/collections/abc/concepts.py +297 -0
  20. lionagi/core/collections/abc/exceptions.py +150 -0
  21. lionagi/core/collections/abc/util.py +45 -0
  22. lionagi/core/collections/exchange.py +161 -0
  23. lionagi/core/collections/flow.py +426 -0
  24. lionagi/core/collections/model.py +419 -0
  25. lionagi/core/collections/pile.py +913 -0
  26. lionagi/core/collections/progression.py +236 -0
  27. lionagi/core/collections/util.py +64 -0
  28. lionagi/core/director/direct.py +314 -0
  29. lionagi/core/director/director.py +2 -0
  30. lionagi/core/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
  31. lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
  32. lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
  33. lionagi/core/executor/base_executor.py +90 -0
  34. lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +83 -67
  35. lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
  36. lionagi/core/generic/__init__.py +3 -33
  37. lionagi/core/generic/edge.py +42 -92
  38. lionagi/core/generic/edge_condition.py +16 -0
  39. lionagi/core/generic/graph.py +236 -0
  40. lionagi/core/generic/hyperedge.py +1 -0
  41. lionagi/core/generic/node.py +156 -221
  42. lionagi/core/generic/tree.py +48 -0
  43. lionagi/core/generic/tree_node.py +79 -0
  44. lionagi/core/mail/__init__.py +12 -0
  45. lionagi/core/mail/mail.py +25 -0
  46. lionagi/core/mail/mail_manager.py +139 -58
  47. lionagi/core/mail/package.py +45 -0
  48. lionagi/core/mail/start_mail.py +36 -0
  49. lionagi/core/message/__init__.py +19 -0
  50. lionagi/core/message/action_request.py +133 -0
  51. lionagi/core/message/action_response.py +135 -0
  52. lionagi/core/message/assistant_response.py +95 -0
  53. lionagi/core/message/instruction.py +234 -0
  54. lionagi/core/message/message.py +101 -0
  55. lionagi/core/message/system.py +86 -0
  56. lionagi/core/message/util.py +283 -0
  57. lionagi/core/report/__init__.py +4 -0
  58. lionagi/core/report/base.py +217 -0
  59. lionagi/core/report/form.py +231 -0
  60. lionagi/core/report/report.py +166 -0
  61. lionagi/core/report/util.py +28 -0
  62. lionagi/core/rule/_default.py +16 -0
  63. lionagi/core/rule/action.py +99 -0
  64. lionagi/core/rule/base.py +238 -0
  65. lionagi/core/rule/boolean.py +56 -0
  66. lionagi/core/rule/choice.py +47 -0
  67. lionagi/core/rule/mapping.py +96 -0
  68. lionagi/core/rule/number.py +71 -0
  69. lionagi/core/rule/rulebook.py +109 -0
  70. lionagi/core/rule/string.py +52 -0
  71. lionagi/core/rule/util.py +35 -0
  72. lionagi/core/session/branch.py +431 -0
  73. lionagi/core/session/directive_mixin.py +287 -0
  74. lionagi/core/session/session.py +229 -903
  75. lionagi/core/structure/__init__.py +1 -0
  76. lionagi/core/structure/chain.py +1 -0
  77. lionagi/core/structure/forest.py +1 -0
  78. lionagi/core/structure/graph.py +1 -0
  79. lionagi/core/structure/tree.py +1 -0
  80. lionagi/core/unit/__init__.py +5 -0
  81. lionagi/core/unit/parallel_unit.py +245 -0
  82. lionagi/core/unit/template/action.py +81 -0
  83. lionagi/core/unit/template/base.py +51 -0
  84. lionagi/core/unit/template/plan.py +84 -0
  85. lionagi/core/unit/template/predict.py +109 -0
  86. lionagi/core/unit/template/score.py +124 -0
  87. lionagi/core/unit/template/select.py +104 -0
  88. lionagi/core/unit/unit.py +362 -0
  89. lionagi/core/unit/unit_form.py +305 -0
  90. lionagi/core/unit/unit_mixin.py +1168 -0
  91. lionagi/core/unit/util.py +71 -0
  92. lionagi/core/validator/validator.py +364 -0
  93. lionagi/core/work/work.py +74 -0
  94. lionagi/core/work/work_function.py +92 -0
  95. lionagi/core/work/work_queue.py +81 -0
  96. lionagi/core/work/worker.py +195 -0
  97. lionagi/core/work/worklog.py +124 -0
  98. lionagi/experimental/compressor/base.py +46 -0
  99. lionagi/experimental/compressor/llm_compressor.py +247 -0
  100. lionagi/experimental/compressor/llm_summarizer.py +61 -0
  101. lionagi/experimental/compressor/util.py +70 -0
  102. lionagi/experimental/directive/__init__.py +19 -0
  103. lionagi/experimental/directive/parser/base_parser.py +69 -2
  104. lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
  105. lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
  106. lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
  107. lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
  108. lionagi/experimental/knowledge/__init__.py +0 -0
  109. lionagi/experimental/knowledge/base.py +10 -0
  110. lionagi/experimental/knowledge/graph.py +0 -0
  111. lionagi/experimental/memory/__init__.py +0 -0
  112. lionagi/experimental/strategies/__init__.py +0 -0
  113. lionagi/experimental/strategies/base.py +1 -0
  114. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  115. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  116. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  117. lionagi/integrations/chunker/chunk.py +161 -24
  118. lionagi/integrations/config/oai_configs.py +34 -3
  119. lionagi/integrations/config/openrouter_configs.py +14 -2
  120. lionagi/integrations/loader/load.py +122 -21
  121. lionagi/integrations/loader/load_util.py +6 -77
  122. lionagi/integrations/provider/_mapping.py +46 -0
  123. lionagi/integrations/provider/litellm.py +2 -1
  124. lionagi/integrations/provider/mlx_service.py +16 -9
  125. lionagi/integrations/provider/oai.py +91 -4
  126. lionagi/integrations/provider/ollama.py +6 -5
  127. lionagi/integrations/provider/openrouter.py +115 -8
  128. lionagi/integrations/provider/services.py +2 -2
  129. lionagi/integrations/provider/transformers.py +18 -22
  130. lionagi/integrations/storage/__init__.py +3 -3
  131. lionagi/integrations/storage/neo4j.py +52 -60
  132. lionagi/integrations/storage/storage_util.py +45 -47
  133. lionagi/integrations/storage/structure_excel.py +285 -0
  134. lionagi/integrations/storage/to_excel.py +23 -7
  135. lionagi/libs/__init__.py +26 -1
  136. lionagi/libs/ln_api.py +75 -20
  137. lionagi/libs/ln_context.py +37 -0
  138. lionagi/libs/ln_convert.py +21 -9
  139. lionagi/libs/ln_func_call.py +69 -28
  140. lionagi/libs/ln_image.py +107 -0
  141. lionagi/libs/ln_nested.py +26 -11
  142. lionagi/libs/ln_parse.py +82 -23
  143. lionagi/libs/ln_queue.py +16 -0
  144. lionagi/libs/ln_tokenize.py +164 -0
  145. lionagi/libs/ln_validate.py +16 -0
  146. lionagi/libs/special_tokens.py +172 -0
  147. lionagi/libs/sys_util.py +95 -24
  148. lionagi/lions/coder/code_form.py +13 -0
  149. lionagi/lions/coder/coder.py +50 -3
  150. lionagi/lions/coder/util.py +30 -25
  151. lionagi/tests/libs/test_func_call.py +23 -21
  152. lionagi/tests/libs/test_nested.py +36 -21
  153. lionagi/tests/libs/test_parse.py +1 -1
  154. lionagi/tests/test_core/collections/__init__.py +0 -0
  155. lionagi/tests/test_core/collections/test_component.py +206 -0
  156. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  157. lionagi/tests/test_core/collections/test_flow.py +145 -0
  158. lionagi/tests/test_core/collections/test_pile.py +171 -0
  159. lionagi/tests/test_core/collections/test_progression.py +129 -0
  160. lionagi/tests/test_core/generic/__init__.py +0 -0
  161. lionagi/tests/test_core/generic/test_edge.py +67 -0
  162. lionagi/tests/test_core/generic/test_graph.py +96 -0
  163. lionagi/tests/test_core/generic/test_node.py +106 -0
  164. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  165. lionagi/tests/test_core/test_branch.py +115 -294
  166. lionagi/tests/test_core/test_form.py +46 -0
  167. lionagi/tests/test_core/test_report.py +105 -0
  168. lionagi/tests/test_core/test_validator.py +111 -0
  169. lionagi/version.py +1 -1
  170. lionagi-0.2.0.dist-info/LICENSE +202 -0
  171. lionagi-0.2.0.dist-info/METADATA +272 -0
  172. lionagi-0.2.0.dist-info/RECORD +240 -0
  173. lionagi/core/branch/base.py +0 -653
  174. lionagi/core/branch/branch.py +0 -474
  175. lionagi/core/branch/flow_mixin.py +0 -96
  176. lionagi/core/branch/util.py +0 -323
  177. lionagi/core/direct/__init__.py +0 -19
  178. lionagi/core/direct/cot.py +0 -123
  179. lionagi/core/direct/plan.py +0 -164
  180. lionagi/core/direct/predict.py +0 -166
  181. lionagi/core/direct/react.py +0 -171
  182. lionagi/core/direct/score.py +0 -279
  183. lionagi/core/direct/select.py +0 -170
  184. lionagi/core/direct/sentiment.py +0 -1
  185. lionagi/core/direct/utils.py +0 -110
  186. lionagi/core/direct/vote.py +0 -64
  187. lionagi/core/execute/base_executor.py +0 -47
  188. lionagi/core/flow/baseflow.py +0 -23
  189. lionagi/core/flow/monoflow/ReAct.py +0 -238
  190. lionagi/core/flow/monoflow/__init__.py +0 -9
  191. lionagi/core/flow/monoflow/chat.py +0 -95
  192. lionagi/core/flow/monoflow/chat_mixin.py +0 -253
  193. lionagi/core/flow/monoflow/followup.py +0 -213
  194. lionagi/core/flow/polyflow/__init__.py +0 -1
  195. lionagi/core/flow/polyflow/chat.py +0 -251
  196. lionagi/core/form/action_form.py +0 -26
  197. lionagi/core/form/field_validator.py +0 -287
  198. lionagi/core/form/form.py +0 -302
  199. lionagi/core/form/mixin.py +0 -214
  200. lionagi/core/form/scored_form.py +0 -13
  201. lionagi/core/generic/action.py +0 -26
  202. lionagi/core/generic/component.py +0 -455
  203. lionagi/core/generic/condition.py +0 -44
  204. lionagi/core/generic/mail.py +0 -90
  205. lionagi/core/generic/mailbox.py +0 -36
  206. lionagi/core/generic/relation.py +0 -70
  207. lionagi/core/generic/signal.py +0 -22
  208. lionagi/core/generic/structure.py +0 -362
  209. lionagi/core/generic/transfer.py +0 -20
  210. lionagi/core/generic/work.py +0 -40
  211. lionagi/core/graph/graph.py +0 -126
  212. lionagi/core/graph/tree.py +0 -190
  213. lionagi/core/mail/schema.py +0 -63
  214. lionagi/core/messages/schema.py +0 -325
  215. lionagi/core/tool/__init__.py +0 -5
  216. lionagi/core/tool/tool.py +0 -28
  217. lionagi/core/tool/tool_manager.py +0 -282
  218. lionagi/experimental/tool/function_calling.py +0 -43
  219. lionagi/experimental/tool/manual.py +0 -66
  220. lionagi/experimental/tool/schema.py +0 -59
  221. lionagi/experimental/tool/tool_manager.py +0 -138
  222. lionagi/experimental/tool/util.py +0 -16
  223. lionagi/experimental/work/_logger.py +0 -25
  224. lionagi/experimental/work/schema.py +0 -30
  225. lionagi/experimental/work/tests.py +0 -72
  226. lionagi/experimental/work/work_function.py +0 -89
  227. lionagi/experimental/work/worker.py +0 -12
  228. lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
  229. lionagi/tests/test_core/test_base_branch.py +0 -426
  230. lionagi/tests/test_core/test_chat_flow.py +0 -63
  231. lionagi/tests/test_core/test_mail_manager.py +0 -75
  232. lionagi/tests/test_core/test_prompts.py +0 -51
  233. lionagi/tests/test_core/test_session.py +0 -254
  234. lionagi/tests/test_core/test_session_base_util.py +0 -313
  235. lionagi/tests/test_core/test_tool_manager.py +0 -95
  236. lionagi-0.1.1.dist-info/LICENSE +0 -9
  237. lionagi-0.1.1.dist-info/METADATA +0 -174
  238. lionagi-0.1.1.dist-info/RECORD +0 -190
  239. /lionagi/core/{branch → _setting}/__init__.py +0 -0
  240. /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
  241. /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
  242. /lionagi/core/{form → agent/plan}/__init__.py +0 -0
  243. /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
  244. /lionagi/core/{graph → director}/__init__.py +0 -0
  245. /lionagi/core/{messages → engine}/__init__.py +0 -0
  246. /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
  247. /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
  248. /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
  249. /lionagi/{experimental/tool → core/unit/template}/__init__.py +0 -0
  250. /lionagi/{experimental/work → core/validator}/__init__.py +0 -0
  251. /lionagi/core/{flow/mono_chat_mixin.py → work/__init__.py} +0 -0
  252. /lionagi/experimental/{work/exchange.py → compressor/__init__.py} +0 -0
  253. /lionagi/experimental/{work/util.py → directive/template/__init__.py} +0 -0
  254. /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
  255. /lionagi/{tests/libs/test_async.py → experimental/evaluator/__init__.py} +0 -0
  256. {lionagi-0.1.1.dist-info → lionagi-0.2.0.dist-info}/WHEEL +0 -0
  257. {lionagi-0.1.1.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,455 +0,0 @@
1
- """This module provides base components used in lionagi"""
2
-
3
- from abc import ABC
4
- from functools import singledispatchmethod
5
- from typing import Any, TypeVar
6
-
7
- from pydantic import AliasChoices, BaseModel, Field, ValidationError
8
- from pandas import DataFrame, Series
9
-
10
- from lionagi.libs import SysUtil, func_call, convert, ParseUtil, nested
11
-
12
-
13
- T = TypeVar("T")
14
-
15
-
16
- class BaseComponent(BaseModel, ABC):
17
- """
18
- Base class for creating component models.
19
-
20
- Attributes:
21
- id_ (str): A 32-char unique hash identifier for the node.
22
- timestamp (str): The timestamp of when the node was created.
23
- """
24
-
25
- id_: str = Field(
26
- title="ID",
27
- default_factory=SysUtil.create_id,
28
- validation_alias=AliasChoices("node_id", "ID", "id"),
29
- description="A 32-char unique hash identifier for the node.",
30
- )
31
-
32
- timestamp: str = Field(
33
- default_factory=lambda: SysUtil.get_timestamp(sep=None),
34
- description="The timestamp of when the node was created.",
35
- )
36
-
37
- class Config:
38
- """Model configuration settings."""
39
-
40
- extra = "allow"
41
- arbitrary_types_allowed = True
42
- populate_by_name = True
43
- validate_assignment = True
44
- validate_return = True
45
- str_strip_whitespace = True
46
-
47
- @classmethod
48
- def class_name(cls) -> str:
49
- """
50
- Retrieve the name of the class.
51
-
52
- Returns:
53
- str: The name of the class.
54
- """
55
- return cls.__name__
56
-
57
- @property
58
- def _field_annotations(self) -> dict:
59
- """
60
- Return the annotations for each field in the model.
61
-
62
- Returns:
63
- dict: A dictionary mapping field names to their annotations.
64
- """
65
- return self._get_field_annotation(list(self.model_fields.keys()))
66
-
67
- def _get_field_attr(self, k: str, attr: str, default=False) -> Any:
68
- """
69
- Get the value of a field attribute.
70
-
71
- Args:
72
- k (str): The field name.
73
- attr (str): The attribute name.
74
- default (Any): Default value to return if the attribute is not
75
- found.
76
-
77
- Returns:
78
- Any: The value of the field attribute, or the default value if not
79
- found.
80
-
81
- Raises:
82
- ValueError: If the field does not have the specified attribute.
83
- """
84
- try:
85
- if not self._field_has_attr(k, attr):
86
- raise ValueError(f"field {k} has no attribute {attr}")
87
- field = self.model_fields[k]
88
- a = getattr(field, attr)
89
- if not a:
90
- try:
91
- a = field.json_schema_extra[attr]
92
- return a
93
- except Exception:
94
- return None
95
- return a
96
- except Exception as e:
97
- if default is not False:
98
- return default
99
- raise e
100
-
101
- @singledispatchmethod
102
- def _get_field_annotation(self, field_name: str) -> Any:
103
- """
104
- Get the annotation for a field.
105
-
106
- Args:
107
- field_name (str): The name of the field.
108
-
109
- Raises:
110
- TypeError: If the field_name is of an unsupported type.
111
- """
112
- raise TypeError(f"Unsupported type {type(field_name)}")
113
-
114
- @_get_field_annotation.register(str)
115
- def _(self, field_name) -> dict[str, Any]:
116
- """
117
- Get the annotation for a field as a dictionary.
118
-
119
- Args:
120
- field_name (str): The name of the field.
121
-
122
- Returns:
123
- dict[str, Any]: A dictionary mapping the field name to its
124
- annotation.
125
- """
126
- dict_ = {field_name: self.model_fields[field_name].annotation}
127
- for k, v in dict_.items():
128
- if "|" in str(v):
129
- v = str(v)
130
- v = v.split("|")
131
- dict_[k] = func_call.lcall(v, convert.strip_lower)
132
- else:
133
- dict_[k] = [v.__name__]
134
- return dict_
135
-
136
- @_get_field_annotation.register(list)
137
- def _(self, field_name) -> dict[str, Any]:
138
- """
139
- Get the annotations for multiple fields as a dictionary.
140
-
141
- Args:
142
- field_name (list): A list or tuple of field names.
143
-
144
- Returns:
145
- dict[str, Any]: A dictionary mapping field names to their
146
- annotations.
147
- """
148
- dict_ = {}
149
- for i in field_name:
150
- dict_.update(self._get_field_annotation(i))
151
- return dict_
152
-
153
- @_get_field_annotation.register(tuple)
154
- def _(self, field_name) -> dict[str, Any]:
155
- """
156
- Get the annotations for multiple fields as a dictionary.
157
-
158
- Args:
159
- field_name (tuple): A list or tuple of field names.
160
-
161
- Returns:
162
- dict[str, Any]: A dictionary mapping field names to their
163
- annotations.
164
- """
165
- dict_ = {}
166
- for i in field_name:
167
- dict_.update(self._get_field_annotation(i))
168
- return dict_
169
-
170
- def _field_has_attr(self, k: str, attr: str) -> bool:
171
- """
172
- Check if a field has a specific attribute.
173
-
174
- Args:
175
- k (str): The field name.
176
- attr (str): The attribute name.
177
-
178
- Returns:
179
- bool: True if the field has the attribute, False otherwise.
180
- """
181
- field = self.model_fields.get(k, None)
182
- if field is None:
183
- raise ValueError(f"Field {k} not found in model fields.")
184
-
185
- a = attr in str(field)
186
- if not a:
187
- try:
188
- a = (
189
- self.model_fields[k].json_schema_extra[attr] is not None
190
- and attr in self.model_fields[k].json_schema_extra
191
- )
192
- return a if isinstance(a, bool) else False
193
- except Exception:
194
- return False
195
- return a
196
-
197
- def to_json_str(self, *args, **kwargs) -> str:
198
- """
199
- Convert the component to a JSON string.
200
-
201
- Returns:
202
- str: The JSON string representation of the component.
203
- """
204
- return self.model_dump_json(*args, by_alias=True, **kwargs)
205
-
206
- def to_dict(self, *args, **kwargs) -> dict[str, Any]:
207
- """
208
- Convert the component to a dictionary.
209
-
210
- Returns:
211
- dict[str, Any]: The dictionary representation of the component.
212
- """
213
- return self.model_dump(*args, by_alias=True, **kwargs)
214
-
215
- def to_xml(self) -> str:
216
- """
217
- Convert the component to an XML string.
218
-
219
- Returns:
220
- str: The XML string representation of the component.
221
- """
222
- import xml.etree.ElementTree as ET
223
-
224
- root = ET.Element(self.__class__.__name__)
225
-
226
- def convert(dict_obj, parent):
227
- for key, val in dict_obj.items():
228
- if isinstance(val, dict):
229
- element = ET.SubElement(parent, key)
230
- convert(val, element)
231
- else:
232
- element = ET.SubElement(parent, key)
233
- element.text = str(val)
234
-
235
- convert(self.to_dict(), root)
236
- return ET.tostring(root, encoding="unicode")
237
-
238
- def to_pd_series(self, *args, pd_kwargs: dict | None = None, **kwargs) -> Series:
239
- """
240
- Convert the node to a Pandas Series.
241
-
242
- Returns:
243
- Series: The Pandas Series representation of the node.
244
- """
245
- pd_kwargs = {} if pd_kwargs is None else pd_kwargs
246
- dict_ = self.to_dict(*args, **kwargs)
247
- return Series(dict_, **pd_kwargs)
248
-
249
-
250
- class BaseNode(BaseComponent):
251
- """
252
- Base class for creating node models.
253
-
254
- Attributes:
255
- content (Any | None): The optional content of the node.
256
- metadata (dict[str, Any]): Additional metadata for the node.
257
- """
258
-
259
- content: Any | None = Field(
260
- default=None,
261
- validation_alias=AliasChoices("text", "page_content", "chunk_content", "data"),
262
- description="The optional content of the node.",
263
- )
264
-
265
- metadata: dict[str, Any] = Field(
266
- default_factory=dict,
267
- alias="meta",
268
- description="Additional metadata for the node.",
269
- )
270
-
271
- @singledispatchmethod
272
- @classmethod
273
- def from_obj(cls, obj: Any, *args, **kwargs) -> T:
274
- """
275
- Create a node instance from an object.
276
-
277
- Args:
278
- obj (Any): The object to create the node from.
279
-
280
- Raises:
281
- NotImplementedError: If the object type is not supported.
282
- """
283
- raise NotImplementedError(f"Unsupported type: {type(obj)}")
284
-
285
- @from_obj.register(dict)
286
- @classmethod
287
- def _from_dict(cls, obj, *args, **kwargs) -> T:
288
- """
289
- Create a node instance from a dictionary.
290
-
291
- Args:
292
- obj (dict): The dictionary to create the node from.
293
-
294
- Returns:
295
- T: The created node instance.
296
- """
297
- return cls.model_validate(obj, *args, **kwargs)
298
-
299
- @from_obj.register(str)
300
- @classmethod
301
- def _from_str(cls, obj, *args, fuzzy_parse=False, **kwargs) -> T:
302
- """
303
- Create a node instance from a JSON string.
304
-
305
- Args:
306
- obj (str): The JSON string to create the node from.
307
- fuzzy_parse (bool): Whether to perform fuzzy parsing.
308
-
309
- Returns:
310
- T: The created node instance.
311
- """
312
- obj = ParseUtil.fuzzy_parse_json(obj) if fuzzy_parse else convert.to_dict(obj)
313
- try:
314
- return cls.from_obj(obj, *args, **kwargs)
315
- except ValidationError as e:
316
- raise ValueError(f"Invalid JSON for deserialization: {e}") from e
317
-
318
- @from_obj.register(list)
319
- @classmethod
320
- def _from_list(cls, obj, *args, **kwargs) -> list[T]:
321
- """
322
- Create a list of node instances from a list of objects.
323
-
324
- Args:
325
- obj (list): The list of objects to create nodes from.
326
-
327
- Returns:
328
- list[T]: The list of created node instances.
329
- """
330
- return [cls.from_obj(item, *args, **kwargs) for item in obj]
331
-
332
- @from_obj.register(Series)
333
- @classmethod
334
- def _from_pd_series(cls, obj, *args, pd_kwargs=None, **kwargs) -> T:
335
- """
336
- Create a node instance from a Pandas Series.
337
-
338
- Args:
339
- obj (Series): The Pandas Series to create the node from.
340
-
341
- Returns:
342
- T: The created node instance.
343
- """
344
- if pd_kwargs is None:
345
- pd_kwargs = {}
346
- return cls.from_obj(obj.to_dict(**pd_kwargs), *args, **kwargs)
347
-
348
- @from_obj.register(DataFrame)
349
- @classmethod
350
- def _from_pd_dataframe(cls, obj, *args, pd_kwargs=None, **kwargs) -> list[T]:
351
- """
352
- Create a list of node instances from a Pandas DataFrame.
353
-
354
- Args:
355
- obj (DataFrame): The Pandas DataFrame to create nodes from.
356
-
357
- Returns:
358
- list[T]: The list of created node instances.
359
- """
360
- if pd_kwargs is None:
361
- pd_kwargs = {}
362
- return [
363
- cls.from_obj(row, *args, **pd_kwargs, **kwargs) for _, row in obj.iterrows()
364
- ]
365
-
366
- @from_obj.register(BaseModel)
367
- @classmethod
368
- def _from_base_model(cls, obj, pydantic_kwargs=None, **kwargs) -> T:
369
- """
370
- Create a node instance from a Pydantic BaseModel.
371
-
372
- Args:
373
- obj (BaseModel): The Pydantic BaseModel to create the node from.
374
-
375
- Returns:
376
- T: The created node instance.
377
- """
378
- if pydantic_kwargs is None:
379
- pydantic_kwargs = {"by_alias": True}
380
-
381
- config_ = {}
382
- try:
383
- config_ = obj.model_dump(**pydantic_kwargs)
384
- except:
385
- config_ = obj.dict(**pydantic_kwargs)
386
-
387
- return cls.from_obj(config_ | kwargs)
388
-
389
- def meta_get(
390
- self, key: str, indices: list[str | int] = None, default: Any = None
391
- ) -> Any:
392
- """
393
- Get a value from the metadata dictionary.
394
-
395
- Args:
396
- key (str): The key to retrieve the value for.
397
- indices (list[str | int]): Optional list of indices for nested
398
- retrieval.
399
- default (Any): The default value to return if the key is not found.
400
-
401
- Returns:
402
- Any: The retrieved value or the default value if not found.
403
- """
404
- if indices:
405
- return nested.nget(self.metadata, indices, default)
406
- return self.metadata.get(key, default)
407
-
408
- def meta_change_key(self, old_key: str, new_key: str) -> bool:
409
- """
410
- Change a key in the metadata dictionary.
411
-
412
- Args:
413
- old_key (str): The old key to be changed.
414
- new_key (str): The new key to replace the old key.
415
-
416
- Returns:
417
- bool: True if the key was changed successfully, False otherwise.
418
- """
419
- if old_key in self.metadata:
420
- SysUtil.change_dict_key(self.metadata, old_key, new_key)
421
- return True
422
- return False
423
-
424
- def meta_insert(self, indices: str | list, value: Any, **kwargs) -> bool:
425
- """
426
- Insert a value into the metadata dictionary at the specified indices.
427
-
428
- Args:
429
- indices (str | list): The indices to insert the value at.
430
- value (Any): The value to be inserted.
431
- **kwargs: Additional keyword arguments for the `nested.ninsert`
432
- function.
433
-
434
- Returns:
435
- bool: True if the value was inserted successfully, False otherwise.
436
- """
437
- return nested.ninsert(self.metadata, indices, value, **kwargs)
438
-
439
- def meta_merge(
440
- self, additional_metadata: dict[str, Any], overwrite: bool = False, **kwargs
441
- ) -> None:
442
- """
443
- Merge additional metadata into the existing metadata dictionary.
444
-
445
- Args:
446
- additional_metadata (dict[str, Any]): The additional metadata to be
447
- merged.
448
- overwrite (bool): Whether to overwrite existing keys with the new
449
- values.
450
- **kwargs: Additional keyword arguments for the `nested.nmerge`
451
- function.
452
- """
453
- self.metadata = nested.nmerge(
454
- [self.metadata, additional_metadata], overwrite=overwrite, **kwargs
455
- )
@@ -1,44 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from enum import Enum
3
- from pydantic import BaseModel, Field
4
-
5
-
6
- class ConditionSource(str, Enum):
7
- """
8
- Enumeration for specifying the source type of a condition.
9
-
10
- Attributes:
11
- STRUCTURE: Represents a condition based on the structure.
12
- EXECUTABLE: Represents a condition that can be executed or evaluated.
13
- """
14
-
15
- STRUCTURE = "structure"
16
- EXECUTABLE = "executable"
17
-
18
-
19
- class Condition(BaseModel, ABC):
20
- """
21
- Abstract base class for defining conditions associated with edges.
22
-
23
- Attributes:
24
- source_type (ConditionSource): Specifies the type of source for the condition.
25
-
26
- Methods:
27
- check: Abstract method that should be implemented to evaluate the condition.
28
- """
29
-
30
- source_type: str = Field(..., description="The type of source for the condition.")
31
-
32
- class Config:
33
- """Model configuration settings."""
34
-
35
- extra = "allow"
36
-
37
- @abstractmethod
38
- def __call__(self, executable) -> bool:
39
- """Evaluates the condition based on implemented logic.
40
-
41
- Returns:
42
- bool: The boolean result of the condition evaluation.
43
- """
44
- pass
@@ -1,90 +0,0 @@
1
- """
2
- This module defines classes for representing mail packages and mailboxes
3
- in a messaging system.
4
-
5
- The module includes the following classes:
6
- - MailPackageCategory: An enumeration of categories for mail packages.
7
- - Mail: Represents a mail message sent from one component to another.
8
- - MailBox: Represents a mailbox that stores pending incoming and outgoing mails.
9
- """
10
-
11
- from typing import Any
12
- from enum import Enum
13
-
14
- from pydantic import Field, field_validator
15
-
16
- from lionagi.core.generic.component import BaseComponent
17
-
18
-
19
- class MailPackageCategory(str, Enum):
20
- """
21
- Defines categories for mail packages in a messaging system.
22
-
23
- Attributes:
24
- MESSAGES: Represents general messages.
25
- TOOL: Represents tools.
26
- SERVICE: Represents services.
27
- MODEL: Represents models.
28
- NODE: Represents nodes.
29
- NODE_LIST: Represents a list of nodes.
30
- NODE_ID: Represents a node's ID.
31
- START: Represents a start signal or value.
32
- END: Represents an end signal or value.
33
- CONDITION: Represents a condition.
34
- """
35
-
36
- MESSAGES = "messages"
37
- TOOL = "tool"
38
- SERVICE = "service"
39
- MODEL = "model"
40
- NODE = "node"
41
- NODE_LIST = "node_list"
42
- NODE_ID = "node_id"
43
- START = "start"
44
- END = "end"
45
- CONDITION = "condition"
46
-
47
-
48
- class Package(BaseComponent):
49
- category: MailPackageCategory = Field(
50
- ..., title="Category", description="The category of the mail package."
51
- )
52
-
53
- package: Any = Field(
54
- ..., title="Package", description="The package to send in the mail."
55
- )
56
-
57
-
58
- class Mail(BaseComponent):
59
- """
60
- Represents a mail message sent from one component to another within
61
- the system.
62
-
63
- Attributes:
64
- sender (str): The ID of the sender node.
65
- recipient (str): The ID of the recipient node.
66
- category (MailPackageCategory): The category of the mail package.
67
- package (Any): The content of the mail package.
68
- """
69
-
70
- sender: str = Field(
71
- title="Sender",
72
- description="The id of the sender node.",
73
- )
74
-
75
- recipient: str = Field(
76
- title="Recipient",
77
- description="The id of the recipient node.",
78
- )
79
-
80
- packages: dict[str, Package] = Field(
81
- title="Packages",
82
- default_factory=dict,
83
- description="The packages to send in the mail.",
84
- )
85
-
86
- @field_validator("sender", "recipient", mode="before")
87
- def _validate_sender_recipient(cls, value):
88
- if isinstance(value, BaseComponent):
89
- return value.id_
90
- return value
@@ -1,36 +0,0 @@
1
- from collections import deque
2
- from pydantic import Field
3
- from pydantic.dataclasses import dataclass
4
-
5
- from lionagi.core.generic.mail import Mail
6
-
7
-
8
- @dataclass
9
- class MailBox:
10
-
11
- pile: dict[str, Mail] = Field(
12
- default_factory=dict, description="The pile of all mails - {mail_id: Mail}"
13
- )
14
-
15
- sequence_in: dict[str, deque] = Field(
16
- default_factory=dict,
17
- description="The sequence of all incoming mails - {sender_id: deque[mail_id]}",
18
- )
19
-
20
- sequence_out: deque = Field(
21
- default_factory=deque,
22
- description="The sequence of all outgoing mails - deque[mail_id]",
23
- )
24
-
25
- def __str__(self) -> str:
26
- """
27
- Returns a string representation of the MailBox instance.
28
-
29
- Returns:
30
- str: A string describing the number of pending incoming and
31
- outgoing mails in the MailBox.
32
- """
33
- return (
34
- f"MailBox with {len(self.receieving)} pending incoming mails and "
35
- f"{len(self.sending)} pending outgoing mails."
36
- )
@@ -1,70 +0,0 @@
1
- """
2
- A module for representing relationships between nodes in a graph structure,
3
- encapsulating incoming and outgoing edges.
4
- """
5
-
6
- from pydantic import Field
7
- from pydantic.dataclasses import dataclass
8
- from lionagi.libs import convert
9
- from lionagi.core.generic.edge import Edge
10
-
11
-
12
- @dataclass
13
- class Relations:
14
- """
15
- Represents the relationships of a node via its incoming and outgoing edges.
16
-
17
- This class stores edges in two dictionaries: `preceding` for outgoing edges
18
- and `succeeding` for incoming edges. It provides properties to access all
19
- edges together and to get a unique set of all connected node IDs.
20
-
21
- Attributes:
22
- preceding (dict[str, Edge]): A dictionary of outgoing edges from the
23
- node, with the edge ID as the key and the `Edge` object as the
24
- value. Represents edges leading from this node to other nodes.
25
- succeeding (dict[str, Edge]): A dictionary of incoming edges to the
26
- node, with the edge ID as the key and the `Edge` object as the
27
- value. Represents edges from other nodes leading to this node.
28
- """
29
-
30
- points_to: dict[str, Edge] = Field(
31
- title="Outgoing edges",
32
- default_factory=dict,
33
- description="The Outgoing edges of the node, reads self precedes other, \
34
- {edge_id: Edge}",
35
- )
36
-
37
- pointed_by: dict[str, Edge] = Field(
38
- title="Incoming edges",
39
- default_factory=dict,
40
- description="The Incoming edges of the node, reads self succeeds other, \
41
- {edge_id: Edge}",
42
- )
43
-
44
- @property
45
- def all_edges(self) -> dict[str, Edge]:
46
- """
47
- Combines and returns all incoming and outgoing edges of the node.
48
-
49
- Returns:
50
- dict[str, Edge]: A dictionary of all edges connected to the node,
51
- including both preceding (outgoing) and succeeding (incoming)
52
- edges, indexed by edge IDs.
53
- """
54
- return {**self.points_to, **self.pointed_by}
55
-
56
- @property
57
- def all_nodes(self) -> set[str]:
58
- """
59
- Extracts and returns a unique set of all node IDs connected to this
60
- node through its edges.
61
-
62
- It processes both heads and tails of each edge in `all_edges`, flattens
63
- the list to a one-dimensional list, and then converts it to a set to
64
- ensure uniqueness.
65
-
66
- Returns:
67
- set[str]: A set of unique node IDs connected to this node, derived
68
- from both incoming and outgoing edges.
69
- """
70
- return set(convert.to_list([[i.head, i.tail] for i in self.all_edges.values()]))