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.
- lionagi/__init__.py +61 -3
- lionagi/core/__init__.py +0 -14
- lionagi/core/_setting/_setting.py +59 -0
- lionagi/core/action/__init__.py +14 -0
- lionagi/core/action/function_calling.py +136 -0
- lionagi/core/action/manual.py +1 -0
- lionagi/core/action/node.py +109 -0
- lionagi/core/action/tool.py +114 -0
- lionagi/core/action/tool_manager.py +356 -0
- lionagi/core/agent/__init__.py +0 -3
- lionagi/core/agent/base_agent.py +45 -36
- lionagi/core/agent/eval/evaluator.py +1 -0
- lionagi/core/agent/eval/vote.py +40 -0
- lionagi/core/agent/learn/learner.py +59 -0
- lionagi/core/agent/plan/unit_template.py +1 -0
- lionagi/core/collections/__init__.py +17 -0
- lionagi/core/collections/_logger.py +319 -0
- lionagi/core/collections/abc/__init__.py +53 -0
- lionagi/core/collections/abc/component.py +615 -0
- lionagi/core/collections/abc/concepts.py +297 -0
- lionagi/core/collections/abc/exceptions.py +150 -0
- lionagi/core/collections/abc/util.py +45 -0
- lionagi/core/collections/exchange.py +161 -0
- lionagi/core/collections/flow.py +426 -0
- lionagi/core/collections/model.py +419 -0
- lionagi/core/collections/pile.py +913 -0
- lionagi/core/collections/progression.py +236 -0
- lionagi/core/collections/util.py +64 -0
- lionagi/core/director/direct.py +314 -0
- lionagi/core/director/director.py +2 -0
- lionagi/core/engine/branch_engine.py +333 -0
- lionagi/core/engine/instruction_map_engine.py +204 -0
- lionagi/core/engine/sandbox_.py +14 -0
- lionagi/core/engine/script_engine.py +99 -0
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/executor/graph_executor.py +330 -0
- lionagi/core/executor/neo4j_executor.py +384 -0
- lionagi/core/generic/__init__.py +7 -0
- lionagi/core/generic/edge.py +112 -0
- lionagi/core/generic/edge_condition.py +16 -0
- lionagi/core/generic/graph.py +236 -0
- lionagi/core/generic/hyperedge.py +1 -0
- lionagi/core/generic/node.py +220 -0
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +7 -3
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +142 -58
- lionagi/core/mail/package.py +45 -0
- lionagi/core/mail/start_mail.py +36 -0
- lionagi/core/message/__init__.py +19 -0
- lionagi/core/message/action_request.py +133 -0
- lionagi/core/message/action_response.py +135 -0
- lionagi/core/message/assistant_response.py +95 -0
- lionagi/core/message/instruction.py +234 -0
- lionagi/core/message/message.py +101 -0
- lionagi/core/message/system.py +86 -0
- lionagi/core/message/util.py +283 -0
- lionagi/core/report/__init__.py +4 -0
- lionagi/core/report/base.py +217 -0
- lionagi/core/report/form.py +231 -0
- lionagi/core/report/report.py +166 -0
- lionagi/core/report/util.py +28 -0
- lionagi/core/rule/__init__.py +0 -0
- lionagi/core/rule/_default.py +16 -0
- lionagi/core/rule/action.py +99 -0
- lionagi/core/rule/base.py +238 -0
- lionagi/core/rule/boolean.py +56 -0
- lionagi/core/rule/choice.py +47 -0
- lionagi/core/rule/mapping.py +96 -0
- lionagi/core/rule/number.py +71 -0
- lionagi/core/rule/rulebook.py +109 -0
- lionagi/core/rule/string.py +52 -0
- lionagi/core/rule/util.py +35 -0
- lionagi/core/session/__init__.py +0 -3
- lionagi/core/session/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +230 -902
- lionagi/core/structure/__init__.py +1 -0
- lionagi/core/structure/chain.py +1 -0
- lionagi/core/structure/forest.py +1 -0
- lionagi/core/structure/graph.py +1 -0
- lionagi/core/structure/tree.py +1 -0
- lionagi/core/unit/__init__.py +5 -0
- lionagi/core/unit/parallel_unit.py +245 -0
- lionagi/core/unit/template/__init__.py +0 -0
- lionagi/core/unit/template/action.py +81 -0
- lionagi/core/unit/template/base.py +51 -0
- lionagi/core/unit/template/plan.py +84 -0
- lionagi/core/unit/template/predict.py +109 -0
- lionagi/core/unit/template/score.py +124 -0
- lionagi/core/unit/template/select.py +104 -0
- lionagi/core/unit/unit.py +362 -0
- lionagi/core/unit/unit_form.py +305 -0
- lionagi/core/unit/unit_mixin.py +1168 -0
- lionagi/core/unit/util.py +71 -0
- lionagi/core/validator/__init__.py +0 -0
- lionagi/core/validator/validator.py +364 -0
- lionagi/core/work/__init__.py +0 -0
- lionagi/core/work/work.py +76 -0
- lionagi/core/work/work_function.py +101 -0
- lionagi/core/work/work_queue.py +103 -0
- lionagi/core/work/worker.py +258 -0
- lionagi/core/work/worklog.py +120 -0
- lionagi/experimental/__init__.py +0 -0
- lionagi/experimental/compressor/__init__.py +0 -0
- lionagi/experimental/compressor/base.py +46 -0
- lionagi/experimental/compressor/llm_compressor.py +247 -0
- lionagi/experimental/compressor/llm_summarizer.py +61 -0
- lionagi/experimental/compressor/util.py +70 -0
- lionagi/experimental/directive/__init__.py +19 -0
- lionagi/experimental/directive/parser/__init__.py +0 -0
- lionagi/experimental/directive/parser/base_parser.py +282 -0
- lionagi/experimental/directive/template/__init__.py +0 -0
- lionagi/experimental/directive/template/base_template.py +79 -0
- lionagi/experimental/directive/template/schema.py +36 -0
- lionagi/experimental/directive/tokenizer.py +73 -0
- lionagi/experimental/evaluator/__init__.py +0 -0
- lionagi/experimental/evaluator/ast_evaluator.py +131 -0
- lionagi/experimental/evaluator/base_evaluator.py +218 -0
- lionagi/experimental/knowledge/__init__.py +0 -0
- lionagi/experimental/knowledge/base.py +10 -0
- lionagi/experimental/knowledge/graph.py +0 -0
- lionagi/experimental/memory/__init__.py +0 -0
- lionagi/experimental/strategies/__init__.py +0 -0
- lionagi/experimental/strategies/base.py +1 -0
- lionagi/integrations/bridge/autogen_/__init__.py +0 -0
- lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
- lionagi/integrations/bridge/langchain_/documents.py +4 -0
- lionagi/integrations/bridge/llamaindex_/index.py +30 -0
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
- lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
- lionagi/integrations/bridge/llamaindex_/node_parser.py +6 -9
- lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +1 -0
- lionagi/integrations/bridge/transformers_/__init__.py +0 -0
- lionagi/integrations/bridge/transformers_/install_.py +36 -0
- lionagi/integrations/chunker/__init__.py +0 -0
- lionagi/integrations/chunker/chunk.py +312 -0
- lionagi/integrations/config/oai_configs.py +38 -7
- lionagi/integrations/config/ollama_configs.py +1 -1
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/__init__.py +0 -0
- lionagi/integrations/loader/load.py +253 -0
- lionagi/integrations/loader/load_util.py +195 -0
- lionagi/integrations/provider/_mapping.py +46 -0
- lionagi/integrations/provider/litellm.py +2 -1
- lionagi/integrations/provider/mlx_service.py +16 -9
- lionagi/integrations/provider/oai.py +91 -4
- lionagi/integrations/provider/ollama.py +7 -6
- lionagi/integrations/provider/openrouter.py +115 -8
- lionagi/integrations/provider/services.py +2 -2
- lionagi/integrations/provider/transformers.py +18 -22
- lionagi/integrations/storage/__init__.py +3 -0
- lionagi/integrations/storage/neo4j.py +665 -0
- lionagi/integrations/storage/storage_util.py +287 -0
- lionagi/integrations/storage/structure_excel.py +285 -0
- lionagi/integrations/storage/to_csv.py +63 -0
- lionagi/integrations/storage/to_excel.py +83 -0
- lionagi/libs/__init__.py +26 -1
- lionagi/libs/ln_api.py +78 -23
- lionagi/libs/ln_context.py +37 -0
- lionagi/libs/ln_convert.py +21 -9
- lionagi/libs/ln_func_call.py +69 -28
- lionagi/libs/ln_image.py +107 -0
- lionagi/libs/ln_knowledge_graph.py +405 -0
- lionagi/libs/ln_nested.py +26 -11
- lionagi/libs/ln_parse.py +110 -14
- lionagi/libs/ln_queue.py +117 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/{core/prompt/field_validator.py → libs/ln_validate.py} +79 -14
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +107 -2
- lionagi/lions/__init__.py +0 -0
- lionagi/lions/coder/__init__.py +0 -0
- lionagi/lions/coder/add_feature.py +20 -0
- lionagi/lions/coder/base_prompts.py +22 -0
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +168 -0
- lionagi/lions/coder/util.py +96 -0
- lionagi/lions/researcher/__init__.py +0 -0
- lionagi/lions/researcher/data_source/__init__.py +0 -0
- lionagi/lions/researcher/data_source/finhub_.py +191 -0
- lionagi/lions/researcher/data_source/google_.py +199 -0
- lionagi/lions/researcher/data_source/wiki_.py +96 -0
- lionagi/lions/researcher/data_source/yfinance_.py +21 -0
- lionagi/tests/integrations/__init__.py +0 -0
- lionagi/tests/libs/__init__.py +0 -0
- lionagi/tests/libs/test_field_validators.py +353 -0
- lionagi/tests/{test_libs → libs}/test_func_call.py +23 -21
- lionagi/tests/{test_libs → libs}/test_nested.py +36 -21
- lionagi/tests/{test_libs → libs}/test_parse.py +1 -1
- lionagi/tests/libs/test_queue.py +67 -0
- lionagi/tests/test_core/collections/__init__.py +0 -0
- lionagi/tests/test_core/collections/test_component.py +206 -0
- lionagi/tests/test_core/collections/test_exchange.py +138 -0
- lionagi/tests/test_core/collections/test_flow.py +145 -0
- lionagi/tests/test_core/collections/test_pile.py +171 -0
- lionagi/tests/test_core/collections/test_progression.py +129 -0
- lionagi/tests/test_core/generic/__init__.py +0 -0
- lionagi/tests/test_core/generic/test_edge.py +67 -0
- lionagi/tests/test_core/generic/test_graph.py +96 -0
- lionagi/tests/test_core/generic/test_node.py +106 -0
- lionagi/tests/test_core/generic/test_tree_node.py +73 -0
- lionagi/tests/test_core/test_branch.py +115 -292
- lionagi/tests/test_core/test_form.py +46 -0
- lionagi/tests/test_core/test_report.py +105 -0
- lionagi/tests/test_core/test_validator.py +111 -0
- lionagi/version.py +1 -1
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/LICENSE +12 -11
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/METADATA +19 -118
- lionagi-0.2.1.dist-info/RECORD +240 -0
- lionagi/core/branch/__init__.py +0 -4
- lionagi/core/branch/base_branch.py +0 -654
- lionagi/core/branch/branch.py +0 -471
- lionagi/core/branch/branch_flow_mixin.py +0 -96
- lionagi/core/branch/executable_branch.py +0 -347
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -6
- lionagi/core/direct/predict.py +0 -161
- lionagi/core/direct/score.py +0 -278
- lionagi/core/direct/select.py +0 -169
- lionagi/core/direct/utils.py +0 -87
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/flow/base/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -238
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -263
- lionagi/core/flow/monoflow/followup.py +0 -214
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -248
- lionagi/core/mail/schema.py +0 -56
- lionagi/core/messages/__init__.py +0 -3
- lionagi/core/messages/schema.py +0 -533
- lionagi/core/prompt/prompt_template.py +0 -316
- lionagi/core/schema/__init__.py +0 -22
- lionagi/core/schema/action_node.py +0 -29
- lionagi/core/schema/base_mixin.py +0 -296
- lionagi/core/schema/base_node.py +0 -199
- lionagi/core/schema/condition.py +0 -24
- lionagi/core/schema/data_logger.py +0 -354
- lionagi/core/schema/data_node.py +0 -93
- lionagi/core/schema/prompt_template.py +0 -67
- lionagi/core/schema/structure.py +0 -910
- lionagi/core/tool/__init__.py +0 -3
- lionagi/core/tool/tool_manager.py +0 -280
- lionagi/integrations/bridge/pydantic_/base_model.py +0 -7
- lionagi/tests/test_core/test_base_branch.py +0 -427
- lionagi/tests/test_core/test_chat_flow.py +0 -63
- lionagi/tests/test_core/test_mail_manager.py +0 -75
- lionagi/tests/test_core/test_prompts.py +0 -51
- lionagi/tests/test_core/test_session.py +0 -254
- lionagi/tests/test_core/test_session_base_util.py +0 -312
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.0.312.dist-info/RECORD +0 -111
- /lionagi/core/{branch/base → _setting}/__init__.py +0 -0
- /lionagi/core/{flow → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow/base → agent/learn}/__init__.py +0 -0
- /lionagi/core/{prompt → agent/plan}/__init__.py +0 -0
- /lionagi/core/{tool/manual.py → agent/plan/plan.py} +0 -0
- /lionagi/{tests/test_integrations → core/director}/__init__.py +0 -0
- /lionagi/{tests/test_libs → core/engine}/__init__.py +0 -0
- /lionagi/{tests/test_libs/test_async.py → core/executor/__init__.py} +0 -0
- /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
- {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
|
+
]
|