lionagi 0.0.312__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 +61 -3
  2. lionagi/core/__init__.py +0 -14
  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/__init__.py +0 -3
  11. lionagi/core/agent/base_agent.py +45 -36
  12. lionagi/core/agent/eval/evaluator.py +1 -0
  13. lionagi/core/agent/eval/vote.py +40 -0
  14. lionagi/core/agent/learn/learner.py +59 -0
  15. lionagi/core/agent/plan/unit_template.py +1 -0
  16. lionagi/core/collections/__init__.py +17 -0
  17. lionagi/core/collections/_logger.py +319 -0
  18. lionagi/core/collections/abc/__init__.py +53 -0
  19. lionagi/core/collections/abc/component.py +615 -0
  20. lionagi/core/collections/abc/concepts.py +297 -0
  21. lionagi/core/collections/abc/exceptions.py +150 -0
  22. lionagi/core/collections/abc/util.py +45 -0
  23. lionagi/core/collections/exchange.py +161 -0
  24. lionagi/core/collections/flow.py +426 -0
  25. lionagi/core/collections/model.py +419 -0
  26. lionagi/core/collections/pile.py +913 -0
  27. lionagi/core/collections/progression.py +236 -0
  28. lionagi/core/collections/util.py +64 -0
  29. lionagi/core/director/direct.py +314 -0
  30. lionagi/core/director/director.py +2 -0
  31. lionagi/core/engine/branch_engine.py +333 -0
  32. lionagi/core/engine/instruction_map_engine.py +204 -0
  33. lionagi/core/engine/sandbox_.py +14 -0
  34. lionagi/core/engine/script_engine.py +99 -0
  35. lionagi/core/executor/base_executor.py +90 -0
  36. lionagi/core/executor/graph_executor.py +330 -0
  37. lionagi/core/executor/neo4j_executor.py +384 -0
  38. lionagi/core/generic/__init__.py +7 -0
  39. lionagi/core/generic/edge.py +112 -0
  40. lionagi/core/generic/edge_condition.py +16 -0
  41. lionagi/core/generic/graph.py +236 -0
  42. lionagi/core/generic/hyperedge.py +1 -0
  43. lionagi/core/generic/node.py +220 -0
  44. lionagi/core/generic/tree.py +48 -0
  45. lionagi/core/generic/tree_node.py +79 -0
  46. lionagi/core/mail/__init__.py +7 -3
  47. lionagi/core/mail/mail.py +25 -0
  48. lionagi/core/mail/mail_manager.py +142 -58
  49. lionagi/core/mail/package.py +45 -0
  50. lionagi/core/mail/start_mail.py +36 -0
  51. lionagi/core/message/__init__.py +19 -0
  52. lionagi/core/message/action_request.py +133 -0
  53. lionagi/core/message/action_response.py +135 -0
  54. lionagi/core/message/assistant_response.py +95 -0
  55. lionagi/core/message/instruction.py +234 -0
  56. lionagi/core/message/message.py +101 -0
  57. lionagi/core/message/system.py +86 -0
  58. lionagi/core/message/util.py +283 -0
  59. lionagi/core/report/__init__.py +4 -0
  60. lionagi/core/report/base.py +217 -0
  61. lionagi/core/report/form.py +231 -0
  62. lionagi/core/report/report.py +166 -0
  63. lionagi/core/report/util.py +28 -0
  64. lionagi/core/rule/__init__.py +0 -0
  65. lionagi/core/rule/_default.py +16 -0
  66. lionagi/core/rule/action.py +99 -0
  67. lionagi/core/rule/base.py +238 -0
  68. lionagi/core/rule/boolean.py +56 -0
  69. lionagi/core/rule/choice.py +47 -0
  70. lionagi/core/rule/mapping.py +96 -0
  71. lionagi/core/rule/number.py +71 -0
  72. lionagi/core/rule/rulebook.py +109 -0
  73. lionagi/core/rule/string.py +52 -0
  74. lionagi/core/rule/util.py +35 -0
  75. lionagi/core/session/__init__.py +0 -3
  76. lionagi/core/session/branch.py +431 -0
  77. lionagi/core/session/directive_mixin.py +287 -0
  78. lionagi/core/session/session.py +230 -902
  79. lionagi/core/structure/__init__.py +1 -0
  80. lionagi/core/structure/chain.py +1 -0
  81. lionagi/core/structure/forest.py +1 -0
  82. lionagi/core/structure/graph.py +1 -0
  83. lionagi/core/structure/tree.py +1 -0
  84. lionagi/core/unit/__init__.py +5 -0
  85. lionagi/core/unit/parallel_unit.py +245 -0
  86. lionagi/core/unit/template/__init__.py +0 -0
  87. lionagi/core/unit/template/action.py +81 -0
  88. lionagi/core/unit/template/base.py +51 -0
  89. lionagi/core/unit/template/plan.py +84 -0
  90. lionagi/core/unit/template/predict.py +109 -0
  91. lionagi/core/unit/template/score.py +124 -0
  92. lionagi/core/unit/template/select.py +104 -0
  93. lionagi/core/unit/unit.py +362 -0
  94. lionagi/core/unit/unit_form.py +305 -0
  95. lionagi/core/unit/unit_mixin.py +1168 -0
  96. lionagi/core/unit/util.py +71 -0
  97. lionagi/core/validator/__init__.py +0 -0
  98. lionagi/core/validator/validator.py +364 -0
  99. lionagi/core/work/__init__.py +0 -0
  100. lionagi/core/work/work.py +76 -0
  101. lionagi/core/work/work_function.py +101 -0
  102. lionagi/core/work/work_queue.py +103 -0
  103. lionagi/core/work/worker.py +258 -0
  104. lionagi/core/work/worklog.py +120 -0
  105. lionagi/experimental/__init__.py +0 -0
  106. lionagi/experimental/compressor/__init__.py +0 -0
  107. lionagi/experimental/compressor/base.py +46 -0
  108. lionagi/experimental/compressor/llm_compressor.py +247 -0
  109. lionagi/experimental/compressor/llm_summarizer.py +61 -0
  110. lionagi/experimental/compressor/util.py +70 -0
  111. lionagi/experimental/directive/__init__.py +19 -0
  112. lionagi/experimental/directive/parser/__init__.py +0 -0
  113. lionagi/experimental/directive/parser/base_parser.py +282 -0
  114. lionagi/experimental/directive/template/__init__.py +0 -0
  115. lionagi/experimental/directive/template/base_template.py +79 -0
  116. lionagi/experimental/directive/template/schema.py +36 -0
  117. lionagi/experimental/directive/tokenizer.py +73 -0
  118. lionagi/experimental/evaluator/__init__.py +0 -0
  119. lionagi/experimental/evaluator/ast_evaluator.py +131 -0
  120. lionagi/experimental/evaluator/base_evaluator.py +218 -0
  121. lionagi/experimental/knowledge/__init__.py +0 -0
  122. lionagi/experimental/knowledge/base.py +10 -0
  123. lionagi/experimental/knowledge/graph.py +0 -0
  124. lionagi/experimental/memory/__init__.py +0 -0
  125. lionagi/experimental/strategies/__init__.py +0 -0
  126. lionagi/experimental/strategies/base.py +1 -0
  127. lionagi/integrations/bridge/autogen_/__init__.py +0 -0
  128. lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
  129. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  130. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  131. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  132. lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
  133. lionagi/integrations/bridge/llamaindex_/node_parser.py +6 -9
  134. lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +1 -0
  135. lionagi/integrations/bridge/transformers_/__init__.py +0 -0
  136. lionagi/integrations/bridge/transformers_/install_.py +36 -0
  137. lionagi/integrations/chunker/__init__.py +0 -0
  138. lionagi/integrations/chunker/chunk.py +312 -0
  139. lionagi/integrations/config/oai_configs.py +38 -7
  140. lionagi/integrations/config/ollama_configs.py +1 -1
  141. lionagi/integrations/config/openrouter_configs.py +14 -2
  142. lionagi/integrations/loader/__init__.py +0 -0
  143. lionagi/integrations/loader/load.py +253 -0
  144. lionagi/integrations/loader/load_util.py +195 -0
  145. lionagi/integrations/provider/_mapping.py +46 -0
  146. lionagi/integrations/provider/litellm.py +2 -1
  147. lionagi/integrations/provider/mlx_service.py +16 -9
  148. lionagi/integrations/provider/oai.py +91 -4
  149. lionagi/integrations/provider/ollama.py +7 -6
  150. lionagi/integrations/provider/openrouter.py +115 -8
  151. lionagi/integrations/provider/services.py +2 -2
  152. lionagi/integrations/provider/transformers.py +18 -22
  153. lionagi/integrations/storage/__init__.py +3 -0
  154. lionagi/integrations/storage/neo4j.py +665 -0
  155. lionagi/integrations/storage/storage_util.py +287 -0
  156. lionagi/integrations/storage/structure_excel.py +285 -0
  157. lionagi/integrations/storage/to_csv.py +63 -0
  158. lionagi/integrations/storage/to_excel.py +83 -0
  159. lionagi/libs/__init__.py +26 -1
  160. lionagi/libs/ln_api.py +78 -23
  161. lionagi/libs/ln_context.py +37 -0
  162. lionagi/libs/ln_convert.py +21 -9
  163. lionagi/libs/ln_func_call.py +69 -28
  164. lionagi/libs/ln_image.py +107 -0
  165. lionagi/libs/ln_knowledge_graph.py +405 -0
  166. lionagi/libs/ln_nested.py +26 -11
  167. lionagi/libs/ln_parse.py +110 -14
  168. lionagi/libs/ln_queue.py +117 -0
  169. lionagi/libs/ln_tokenize.py +164 -0
  170. lionagi/{core/prompt/field_validator.py → libs/ln_validate.py} +79 -14
  171. lionagi/libs/special_tokens.py +172 -0
  172. lionagi/libs/sys_util.py +107 -2
  173. lionagi/lions/__init__.py +0 -0
  174. lionagi/lions/coder/__init__.py +0 -0
  175. lionagi/lions/coder/add_feature.py +20 -0
  176. lionagi/lions/coder/base_prompts.py +22 -0
  177. lionagi/lions/coder/code_form.py +13 -0
  178. lionagi/lions/coder/coder.py +168 -0
  179. lionagi/lions/coder/util.py +96 -0
  180. lionagi/lions/researcher/__init__.py +0 -0
  181. lionagi/lions/researcher/data_source/__init__.py +0 -0
  182. lionagi/lions/researcher/data_source/finhub_.py +191 -0
  183. lionagi/lions/researcher/data_source/google_.py +199 -0
  184. lionagi/lions/researcher/data_source/wiki_.py +96 -0
  185. lionagi/lions/researcher/data_source/yfinance_.py +21 -0
  186. lionagi/tests/integrations/__init__.py +0 -0
  187. lionagi/tests/libs/__init__.py +0 -0
  188. lionagi/tests/libs/test_field_validators.py +353 -0
  189. lionagi/tests/{test_libs → libs}/test_func_call.py +23 -21
  190. lionagi/tests/{test_libs → libs}/test_nested.py +36 -21
  191. lionagi/tests/{test_libs → libs}/test_parse.py +1 -1
  192. lionagi/tests/libs/test_queue.py +67 -0
  193. lionagi/tests/test_core/collections/__init__.py +0 -0
  194. lionagi/tests/test_core/collections/test_component.py +206 -0
  195. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  196. lionagi/tests/test_core/collections/test_flow.py +145 -0
  197. lionagi/tests/test_core/collections/test_pile.py +171 -0
  198. lionagi/tests/test_core/collections/test_progression.py +129 -0
  199. lionagi/tests/test_core/generic/__init__.py +0 -0
  200. lionagi/tests/test_core/generic/test_edge.py +67 -0
  201. lionagi/tests/test_core/generic/test_graph.py +96 -0
  202. lionagi/tests/test_core/generic/test_node.py +106 -0
  203. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  204. lionagi/tests/test_core/test_branch.py +115 -292
  205. lionagi/tests/test_core/test_form.py +46 -0
  206. lionagi/tests/test_core/test_report.py +105 -0
  207. lionagi/tests/test_core/test_validator.py +111 -0
  208. lionagi/version.py +1 -1
  209. {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/LICENSE +12 -11
  210. {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/METADATA +19 -118
  211. lionagi-0.2.1.dist-info/RECORD +240 -0
  212. lionagi/core/branch/__init__.py +0 -4
  213. lionagi/core/branch/base_branch.py +0 -654
  214. lionagi/core/branch/branch.py +0 -471
  215. lionagi/core/branch/branch_flow_mixin.py +0 -96
  216. lionagi/core/branch/executable_branch.py +0 -347
  217. lionagi/core/branch/util.py +0 -323
  218. lionagi/core/direct/__init__.py +0 -6
  219. lionagi/core/direct/predict.py +0 -161
  220. lionagi/core/direct/score.py +0 -278
  221. lionagi/core/direct/select.py +0 -169
  222. lionagi/core/direct/utils.py +0 -87
  223. lionagi/core/direct/vote.py +0 -64
  224. lionagi/core/flow/base/baseflow.py +0 -23
  225. lionagi/core/flow/monoflow/ReAct.py +0 -238
  226. lionagi/core/flow/monoflow/__init__.py +0 -9
  227. lionagi/core/flow/monoflow/chat.py +0 -95
  228. lionagi/core/flow/monoflow/chat_mixin.py +0 -263
  229. lionagi/core/flow/monoflow/followup.py +0 -214
  230. lionagi/core/flow/polyflow/__init__.py +0 -1
  231. lionagi/core/flow/polyflow/chat.py +0 -248
  232. lionagi/core/mail/schema.py +0 -56
  233. lionagi/core/messages/__init__.py +0 -3
  234. lionagi/core/messages/schema.py +0 -533
  235. lionagi/core/prompt/prompt_template.py +0 -316
  236. lionagi/core/schema/__init__.py +0 -22
  237. lionagi/core/schema/action_node.py +0 -29
  238. lionagi/core/schema/base_mixin.py +0 -296
  239. lionagi/core/schema/base_node.py +0 -199
  240. lionagi/core/schema/condition.py +0 -24
  241. lionagi/core/schema/data_logger.py +0 -354
  242. lionagi/core/schema/data_node.py +0 -93
  243. lionagi/core/schema/prompt_template.py +0 -67
  244. lionagi/core/schema/structure.py +0 -910
  245. lionagi/core/tool/__init__.py +0 -3
  246. lionagi/core/tool/tool_manager.py +0 -280
  247. lionagi/integrations/bridge/pydantic_/base_model.py +0 -7
  248. lionagi/tests/test_core/test_base_branch.py +0 -427
  249. lionagi/tests/test_core/test_chat_flow.py +0 -63
  250. lionagi/tests/test_core/test_mail_manager.py +0 -75
  251. lionagi/tests/test_core/test_prompts.py +0 -51
  252. lionagi/tests/test_core/test_session.py +0 -254
  253. lionagi/tests/test_core/test_session_base_util.py +0 -312
  254. lionagi/tests/test_core/test_tool_manager.py +0 -95
  255. lionagi-0.0.312.dist-info/RECORD +0 -111
  256. /lionagi/core/{branch/base → _setting}/__init__.py +0 -0
  257. /lionagi/core/{flow → agent/eval}/__init__.py +0 -0
  258. /lionagi/core/{flow/base → agent/learn}/__init__.py +0 -0
  259. /lionagi/core/{prompt → agent/plan}/__init__.py +0 -0
  260. /lionagi/core/{tool/manual.py → agent/plan/plan.py} +0 -0
  261. /lionagi/{tests/test_integrations → core/director}/__init__.py +0 -0
  262. /lionagi/{tests/test_libs → core/engine}/__init__.py +0 -0
  263. /lionagi/{tests/test_libs/test_async.py → core/executor/__init__.py} +0 -0
  264. /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
  265. /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
  266. /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
  267. {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
  268. {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,319 @@
1
+ """
2
+ Copyright 2024 HaiyangLi
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
16
+
17
+ import atexit
18
+ import contextlib
19
+ import logging
20
+ from collections import deque
21
+ from dataclasses import dataclass
22
+ from pathlib import Path
23
+ from typing import Any, Dict, List
24
+
25
+ from lionagi.libs import SysUtil, convert, nested
26
+
27
+
28
+ # TODO: there should be a global data logger, under setting
29
+
30
+
31
+ @dataclass
32
+ class DLog:
33
+ """Defines a log entry structure for data processing operations.
34
+
35
+ This class encapsulates both the input to and output from a data processing
36
+ operation, along with an automatically generated timestamp indicating when
37
+ the log entry was created. It aims to standardize logging across applications
38
+ for easier analysis and debugging.
39
+
40
+ Attributes:
41
+ input_data: The data input to the operation. Can be of any type.
42
+ output_data: The data output by the operation. Can be of any type.
43
+ """
44
+
45
+ input_data: Any
46
+ output_data: Any
47
+
48
+ def serialize(self, *, flatten_: bool = True, sep: str = "[^_^]") -> dict[str, Any]:
49
+ """Serialize the DLog instance into a dictionary with an added timestamp.
50
+
51
+ Args:
52
+ flatten_ (bool): If True, flattens dictionary inputs for serialization.
53
+ sep (str): Separator used in flattening nested dictionaries.
54
+
55
+ Returns:
56
+ A dictionary representation of the DLog instance, including 'input_data',
57
+ 'output_data', and 'timestamp'.
58
+ """
59
+ log_dict = {}
60
+
61
+ def _process_data(data, field):
62
+ try:
63
+ data = convert.to_str(data)
64
+ if "{" not in data:
65
+ log_dict[field] = convert.to_str(data)
66
+ else:
67
+ with contextlib.suppress(Exception):
68
+ data = convert.to_dict(data)
69
+
70
+ if isinstance(self.input_data, dict) and flatten_:
71
+ log_dict[field] = convert.to_str(nested.flatten(data, sep=sep))
72
+ else:
73
+ log_dict[field] = convert.to_str(data)
74
+
75
+ except Exception as e:
76
+ log_dict[field] = data
77
+ logging.error(f"Error in processing {field} to str: {e}")
78
+
79
+ _process_data(self.input_data, "input_data")
80
+ _process_data(self.output_data, "output_data")
81
+
82
+ log_dict["timestamp"] = SysUtil.get_timestamp()
83
+
84
+ return log_dict
85
+
86
+ @classmethod
87
+ def deserialize(
88
+ cls,
89
+ *,
90
+ input_str: str,
91
+ output_str: str,
92
+ unflatten_: bool = True,
93
+ sep: str = "[^_^]",
94
+ ) -> "DLog":
95
+ """Deserialize log entries from string representations.
96
+
97
+ This method reconstructs a DLog instance from serialized string data,
98
+ optionally unflattening nested dictionary structures if they were
99
+ flattened during the serialization process. The method is particularly
100
+ useful for reading logs from storage formats like JSON or CSV where
101
+ data is represented as strings.
102
+
103
+ Note:
104
+ The separator '[^_^]' is reserved and should not be used within
105
+ dictionary keys to ensure proper structure preservation during
106
+ unflattening.
107
+
108
+ Args:
109
+ input_str: String representation of the input data.
110
+ output_str: String representation of the output data.
111
+ unflatten_ (bool): Indicates whether to unflatten the string data
112
+ back into nested dictionaries.
113
+ sep (str): Separator used if unflattening is performed.
114
+
115
+ Returns:
116
+ An instance of DLog reconstructed from the provided string data.
117
+
118
+ Raises:
119
+ ValueError: If deserialization or unflattening fails due to incorrect
120
+ data format or separator issues.
121
+ """
122
+
123
+ def _process_data(data):
124
+ if unflatten_:
125
+ try:
126
+ return nested.unflatten(convert.to_dict(data), sep=sep)
127
+ except Exception:
128
+ return data
129
+ else:
130
+ return data
131
+
132
+ input_data = _process_data(input_str)
133
+ output_data = _process_data(output_str)
134
+
135
+ return cls(input_data=input_data, output_data=output_data)
136
+
137
+
138
+ class DataLogger:
139
+ """Manages logging for data processing activities within an application.
140
+
141
+ This class handles the accumulation, structuring, and persistence of log entries.
142
+ It supports exporting logs to disk in both CSV and JSON formats, with features for
143
+ automatic log saving at program exit and customizable file naming.
144
+
145
+ Attributes:
146
+ persist_path: Path to the directory for saving log files.
147
+ log: Container for log entries.
148
+ filename: Base name for log files.
149
+ """
150
+
151
+ def __init__(
152
+ self,
153
+ persist_path: str | Path | None = None,
154
+ log: List[Dict] | None = None,
155
+ filename: str | None = None,
156
+ ) -> None:
157
+ """Initialize the DataLogger with optional custom settings for log storage.
158
+
159
+ Args:
160
+ persist_path: The file system path for storing log files.
161
+ Defaults to 'data/logs/'.
162
+ log: Initial log entries.
163
+ filename: Base name for exported log files.
164
+ """
165
+ self.persist_path = Path(persist_path) if persist_path else Path("data/logs/")
166
+ self.log = deque(log) if log else deque()
167
+ self.filename = filename or "log"
168
+ atexit.register(self.save_at_exit)
169
+
170
+ def extend(self, logs) -> None:
171
+ """Extend the log deque with multiple log entries.
172
+
173
+ This method allows for bulk addition of log entries, which can be useful for
174
+ importing logs from external sources or consolidating logs from different parts
175
+ of an application.
176
+
177
+ Args:
178
+ logs: A list of log entries, each as a dictionary conforming to the log
179
+ structure (e.g., containing 'input_data', 'output_data', etc.).
180
+ """
181
+ if len(logs) > 0:
182
+ log1 = convert.to_list(self.log)
183
+ log1.extend(convert.to_list(logs))
184
+ self.log = deque(log1)
185
+
186
+ def append(self, *, input_data: Any, output_data: Any) -> None:
187
+ """Append a new log entry from provided input and output data.
188
+
189
+ Args:
190
+ input_data: Input data to the operation.
191
+ output_data: Output data from the operation.
192
+ """
193
+ log_entry = DLog(input_data=input_data, output_data=output_data)
194
+ self.log.append(log_entry)
195
+
196
+ def to_csv_file(
197
+ self,
198
+ filename: str = "log.csv",
199
+ *,
200
+ dir_exist_ok: bool = True,
201
+ timestamp: bool = True,
202
+ time_prefix: bool = False,
203
+ verbose: bool = True,
204
+ clear: bool = True,
205
+ flatten_: bool = True,
206
+ sep: str = "[^_^]",
207
+ index: bool = False,
208
+ random_hash_digits: int = 3,
209
+ **kwargs,
210
+ ) -> None:
211
+ """Export log entries to a CSV file with customizable options.
212
+
213
+ Args:
214
+ filename: Filename for the exported CSV. Defaults to 'log.csv'.
215
+ dir_exist_ok: If True, allows writing to an existing directory.
216
+ timestamp: If True, appends a timestamp to the filename.
217
+ time_prefix: If True, places the timestamp prefix before the filename.
218
+ verbose: If True, prints a message upon successful save.
219
+ clear: If True, clears the log deque after saving.
220
+ flatten_: If True, flattens dictionary data for serialization.
221
+ sep: Separator for flattening nested dictionaries.
222
+ index: If True, includes an index column in the CSV.
223
+ random_hash_digits: Number of random hash digits to add to the filename.
224
+ **kwargs: Additional arguments for DataFrame.to_csv().
225
+ """
226
+ if not filename.endswith(".csv"):
227
+ filename += ".csv"
228
+
229
+ filepath = SysUtil.create_path(
230
+ self.persist_path,
231
+ filename,
232
+ timestamp=timestamp,
233
+ dir_exist_ok=dir_exist_ok,
234
+ time_prefix=time_prefix,
235
+ random_hash_digits=random_hash_digits,
236
+ )
237
+ try:
238
+ logs = [log.serialize(flatten_=flatten_, sep=sep) for log in self.log]
239
+ df = convert.to_df(convert.to_list(logs, flatten=True))
240
+ df.to_csv(filepath, index=index, **kwargs)
241
+ if verbose:
242
+ print(f"{len(self.log)} logs saved to {filepath}")
243
+ if clear:
244
+ self.log.clear()
245
+ except Exception as e:
246
+ raise ValueError(f"Error in saving to csv: {e}") from e
247
+
248
+ def to_json_file(
249
+ self,
250
+ filename: str = "log.json",
251
+ *,
252
+ dir_exist_ok: bool = True,
253
+ timestamp: bool = True,
254
+ time_prefix: bool = False,
255
+ verbose: bool = True,
256
+ clear: bool = True,
257
+ flatten_: bool = True,
258
+ sep: str = "[^_^]",
259
+ index: bool = False,
260
+ random_hash_digits: int = 3,
261
+ **kwargs,
262
+ ) -> None:
263
+ """Export log entries to a JSON file with customizable options.
264
+
265
+ Args:
266
+ filename: Filename for the exported JSON. Defaults to 'log.json'.
267
+ dir_exist_ok: If True, allows writing to an existing directory.
268
+ timestamp: If True, appends a timestamp to the filename.
269
+ time_prefix: If True, places the timestamp prefix before the filename.
270
+ verbose: If True, prints a message upon successful save.
271
+ clear: If True, clears the log deque after saving.
272
+ flatten_: If True, flattens dictionary data for serialization.
273
+ sep: Separator for flattening nested dictionaries.
274
+ index: If True, includes an index in the JSON.
275
+ random_hash_digits: Number of random hash digits to add to the filename.
276
+ **kwargs: Additional arguments for DataFrame.to_json().
277
+ """
278
+ if not filename.endswith(".json"):
279
+ filename += ".json"
280
+
281
+ filepath = SysUtil.create_path(
282
+ self.persist_path,
283
+ filename,
284
+ timestamp=timestamp,
285
+ dir_exist_ok=dir_exist_ok,
286
+ time_prefix=time_prefix,
287
+ random_hash_digits=random_hash_digits,
288
+ )
289
+
290
+ try:
291
+ logs = [log.serialize(flatten_=flatten_, sep=sep) for log in self.log]
292
+ df = convert.to_df(convert.to_list(logs, flatten=True))
293
+ df.to_json(filepath, index=index, **kwargs)
294
+ if verbose:
295
+ print(f"{len(self.log)} logs saved to {filepath}")
296
+ if clear:
297
+ self.log.clear()
298
+ except Exception as e:
299
+ raise ValueError(f"Error in saving to json: {e}") from e
300
+
301
+ def save_at_exit(self):
302
+ """Save any unsaved logs automatically upon program termination.
303
+
304
+ This method is registered as an at-exit handler to ensure that any unsaved
305
+ logs are automatically persisted to a file upon program termination. This
306
+ safeguard helps prevent the loss of log data due to unexpected shutdowns
307
+ or program exits.
308
+
309
+ The method is configured to save the logs to a CSV file, named
310
+ 'unsaved_logs.csv', which is stored in the designated persisting directory.
311
+ This automatic save operation is triggered only if there are unsaved logs
312
+ present at the time of program exit.
313
+
314
+ Note:
315
+ This method does not clear the logs after saving, allowing for the
316
+ possibility of manual review or recovery after the program has terminated.
317
+ """
318
+ if self.log:
319
+ self.to_csv_file("unsaved_logs.csv", clear=False)
@@ -0,0 +1,53 @@
1
+ """abc: Abstract Base Classes for lionagi."""
2
+
3
+ from pydantic import Field
4
+ from .exceptions import (
5
+ LionTypeError,
6
+ LionValueError,
7
+ ItemNotFoundError,
8
+ FieldError,
9
+ LionOperationError,
10
+ RelationError,
11
+ ActionError,
12
+ ModelLimitExceededError,
13
+ )
14
+ from .component import Element, Component, LionIDable, get_lion_id
15
+ from .concepts import (
16
+ Record,
17
+ Ordering,
18
+ Condition,
19
+ Actionable,
20
+ Relatable,
21
+ Progressable,
22
+ Sendable,
23
+ Executable,
24
+ Directive,
25
+ )
26
+ from .util import SYSTEM_FIELDS
27
+
28
+
29
+ __all__ = [
30
+ "Element",
31
+ "Record",
32
+ "Ordering",
33
+ "Condition",
34
+ "Actionable",
35
+ "Component",
36
+ "LionIDable",
37
+ "get_lion_id",
38
+ "LionTypeError",
39
+ "LionValueError",
40
+ "ActionError",
41
+ "ItemNotFoundError",
42
+ "FieldError",
43
+ "LionOperationError",
44
+ "Relatable",
45
+ "Progressable",
46
+ "RelationError",
47
+ "Sendable",
48
+ "Field",
49
+ "Executable",
50
+ "SYSTEM_FIELDS",
51
+ "Directive",
52
+ "ModelLimitExceededError",
53
+ ]