lionagi 0.1.2__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 (268) 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} +62 -66
  35. lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
  36. lionagi/core/generic/__init__.py +3 -33
  37. lionagi/core/generic/edge.py +29 -79
  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/base.py +10 -0
  109. lionagi/experimental/memory/__init__.py +0 -0
  110. lionagi/experimental/strategies/__init__.py +0 -0
  111. lionagi/experimental/strategies/base.py +1 -0
  112. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  113. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  114. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  115. lionagi/integrations/chunker/chunk.py +161 -24
  116. lionagi/integrations/config/oai_configs.py +34 -3
  117. lionagi/integrations/config/openrouter_configs.py +14 -2
  118. lionagi/integrations/loader/load.py +122 -21
  119. lionagi/integrations/loader/load_util.py +6 -77
  120. lionagi/integrations/provider/_mapping.py +46 -0
  121. lionagi/integrations/provider/litellm.py +2 -1
  122. lionagi/integrations/provider/mlx_service.py +16 -9
  123. lionagi/integrations/provider/oai.py +91 -4
  124. lionagi/integrations/provider/ollama.py +6 -5
  125. lionagi/integrations/provider/openrouter.py +115 -8
  126. lionagi/integrations/provider/services.py +2 -2
  127. lionagi/integrations/provider/transformers.py +18 -22
  128. lionagi/integrations/storage/__init__.py +3 -3
  129. lionagi/integrations/storage/neo4j.py +52 -60
  130. lionagi/integrations/storage/storage_util.py +44 -46
  131. lionagi/integrations/storage/structure_excel.py +43 -26
  132. lionagi/integrations/storage/to_excel.py +11 -4
  133. lionagi/libs/__init__.py +22 -1
  134. lionagi/libs/ln_api.py +75 -20
  135. lionagi/libs/ln_context.py +37 -0
  136. lionagi/libs/ln_convert.py +21 -9
  137. lionagi/libs/ln_func_call.py +69 -28
  138. lionagi/libs/ln_image.py +107 -0
  139. lionagi/libs/ln_nested.py +26 -11
  140. lionagi/libs/ln_parse.py +82 -23
  141. lionagi/libs/ln_queue.py +16 -0
  142. lionagi/libs/ln_tokenize.py +164 -0
  143. lionagi/libs/ln_validate.py +16 -0
  144. lionagi/libs/special_tokens.py +172 -0
  145. lionagi/libs/sys_util.py +95 -24
  146. lionagi/lions/coder/code_form.py +13 -0
  147. lionagi/lions/coder/coder.py +50 -3
  148. lionagi/lions/coder/util.py +30 -25
  149. lionagi/tests/libs/test_func_call.py +23 -21
  150. lionagi/tests/libs/test_nested.py +36 -21
  151. lionagi/tests/libs/test_parse.py +1 -1
  152. lionagi/tests/test_core/collections/__init__.py +0 -0
  153. lionagi/tests/test_core/collections/test_component.py +206 -0
  154. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  155. lionagi/tests/test_core/collections/test_flow.py +145 -0
  156. lionagi/tests/test_core/collections/test_pile.py +171 -0
  157. lionagi/tests/test_core/collections/test_progression.py +129 -0
  158. lionagi/tests/test_core/generic/test_edge.py +67 -0
  159. lionagi/tests/test_core/generic/test_graph.py +96 -0
  160. lionagi/tests/test_core/generic/test_node.py +106 -0
  161. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  162. lionagi/tests/test_core/test_branch.py +115 -294
  163. lionagi/tests/test_core/test_form.py +46 -0
  164. lionagi/tests/test_core/test_report.py +105 -0
  165. lionagi/tests/test_core/test_validator.py +111 -0
  166. lionagi/version.py +1 -1
  167. lionagi-0.2.0.dist-info/LICENSE +202 -0
  168. lionagi-0.2.0.dist-info/METADATA +272 -0
  169. lionagi-0.2.0.dist-info/RECORD +240 -0
  170. lionagi/core/branch/base.py +0 -653
  171. lionagi/core/branch/branch.py +0 -474
  172. lionagi/core/branch/flow_mixin.py +0 -96
  173. lionagi/core/branch/util.py +0 -323
  174. lionagi/core/direct/__init__.py +0 -19
  175. lionagi/core/direct/cot.py +0 -123
  176. lionagi/core/direct/plan.py +0 -164
  177. lionagi/core/direct/predict.py +0 -166
  178. lionagi/core/direct/react.py +0 -171
  179. lionagi/core/direct/score.py +0 -279
  180. lionagi/core/direct/select.py +0 -170
  181. lionagi/core/direct/sentiment.py +0 -1
  182. lionagi/core/direct/utils.py +0 -110
  183. lionagi/core/direct/vote.py +0 -64
  184. lionagi/core/execute/base_executor.py +0 -47
  185. lionagi/core/flow/baseflow.py +0 -23
  186. lionagi/core/flow/monoflow/ReAct.py +0 -240
  187. lionagi/core/flow/monoflow/__init__.py +0 -9
  188. lionagi/core/flow/monoflow/chat.py +0 -95
  189. lionagi/core/flow/monoflow/chat_mixin.py +0 -253
  190. lionagi/core/flow/monoflow/followup.py +0 -215
  191. lionagi/core/flow/polyflow/__init__.py +0 -1
  192. lionagi/core/flow/polyflow/chat.py +0 -251
  193. lionagi/core/form/action_form.py +0 -26
  194. lionagi/core/form/field_validator.py +0 -287
  195. lionagi/core/form/form.py +0 -302
  196. lionagi/core/form/mixin.py +0 -214
  197. lionagi/core/form/scored_form.py +0 -13
  198. lionagi/core/generic/action.py +0 -26
  199. lionagi/core/generic/component.py +0 -532
  200. lionagi/core/generic/condition.py +0 -46
  201. lionagi/core/generic/mail.py +0 -90
  202. lionagi/core/generic/mailbox.py +0 -36
  203. lionagi/core/generic/relation.py +0 -70
  204. lionagi/core/generic/signal.py +0 -22
  205. lionagi/core/generic/structure.py +0 -362
  206. lionagi/core/generic/transfer.py +0 -20
  207. lionagi/core/generic/work.py +0 -40
  208. lionagi/core/graph/graph.py +0 -126
  209. lionagi/core/graph/tree.py +0 -190
  210. lionagi/core/mail/schema.py +0 -63
  211. lionagi/core/messages/schema.py +0 -325
  212. lionagi/core/tool/__init__.py +0 -5
  213. lionagi/core/tool/tool.py +0 -28
  214. lionagi/core/tool/tool_manager.py +0 -283
  215. lionagi/experimental/report/form.py +0 -64
  216. lionagi/experimental/report/report.py +0 -138
  217. lionagi/experimental/report/util.py +0 -47
  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/validator/rule.py +0 -139
  224. lionagi/experimental/validator/validator.py +0 -56
  225. lionagi/experimental/work/__init__.py +0 -10
  226. lionagi/experimental/work/async_queue.py +0 -54
  227. lionagi/experimental/work/schema.py +0 -73
  228. lionagi/experimental/work/work_function.py +0 -67
  229. lionagi/experimental/work/worker.py +0 -56
  230. lionagi/experimental/work2/form.py +0 -371
  231. lionagi/experimental/work2/report.py +0 -289
  232. lionagi/experimental/work2/schema.py +0 -30
  233. lionagi/experimental/work2/tests.py +0 -72
  234. lionagi/experimental/work2/work_function.py +0 -89
  235. lionagi/experimental/work2/worker.py +0 -12
  236. lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
  237. lionagi/tests/test_core/generic/test_component.py +0 -89
  238. lionagi/tests/test_core/test_base_branch.py +0 -426
  239. lionagi/tests/test_core/test_chat_flow.py +0 -63
  240. lionagi/tests/test_core/test_mail_manager.py +0 -75
  241. lionagi/tests/test_core/test_prompts.py +0 -51
  242. lionagi/tests/test_core/test_session.py +0 -254
  243. lionagi/tests/test_core/test_session_base_util.py +0 -313
  244. lionagi/tests/test_core/test_tool_manager.py +0 -95
  245. lionagi-0.1.2.dist-info/LICENSE +0 -9
  246. lionagi-0.1.2.dist-info/METADATA +0 -174
  247. lionagi-0.1.2.dist-info/RECORD +0 -206
  248. /lionagi/core/{branch → _setting}/__init__.py +0 -0
  249. /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
  250. /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
  251. /lionagi/core/{form → agent/plan}/__init__.py +0 -0
  252. /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
  253. /lionagi/core/{graph → director}/__init__.py +0 -0
  254. /lionagi/core/{messages → engine}/__init__.py +0 -0
  255. /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
  256. /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
  257. /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
  258. /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
  259. /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
  260. /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
  261. /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
  262. /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
  263. /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
  264. /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
  265. /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
  266. /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
  267. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/WHEEL +0 -0
  268. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,532 +0,0 @@
1
- """base components in lionagi"""
2
-
3
- from abc import ABC
4
- from functools import singledispatchmethod
5
- from typing import Any, TypeVar, Type
6
- from pydantic import AliasChoices, BaseModel, Field, ValidationError
7
- from pandas import DataFrame, Series
8
-
9
- from lionagi.libs import SysUtil, convert, ParseUtil, nested, func_call
10
-
11
-
12
- T = TypeVar("T")
13
-
14
-
15
- class BaseComponent(BaseModel, ABC):
16
- """
17
- Base class for creating component models.
18
-
19
- Attributes:
20
- id_ (str): A 32-char unique hash identifier for the node.
21
- timestamp (str): The timestamp of when the node was created.
22
- """
23
-
24
- id_: str = Field(
25
- title="ID",
26
- default_factory=SysUtil.create_id,
27
- validation_alias=AliasChoices("node_id", "ID", "id"),
28
- description="A 32-char unique hash identifier for the node.",
29
- )
30
- timestamp: str = Field(
31
- default_factory=lambda: SysUtil.get_timestamp(sep=None),
32
- description="The timestamp of when the node was created.",
33
- )
34
-
35
- extra_fields: dict[str, Any] = Field(
36
- default_factory=dict,
37
- validation_alias=AliasChoices(
38
- "extra", "additional_fields", "schema_extra", "extra_schema"
39
- ),
40
- description="Additional fields for the component.",
41
- )
42
-
43
- class Config:
44
- """Model configuration settings."""
45
-
46
- extra = "allow"
47
- arbitrary_types_allowed = True
48
- populate_by_name = True
49
-
50
- @property
51
- def class_name(self) -> str:
52
- """
53
- Retrieve the name of the class.
54
-
55
- Returns:
56
- str: The name of the class.
57
- """
58
- return self._class_name()
59
-
60
- @classmethod
61
- def _class_name(cls) -> str:
62
- """
63
- Retrieve the name of the class.
64
-
65
- Returns:
66
- str: The name of the class.
67
- """
68
- return cls.__name__
69
-
70
- def to_json_str(self, *args, **kwargs) -> str:
71
- """
72
- Convert the component to a JSON string.
73
-
74
- Returns:
75
- str: The JSON string representation of the component.
76
- """
77
- dict_ = self.to_dict(*args, **kwargs)
78
- return convert.to_str(dict_)
79
-
80
- def to_dict(self, *args, **kwargs) -> dict[str, Any]:
81
- """
82
- Convert the component to a dictionary.
83
-
84
- Returns:
85
- dict[str, Any]: The dictionary representation of the component.
86
- """
87
- dict_ = self.model_dump(*args, by_alias=True, **kwargs)
88
- for field_name in list(self.extra_fields.keys()):
89
- if field_name not in dict_:
90
- dict_[field_name] = getattr(self, field_name, None)
91
- dict_.pop("extra_fields", None)
92
- return dict_
93
-
94
- def to_xml(self, *args, **kwargs) -> str:
95
- """
96
- Convert the component to an XML string.
97
-
98
- Returns:
99
- str: The XML string representation of the component.
100
- """
101
- import xml.etree.ElementTree as ET
102
-
103
- root = ET.Element(self.__class__.__name__)
104
-
105
- def convert(dict_obj: dict, parent: ET.Element) -> None:
106
- for key, val in dict_obj.items():
107
- if isinstance(val, dict):
108
- element = ET.SubElement(parent, key)
109
- convert(val, element)
110
- else:
111
- element = ET.SubElement(parent, key)
112
- element.text = str(val)
113
-
114
- convert(self.to_dict(*args, **kwargs), root)
115
- return ET.tostring(root, encoding="unicode")
116
-
117
- def to_pd_series(self, *args, pd_kwargs: dict | None = None, **kwargs) -> Series:
118
- """
119
- Convert the node to a Pandas Series.
120
-
121
- Args:
122
- pd_kwargs (dict | None): Additional keyword arguments for Pandas Series.
123
-
124
- Returns:
125
- Series: The Pandas Series representation of the node.
126
- """
127
- pd_kwargs = {} if pd_kwargs is None else pd_kwargs
128
- dict_ = self.to_dict(*args, **kwargs)
129
- return Series(dict_, **pd_kwargs)
130
-
131
- def _add_field(
132
- self,
133
- field_name: str,
134
- annotation: Any | Type | None = Any,
135
- default: Any | None = None,
136
- value: Any | None = None,
137
- field: Any = None,
138
- **kwargs,
139
- ) -> None:
140
- """
141
- Add a field to the model after initialization.
142
-
143
- Args:
144
- field_name (str): The name of the field.
145
- annotation (Any | Type | None): The type annotation for the field.
146
- default (Any | None): The default value for the field.
147
- value (Any | None): The initial value for the field.
148
- field (Any): The Field object for the field.
149
- **kwargs: Additional keyword arguments for the Field object.
150
- """
151
- field = field or Field(default=default, **kwargs)
152
- self.extra_fields[field_name] = field
153
- if annotation:
154
- self.extra_fields[field_name].annotation = annotation
155
-
156
- if not value and (a := self._get_field_attr(field_name, "default", None)):
157
- value = a
158
-
159
- self.__setattr__(field_name, value)
160
-
161
- @property
162
- def _all_fields(self):
163
- return {**self.model_fields, **self.extra_fields}
164
-
165
- @property
166
- def _field_annotations(self) -> dict:
167
- """
168
- Return the annotations for each field in the model.
169
-
170
- Returns:
171
- dict: A dictionary mapping field names to their annotations.
172
- """
173
-
174
- return self._get_field_annotation(list(self._all_fields.keys()))
175
-
176
- def _get_field_attr(self, k: str, attr: str, default: Any = False) -> Any:
177
- """
178
- Get the value of a field attribute.
179
-
180
- Args:
181
- k (str): The field name.
182
- attr (str): The attribute name.
183
- default (Any): Default value to return if the attribute is not found.
184
-
185
- Returns:
186
- Any: The value of the field attribute, or the default value if not found.
187
-
188
- Raises:
189
- ValueError: If the field does not have the specified attribute.
190
- """
191
- try:
192
- if not self._field_has_attr(k, attr):
193
- raise ValueError(f"field {k} has no attribute {attr}")
194
-
195
- field = self._all_fields[k]
196
- a = getattr(field, attr, None)
197
- if not a:
198
- try:
199
- a = field.json_schema_extra[attr]
200
- return a
201
- except Exception:
202
- return None
203
- return a
204
- except Exception as e:
205
- if default is not False:
206
- return default
207
- raise e
208
-
209
- @singledispatchmethod
210
- def _get_field_annotation(self, field_name: Any) -> Any:
211
- """
212
- Get the annotation for a field.
213
-
214
- Args:
215
- field_name (str): The name of the field.
216
-
217
- Raises:
218
- TypeError: If the field_name is of an unsupported type.
219
- """
220
- raise TypeError(f"Unsupported type {type(field_name)}")
221
-
222
- @_get_field_annotation.register(str)
223
- def _(self, field_name: str) -> dict[str, Any]:
224
- """
225
- Get the annotation for a field as a dictionary.
226
-
227
- Args:
228
- field_name (str): The name of the field.
229
-
230
- Returns:
231
- dict[str, Any]: A dictionary mapping the field name to its annotation.
232
- """
233
- dict_ = {field_name: self._all_fields[field_name].annotation}
234
- for k, v in dict_.items():
235
- if "|" in str(v):
236
- v = str(v)
237
- v = v.split("|")
238
- dict_[k] = func_call.lcall(v, convert.strip_lower)
239
- else:
240
- dict_[k] = [v.__name__]
241
- return dict_
242
-
243
- @_get_field_annotation.register(list)
244
- @_get_field_annotation.register(tuple)
245
- def _(self, field_names: list | tuple) -> dict[str, Any]:
246
- """
247
- Get the annotations for multiple fields as a dictionary.
248
-
249
- Args:
250
- field_names (list | tuple): A list or tuple of field names.
251
-
252
- Returns:
253
- dict[str, Any]: A dictionary mapping field names to their annotations.
254
- """
255
- dict_ = {}
256
- for field_name in field_names:
257
- dict_.update(self._get_field_annotation(field_name))
258
- return dict_
259
-
260
- def _field_has_attr(self, k: str, attr: str) -> bool:
261
- """
262
- Check if a field has a specific attribute.
263
-
264
- Args:
265
- k (str): The field name.
266
- attr (str): The attribute name.
267
-
268
- Returns:
269
- bool: True if the field has the attribute, False otherwise.
270
- """
271
- field = self._all_fields.get(k, None)
272
- if field is None:
273
- raise ValueError(f"Field {k} not found in model fields.")
274
-
275
- a = attr in str(field)
276
- if not a:
277
- try:
278
- a = (
279
- self._all_fields[k].json_schema_extra[attr] is not None
280
- and attr in self._all_fields[k].json_schema_extra
281
- )
282
- return a if isinstance(a, bool) else False
283
- except Exception:
284
- return False
285
- return a
286
-
287
- def __str__(self):
288
- return f"{self.__class__.__name__}({self.to_json_str()})"
289
-
290
-
291
- class BaseNode(BaseComponent):
292
- """
293
- Base class for creating node models.
294
-
295
- Attributes:
296
- content (Any | None): The optional content of the node.
297
- metadata (dict[str, Any]): Additional metadata for the node.
298
- """
299
-
300
- content: Any | None = Field(
301
- default=None,
302
- validation_alias=AliasChoices("text", "page_content", "chunk_content", "data"),
303
- description="The optional content of the node.",
304
- )
305
-
306
- metadata: dict[str, Any] = Field(
307
- default_factory=dict,
308
- validation_alias="meta",
309
- description="Additional metadata for the node.",
310
- )
311
-
312
- @singledispatchmethod
313
- @classmethod
314
- def from_obj(cls, obj: Any, *args, **kwargs) -> T:
315
- """
316
- Create a node instance from an object.
317
-
318
- Args:
319
- obj (Any): The object to create the node from.
320
- *args: Additional positional arguments.
321
- **kwargs: Additional keyword arguments.
322
-
323
- Raises:
324
- NotImplementedError: If the object type is not supported.
325
- """
326
- if not isinstance(obj, (dict, str, list, Series, DataFrame, BaseModel)):
327
- type_ = str(type(obj))
328
- if "llama_index" in type_:
329
- return cls.from_obj(obj.to_dict())
330
- elif "langchain" in type_:
331
- langchain_json = obj.to_json()
332
- langchain_dict = {
333
- "lc_id": langchain_json["id"],
334
- **langchain_json["kwargs"],
335
- }
336
- return cls.from_obj(langchain_dict)
337
-
338
- raise NotImplementedError(f"Unsupported type: {type(obj)}")
339
-
340
- @from_obj.register(dict)
341
- @classmethod
342
- def _from_dict(cls, obj: dict, *args, **kwargs) -> T:
343
- """
344
- Create a node instance from a dictionary.
345
-
346
- Args:
347
- obj (dict): The dictionary to create the node from.
348
- *args: Additional positional arguments.
349
- **kwargs: Additional keyword arguments.
350
-
351
- Returns:
352
- T: The created node instance.
353
- """
354
- return cls.model_validate(obj, *args, **kwargs)
355
-
356
- @from_obj.register(str)
357
- @classmethod
358
- def _from_str(cls, obj: str, *args, fuzzy_parse: bool = False, **kwargs) -> T:
359
- """
360
- Create a node instance from a JSON string.
361
-
362
- Args:
363
- obj (str): The JSON string to create the node from.
364
- *args: Additional positional arguments.
365
- fuzzy_parse (bool): Whether to perform fuzzy parsing.
366
- **kwargs: Additional keyword arguments.
367
-
368
- Returns:
369
- T: The created node instance.
370
- """
371
- obj = ParseUtil.fuzzy_parse_json(obj) if fuzzy_parse else convert.to_dict(obj)
372
- try:
373
- return cls.from_obj(obj, *args, **kwargs)
374
- except ValidationError as e:
375
- raise ValueError(f"Invalid JSON for deserialization: {e}") from e
376
-
377
- @from_obj.register(list)
378
- @classmethod
379
- def _from_list(cls, obj: list, *args, **kwargs) -> list[T]:
380
- """
381
- Create a list of node instances from a list of objects.
382
-
383
- Args:
384
- obj (list): The list of objects to create nodes from.
385
- *args: Additional positional arguments.
386
- **kwargs: Additional keyword arguments.
387
-
388
- Returns:
389
- list[T]: The list of created node instances.
390
- """
391
- return [cls.from_obj(item, *args, **kwargs) for item in obj]
392
-
393
- @from_obj.register(Series)
394
- @classmethod
395
- def _from_pd_series(
396
- cls, obj: Series, *args, pd_kwargs: dict | None = None, **kwargs
397
- ) -> T:
398
- """
399
- Create a node instance from a Pandas Series.
400
-
401
- Args:
402
- obj (Series): The Pandas Series to create the node from.
403
- *args: Additional positional arguments.
404
- pd_kwargs (dict | None): Additional keyword arguments for Pandas Series.
405
- **kwargs: Additional keyword arguments.
406
-
407
- Returns:
408
- T: The created node instance.
409
- """
410
- pd_kwargs = pd_kwargs or {}
411
- return cls.from_obj(obj.to_dict(**pd_kwargs), *args, **kwargs)
412
-
413
- @from_obj.register(DataFrame)
414
- @classmethod
415
- def _from_pd_dataframe(
416
- cls, obj: DataFrame, *args, pd_kwargs: dict | None = None, **kwargs
417
- ) -> list[T]:
418
- """
419
- Create a list of node instances from a Pandas DataFrame.
420
-
421
- Args:
422
- obj (DataFrame): The Pandas DataFrame to create nodes from.
423
- *args: Additional positional arguments.
424
- pd_kwargs (dict | None): Additional keyword arguments for Pandas DataFrame.
425
- **kwargs: Additional keyword arguments.
426
-
427
- Returns:
428
- list[T]: The list of created node instances.
429
- """
430
- if pd_kwargs is None:
431
- pd_kwargs = {}
432
-
433
- _objs = []
434
- for index, row in obj.iterrows():
435
- _obj = cls.from_obj(row, *args, **pd_kwargs, **kwargs)
436
- _obj.metadata["df_index"] = index
437
- _objs.append(_obj)
438
-
439
- return _objs
440
-
441
- @from_obj.register(BaseModel)
442
- @classmethod
443
- def _from_base_model(cls, obj, pydantic_kwargs=None, **kwargs) -> T:
444
- """
445
- Create a node instance from a Pydantic BaseModel.
446
-
447
- Args:
448
- obj (BaseModel): The Pydantic BaseModel to create the node from.
449
-
450
- Returns:
451
- T: The created node instance.
452
- """
453
- pydantic_kwargs = pydantic_kwargs or {"by_alias": True}
454
- try:
455
- config_ = {}
456
- try:
457
- config_ = obj.model_dump(**pydantic_kwargs)
458
- except:
459
- config_ = obj.to_dict(**pydantic_kwargs)
460
- else:
461
- config_ = obj.dict(**pydantic_kwargs)
462
- except Exception as e:
463
- raise ValueError(f"Invalid Pydantic model for deserialization: {e}") from e
464
-
465
- return cls.from_obj(config_ | kwargs)
466
-
467
- def meta_get(
468
- self, key: str, indices: list[str | int] | None = None, default: Any = None
469
- ) -> Any:
470
- """
471
- Get a value from the metadata dictionary.
472
-
473
- Args:
474
- key (str): The key to retrieve the value for.
475
- indices (list[str | int] | None): Optional list of indices for nested retrieval.
476
- default (Any): The default value to return if the key is not found.
477
-
478
- Returns:
479
- Any: The retrieved value or the default value if not found.
480
- """
481
- if indices:
482
- return nested.nget(self.metadata, indices, default)
483
- return self.metadata.get(key, default)
484
-
485
- def meta_change_key(self, old_key: str, new_key: str) -> bool:
486
- """
487
- Change a key in the metadata dictionary.
488
-
489
- Args:
490
- old_key (str): The old key to be changed.
491
- new_key (str): The new key to replace the old key.
492
-
493
- Returns:
494
- bool: True if the key was changed successfully, False otherwise.
495
- """
496
- if old_key in self.metadata:
497
- SysUtil.change_dict_key(self.metadata, old_key, new_key)
498
- return True
499
- return False
500
-
501
- def meta_insert(self, indices: str | list, value: Any, **kwargs) -> bool:
502
- """
503
- Insert a value into the metadata dictionary at the specified indices.
504
-
505
- Args:
506
- indices (str | list): The indices to insert the value at.
507
- value (Any): The value to be inserted.
508
- **kwargs: Additional keyword arguments for the `nested.ninsert`
509
- function.
510
-
511
- Returns:
512
- bool: True if the value was inserted successfully, False otherwise.
513
- """
514
- return nested.ninsert(self.metadata, indices, value, **kwargs)
515
-
516
- def meta_merge(
517
- self, additional_metadata: dict[str, Any], overwrite: bool = False, **kwargs
518
- ) -> None:
519
- """
520
- Merge additional metadata into the existing metadata dictionary.
521
-
522
- Args:
523
- additional_metadata (dict[str, Any]): The additional metadata to be
524
- merged.
525
- overwrite (bool): Whether to overwrite existing keys with the new
526
- values.
527
- **kwargs: Additional keyword arguments for the `nested.nmerge`
528
- function.
529
- """
530
- self.metadata = nested.nmerge(
531
- [self.metadata, additional_metadata], overwrite=overwrite, **kwargs
532
- )
@@ -1,46 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from enum import Enum
3
- from typing import Callable
4
- from pydantic import BaseModel, Field
5
-
6
-
7
- class ConditionSource(str, Enum):
8
- """
9
- Enumeration for specifying the source type of a condition.
10
-
11
- Attributes:
12
- STRUCTURE: Represents a condition based on the structure.
13
- EXECUTABLE: Represents a condition that can be executed or evaluated.
14
- """
15
-
16
- STRUCTURE = "structure"
17
- EXECUTABLE = "executable"
18
- RULE = "rule"
19
-
20
-
21
- class Condition(BaseModel, ABC):
22
- """
23
- Abstract base class for defining conditions associated with edges.
24
-
25
- Attributes:
26
- source_type (ConditionSource): Specifies the type of source for the condition.
27
-
28
- Methods:
29
- check: Abstract method that should be implemented to evaluate the condition.
30
- """
31
-
32
- source_type: str = Field(..., description="The type of source for the condition.")
33
-
34
- class Config:
35
- """Model configuration settings."""
36
-
37
- extra = "allow"
38
-
39
- @abstractmethod
40
- def __call__(self, executable) -> bool:
41
- """Evaluates the condition based on implemented logic.
42
-
43
- Returns:
44
- bool: The boolean result of the condition evaluation.
45
- """
46
- 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
- )