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.
- lionagi/__init__.py +60 -5
- lionagi/core/__init__.py +0 -25
- 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/base_agent.py +27 -13
- 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/{generic/data_logger.py → collections/_logger.py} +69 -55
- 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/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
- lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
- lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +62 -66
- lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
- lionagi/core/generic/__init__.py +3 -33
- lionagi/core/generic/edge.py +29 -79
- 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 +156 -221
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +12 -0
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +139 -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/_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/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +229 -903
- 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/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/validator.py +364 -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/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/base_parser.py +69 -2
- lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
- lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
- lionagi/experimental/knowledge/base.py +10 -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/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/chunker/chunk.py +161 -24
- lionagi/integrations/config/oai_configs.py +34 -3
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/load.py +122 -21
- lionagi/integrations/loader/load_util.py +6 -77
- 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 +6 -5
- 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 -3
- lionagi/integrations/storage/neo4j.py +52 -60
- lionagi/integrations/storage/storage_util.py +44 -46
- lionagi/integrations/storage/structure_excel.py +43 -26
- lionagi/integrations/storage/to_excel.py +11 -4
- lionagi/libs/__init__.py +22 -1
- lionagi/libs/ln_api.py +75 -20
- 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_nested.py +26 -11
- lionagi/libs/ln_parse.py +82 -23
- lionagi/libs/ln_queue.py +16 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/libs/ln_validate.py +16 -0
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +95 -24
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +50 -3
- lionagi/lions/coder/util.py +30 -25
- lionagi/tests/libs/test_func_call.py +23 -21
- lionagi/tests/libs/test_nested.py +36 -21
- lionagi/tests/libs/test_parse.py +1 -1
- 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/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 -294
- 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.2.1.dist-info/LICENSE +202 -0
- lionagi-0.2.1.dist-info/METADATA +272 -0
- lionagi-0.2.1.dist-info/RECORD +240 -0
- lionagi/core/branch/base.py +0 -653
- lionagi/core/branch/branch.py +0 -474
- lionagi/core/branch/flow_mixin.py +0 -96
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -19
- lionagi/core/direct/cot.py +0 -123
- lionagi/core/direct/plan.py +0 -164
- lionagi/core/direct/predict.py +0 -166
- lionagi/core/direct/react.py +0 -171
- lionagi/core/direct/score.py +0 -279
- lionagi/core/direct/select.py +0 -170
- lionagi/core/direct/sentiment.py +0 -1
- lionagi/core/direct/utils.py +0 -110
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/execute/base_executor.py +0 -47
- lionagi/core/flow/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -240
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -253
- lionagi/core/flow/monoflow/followup.py +0 -215
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -251
- lionagi/core/form/action_form.py +0 -26
- lionagi/core/form/field_validator.py +0 -287
- lionagi/core/form/form.py +0 -302
- lionagi/core/form/mixin.py +0 -214
- lionagi/core/form/scored_form.py +0 -13
- lionagi/core/generic/action.py +0 -26
- lionagi/core/generic/component.py +0 -532
- lionagi/core/generic/condition.py +0 -46
- lionagi/core/generic/mail.py +0 -90
- lionagi/core/generic/mailbox.py +0 -36
- lionagi/core/generic/relation.py +0 -70
- lionagi/core/generic/signal.py +0 -22
- lionagi/core/generic/structure.py +0 -362
- lionagi/core/generic/transfer.py +0 -20
- lionagi/core/generic/work.py +0 -40
- lionagi/core/graph/graph.py +0 -126
- lionagi/core/graph/tree.py +0 -190
- lionagi/core/mail/schema.py +0 -63
- lionagi/core/messages/schema.py +0 -325
- lionagi/core/tool/__init__.py +0 -5
- lionagi/core/tool/tool.py +0 -28
- lionagi/core/tool/tool_manager.py +0 -283
- lionagi/experimental/report/form.py +0 -64
- lionagi/experimental/report/report.py +0 -138
- lionagi/experimental/report/util.py +0 -47
- lionagi/experimental/tool/function_calling.py +0 -43
- lionagi/experimental/tool/manual.py +0 -66
- lionagi/experimental/tool/schema.py +0 -59
- lionagi/experimental/tool/tool_manager.py +0 -138
- lionagi/experimental/tool/util.py +0 -16
- lionagi/experimental/validator/rule.py +0 -139
- lionagi/experimental/validator/validator.py +0 -56
- lionagi/experimental/work/__init__.py +0 -10
- lionagi/experimental/work/async_queue.py +0 -54
- lionagi/experimental/work/schema.py +0 -73
- lionagi/experimental/work/work_function.py +0 -67
- lionagi/experimental/work/worker.py +0 -56
- lionagi/experimental/work2/form.py +0 -371
- lionagi/experimental/work2/report.py +0 -289
- lionagi/experimental/work2/schema.py +0 -30
- lionagi/experimental/work2/tests.py +0 -72
- lionagi/experimental/work2/work_function.py +0 -89
- lionagi/experimental/work2/worker.py +0 -12
- lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
- lionagi/tests/test_core/generic/test_component.py +0 -89
- lionagi/tests/test_core/test_base_branch.py +0 -426
- 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 -313
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.1.2.dist-info/LICENSE +0 -9
- lionagi-0.1.2.dist-info/METADATA +0 -174
- lionagi-0.1.2.dist-info/RECORD +0 -206
- /lionagi/core/{branch → _setting}/__init__.py +0 -0
- /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
- /lionagi/core/{form → agent/plan}/__init__.py +0 -0
- /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
- /lionagi/core/{graph → director}/__init__.py +0 -0
- /lionagi/core/{messages → engine}/__init__.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
- /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
- /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
- /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
- /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
- /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
- /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
- /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
- /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
- /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
- /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,172 @@
|
|
1
|
+
# disallowed special tokens
|
2
|
+
|
3
|
+
disallowed_tokens = [
|
4
|
+
"▄",
|
5
|
+
"▅",
|
6
|
+
"▆",
|
7
|
+
"▇",
|
8
|
+
"█",
|
9
|
+
"▏",
|
10
|
+
"▎",
|
11
|
+
"▍",
|
12
|
+
"▌",
|
13
|
+
"▋",
|
14
|
+
"▊",
|
15
|
+
"▉",
|
16
|
+
"▔",
|
17
|
+
"▕",
|
18
|
+
"▁▁",
|
19
|
+
"▁▂",
|
20
|
+
"▁▃",
|
21
|
+
"▁▄",
|
22
|
+
"▁▅",
|
23
|
+
"▁▆",
|
24
|
+
"▁▇",
|
25
|
+
"▁█",
|
26
|
+
"▁▏",
|
27
|
+
"▁▎",
|
28
|
+
"▁▍",
|
29
|
+
"▁▌",
|
30
|
+
"▁▋",
|
31
|
+
"▁▊",
|
32
|
+
"▁▉",
|
33
|
+
"▁▔",
|
34
|
+
"▁▕",
|
35
|
+
"▄▄",
|
36
|
+
"▄▅",
|
37
|
+
"▄▆",
|
38
|
+
"▄▇",
|
39
|
+
"▄█",
|
40
|
+
"▄▏",
|
41
|
+
"▄▎",
|
42
|
+
"▄▍",
|
43
|
+
"▄▌",
|
44
|
+
"▄▋",
|
45
|
+
"▄▊",
|
46
|
+
"▄▉",
|
47
|
+
"▄▔",
|
48
|
+
"▄▕",
|
49
|
+
"▅▅",
|
50
|
+
"▅▆",
|
51
|
+
"▅▇",
|
52
|
+
"▅█",
|
53
|
+
"▅▏",
|
54
|
+
"▅▎",
|
55
|
+
"▅▍",
|
56
|
+
"▅▌",
|
57
|
+
"▅▋",
|
58
|
+
"▅▊",
|
59
|
+
"▅▉",
|
60
|
+
"▅▔",
|
61
|
+
"▅▕",
|
62
|
+
"▆▆",
|
63
|
+
"▆▇",
|
64
|
+
"▆█",
|
65
|
+
"▆▏",
|
66
|
+
"▆▎",
|
67
|
+
"▆▍",
|
68
|
+
"▆▌",
|
69
|
+
"▆▋",
|
70
|
+
"▆▊",
|
71
|
+
"▆▉",
|
72
|
+
"▆▔",
|
73
|
+
"▆▕",
|
74
|
+
"▇▇",
|
75
|
+
"▇█",
|
76
|
+
"▇▏",
|
77
|
+
"▇▎",
|
78
|
+
"▇▍",
|
79
|
+
"▇▌",
|
80
|
+
"▇▋",
|
81
|
+
"▇▊",
|
82
|
+
"▇▉",
|
83
|
+
"▇▔",
|
84
|
+
"▇▕",
|
85
|
+
"██",
|
86
|
+
"█▏",
|
87
|
+
"█▎",
|
88
|
+
"█▍",
|
89
|
+
"█▌",
|
90
|
+
"█▋",
|
91
|
+
"█▊",
|
92
|
+
"█▉",
|
93
|
+
"█",
|
94
|
+
"█▔",
|
95
|
+
"█▕",
|
96
|
+
"▏▏",
|
97
|
+
"▏▎",
|
98
|
+
"▏▍",
|
99
|
+
"▏▌",
|
100
|
+
"▏▋",
|
101
|
+
"▏▊",
|
102
|
+
"▏▉",
|
103
|
+
"▏",
|
104
|
+
"▏▔",
|
105
|
+
"▏▕",
|
106
|
+
"▎▎",
|
107
|
+
"▎▍",
|
108
|
+
"▎▌",
|
109
|
+
"▎▋",
|
110
|
+
"▎▊",
|
111
|
+
"▎▉",
|
112
|
+
"▎",
|
113
|
+
"▎▔",
|
114
|
+
"▎▕",
|
115
|
+
"▍▍",
|
116
|
+
"▍▌",
|
117
|
+
"▍▋",
|
118
|
+
"▍▊",
|
119
|
+
"▍▉",
|
120
|
+
"▍",
|
121
|
+
"▍▔",
|
122
|
+
"▍▕",
|
123
|
+
"▌▌",
|
124
|
+
"▌▋",
|
125
|
+
"▌▊",
|
126
|
+
"▌▉",
|
127
|
+
"▌",
|
128
|
+
"▌▔",
|
129
|
+
"▌▕",
|
130
|
+
"▋▋",
|
131
|
+
"▋▊",
|
132
|
+
"▋▉",
|
133
|
+
"▋",
|
134
|
+
"▋▔",
|
135
|
+
"▋▕",
|
136
|
+
"▊▊",
|
137
|
+
"▊▉",
|
138
|
+
"▊",
|
139
|
+
"▊▔",
|
140
|
+
"▊▕",
|
141
|
+
"▉▉",
|
142
|
+
"▉",
|
143
|
+
"▉▔",
|
144
|
+
"▉▕",
|
145
|
+
"▔▔",
|
146
|
+
"▔▕",
|
147
|
+
"▕▕",
|
148
|
+
"▁▁▁",
|
149
|
+
"▁▁▂",
|
150
|
+
"▁▁▃",
|
151
|
+
"▁▁▄",
|
152
|
+
"▁▁▅",
|
153
|
+
"▁▁▆",
|
154
|
+
"▁▁▇",
|
155
|
+
"▁▁█",
|
156
|
+
"▁▁▏",
|
157
|
+
"▁▁▎",
|
158
|
+
"▁▁▍",
|
159
|
+
"▁▁▌",
|
160
|
+
"▁▁▋",
|
161
|
+
"▁▁▊",
|
162
|
+
"▁▁▉",
|
163
|
+
"▁▁▔",
|
164
|
+
"▁▁▕",
|
165
|
+
"▁▂▂",
|
166
|
+
"▁▂▃",
|
167
|
+
"▁▂▄",
|
168
|
+
"▁▂▅",
|
169
|
+
"▁▂▆",
|
170
|
+
"▁▂▇",
|
171
|
+
"▁▂█",
|
172
|
+
]
|
lionagi/libs/sys_util.py
CHANGED
@@ -1,28 +1,17 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
The above copyright notice and this permission notice shall be
|
16
|
-
included in all copies or substantial portions of the Software.
|
17
|
-
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
20
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
22
|
-
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
23
|
-
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
24
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
25
|
-
SOFTWARE.
|
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.
|
26
15
|
"""
|
27
16
|
|
28
17
|
import copy
|
@@ -430,6 +419,19 @@ class SysUtil:
|
|
430
419
|
|
431
420
|
@staticmethod
|
432
421
|
def list_files(dir_path: Path | str, extension: str = None) -> list[Path]:
|
422
|
+
"""
|
423
|
+
Lists all files in a specified directory with an optional filter for file extensions.
|
424
|
+
|
425
|
+
Args:
|
426
|
+
dir_path (Path | str): The directory path where files are listed.
|
427
|
+
extension (str, optional): Filter files by extension. Default is None, which lists all files.
|
428
|
+
|
429
|
+
Returns:
|
430
|
+
list[Path]: A list of Path objects representing files in the directory.
|
431
|
+
|
432
|
+
Raises:
|
433
|
+
NotADirectoryError: If the provided dir_path is not a directory.
|
434
|
+
"""
|
433
435
|
dir_path = Path(dir_path)
|
434
436
|
if not dir_path.is_dir():
|
435
437
|
raise NotADirectoryError(f"{dir_path} is not a directory.")
|
@@ -440,6 +442,16 @@ class SysUtil:
|
|
440
442
|
|
441
443
|
@staticmethod
|
442
444
|
def copy_file(src: Path | str, dest: Path | str) -> None:
|
445
|
+
"""
|
446
|
+
Copies a file from a source path to a destination path.
|
447
|
+
|
448
|
+
Args:
|
449
|
+
src (Path | str): The source file path.
|
450
|
+
dest (Path | str): The destination file path.
|
451
|
+
|
452
|
+
Raises:
|
453
|
+
FileNotFoundError: If the source file does not exist or is not a file.
|
454
|
+
"""
|
443
455
|
from shutil import copy2
|
444
456
|
|
445
457
|
src, dest = Path(src), Path(dest)
|
@@ -450,6 +462,18 @@ class SysUtil:
|
|
450
462
|
|
451
463
|
@staticmethod
|
452
464
|
def get_size(path: Path | str) -> int:
|
465
|
+
"""
|
466
|
+
Gets the size of a file or total size of files in a directory.
|
467
|
+
|
468
|
+
Args:
|
469
|
+
path (Path | str): The file or directory path.
|
470
|
+
|
471
|
+
Returns:
|
472
|
+
int: The size in bytes.
|
473
|
+
|
474
|
+
Raises:
|
475
|
+
FileNotFoundError: If the path does not exist.
|
476
|
+
"""
|
453
477
|
path = Path(path)
|
454
478
|
if path.is_file():
|
455
479
|
return path.stat().st_size
|
@@ -457,3 +481,50 @@ class SysUtil:
|
|
457
481
|
return sum(f.stat().st_size for f in path.glob("**/*") if f.is_file())
|
458
482
|
else:
|
459
483
|
raise FileNotFoundError(f"{path} does not exist.")
|
484
|
+
|
485
|
+
@staticmethod
|
486
|
+
def save_to_file(
|
487
|
+
text,
|
488
|
+
directory: Path | str,
|
489
|
+
filename: str,
|
490
|
+
timestamp: bool = True,
|
491
|
+
dir_exist_ok: bool = True,
|
492
|
+
time_prefix: bool = False,
|
493
|
+
custom_timestamp_format: str | None = None,
|
494
|
+
random_hash_digits=0,
|
495
|
+
verbose=True,
|
496
|
+
):
|
497
|
+
"""
|
498
|
+
Saves text to a file within a specified directory, optionally adding a timestamp, hash, and verbose logging.
|
499
|
+
|
500
|
+
Args:
|
501
|
+
text (str): The text to save.
|
502
|
+
directory (Path | str): The directory path to save the file.
|
503
|
+
filename (str): The filename for the saved text.
|
504
|
+
timestamp (bool): If True, append a timestamp to the filename. Default is True.
|
505
|
+
dir_exist_ok (bool): If True, creates the directory if it does not exist. Default is True.
|
506
|
+
time_prefix (bool): If True, prepend the timestamp instead of appending. Default is False.
|
507
|
+
custom_timestamp_format (str | None): A custom format for the timestamp, if None uses default format. Default is None.
|
508
|
+
random_hash_digits (int): Number of random hash digits to append to filename. Default is 0.
|
509
|
+
verbose (bool): If True, prints the file path after saving. Default is True.
|
510
|
+
|
511
|
+
Returns:
|
512
|
+
bool: True if the text was successfully saved.
|
513
|
+
"""
|
514
|
+
file_path = SysUtil.create_path(
|
515
|
+
directory=directory,
|
516
|
+
filename=filename,
|
517
|
+
timestamp=timestamp,
|
518
|
+
dir_exist_ok=dir_exist_ok,
|
519
|
+
time_prefix=time_prefix,
|
520
|
+
custom_timestamp_format=custom_timestamp_format,
|
521
|
+
random_hash_digits=random_hash_digits,
|
522
|
+
)
|
523
|
+
|
524
|
+
with open(file_path, "w") as file:
|
525
|
+
file.write(text)
|
526
|
+
|
527
|
+
if verbose:
|
528
|
+
print(f"Text saved to: {file_path}")
|
529
|
+
|
530
|
+
return True
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import Any
|
2
|
+
from pydantic import Field
|
3
|
+
from lionagi.libs import ParseUtil, SysUtil
|
4
|
+
from lionagi.core import Session
|
5
|
+
from lionagi.core.form.action_form import ActionForm
|
6
|
+
|
7
|
+
|
8
|
+
class CodeForm(ActionForm):
|
9
|
+
template_name: str = "code_form"
|
10
|
+
language: str = Field(
|
11
|
+
default="python",
|
12
|
+
description="The programming language of the code to be executed.",
|
13
|
+
)
|
lionagi/lions/coder/coder.py
CHANGED
@@ -1,18 +1,49 @@
|
|
1
1
|
import asyncio
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
from lionagi import logging as _logging
|
2
5
|
from lionagi.core import Session
|
6
|
+
from lionagi.libs import ParseUtil
|
3
7
|
|
4
8
|
from .base_prompts import CODER_PROMPTS
|
5
|
-
from .util import
|
9
|
+
from .util import install_missing_dependencies, set_up_interpreter, save_code_file
|
6
10
|
|
7
11
|
|
8
12
|
class Coder:
|
13
|
+
|
9
14
|
def __init__(
|
10
|
-
self,
|
15
|
+
self,
|
16
|
+
prompts: dict = None,
|
17
|
+
session: Session = None,
|
18
|
+
session_kwargs: dict = None,
|
19
|
+
required_libraries: list = None,
|
20
|
+
work_dir: Path | str = None,
|
21
|
+
) -> None:
|
22
|
+
|
23
|
+
self.prompts = prompts or CODER_PROMPTS
|
24
|
+
self.session = session or self._create_session(session_kwargs)
|
25
|
+
self.required_libraries = required_libraries or ["lionagi"]
|
26
|
+
self.work_dir = work_dir or Path.cwd() / "coder" / "code_files"
|
27
|
+
|
28
|
+
def _create_session(self, session_kwargs: dict = None) -> Session:
|
29
|
+
session_kwargs = session_kwargs or {}
|
30
|
+
return Session(system=self.prompts["system"], **session_kwargs)
|
31
|
+
|
32
|
+
|
33
|
+
class Coder:
|
34
|
+
def __init__(
|
35
|
+
self,
|
36
|
+
prompts=None,
|
37
|
+
session=None,
|
38
|
+
session_kwargs=None,
|
39
|
+
required_libraries=None,
|
40
|
+
work_dir=None,
|
11
41
|
):
|
12
42
|
print("Initializing Coder...")
|
13
43
|
self.prompts = prompts or CODER_PROMPTS
|
14
44
|
self.session = session or self._create_session(session_kwargs)
|
15
45
|
self.required_libraries = required_libraries or ["lionagi"]
|
46
|
+
self.work_dir = work_dir or Path.cwd() / "coder" / "code_files"
|
16
47
|
print("Coder initialized.")
|
17
48
|
|
18
49
|
def _create_session(self, session_kwargs=None):
|
@@ -32,7 +63,7 @@ class Coder:
|
|
32
63
|
print("Writing code...")
|
33
64
|
code = await self.session.chat(self.prompts["write_code"], context=context)
|
34
65
|
print("Code writing completed.")
|
35
|
-
return extract_code_blocks(code)
|
66
|
+
return ParseUtil.extract_code_blocks(code)
|
36
67
|
|
37
68
|
async def _review_code(self, context=None):
|
38
69
|
print("Reviewing code...")
|
@@ -78,6 +109,22 @@ class Coder:
|
|
78
109
|
print("Code execution completed.")
|
79
110
|
return execution
|
80
111
|
|
112
|
+
def _save_code_file(self, code, **kwargs):
|
113
|
+
print("Saving code...")
|
114
|
+
save_code_file(code, self.work_dir, **kwargs)
|
115
|
+
print("Code saved.")
|
116
|
+
|
117
|
+
@staticmethod
|
118
|
+
def _load_code_file(file_path):
|
119
|
+
print("Loading code...")
|
120
|
+
try:
|
121
|
+
with open(file_path, "r") as file:
|
122
|
+
print("Code loaded.")
|
123
|
+
return file.read()
|
124
|
+
except FileNotFoundError:
|
125
|
+
_logging.error(f"File not found: {file_path}")
|
126
|
+
return None
|
127
|
+
|
81
128
|
|
82
129
|
async def main():
|
83
130
|
print("Starting main function...")
|
lionagi/lions/coder/util.py
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
from typing import Any
|
2
|
+
from pathlib import Path
|
3
|
+
|
1
4
|
E2B_key_scheme = "E2B_API_KEY"
|
2
5
|
|
3
6
|
|
@@ -21,31 +24,6 @@ def set_up_interpreter(interpreter_provider="e2b", key_scheme=E2B_key_scheme):
|
|
21
24
|
raise ValueError("Invalid interpreter provider")
|
22
25
|
|
23
26
|
|
24
|
-
def extract_code_blocks(code):
|
25
|
-
print("Extracting code blocks...")
|
26
|
-
code_blocks = []
|
27
|
-
lines = code.split("\n")
|
28
|
-
inside_code_block = False
|
29
|
-
current_block = []
|
30
|
-
|
31
|
-
for line in lines:
|
32
|
-
if line.startswith("```"):
|
33
|
-
if inside_code_block:
|
34
|
-
code_blocks.append("\n".join(current_block))
|
35
|
-
current_block = []
|
36
|
-
inside_code_block = False
|
37
|
-
else:
|
38
|
-
inside_code_block = True
|
39
|
-
elif inside_code_block:
|
40
|
-
current_block.append(line)
|
41
|
-
|
42
|
-
if current_block:
|
43
|
-
code_blocks.append("\n".join(current_block))
|
44
|
-
|
45
|
-
print(f"Extracted {len(code_blocks)} code block(s).")
|
46
|
-
return "\n\n".join(code_blocks)
|
47
|
-
|
48
|
-
|
49
27
|
def install_missing_dependencies(required_libraries):
|
50
28
|
print("Checking for missing dependencies...")
|
51
29
|
missing_libraries = [
|
@@ -89,3 +67,30 @@ def install_library(library):
|
|
89
67
|
print(
|
90
68
|
"You may need to run the script with administrative privileges or use a virtual environment."
|
91
69
|
)
|
70
|
+
|
71
|
+
|
72
|
+
def save_code_file(
|
73
|
+
code: Any,
|
74
|
+
directory: Path | str = None,
|
75
|
+
filename: str = "code.py",
|
76
|
+
timestamp: bool = True,
|
77
|
+
dir_exist_ok: bool = True,
|
78
|
+
time_prefix: bool = False,
|
79
|
+
custom_timestamp_format: str | None = None,
|
80
|
+
random_hash_digits: int = 3,
|
81
|
+
verbose: bool = True,
|
82
|
+
):
|
83
|
+
|
84
|
+
from lionagi.libs import SysUtil
|
85
|
+
|
86
|
+
return SysUtil.save_to_file(
|
87
|
+
text=code,
|
88
|
+
directory=directory,
|
89
|
+
filename=filename,
|
90
|
+
timestamp=timestamp,
|
91
|
+
dir_exist_ok=dir_exist_ok,
|
92
|
+
time_prefix=time_prefix,
|
93
|
+
custom_timestamp_format=custom_timestamp_format,
|
94
|
+
random_hash_digits=random_hash_digits,
|
95
|
+
verbose=verbose,
|
96
|
+
)
|
@@ -296,8 +296,8 @@ class TestRCall(unittest.IsolatedAsyncioTestCase):
|
|
296
296
|
await asyncio.sleep(2)
|
297
297
|
return x
|
298
298
|
|
299
|
-
with self.assertRaises(
|
300
|
-
await rcall(async_func, 5, timeout=1)
|
299
|
+
with self.assertRaises(RuntimeError):
|
300
|
+
await rcall(async_func, 5, timeout=0.1)
|
301
301
|
|
302
302
|
async def test_retry_mechanism(self):
|
303
303
|
attempt_count = 0
|
@@ -307,22 +307,22 @@ class TestRCall(unittest.IsolatedAsyncioTestCase):
|
|
307
307
|
attempt_count += 1
|
308
308
|
raise ValueError("Test Error")
|
309
309
|
|
310
|
-
with self.assertRaises(
|
311
|
-
await rcall(sync_func, 5, retries=3)
|
310
|
+
with self.assertRaises(RuntimeError):
|
311
|
+
await rcall(sync_func, 5, retries=3, delay=0.1, backoff_factor=1.1)
|
312
312
|
self.assertEqual(attempt_count, 3) # Initial call + 3 retries
|
313
313
|
|
314
314
|
async def test_default_value_on_exception(self):
|
315
315
|
def sync_func(x):
|
316
316
|
raise ValueError("Test Error")
|
317
317
|
|
318
|
-
result = await rcall(sync_func, 5, default=10)
|
318
|
+
result = await rcall(sync_func, 5, default=10, delay=0)
|
319
319
|
self.assertEqual(result, 10)
|
320
320
|
|
321
321
|
async def test_exception_propagation(self):
|
322
322
|
def sync_func(x):
|
323
323
|
raise ValueError("Test Error")
|
324
324
|
|
325
|
-
with self.assertRaises(
|
325
|
+
with self.assertRaises(RuntimeError):
|
326
326
|
await rcall(sync_func, 5)
|
327
327
|
|
328
328
|
|
@@ -581,22 +581,22 @@ class TestCallDecorator(unittest.IsolatedAsyncioTestCase):
|
|
581
581
|
class TestThrottleClass(unittest.TestCase):
|
582
582
|
|
583
583
|
def test_throttling_behavior_sync(self):
|
584
|
-
throttle_decorator = Throttle(
|
584
|
+
throttle_decorator = Throttle(0.1) # 2 seconds throttle period
|
585
585
|
|
586
586
|
@throttle_decorator
|
587
587
|
def test_func():
|
588
588
|
return time.time()
|
589
589
|
|
590
590
|
first_call_time = test_func()
|
591
|
-
time.sleep(1) # Sleep less than the throttle period
|
591
|
+
time.sleep(0.1) # Sleep less than the throttle period
|
592
592
|
second_call_time = test_func()
|
593
593
|
|
594
594
|
self.assertGreaterEqual(
|
595
|
-
second_call_time - first_call_time,
|
595
|
+
second_call_time - first_call_time, 0.1
|
596
596
|
) # Second call should be throttled
|
597
597
|
|
598
598
|
def test_throttling_behavior_async(self):
|
599
|
-
throttle_decorator = Throttle(
|
599
|
+
throttle_decorator = Throttle(1) # 2 seconds throttle period
|
600
600
|
|
601
601
|
@throttle_decorator
|
602
602
|
async def test_func():
|
@@ -604,28 +604,28 @@ class TestThrottleClass(unittest.TestCase):
|
|
604
604
|
|
605
605
|
async def async_test():
|
606
606
|
first_call_time = await test_func()
|
607
|
-
await asyncio.sleep(1) # Sleep less than the throttle period
|
607
|
+
await asyncio.sleep(0.1) # Sleep less than the throttle period
|
608
608
|
second_call_time = await test_func()
|
609
609
|
|
610
610
|
self.assertGreaterEqual(
|
611
|
-
second_call_time - first_call_time,
|
611
|
+
second_call_time - first_call_time, 1
|
612
612
|
) # Second call should be throttled
|
613
613
|
|
614
614
|
asyncio.run(async_test())
|
615
615
|
|
616
616
|
def test_successive_calls_with_sufficient_delay(self):
|
617
|
-
throttle_decorator = Throttle(1) # 1 second throttle period
|
617
|
+
throttle_decorator = Throttle(0.1) # 1 second throttle period
|
618
618
|
|
619
619
|
@throttle_decorator
|
620
620
|
def test_func():
|
621
621
|
return time.time()
|
622
622
|
|
623
623
|
first_call_time = test_func()
|
624
|
-
time.sleep(
|
624
|
+
time.sleep(0.12) # Sleep more than the throttle period
|
625
625
|
second_call_time = test_func()
|
626
626
|
|
627
627
|
self.assertLess(
|
628
|
-
second_call_time - first_call_time,
|
628
|
+
second_call_time - first_call_time, 0.2
|
629
629
|
) # Second call should not be throttled
|
630
630
|
|
631
631
|
|
@@ -633,7 +633,7 @@ class TestAsyncRetryDecorator(unittest.IsolatedAsyncioTestCase):
|
|
633
633
|
async def test_successful_retry(self):
|
634
634
|
attempt = 0
|
635
635
|
|
636
|
-
@CallDecorator.retry(retries=3, delay=1, backoff_factor=2)
|
636
|
+
@CallDecorator.retry(retries=3, delay=0.1, backoff_factor=2)
|
637
637
|
async def test_func():
|
638
638
|
nonlocal attempt
|
639
639
|
attempt += 1
|
@@ -648,20 +648,22 @@ class TestAsyncRetryDecorator(unittest.IsolatedAsyncioTestCase):
|
|
648
648
|
async def test_retry_limit(self):
|
649
649
|
attempt = 0
|
650
650
|
|
651
|
-
@CallDecorator.retry(retries=2, delay=1, backoff_factor=2)
|
651
|
+
@CallDecorator.retry(retries=2, delay=0.1, backoff_factor=2)
|
652
652
|
async def test_func():
|
653
653
|
nonlocal attempt
|
654
654
|
attempt += 1
|
655
655
|
raise ValueError("Test failure")
|
656
656
|
|
657
|
-
|
657
|
+
try:
|
658
658
|
await test_func()
|
659
|
+
except:
|
660
|
+
pass
|
659
661
|
self.assertEqual(attempt, 2)
|
660
662
|
|
661
663
|
async def test_immediate_success(self):
|
662
664
|
attempt = 0
|
663
665
|
|
664
|
-
@CallDecorator.retry(retries=3, delay=1, backoff_factor=2)
|
666
|
+
@CallDecorator.retry(retries=3, delay=0.1, backoff_factor=2)
|
665
667
|
async def test_func():
|
666
668
|
nonlocal attempt
|
667
669
|
attempt += 1
|
@@ -675,7 +677,7 @@ class TestAsyncRetryDecorator(unittest.IsolatedAsyncioTestCase):
|
|
675
677
|
attempt = 0
|
676
678
|
start_time = time.time()
|
677
679
|
|
678
|
-
@CallDecorator.retry(retries=3, delay=1, backoff_factor=2)
|
680
|
+
@CallDecorator.retry(retries=3, delay=0.1, backoff_factor=2)
|
679
681
|
async def test_func():
|
680
682
|
nonlocal attempt
|
681
683
|
attempt += 1
|
@@ -690,7 +692,7 @@ class TestAsyncRetryDecorator(unittest.IsolatedAsyncioTestCase):
|
|
690
692
|
self.assertEqual(result, "Success")
|
691
693
|
# Note: The actual delay might be slightly longer than expected due to asyncio's event loop scheduling.
|
692
694
|
self.assertTrue(
|
693
|
-
elapsed_time >= 3, f"Elapsed time was {elapsed_time}, expected >= 3"
|
695
|
+
elapsed_time >= 0.3, f"Elapsed time was {elapsed_time}, expected >= 3"
|
694
696
|
)
|
695
697
|
self.assertEqual(attempt, 3)
|
696
698
|
|