lionagi 0.1.2__py3-none-any.whl → 0.2.1__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.
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 +76 -0
  94. lionagi/core/work/work_function.py +101 -0
  95. lionagi/core/work/work_queue.py +103 -0
  96. lionagi/core/work/worker.py +258 -0
  97. lionagi/core/work/worklog.py +120 -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.1.dist-info/LICENSE +202 -0
  168. lionagi-0.2.1.dist-info/METADATA +272 -0
  169. lionagi-0.2.1.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.1.dist-info}/WHEEL +0 -0
  268. {lionagi-0.1.2.dist-info → lionagi-0.2.1.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
- )