lionagi 0.1.2__py3-none-any.whl → 0.2.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (268) hide show
  1. lionagi/__init__.py +60 -5
  2. lionagi/core/__init__.py +0 -25
  3. lionagi/core/_setting/_setting.py +59 -0
  4. lionagi/core/action/__init__.py +14 -0
  5. lionagi/core/action/function_calling.py +136 -0
  6. lionagi/core/action/manual.py +1 -0
  7. lionagi/core/action/node.py +109 -0
  8. lionagi/core/action/tool.py +114 -0
  9. lionagi/core/action/tool_manager.py +356 -0
  10. lionagi/core/agent/base_agent.py +27 -13
  11. lionagi/core/agent/eval/evaluator.py +1 -0
  12. lionagi/core/agent/eval/vote.py +40 -0
  13. lionagi/core/agent/learn/learner.py +59 -0
  14. lionagi/core/agent/plan/unit_template.py +1 -0
  15. lionagi/core/collections/__init__.py +17 -0
  16. lionagi/core/{generic/data_logger.py → collections/_logger.py} +69 -55
  17. lionagi/core/collections/abc/__init__.py +53 -0
  18. lionagi/core/collections/abc/component.py +615 -0
  19. lionagi/core/collections/abc/concepts.py +297 -0
  20. lionagi/core/collections/abc/exceptions.py +150 -0
  21. lionagi/core/collections/abc/util.py +45 -0
  22. lionagi/core/collections/exchange.py +161 -0
  23. lionagi/core/collections/flow.py +426 -0
  24. lionagi/core/collections/model.py +419 -0
  25. lionagi/core/collections/pile.py +913 -0
  26. lionagi/core/collections/progression.py +236 -0
  27. lionagi/core/collections/util.py +64 -0
  28. lionagi/core/director/direct.py +314 -0
  29. lionagi/core/director/director.py +2 -0
  30. lionagi/core/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
  31. lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
  32. lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
  33. lionagi/core/executor/base_executor.py +90 -0
  34. lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +62 -66
  35. lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
  36. lionagi/core/generic/__init__.py +3 -33
  37. lionagi/core/generic/edge.py +29 -79
  38. lionagi/core/generic/edge_condition.py +16 -0
  39. lionagi/core/generic/graph.py +236 -0
  40. lionagi/core/generic/hyperedge.py +1 -0
  41. lionagi/core/generic/node.py +156 -221
  42. lionagi/core/generic/tree.py +48 -0
  43. lionagi/core/generic/tree_node.py +79 -0
  44. lionagi/core/mail/__init__.py +12 -0
  45. lionagi/core/mail/mail.py +25 -0
  46. lionagi/core/mail/mail_manager.py +139 -58
  47. lionagi/core/mail/package.py +45 -0
  48. lionagi/core/mail/start_mail.py +36 -0
  49. lionagi/core/message/__init__.py +19 -0
  50. lionagi/core/message/action_request.py +133 -0
  51. lionagi/core/message/action_response.py +135 -0
  52. lionagi/core/message/assistant_response.py +95 -0
  53. lionagi/core/message/instruction.py +234 -0
  54. lionagi/core/message/message.py +101 -0
  55. lionagi/core/message/system.py +86 -0
  56. lionagi/core/message/util.py +283 -0
  57. lionagi/core/report/__init__.py +4 -0
  58. lionagi/core/report/base.py +217 -0
  59. lionagi/core/report/form.py +231 -0
  60. lionagi/core/report/report.py +166 -0
  61. lionagi/core/report/util.py +28 -0
  62. lionagi/core/rule/_default.py +16 -0
  63. lionagi/core/rule/action.py +99 -0
  64. lionagi/core/rule/base.py +238 -0
  65. lionagi/core/rule/boolean.py +56 -0
  66. lionagi/core/rule/choice.py +47 -0
  67. lionagi/core/rule/mapping.py +96 -0
  68. lionagi/core/rule/number.py +71 -0
  69. lionagi/core/rule/rulebook.py +109 -0
  70. lionagi/core/rule/string.py +52 -0
  71. lionagi/core/rule/util.py +35 -0
  72. lionagi/core/session/branch.py +431 -0
  73. lionagi/core/session/directive_mixin.py +287 -0
  74. lionagi/core/session/session.py +229 -903
  75. lionagi/core/structure/__init__.py +1 -0
  76. lionagi/core/structure/chain.py +1 -0
  77. lionagi/core/structure/forest.py +1 -0
  78. lionagi/core/structure/graph.py +1 -0
  79. lionagi/core/structure/tree.py +1 -0
  80. lionagi/core/unit/__init__.py +5 -0
  81. lionagi/core/unit/parallel_unit.py +245 -0
  82. lionagi/core/unit/template/action.py +81 -0
  83. lionagi/core/unit/template/base.py +51 -0
  84. lionagi/core/unit/template/plan.py +84 -0
  85. lionagi/core/unit/template/predict.py +109 -0
  86. lionagi/core/unit/template/score.py +124 -0
  87. lionagi/core/unit/template/select.py +104 -0
  88. lionagi/core/unit/unit.py +362 -0
  89. lionagi/core/unit/unit_form.py +305 -0
  90. lionagi/core/unit/unit_mixin.py +1168 -0
  91. lionagi/core/unit/util.py +71 -0
  92. lionagi/core/validator/validator.py +364 -0
  93. lionagi/core/work/work.py +74 -0
  94. lionagi/core/work/work_function.py +92 -0
  95. lionagi/core/work/work_queue.py +81 -0
  96. lionagi/core/work/worker.py +195 -0
  97. lionagi/core/work/worklog.py +124 -0
  98. lionagi/experimental/compressor/base.py +46 -0
  99. lionagi/experimental/compressor/llm_compressor.py +247 -0
  100. lionagi/experimental/compressor/llm_summarizer.py +61 -0
  101. lionagi/experimental/compressor/util.py +70 -0
  102. lionagi/experimental/directive/__init__.py +19 -0
  103. lionagi/experimental/directive/parser/base_parser.py +69 -2
  104. lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
  105. lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
  106. lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
  107. lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
  108. lionagi/experimental/knowledge/base.py +10 -0
  109. lionagi/experimental/memory/__init__.py +0 -0
  110. lionagi/experimental/strategies/__init__.py +0 -0
  111. lionagi/experimental/strategies/base.py +1 -0
  112. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  113. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  114. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  115. lionagi/integrations/chunker/chunk.py +161 -24
  116. lionagi/integrations/config/oai_configs.py +34 -3
  117. lionagi/integrations/config/openrouter_configs.py +14 -2
  118. lionagi/integrations/loader/load.py +122 -21
  119. lionagi/integrations/loader/load_util.py +6 -77
  120. lionagi/integrations/provider/_mapping.py +46 -0
  121. lionagi/integrations/provider/litellm.py +2 -1
  122. lionagi/integrations/provider/mlx_service.py +16 -9
  123. lionagi/integrations/provider/oai.py +91 -4
  124. lionagi/integrations/provider/ollama.py +6 -5
  125. lionagi/integrations/provider/openrouter.py +115 -8
  126. lionagi/integrations/provider/services.py +2 -2
  127. lionagi/integrations/provider/transformers.py +18 -22
  128. lionagi/integrations/storage/__init__.py +3 -3
  129. lionagi/integrations/storage/neo4j.py +52 -60
  130. lionagi/integrations/storage/storage_util.py +44 -46
  131. lionagi/integrations/storage/structure_excel.py +43 -26
  132. lionagi/integrations/storage/to_excel.py +11 -4
  133. lionagi/libs/__init__.py +22 -1
  134. lionagi/libs/ln_api.py +75 -20
  135. lionagi/libs/ln_context.py +37 -0
  136. lionagi/libs/ln_convert.py +21 -9
  137. lionagi/libs/ln_func_call.py +69 -28
  138. lionagi/libs/ln_image.py +107 -0
  139. lionagi/libs/ln_nested.py +26 -11
  140. lionagi/libs/ln_parse.py +82 -23
  141. lionagi/libs/ln_queue.py +16 -0
  142. lionagi/libs/ln_tokenize.py +164 -0
  143. lionagi/libs/ln_validate.py +16 -0
  144. lionagi/libs/special_tokens.py +172 -0
  145. lionagi/libs/sys_util.py +95 -24
  146. lionagi/lions/coder/code_form.py +13 -0
  147. lionagi/lions/coder/coder.py +50 -3
  148. lionagi/lions/coder/util.py +30 -25
  149. lionagi/tests/libs/test_func_call.py +23 -21
  150. lionagi/tests/libs/test_nested.py +36 -21
  151. lionagi/tests/libs/test_parse.py +1 -1
  152. lionagi/tests/test_core/collections/__init__.py +0 -0
  153. lionagi/tests/test_core/collections/test_component.py +206 -0
  154. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  155. lionagi/tests/test_core/collections/test_flow.py +145 -0
  156. lionagi/tests/test_core/collections/test_pile.py +171 -0
  157. lionagi/tests/test_core/collections/test_progression.py +129 -0
  158. lionagi/tests/test_core/generic/test_edge.py +67 -0
  159. lionagi/tests/test_core/generic/test_graph.py +96 -0
  160. lionagi/tests/test_core/generic/test_node.py +106 -0
  161. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  162. lionagi/tests/test_core/test_branch.py +115 -294
  163. lionagi/tests/test_core/test_form.py +46 -0
  164. lionagi/tests/test_core/test_report.py +105 -0
  165. lionagi/tests/test_core/test_validator.py +111 -0
  166. lionagi/version.py +1 -1
  167. lionagi-0.2.0.dist-info/LICENSE +202 -0
  168. lionagi-0.2.0.dist-info/METADATA +272 -0
  169. lionagi-0.2.0.dist-info/RECORD +240 -0
  170. lionagi/core/branch/base.py +0 -653
  171. lionagi/core/branch/branch.py +0 -474
  172. lionagi/core/branch/flow_mixin.py +0 -96
  173. lionagi/core/branch/util.py +0 -323
  174. lionagi/core/direct/__init__.py +0 -19
  175. lionagi/core/direct/cot.py +0 -123
  176. lionagi/core/direct/plan.py +0 -164
  177. lionagi/core/direct/predict.py +0 -166
  178. lionagi/core/direct/react.py +0 -171
  179. lionagi/core/direct/score.py +0 -279
  180. lionagi/core/direct/select.py +0 -170
  181. lionagi/core/direct/sentiment.py +0 -1
  182. lionagi/core/direct/utils.py +0 -110
  183. lionagi/core/direct/vote.py +0 -64
  184. lionagi/core/execute/base_executor.py +0 -47
  185. lionagi/core/flow/baseflow.py +0 -23
  186. lionagi/core/flow/monoflow/ReAct.py +0 -240
  187. lionagi/core/flow/monoflow/__init__.py +0 -9
  188. lionagi/core/flow/monoflow/chat.py +0 -95
  189. lionagi/core/flow/monoflow/chat_mixin.py +0 -253
  190. lionagi/core/flow/monoflow/followup.py +0 -215
  191. lionagi/core/flow/polyflow/__init__.py +0 -1
  192. lionagi/core/flow/polyflow/chat.py +0 -251
  193. lionagi/core/form/action_form.py +0 -26
  194. lionagi/core/form/field_validator.py +0 -287
  195. lionagi/core/form/form.py +0 -302
  196. lionagi/core/form/mixin.py +0 -214
  197. lionagi/core/form/scored_form.py +0 -13
  198. lionagi/core/generic/action.py +0 -26
  199. lionagi/core/generic/component.py +0 -532
  200. lionagi/core/generic/condition.py +0 -46
  201. lionagi/core/generic/mail.py +0 -90
  202. lionagi/core/generic/mailbox.py +0 -36
  203. lionagi/core/generic/relation.py +0 -70
  204. lionagi/core/generic/signal.py +0 -22
  205. lionagi/core/generic/structure.py +0 -362
  206. lionagi/core/generic/transfer.py +0 -20
  207. lionagi/core/generic/work.py +0 -40
  208. lionagi/core/graph/graph.py +0 -126
  209. lionagi/core/graph/tree.py +0 -190
  210. lionagi/core/mail/schema.py +0 -63
  211. lionagi/core/messages/schema.py +0 -325
  212. lionagi/core/tool/__init__.py +0 -5
  213. lionagi/core/tool/tool.py +0 -28
  214. lionagi/core/tool/tool_manager.py +0 -283
  215. lionagi/experimental/report/form.py +0 -64
  216. lionagi/experimental/report/report.py +0 -138
  217. lionagi/experimental/report/util.py +0 -47
  218. lionagi/experimental/tool/function_calling.py +0 -43
  219. lionagi/experimental/tool/manual.py +0 -66
  220. lionagi/experimental/tool/schema.py +0 -59
  221. lionagi/experimental/tool/tool_manager.py +0 -138
  222. lionagi/experimental/tool/util.py +0 -16
  223. lionagi/experimental/validator/rule.py +0 -139
  224. lionagi/experimental/validator/validator.py +0 -56
  225. lionagi/experimental/work/__init__.py +0 -10
  226. lionagi/experimental/work/async_queue.py +0 -54
  227. lionagi/experimental/work/schema.py +0 -73
  228. lionagi/experimental/work/work_function.py +0 -67
  229. lionagi/experimental/work/worker.py +0 -56
  230. lionagi/experimental/work2/form.py +0 -371
  231. lionagi/experimental/work2/report.py +0 -289
  232. lionagi/experimental/work2/schema.py +0 -30
  233. lionagi/experimental/work2/tests.py +0 -72
  234. lionagi/experimental/work2/work_function.py +0 -89
  235. lionagi/experimental/work2/worker.py +0 -12
  236. lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
  237. lionagi/tests/test_core/generic/test_component.py +0 -89
  238. lionagi/tests/test_core/test_base_branch.py +0 -426
  239. lionagi/tests/test_core/test_chat_flow.py +0 -63
  240. lionagi/tests/test_core/test_mail_manager.py +0 -75
  241. lionagi/tests/test_core/test_prompts.py +0 -51
  242. lionagi/tests/test_core/test_session.py +0 -254
  243. lionagi/tests/test_core/test_session_base_util.py +0 -313
  244. lionagi/tests/test_core/test_tool_manager.py +0 -95
  245. lionagi-0.1.2.dist-info/LICENSE +0 -9
  246. lionagi-0.1.2.dist-info/METADATA +0 -174
  247. lionagi-0.1.2.dist-info/RECORD +0 -206
  248. /lionagi/core/{branch → _setting}/__init__.py +0 -0
  249. /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
  250. /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
  251. /lionagi/core/{form → agent/plan}/__init__.py +0 -0
  252. /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
  253. /lionagi/core/{graph → director}/__init__.py +0 -0
  254. /lionagi/core/{messages → engine}/__init__.py +0 -0
  255. /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
  256. /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
  257. /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
  258. /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
  259. /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
  260. /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
  261. /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
  262. /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
  263. /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
  264. /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
  265. /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
  266. /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
  267. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/WHEEL +0 -0
  268. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,254 +0,0 @@
1
- # from lionagi.core.branch.branch import Branch
2
- # from lionagi.core.session.session import Session
3
-
4
- # import unittest
5
- # from unittest.mock import patch, call, MagicMock
6
- # import pandas as pd
7
- # import json
8
- # from datetime import datetime
9
-
10
-
11
- # class TestSession(unittest.TestCase):
12
-
13
- # def setUp(self):
14
- # mock_branch = MagicMock()
15
-
16
- # mock_branch.to_csv_file = MagicMock()
17
- # mock_branch.to_json_file = MagicMock()
18
-
19
- # mock_datalogger = MagicMock()
20
- # mock_datalogger.to_csv_file = MagicMock()
21
- # mock_datalogger.to_json_file = MagicMock()
22
-
23
- # # Assign the mocked datalogger to the mock_branch
24
- # mock_branch.datalogger = mock_datalogger
25
-
26
- # self.branch1 = mock_branch(name="branch1")
27
- # self.branch1.messages = pd.DataFrame(
28
- # [{
29
- # "node_id": "1", "timestamp": "2021-01-01 00:00:00",
30
- # "role": "system", "sender": "system",
31
- # "content": json.dumps({"system_info": "System message"}),
32
- # }]
33
- # )
34
- # self.branch2 = mock_branch(name="branch2")
35
- # self.branch1.messages = pd.DataFrame(
36
- # [{
37
- # "node_id": "2", "timestamp": "2021-01-01 00:01:00",
38
- # "role": "user", "sender": "user1",
39
- # "content": json.dumps({"instruction": "User message"}),
40
- # }]
41
- # )
42
-
43
- # branches = {"branch1": self.branch1, "branch2": self.branch2}
44
-
45
- # self.session = Session(
46
- # branches=branches, default_branch_name="branch1",
47
- # default_branch=branches["branch1"], )
48
- # self.session.mail_manager = MagicMock()
49
-
50
- # # def test_from_csv_initialization(self):
51
- # # """Test Session initialization from a CSV file."""
52
- # # mock_df = pd.DataFrame(
53
- # # {
54
- # # "node_id": ["1", "2"],
55
- # # "timestamp": [datetime(2021, 1, 1), datetime(2021, 1, 1)],
56
- # # "role": ["system", "user"],
57
- # # "sender": ["system", "user1"],
58
- # # "content": [
59
- # # json.dumps({"system_info": "System message"}),
60
- # # json.dumps({"instruction": "User message"}),
61
- # # ],
62
- # # }
63
- # # )
64
- # # filepath = "path/to/mock.csv"
65
-
66
- # # with patch("pandas.read_csv", return_value=mock_df) as mock_read_csv:
67
- # # session = Session.from_csv(filepath)
68
- # # mock_read_csv.assert_called_once_with(filepath)
69
- # # pd.testing.assert_frame_equal(session.messages, mock_df)
70
-
71
- # # def test_from_json_initialization(self):
72
- # # """Test Session initialization from a CSV file."""
73
- # # mock_df = pd.DataFrame(
74
- # # {
75
- # # "node_id": ["1", "2"],
76
- # # "timestamp": [datetime(2021, 1, 1), datetime(2021, 1, 1)],
77
- # # "role": ["system", "user"],
78
- # # "sender": ["system", "user1"],
79
- # # "content": [
80
- # # json.dumps({"system_info": "System message"}),
81
- # # json.dumps({"instruction": "User message"}),
82
- # # ],
83
- # # }
84
- # # )
85
- # # filepath = "path/to/mock.json"
86
-
87
- # # with patch("pandas.read_json", return_value=mock_df) as mock_read_json:
88
- # # session = Session.from_json(filepath)
89
- # # mock_read_json.assert_called_once_with(filepath)
90
- # # pd.testing.assert_frame_equal(session.messages, mock_df)
91
-
92
- # def test_to_csv_file(self):
93
- # """Ensure to_csv_file calls each branch's to_csv_file method."""
94
- # filename = "test_export.csv"
95
- # self.session.to_csv_file(filename=filename)
96
-
97
- # for name, branch in self.session.branches.items():
98
- # # Verify it was called twice
99
- # self.assertEqual(branch.to_csv_file.call_count, 2)
100
-
101
- # # Verify the arguments of the last call
102
- # expected_filename = f"{name}_{filename}"
103
- # self.assertIn(
104
- # expected_filename,
105
- # ["branch1_test_export.csv", "branch2_test_export.csv"], )
106
-
107
- # def test_to_json_file(self):
108
- # """Ensure to_json_file calls each branch's to_json_file method."""
109
- # filename = "test_export.json"
110
- # self.session.to_json_file(filename=filename)
111
-
112
- # for name, branch in self.session.branches.items():
113
- # # Verify it was called twice
114
- # self.assertEqual(branch.to_json_file.call_count, 2)
115
-
116
- # # Verify the arguments of the last call
117
- # expected_filename = f"{name}_{filename}"
118
- # self.assertIn(
119
- # expected_filename,
120
- # ["branch1_test_export.json", "branch2_test_export.json"], )
121
-
122
- # def test_log_to_csv(self):
123
- # """Ensure log_to_csv calls each branch's log_to_csv method."""
124
- # filename = "test_export.csv"
125
- # self.session.log_to_csv(filename=filename)
126
-
127
- # for name, branch in self.session.branches.items():
128
- # # Verify it was called twice
129
- # self.assertEqual(branch.log_to_csv.call_count, 2)
130
-
131
- # # Verify the arguments of the last call
132
- # expected_filename = f"{name}_{filename}"
133
- # self.assertIn(
134
- # expected_filename,
135
- # ["branch1_test_export.csv", "branch2_test_export.csv"], )
136
-
137
- # def test_log_to_json(self):
138
- # """Ensure log_to_json calls each branch's log_to_json method."""
139
- # filename = "test_export.json"
140
- # self.session.log_to_json(filename=filename)
141
-
142
- # for name, branch in self.session.branches.items():
143
- # # Verify it was called twice
144
- # self.assertEqual(branch.log_to_json.call_count, 2)
145
-
146
- # # Verify the arguments of the last call
147
- # expected_filename = f"{name}_{filename}"
148
- # self.assertIn(
149
- # expected_filename,
150
- # ["branch1_test_export.json", "branch2_test_export.json"], )
151
-
152
- # def test_all_messages(self):
153
- # """Test aggregation of all messages across branches."""
154
- # expected_df = pd.concat(
155
- # [self.branch1.messages, self.branch2.messages], ignore_index=True
156
- # )
157
-
158
- # actual_df = self.session.all_messages
159
-
160
- # pd.testing.assert_frame_equal(actual_df, expected_df)
161
-
162
- # def test_new_branch_creation(self):
163
- # """Test creating a new branch successfully."""
164
- # branch_name = "test_branch"
165
- # self.session.new_branch(branch_name=branch_name)
166
- # self.assertIn(branch_name, self.session.branches)
167
-
168
- # def test_new_branch_duplicate_name(self):
169
- # """Test error handling for duplicate branch names."""
170
- # branch_name = "test_branch"
171
- # self.session.new_branch(branch_name=branch_name)
172
- # with self.assertRaises(ValueError):
173
- # self.session.new_branch(branch_name=branch_name)
174
-
175
- # def test_get_branch_by_name(self):
176
- # """Test retrieving a branch by its name."""
177
- # branch_name = "test_branch"
178
- # self.session.new_branch(branch_name=branch_name)
179
- # branch = self.session.get_branch(branch_name)
180
- # self.assertIsInstance(branch, Branch)
181
-
182
- # def test_get_branch_invalid_name(self):
183
- # """Test error handling for invalid branch names."""
184
- # with self.assertRaises(ValueError):
185
- # self.session.get_branch("nonexistent_branch")
186
-
187
- # def test_change_default_branch(self):
188
- # """Test changing the default branch."""
189
- # branch_name = "new_default"
190
- # self.session.new_branch(branch_name=branch_name)
191
- # self.session.change_default_branch(branch_name)
192
- # self.assertEqual(self.session.default_branch_name, branch_name)
193
-
194
- # def test_delete_branch(self):
195
- # """Test deleting a branch."""
196
- # branch_name = "test_branch"
197
- # self.session.new_branch(branch_name=branch_name)
198
- # self.session.delete_branch(branch_name)
199
- # self.assertNotIn(branch_name, self.session.branches)
200
-
201
- # def test_delete_default_branch_error(self):
202
- # """Test error when trying to delete the default branch."""
203
- # with self.assertRaises(ValueError):
204
- # self.session.delete_branch(self.session.default_branch_name)
205
-
206
- # def test_merge_branch(self):
207
- # """Test merging two branches."""
208
- # from_branch = "source_branch"
209
- # to_branch = "target_branch"
210
- # self.session.new_branch(branch_name=from_branch)
211
- # self.session.new_branch(branch_name=to_branch)
212
- # self.session.merge_branch(
213
- # from_=from_branch, to_branch=to_branch, del_=True
214
- # )
215
- # self.assertIn(to_branch, self.session.branches)
216
- # self.assertNotIn(from_branch, self.session.branches)
217
-
218
- # def test_collect_from_specified_branches(self):
219
- # """Test collecting requests from specified branches."""
220
- # self.session.collect(from_=["branch1"])
221
- # self.assertEqual(self.session.mail_manager.collect.call_count, 1)
222
-
223
- # def test_collect_from_all_branches(self):
224
- # """Test collecting requests from all branches."""
225
- # self.session.collect()
226
- # self.assertEqual(self.session.mail_manager.collect.call_count, 2)
227
-
228
- # def test_send_to_specified_branches(self):
229
- # """Test sending requests to specified branches."""
230
- # self.session.send(to_=["branch_1"])
231
- # self.assertEqual(self.session.mail_manager.send.call_count, 1)
232
-
233
- # def test_send_to_all_branches(self):
234
- # """Test sending requests to all branches."""
235
- # self.session.send()
236
- # self.assertEqual(self.session.mail_manager.send.call_count, 2)
237
-
238
- # def test_collect_send_all_without_receive_all(self):
239
- # """Test collecting and sending requests across all branches without receiving."""
240
- # self.session.collect_send_all()
241
- # self.assertEqual(self.session.mail_manager.collect.call_count, 2)
242
- # self.assertEqual(self.session.mail_manager.send.call_count, 2)
243
- # self.branch1.receive_all.assert_not_called()
244
- # self.branch2.receive_all.assert_not_called()
245
-
246
- # def test_collect_send_all_with_receive_all(self):
247
- # """Test collecting and sending requests across all branches with receiving."""
248
- # self.session.collect_send_all(receive_all=True)
249
- # self.branch1.receive_all.assert_called()
250
- # self.branch2.receive_all.assert_called()
251
-
252
-
253
- # if __name__ == "__main__":
254
- # unittest.main()
@@ -1,313 +0,0 @@
1
- # from lionagi.core.branch.util import MessageUtil
2
- # from lionagi.core.messages.schema import System, Instruction, Response
3
-
4
-
5
- # import unittest
6
- # import pandas as pd
7
- # import json
8
- # from datetime import datetime
9
-
10
-
11
- # class TestCreateMessage(unittest.TestCase):
12
-
13
- # def test_create_system_message(self):
14
- # """Test creating a System message."""
15
- # system_info = {"system_info": "System information"}
16
- # message = MessageUtil.create_message(
17
- # system=system_info["system_info"]
18
- # )
19
- # self.assertIsInstance(message, System)
20
- # self.assertEqual(message.content, system_info)
21
-
22
- # def test_create_instruction_message(self):
23
- # """Test creating an Instruction message with context."""
24
- # instruction_info = {"task": "Do something"}
25
- # context = {"additional": "context"}
26
- # message = MessageUtil.create_message(
27
- # instruction=instruction_info, context=context
28
- # )
29
- # self.assertIsInstance(message, Instruction)
30
- # self.assertEqual(message.content["instruction"], instruction_info)
31
- # self.assertEqual(message.content["context"], context)
32
-
33
- # def test_create_response_message(self):
34
- # """Test creating a Response message."""
35
- # response_info = {"message": {"content": "This is a response"}}
36
- # message = MessageUtil.create_message(response=response_info)
37
- # self.assertIsInstance(message, Response)
38
- # self.assertEqual(
39
- # message.content["response"], response_info["message"]["content"]
40
- # )
41
-
42
- # def test_error_on_multiple_roles(self):
43
- # """Test error is raised when multiple roles are provided."""
44
- # with self.assertRaises(ValueError):
45
- # MessageUtil.create_message(
46
- # system={"info": "info"}, instruction={"task": "task"}
47
- # )
48
-
49
- # def test_return_existing_base_message_instance(self):
50
- # """Test returning an existing BaseMessage instance if provided."""
51
- # existing_message = System(system={"info": "Already created"})
52
- # message = MessageUtil.create_message(system=existing_message)
53
- # self.assertEqual(message.content, existing_message.content)
54
-
55
-
56
- # class TestValidateMessages(unittest.TestCase):
57
-
58
- # # def test_validate_messages_correct_format(self):
59
- # # """Test messages DataFrame with the correct format."""
60
- # # messages = pd.DataFrame({
61
- # # "node_id": ["1"],
62
- # # "role": ["user"],
63
- # # "sender": ["test"],
64
- # # "timestamp": ["2020-01-01T00:00:00"],
65
- # # "content": ['{"message": "test"}']
66
- # # })
67
- # # self.assertTrue(MessageUtil.validate_messages(messages))
68
-
69
- # def test_validate_messages_incorrect_columns(self):
70
- # """Test messages DataFrame with incorrect columns raises ValueError."""
71
- # messages = pd.DataFrame(
72
- # {
73
- # "id": ["1"], "type": ["user"], "source": ["test"],
74
- # "time": ["2020-01-01T00:00:00"],
75
- # "data": ['{"message": "test"}'],
76
- # }
77
- # )
78
- # with self.assertRaises(ValueError):
79
- # MessageUtil.validate_messages(messages)
80
-
81
- # def test_validate_messages_null_values(self):
82
- # """Test messages DataFrame with null values raises ValueError."""
83
- # messages = pd.DataFrame(
84
- # {
85
- # "node_id": [None], "role": ["user"], "sender": ["test"],
86
- # "timestamp": ["2020-01-01T00:00:00"],
87
- # "content": ['{"message": "test"}'],
88
- # }
89
- # )
90
- # with self.assertRaises(ValueError):
91
- # MessageUtil.validate_messages(messages)
92
-
93
-
94
- # class TestSignMessage(unittest.TestCase):
95
-
96
- # def test_sign_message(self):
97
- # """Test signing message content with sender."""
98
- # messages = pd.DataFrame(
99
- # {
100
- # "node_id": ["1"], "role": ["user"], "sender": ["test"],
101
- # "timestamp": ["2020-01-01T00:00:00"],
102
- # "content": ["Original message"],
103
- # }
104
- # )
105
- # sender = "system"
106
- # signed_messages = MessageUtil.sign_message(messages, sender)
107
- # expected_content = "Sender system: Original message"
108
- # self.assertEqual(signed_messages["content"][0], expected_content)
109
-
110
- # def test_sign_message_invalid_sender(self):
111
- # """Test signing message with an invalid sender raises ValueError."""
112
- # messages = pd.DataFrame(
113
- # {
114
- # "node_id": ["1"], "role": ["user"], "sender": ["test"],
115
- # "timestamp": ["2020-01-01T00:00:00"],
116
- # "content": ["Original message"],
117
- # }
118
- # )
119
- # with self.assertRaises(ValueError):
120
- # MessageUtil.sign_message(messages, None)
121
-
122
-
123
- # class TestFilterMessagesBy(unittest.TestCase):
124
-
125
- # def setUp(self):
126
- # self.messages = pd.DataFrame(
127
- # {
128
- # "node_id": ["1", "2"], "role": ["user", "assistant"],
129
- # "sender": ["test", "assistant"],
130
- # "timestamp": [datetime(2020, 1, 1), datetime(2020, 1, 2)],
131
- # "content": ['{"message": "test"}', '{"response": "ok"}'],
132
- # }
133
- # )
134
-
135
- # def test_filter_by_role(self):
136
- # """Test filtering messages by role."""
137
- # filtered = MessageUtil.filter_messages_by(
138
- # self.messages, role="assistant"
139
- # )
140
- # self.assertEqual(len(filtered), 1)
141
- # self.assertEqual(filtered.iloc[0]["sender"], "assistant")
142
-
143
- # def test_filter_by_sender(self):
144
- # """Test filtering messages by sender."""
145
- # filtered = MessageUtil.filter_messages_by(
146
- # self.messages, sender="test"
147
- # )
148
- # self.assertEqual(len(filtered), 1)
149
- # self.assertEqual(filtered.iloc[0]["sender"], "test")
150
-
151
- # def test_filter_by_time_range(self):
152
- # """Test filtering messages by time range."""
153
- # start_time = datetime(2020, 1, 1, 12)
154
- # end_time = datetime(2020, 1, 2, 12)
155
- # filtered = MessageUtil.filter_messages_by(
156
- # self.messages, start_time=start_time, end_time=end_time
157
- # )
158
- # self.assertEqual(len(filtered), 1)
159
- # self.assertTrue(
160
- # start_time <= filtered.iloc[0]["timestamp"] <= end_time
161
- # )
162
-
163
-
164
- # class TestRemoveMessage(unittest.TestCase):
165
-
166
- # def test_remove_message(self):
167
- # """Test removing a message by node_id."""
168
- # messages = pd.DataFrame(
169
- # {
170
- # "node_id": ["1", "2"], "role": ["user", "assistant"],
171
- # "content": ["message1", "message2"],
172
- # }
173
- # )
174
- # updated_messages = MessageUtil.remove_message(messages, "1")
175
- # self.assertTrue(updated_messages)
176
-
177
-
178
- # class TestGetMessageRows(unittest.TestCase):
179
-
180
- # def test_get_message_rows(self):
181
- # """Test retrieving the last 'n' message rows based on criteria."""
182
- # messages = pd.DataFrame(
183
- # {
184
- # "node_id": ["1", "2", "3"],
185
- # "role": ["user", "assistant", "user"],
186
- # "sender": ["A", "B", "A"],
187
- # "content": ["message1", "message2", "message3"],
188
- # }
189
- # )
190
- # rows = MessageUtil.get_message_rows(
191
- # messages, sender="A", role="user", n=2
192
- # )
193
- # self.assertEqual(len(rows), 2)
194
-
195
-
196
- # # class TestExtend(unittest.TestCase):
197
-
198
- # # def test_extend(self):
199
- # # """Test extending one DataFrame with another, ensuring no duplicate 'node_id'."""
200
- # # df1 = pd.DataFrame({
201
- # # "node_id": ["1"],
202
- # # "role": ["user"],
203
- # # "sender": ["test"],
204
- # # "timestamp": ["2020-01-01T00:00:00"],
205
- # # "content": ['{"message": "test"}']
206
- # # })
207
- # # df2 = pd.DataFrame({
208
- # # "node_id": ["2"],
209
- # # "role": ["user"],
210
- # # "sender": ["test"],
211
- # # "timestamp": ["2020-01-02T00:00:00"],
212
- # # "content": ['{"message": "test2"}']
213
- # # })
214
- # # combined = MessageUtil.extend(df1, df2)
215
- # # self.assertEqual(len(combined), 2)
216
-
217
-
218
- # class TestToMarkdownString(unittest.TestCase):
219
-
220
- # def test_to_markdown_string(self):
221
- # """Test converting messages to a Markdown-formatted string."""
222
- # messages = pd.DataFrame(
223
- # {
224
- # "node_id": ["1"], "role": ["user"],
225
- # "content": [json.dumps({"instruction": "Hello, World!"})],
226
- # }
227
- # )
228
- # markdown_str = MessageUtil.to_markdown_string(messages)
229
- # self.assertIn("Hello, World!", markdown_str)
230
-
231
-
232
- # # class TestSearchKeywords(unittest.TestCase):
233
-
234
- # # def test_search_keywords(self):
235
- # # """Test filtering DataFrame for rows containing specified keywords."""
236
- # # messages = pd.DataFrame(
237
- # # {"node_id": ["1", "2"], "content": ["Hello world", "Goodbye world"]}
238
- # # )
239
- # # filtered = MessageUtil.search_keywords(messages, "Hello")
240
- # # print(filtered)
241
- # # self.assertEqual(len(filtered), 1)
242
-
243
-
244
- # # class TestReplaceKeyword(unittest.TestCase):
245
-
246
- # # def test_replace_keyword(self):
247
- # # """Test replacing a keyword in DataFrame's specified column."""
248
- # # messages = pd.DataFrame({"content": ["Hello world", "Goodbye world"]})
249
- # # MessageUtil.replace_keyword(messages, "world", "universe")
250
- # # self.assertTrue(all(messages["content"].str.contains("universe")))
251
-
252
-
253
- # # class TestReadCsv(unittest.TestCase):
254
-
255
- # # @patch("pandas.read_csv")
256
- # # def test_read_csv(self, mock_read_csv):
257
- # # """Test reading a CSV file into a DataFrame."""
258
- # # mock_df = pd.DataFrame(
259
- # # {"node_id": ["1", "2"], "content": ["Hello, World!", "Goodbye, World!"]}
260
- # # )
261
- # # mock_read_csv.return_value = mock_df
262
-
263
- # # df = MessageUtil.read_csv("path/to/nonexistent/file.csv")
264
-
265
- # # mock_read_csv.assert_called_once_with("path/to/nonexistent/file.csv")
266
-
267
- # # self.assertTrue(isinstance(df, pd.DataFrame))
268
- # # self.assertEqual(len(df), 2)
269
- # # self.assertEqual(list(df.columns), ["node_id", "content"])
270
-
271
-
272
- # # class TestReadJson(unittest.TestCase):
273
-
274
- # # @patch("pandas.read_json")
275
- # # def test_read_json(self, mock_read_json):
276
- # # """Test reading a JSON file into a DataFrame."""
277
- # # mock_df = pd.DataFrame(
278
- # # {"node_id": ["1", "2"], "content": ["JSON Message 1", "JSON Message 2"]}
279
- # # )
280
- # # mock_read_json.return_value = mock_df
281
-
282
- # # df = MessageUtil.read_json("path/to/nonexistent/file.json")
283
-
284
- # # mock_read_json.assert_called_once_with("path/to/nonexistent/file.json")
285
-
286
- # # self.assertTrue(isinstance(df, pd.DataFrame))
287
- # # self.assertEqual(len(df), 2)
288
- # # self.assertEqual(list(df.columns), ["node_id", "content"])
289
-
290
-
291
- # # class TestRemoveLastNRows(unittest.TestCase):
292
-
293
- # # def test_remove_last_n_rows(self):
294
- # # """Test removing the last 'n' rows from a DataFrame."""
295
- # # messages = pd.DataFrame({"content": ["message1", "message2", "message3"]})
296
- # # updated = MessageUtil.remove_last_n_rows(messages, 2)
297
- # # self.assertEqual(len(updated), 1)
298
-
299
-
300
- # # class TestUpdateRow(unittest.TestCase):
301
-
302
- # # def test_update_row(self):
303
- # # """Test updating a row's value for a specified column."""
304
- # # messages = pd.DataFrame(
305
- # # {"node_id": ["1", "2"], "content": ["message1", "message2"]}
306
- # # )
307
- # # success = MessageUtil.update_row(messages, 0, "node_id", "3")
308
- # # self.assertTrue(success)
309
- # # self.assertTrue("3" in messages["node_id"].values)
310
-
311
-
312
- # if __name__ == "__main__":
313
- # unittest.main()
@@ -1,95 +0,0 @@
1
- # from lionagi.core.tool.tool_manager import ToolManager
2
- # from lionagi.core.schema import Tool
3
-
4
- # import unittest
5
- # from unittest.mock import patch, AsyncMock
6
- # import asyncio
7
- # import json
8
-
9
-
10
- # class TestToolManager(unittest.TestCase):
11
- # def setUp(self):
12
- # self.manager = ToolManager()
13
- # self.tool = Tool(
14
- # func=lambda x: x, schema_={"function": {"name": "test_func"}}
15
- # )
16
-
17
- # def test_register_and_check_tool(self):
18
- # """Test registering a tool and checking its existence."""
19
- # self.manager._register_tool(self.tool)
20
- # self.assertTrue(self.manager.name_existed("test_func"))
21
-
22
- # def test_register_tool_type_error(self):
23
- # """Test that registering a non-Tool object raises a TypeError."""
24
- # with self.assertRaises(TypeError):
25
- # self.manager._register_tool("not_a_tool")
26
-
27
- # def test_name_not_existed(self):
28
- # """Test querying a non-registered tool's existence."""
29
- # self.assertFalse(self.manager.name_existed("non_existent_func"))
30
-
31
-
32
- # class TestToolInvocation(unittest.TestCase):
33
-
34
- # def setUp(self):
35
- # self.manager = ToolManager()
36
-
37
- # async def async_tool_func(x):
38
- # return x
39
-
40
- # self.async_tool = Tool(
41
- # func=async_tool_func,
42
- # schema_={"function": {"name": "async_test_func"}}
43
- # )
44
- # self.sync_tool = Tool(
45
- # func=lambda x: x, schema_={"function": {"name": "sync_test_func"}}
46
- # )
47
-
48
- # # @patch('lionagi.core.tool.tool_manager', return_value=False) # def test_invoke_sync_tool(self, mock_is_coroutine): # """Test invoking a synchronous tool.""" # self.manager._register_tool(self.sync_tool) # result = asyncio.run(self.manager.invoke(('sync_test_func', {'x': 10}))) # self.assertEqual(result, 10)
49
-
50
- # # @patch('lionagi.core.tool.tool_manager', return_value=True) # def test_invoke_async_tool(self, mock_call_handler, mock_is_coroutine): # """Test invoking an asynchronous tool.""" # mock_call_handler.return_value = 10 # self.manager._register_tool(self.async_tool) # result = asyncio.run(self.manager.invoke(('async_test_func', {'x': 10}))) # self.assertEqual(result, 10)
51
-
52
-
53
- # class TestFunctionCallExtraction(unittest.TestCase):
54
-
55
- # def setUp(self):
56
- # self.manager = ToolManager()
57
-
58
- # def test_get_function_call_valid(self):
59
- # """Test extracting a valid function call."""
60
- # response = {
61
- # "action": "action_test_func", "arguments": json.dumps({"x": 10})
62
- # }
63
- # func_call = self.manager.get_function_call(response)
64
- # self.assertEqual(func_call, ("test_func", {"x": 10}))
65
-
66
- # def test_get_function_call_invalid(self):
67
- # """Test handling an invalid function call."""
68
- # with self.assertRaises(ValueError):
69
- # self.manager.get_function_call({})
70
-
71
-
72
- # class TestToolParser(unittest.TestCase):
73
-
74
- # def setUp(self):
75
- # self.manager = ToolManager()
76
- # self.tool = Tool(
77
- # func=lambda x: x, schema_={"function": {"name": "test_func"}}
78
- # )
79
- # self.manager._register_tool(self.tool)
80
-
81
- # def test_tool_parser_single_tool(self):
82
- # """Test parsing a single tool name."""
83
- # parsed = self.manager.parse_tool("test_func")
84
- # self.assertIn("tools", parsed)
85
- # self.assertEqual(len(parsed["tools"]), 1)
86
- # self.assertEqual(parsed["tools"][0]["function"]["name"], "test_func")
87
-
88
- # def test_tool_parser_unregistered_tool(self):
89
- # """Test parsing an unregistered tool name."""
90
- # with self.assertRaises(ValueError):
91
- # self.manager.parse_tool("unregistered_func")
92
-
93
-
94
- # if __name__ == "__main__":
95
- # unittest.main()
@@ -1,9 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 HaiyangLi quantocean.li@gmail.com
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
-
7
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.