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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. lionagi/__init__.py +60 -5
  2. lionagi/core/__init__.py +0 -25
  3. lionagi/core/_setting/_setting.py +59 -0
  4. lionagi/core/action/__init__.py +14 -0
  5. lionagi/core/action/function_calling.py +136 -0
  6. lionagi/core/action/manual.py +1 -0
  7. lionagi/core/action/node.py +109 -0
  8. lionagi/core/action/tool.py +114 -0
  9. lionagi/core/action/tool_manager.py +356 -0
  10. lionagi/core/agent/base_agent.py +27 -13
  11. lionagi/core/agent/eval/evaluator.py +1 -0
  12. lionagi/core/agent/eval/vote.py +40 -0
  13. lionagi/core/agent/learn/learner.py +59 -0
  14. lionagi/core/agent/plan/unit_template.py +1 -0
  15. lionagi/core/collections/__init__.py +17 -0
  16. lionagi/core/{generic/data_logger.py → collections/_logger.py} +69 -55
  17. lionagi/core/collections/abc/__init__.py +53 -0
  18. lionagi/core/collections/abc/component.py +615 -0
  19. lionagi/core/collections/abc/concepts.py +297 -0
  20. lionagi/core/collections/abc/exceptions.py +150 -0
  21. lionagi/core/collections/abc/util.py +45 -0
  22. lionagi/core/collections/exchange.py +161 -0
  23. lionagi/core/collections/flow.py +426 -0
  24. lionagi/core/collections/model.py +419 -0
  25. lionagi/core/collections/pile.py +913 -0
  26. lionagi/core/collections/progression.py +236 -0
  27. lionagi/core/collections/util.py +64 -0
  28. lionagi/core/director/direct.py +314 -0
  29. lionagi/core/director/director.py +2 -0
  30. lionagi/core/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
  31. lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
  32. lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
  33. lionagi/core/executor/base_executor.py +90 -0
  34. lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +62 -66
  35. lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
  36. lionagi/core/generic/__init__.py +3 -33
  37. lionagi/core/generic/edge.py +29 -79
  38. lionagi/core/generic/edge_condition.py +16 -0
  39. lionagi/core/generic/graph.py +236 -0
  40. lionagi/core/generic/hyperedge.py +1 -0
  41. lionagi/core/generic/node.py +156 -221
  42. lionagi/core/generic/tree.py +48 -0
  43. lionagi/core/generic/tree_node.py +79 -0
  44. lionagi/core/mail/__init__.py +12 -0
  45. lionagi/core/mail/mail.py +25 -0
  46. lionagi/core/mail/mail_manager.py +139 -58
  47. lionagi/core/mail/package.py +45 -0
  48. lionagi/core/mail/start_mail.py +36 -0
  49. lionagi/core/message/__init__.py +19 -0
  50. lionagi/core/message/action_request.py +133 -0
  51. lionagi/core/message/action_response.py +135 -0
  52. lionagi/core/message/assistant_response.py +95 -0
  53. lionagi/core/message/instruction.py +234 -0
  54. lionagi/core/message/message.py +101 -0
  55. lionagi/core/message/system.py +86 -0
  56. lionagi/core/message/util.py +283 -0
  57. lionagi/core/report/__init__.py +4 -0
  58. lionagi/core/report/base.py +217 -0
  59. lionagi/core/report/form.py +231 -0
  60. lionagi/core/report/report.py +166 -0
  61. lionagi/core/report/util.py +28 -0
  62. lionagi/core/rule/_default.py +16 -0
  63. lionagi/core/rule/action.py +99 -0
  64. lionagi/core/rule/base.py +238 -0
  65. lionagi/core/rule/boolean.py +56 -0
  66. lionagi/core/rule/choice.py +47 -0
  67. lionagi/core/rule/mapping.py +96 -0
  68. lionagi/core/rule/number.py +71 -0
  69. lionagi/core/rule/rulebook.py +109 -0
  70. lionagi/core/rule/string.py +52 -0
  71. lionagi/core/rule/util.py +35 -0
  72. lionagi/core/session/branch.py +431 -0
  73. lionagi/core/session/directive_mixin.py +287 -0
  74. lionagi/core/session/session.py +229 -903
  75. lionagi/core/structure/__init__.py +1 -0
  76. lionagi/core/structure/chain.py +1 -0
  77. lionagi/core/structure/forest.py +1 -0
  78. lionagi/core/structure/graph.py +1 -0
  79. lionagi/core/structure/tree.py +1 -0
  80. lionagi/core/unit/__init__.py +5 -0
  81. lionagi/core/unit/parallel_unit.py +245 -0
  82. lionagi/core/unit/template/action.py +81 -0
  83. lionagi/core/unit/template/base.py +51 -0
  84. lionagi/core/unit/template/plan.py +84 -0
  85. lionagi/core/unit/template/predict.py +109 -0
  86. lionagi/core/unit/template/score.py +124 -0
  87. lionagi/core/unit/template/select.py +104 -0
  88. lionagi/core/unit/unit.py +362 -0
  89. lionagi/core/unit/unit_form.py +305 -0
  90. lionagi/core/unit/unit_mixin.py +1168 -0
  91. lionagi/core/unit/util.py +71 -0
  92. lionagi/core/validator/validator.py +364 -0
  93. lionagi/core/work/work.py +76 -0
  94. lionagi/core/work/work_function.py +101 -0
  95. lionagi/core/work/work_queue.py +103 -0
  96. lionagi/core/work/worker.py +258 -0
  97. lionagi/core/work/worklog.py +120 -0
  98. lionagi/experimental/compressor/base.py +46 -0
  99. lionagi/experimental/compressor/llm_compressor.py +247 -0
  100. lionagi/experimental/compressor/llm_summarizer.py +61 -0
  101. lionagi/experimental/compressor/util.py +70 -0
  102. lionagi/experimental/directive/__init__.py +19 -0
  103. lionagi/experimental/directive/parser/base_parser.py +69 -2
  104. lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
  105. lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
  106. lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
  107. lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
  108. lionagi/experimental/knowledge/base.py +10 -0
  109. lionagi/experimental/memory/__init__.py +0 -0
  110. lionagi/experimental/strategies/__init__.py +0 -0
  111. lionagi/experimental/strategies/base.py +1 -0
  112. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  113. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  114. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  115. lionagi/integrations/chunker/chunk.py +161 -24
  116. lionagi/integrations/config/oai_configs.py +34 -3
  117. lionagi/integrations/config/openrouter_configs.py +14 -2
  118. lionagi/integrations/loader/load.py +122 -21
  119. lionagi/integrations/loader/load_util.py +6 -77
  120. lionagi/integrations/provider/_mapping.py +46 -0
  121. lionagi/integrations/provider/litellm.py +2 -1
  122. lionagi/integrations/provider/mlx_service.py +16 -9
  123. lionagi/integrations/provider/oai.py +91 -4
  124. lionagi/integrations/provider/ollama.py +6 -5
  125. lionagi/integrations/provider/openrouter.py +115 -8
  126. lionagi/integrations/provider/services.py +2 -2
  127. lionagi/integrations/provider/transformers.py +18 -22
  128. lionagi/integrations/storage/__init__.py +3 -3
  129. lionagi/integrations/storage/neo4j.py +52 -60
  130. lionagi/integrations/storage/storage_util.py +44 -46
  131. lionagi/integrations/storage/structure_excel.py +43 -26
  132. lionagi/integrations/storage/to_excel.py +11 -4
  133. lionagi/libs/__init__.py +22 -1
  134. lionagi/libs/ln_api.py +75 -20
  135. lionagi/libs/ln_context.py +37 -0
  136. lionagi/libs/ln_convert.py +21 -9
  137. lionagi/libs/ln_func_call.py +69 -28
  138. lionagi/libs/ln_image.py +107 -0
  139. lionagi/libs/ln_nested.py +26 -11
  140. lionagi/libs/ln_parse.py +82 -23
  141. lionagi/libs/ln_queue.py +16 -0
  142. lionagi/libs/ln_tokenize.py +164 -0
  143. lionagi/libs/ln_validate.py +16 -0
  144. lionagi/libs/special_tokens.py +172 -0
  145. lionagi/libs/sys_util.py +95 -24
  146. lionagi/lions/coder/code_form.py +13 -0
  147. lionagi/lions/coder/coder.py +50 -3
  148. lionagi/lions/coder/util.py +30 -25
  149. lionagi/tests/libs/test_func_call.py +23 -21
  150. lionagi/tests/libs/test_nested.py +36 -21
  151. lionagi/tests/libs/test_parse.py +1 -1
  152. lionagi/tests/test_core/collections/__init__.py +0 -0
  153. lionagi/tests/test_core/collections/test_component.py +206 -0
  154. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  155. lionagi/tests/test_core/collections/test_flow.py +145 -0
  156. lionagi/tests/test_core/collections/test_pile.py +171 -0
  157. lionagi/tests/test_core/collections/test_progression.py +129 -0
  158. lionagi/tests/test_core/generic/test_edge.py +67 -0
  159. lionagi/tests/test_core/generic/test_graph.py +96 -0
  160. lionagi/tests/test_core/generic/test_node.py +106 -0
  161. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  162. lionagi/tests/test_core/test_branch.py +115 -294
  163. lionagi/tests/test_core/test_form.py +46 -0
  164. lionagi/tests/test_core/test_report.py +105 -0
  165. lionagi/tests/test_core/test_validator.py +111 -0
  166. lionagi/version.py +1 -1
  167. lionagi-0.2.1.dist-info/LICENSE +202 -0
  168. lionagi-0.2.1.dist-info/METADATA +272 -0
  169. lionagi-0.2.1.dist-info/RECORD +240 -0
  170. lionagi/core/branch/base.py +0 -653
  171. lionagi/core/branch/branch.py +0 -474
  172. lionagi/core/branch/flow_mixin.py +0 -96
  173. lionagi/core/branch/util.py +0 -323
  174. lionagi/core/direct/__init__.py +0 -19
  175. lionagi/core/direct/cot.py +0 -123
  176. lionagi/core/direct/plan.py +0 -164
  177. lionagi/core/direct/predict.py +0 -166
  178. lionagi/core/direct/react.py +0 -171
  179. lionagi/core/direct/score.py +0 -279
  180. lionagi/core/direct/select.py +0 -170
  181. lionagi/core/direct/sentiment.py +0 -1
  182. lionagi/core/direct/utils.py +0 -110
  183. lionagi/core/direct/vote.py +0 -64
  184. lionagi/core/execute/base_executor.py +0 -47
  185. lionagi/core/flow/baseflow.py +0 -23
  186. lionagi/core/flow/monoflow/ReAct.py +0 -240
  187. lionagi/core/flow/monoflow/__init__.py +0 -9
  188. lionagi/core/flow/monoflow/chat.py +0 -95
  189. lionagi/core/flow/monoflow/chat_mixin.py +0 -253
  190. lionagi/core/flow/monoflow/followup.py +0 -215
  191. lionagi/core/flow/polyflow/__init__.py +0 -1
  192. lionagi/core/flow/polyflow/chat.py +0 -251
  193. lionagi/core/form/action_form.py +0 -26
  194. lionagi/core/form/field_validator.py +0 -287
  195. lionagi/core/form/form.py +0 -302
  196. lionagi/core/form/mixin.py +0 -214
  197. lionagi/core/form/scored_form.py +0 -13
  198. lionagi/core/generic/action.py +0 -26
  199. lionagi/core/generic/component.py +0 -532
  200. lionagi/core/generic/condition.py +0 -46
  201. lionagi/core/generic/mail.py +0 -90
  202. lionagi/core/generic/mailbox.py +0 -36
  203. lionagi/core/generic/relation.py +0 -70
  204. lionagi/core/generic/signal.py +0 -22
  205. lionagi/core/generic/structure.py +0 -362
  206. lionagi/core/generic/transfer.py +0 -20
  207. lionagi/core/generic/work.py +0 -40
  208. lionagi/core/graph/graph.py +0 -126
  209. lionagi/core/graph/tree.py +0 -190
  210. lionagi/core/mail/schema.py +0 -63
  211. lionagi/core/messages/schema.py +0 -325
  212. lionagi/core/tool/__init__.py +0 -5
  213. lionagi/core/tool/tool.py +0 -28
  214. lionagi/core/tool/tool_manager.py +0 -283
  215. lionagi/experimental/report/form.py +0 -64
  216. lionagi/experimental/report/report.py +0 -138
  217. lionagi/experimental/report/util.py +0 -47
  218. lionagi/experimental/tool/function_calling.py +0 -43
  219. lionagi/experimental/tool/manual.py +0 -66
  220. lionagi/experimental/tool/schema.py +0 -59
  221. lionagi/experimental/tool/tool_manager.py +0 -138
  222. lionagi/experimental/tool/util.py +0 -16
  223. lionagi/experimental/validator/rule.py +0 -139
  224. lionagi/experimental/validator/validator.py +0 -56
  225. lionagi/experimental/work/__init__.py +0 -10
  226. lionagi/experimental/work/async_queue.py +0 -54
  227. lionagi/experimental/work/schema.py +0 -73
  228. lionagi/experimental/work/work_function.py +0 -67
  229. lionagi/experimental/work/worker.py +0 -56
  230. lionagi/experimental/work2/form.py +0 -371
  231. lionagi/experimental/work2/report.py +0 -289
  232. lionagi/experimental/work2/schema.py +0 -30
  233. lionagi/experimental/work2/tests.py +0 -72
  234. lionagi/experimental/work2/work_function.py +0 -89
  235. lionagi/experimental/work2/worker.py +0 -12
  236. lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
  237. lionagi/tests/test_core/generic/test_component.py +0 -89
  238. lionagi/tests/test_core/test_base_branch.py +0 -426
  239. lionagi/tests/test_core/test_chat_flow.py +0 -63
  240. lionagi/tests/test_core/test_mail_manager.py +0 -75
  241. lionagi/tests/test_core/test_prompts.py +0 -51
  242. lionagi/tests/test_core/test_session.py +0 -254
  243. lionagi/tests/test_core/test_session_base_util.py +0 -313
  244. lionagi/tests/test_core/test_tool_manager.py +0 -95
  245. lionagi-0.1.2.dist-info/LICENSE +0 -9
  246. lionagi-0.1.2.dist-info/METADATA +0 -174
  247. lionagi-0.1.2.dist-info/RECORD +0 -206
  248. /lionagi/core/{branch → _setting}/__init__.py +0 -0
  249. /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
  250. /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
  251. /lionagi/core/{form → agent/plan}/__init__.py +0 -0
  252. /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
  253. /lionagi/core/{graph → director}/__init__.py +0 -0
  254. /lionagi/core/{messages → engine}/__init__.py +0 -0
  255. /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
  256. /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
  257. /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
  258. /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
  259. /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
  260. /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
  261. /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
  262. /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
  263. /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
  264. /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
  265. /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
  266. /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
  267. {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
  268. {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
@@ -1,426 +0,0 @@
1
- # from lionagi.core.branch.base_branch import BaseBranch
2
- # from lionagi.core.branch.util import MessageUtil
3
- # from lionagi.core.messages.schema import System
4
- # from lionagi.core.schema import DataLogger
5
-
6
- # import unittest
7
- # from unittest.mock import patch, MagicMock
8
- # import pandas as pd
9
- # from datetime import datetime
10
- # import json
11
-
12
-
13
- # class TestBaseBranch(unittest.TestCase):
14
-
15
- # def setUp(self):
16
- # # Patching DataLogger to avoid filesystem interactions during tests
17
- # self.patcher = patch(
18
- # "lionagi.core.branch.base_branch.DataLogger", autospec=True
19
- # )
20
- # self.MockDataLogger = self.patcher.start()
21
- # self.addCleanup(self.patcher.stop)
22
-
23
- # self.branch = BaseBranch()
24
- # # Example messages to populate the DataFrame for testing
25
- # self.test_messages = [
26
- # {
27
- # "node_id": "1",
28
- # "timestamp": "2021-01-01 00:00:00",
29
- # "role": "system",
30
- # "sender": "system",
31
- # "content": json.dumps({"system_info": "System message"}),
32
- # },
33
- # {
34
- # "node_id": "2",
35
- # "timestamp": "2021-01-01 00:01:00",
36
- # "role": "user",
37
- # "sender": "user1",
38
- # "content": json.dumps({"instruction": "User message"}),
39
- # },
40
- # {
41
- # "node_id": "3",
42
- # "timestamp": "2021-01-01 00:02:00",
43
- # "role": "assistant",
44
- # "sender": "assistant",
45
- # "content": json.dumps({"response": "Assistant response"}),
46
- # },
47
- # {
48
- # "node_id": "4",
49
- # "timestamp": "2021-01-01 00:03:00",
50
- # "role": "assistant",
51
- # "sender": "action_request",
52
- # "content": json.dumps({"action_request": "Action request"}),
53
- # },
54
- # {
55
- # "node_id": "5",
56
- # "timestamp": "2021-01-01 00:04:00",
57
- # "role": "assistant",
58
- # "sender": "action_response",
59
- # "content": json.dumps({"action_response": "Action response"}),
60
- # },
61
- # ]
62
- # self.branch = BaseBranch(messages=pd.DataFrame(self.test_messages))
63
-
64
- # def test_init_with_empty_messages(self):
65
- # """Test __init__ method with no messages provided."""
66
- # branch = BaseBranch()
67
- # self.assertTrue(branch.messages.empty)
68
-
69
- # def test_init_with_given_messages(self):
70
- # """Test __init__ method with provided messages DataFrame."""
71
- # messages = pd.DataFrame(
72
- # [
73
- # [
74
- # "0",
75
- # datetime(2024, 1, 1),
76
- # "system",
77
- # "system",
78
- # json.dumps({"system_info": "Hi"}),
79
- # ]
80
- # ],
81
- # columns=["node_id", "timestamp", "role", "sender", "content"],
82
- # )
83
- # branch = BaseBranch(messages=messages)
84
- # self.assertFalse(branch.messages.empty)
85
-
86
- # def test_add_message(self):
87
- # """Test adding a message."""
88
- # message_info = {"info": "Test Message"}
89
- # with patch.object(
90
- # MessageUtil, "create_message", return_value=System(system=message_info)
91
- # ) as mocked_create_message:
92
- # self.branch.add_message(system=message_info)
93
- # mocked_create_message.assert_called_once()
94
- # self.assertEqual(len(self.branch.messages), 6)
95
-
96
- # def test_chat_messages_without_sender(self):
97
- # """Test chat_messages property without including sender information."""
98
- # chat_messages = self.branch.chat_messages
99
- # self.assertEqual(len(chat_messages), 5)
100
- # self.assertNotIn("Sender", chat_messages[0]["content"])
101
-
102
- # def test_chat_messages_with_sender(self):
103
- # """Test retrieving chat messages with sender information included."""
104
- # chat_messages_with_sender = self.branch.chat_messages_with_sender
105
- # expected_prefixes = [
106
- # "Sender system: ",
107
- # "Sender user1: ",
108
- # "Sender assistant: ",
109
- # "Sender action_request: ",
110
- # "Sender action_response: ",
111
- # ]
112
-
113
- # # Verify the number of messages returned matches the number added
114
- # self.assertEqual(len(chat_messages_with_sender), len(self.test_messages))
115
-
116
- # # Check each message for correct sender prefix in content
117
- # for i, message_dict in enumerate(chat_messages_with_sender):
118
- # self.assertTrue(
119
- # message_dict["content"].startswith(expected_prefixes[i]),
120
- # msg=f"Message content does not start with expected sender prefix. Found: {message_dict['content']}",
121
- # )
122
-
123
- # # Optionally, verify the content matches after removing the prefix
124
- # for i, message_dict in enumerate(chat_messages_with_sender):
125
- # prefix, content = message_dict["content"].split(": ", 1)
126
- # self.assertEqual(
127
- # content,
128
- # self.test_messages[i]["content"],
129
- # msg=f"Message content does not match after removing sender prefix. Found: {content}, Expected: {self.test_messages[i]['content']}",
130
- # )
131
-
132
- # def test_last_message(self):
133
- # """Test retrieving the last message."""
134
- # last_message = self.branch.last_message
135
- # self.assertEqual(
136
- # json.loads(last_message.iloc[0]["content"]),
137
- # {"action_response": "Action response"},
138
- # )
139
-
140
- # def test_last_message_content(self):
141
- # """Test retrieving the content of the last message."""
142
- # content = self.branch.last_message_content
143
- # self.assertEqual(content, {"action_response": "Action response"})
144
-
145
- # def test_first_system_message(self):
146
- # """Test retrieving the first 'system' message."""
147
- # first_system_message = self.branch.first_system
148
- # self.assertEqual(
149
- # json.loads(first_system_message.iloc[0]["content"]),
150
- # {"system_info": "System message"},
151
- # )
152
-
153
- # def test_last_response(self):
154
- # """Test retrieving the last 'assistant' message."""
155
- # last_response = self.branch.last_response
156
- # self.assertEqual(last_response.iloc[0]["sender"], "action_response")
157
-
158
- # def test_last_response_content(self):
159
- # """Test extracting content of the last 'assistant' message."""
160
- # content = self.branch.last_response_content
161
- # self.assertEqual(content, {"action_response": "Action response"})
162
-
163
- # def test_action_request_messages(self):
164
- # """Test filtering messages sent by 'action_request'."""
165
- # action_requests = self.branch.action_request
166
- # self.assertTrue(all(action_requests["sender"] == "action_request"))
167
-
168
- # def test_action_response_messages(self):
169
- # """Test filtering messages sent by 'action_response'."""
170
- # action_responses = self.branch.action_response
171
- # self.assertTrue(all(action_responses["sender"] == "action_response"))
172
-
173
- # def test_responses(self):
174
- # """Test filtering of 'assistant' role messages."""
175
- # responses = self.branch.responses
176
- # # Verify that all returned messages have the 'assistant' role
177
- # self.assertTrue(all(responses["role"] == "assistant"))
178
- # # Optionally, check the count matches the expected number of 'assistant' messages
179
- # expected_count = sum(
180
- # 1 for msg in self.test_messages if msg["role"] == "assistant"
181
- # )
182
- # self.assertEqual(len(responses), expected_count)
183
-
184
- # def test_assistant_responses(self):
185
- # """Test filtering of 'assistant' messages excluding action requests/responses."""
186
- # assistant_responses = self.branch.assistant_responses
187
- # # Verify that no returned messages are from 'action_request' or 'action_response' senders
188
- # self.assertTrue(all(assistant_responses["sender"] != "action_request"))
189
- # self.assertTrue(all(assistant_responses["sender"] != "action_response"))
190
- # # Verify that all returned messages have the 'assistant' role
191
- # self.assertTrue(all(assistant_responses["role"] == "assistant"))
192
-
193
- # def test_info(self):
194
- # """Test summarization of message counts by role."""
195
- # info = self.branch.info
196
- # # Verify that the dictionary contains keys for each role and 'total'
197
- # self.assertIn("assistant", info)
198
- # self.assertIn("user", info)
199
- # self.assertIn("system", info)
200
- # self.assertIn("total", info)
201
- # # Optionally, verify the counts match expected values
202
- # for role in ["assistant", "user", "system"]:
203
- # expected_count = sum(1 for msg in self.test_messages if msg["role"] == role)
204
- # self.assertEqual(info[role], expected_count)
205
- # self.assertEqual(info["total"], len(self.test_messages))
206
-
207
- # def test_sender_info(self):
208
- # """Test summarization of message counts by sender."""
209
- # sender_info = self.branch.sender_info
210
- # # Verify that the dictionary contains keys for each sender and the counts match
211
- # for sender in set(msg["sender"] for msg in self.test_messages):
212
- # expected_count = sum(
213
- # 1 for msg in self.test_messages if msg["sender"] == sender
214
- # )
215
- # self.assertEqual(sender_info.get(sender, 0), expected_count)
216
-
217
- # def test_describe(self):
218
- # """Test detailed description of the branch."""
219
- # description = self.branch.describe
220
- # # Verify that the description contains expected keys
221
- # self.assertIn("total_messages", description)
222
- # self.assertIn("summary_by_role", description)
223
- # self.assertIn("messages", description)
224
- # # Optionally, verify the accuracy of the values
225
- # self.assertEqual(description["total_messages"], len(self.test_messages))
226
- # self.assertEqual(len(description["messages"]), min(5, len(self.test_messages)))
227
-
228
- # @patch("lionagi.libs.ln_dataframe.read_csv")
229
- # def test_from_csv(cls, mock_read_csv):
230
- # # Define a mock return value for read_csv
231
- # mock_messages_df = pd.DataFrame(
232
- # {
233
- # "node_id": ["1", "2"],
234
- # "timestamp": [datetime(2021, 1, 1), datetime(2021, 1, 1)],
235
- # "role": ["system", "user"],
236
- # "sender": ["system", "user1"],
237
- # "content": [
238
- # json.dumps({"system_info": "System message"}),
239
- # json.dumps({"instruction": "User message"}),
240
- # ],
241
- # }
242
- # )
243
- # mock_read_csv.return_value = mock_messages_df
244
-
245
- # # Call the from_csv class method
246
- # branch = BaseBranch.from_csv(filename="dummy.csv")
247
-
248
- # # Verify that read_csv was called correctly
249
- # mock_read_csv.assert_called_once_with("dummy.csv")
250
-
251
- # # Verify that the branch instance contains the correct messages
252
- # pd.testing.assert_frame_equal(branch.messages, mock_messages_df)
253
-
254
- # @patch("lionagi.libs.ln_dataframe.read_json")
255
- # def test_from_json(cls, mock_read_csv):
256
- # # Define a mock return value for read_csv
257
- # mock_messages_df = pd.DataFrame(
258
- # {
259
- # "node_id": ["1", "2"],
260
- # "timestamp": [datetime(2021, 1, 1), datetime(2021, 1, 1)],
261
- # "role": ["system", "user"],
262
- # "sender": ["system", "user1"],
263
- # "content": [
264
- # json.dumps({"system_info": "System message"}),
265
- # json.dumps({"instruction": "User message"}),
266
- # ],
267
- # }
268
- # )
269
- # mock_read_csv.return_value = mock_messages_df
270
-
271
- # # Call the from_csv class method
272
- # branch = BaseBranch.from_json_string(filename="dummy.json")
273
-
274
- # # Verify that read_csv was called correctly
275
- # mock_read_csv.assert_called_once_with("dummy.json")
276
-
277
- # # Verify that the branch instance contains the correct messages
278
- # pd.testing.assert_frame_equal(branch.messages, mock_messages_df)
279
-
280
- # @patch(
281
- # "lionagi.libs.sys_util.SysUtil.create_path",
282
- # return_value="path/to/messages.csv",
283
- # )
284
- # @patch.object(pd.DataFrame, "to_csv")
285
- # def test_to_csv(self, mock_to_csv, mock_create_path):
286
- # self.branch.datalogger = MagicMock()
287
- # self.branch.datalogger.persist_path = "data/logs/"
288
-
289
- # self.branch.to_csv_file("messages.csv", verbose=False, clear=False)
290
-
291
- # mock_create_path.assert_called_once_with(
292
- # self.branch.datalogger.persist_path,
293
- # "messages.csv",
294
- # timestamp=True,
295
- # dir_exist_ok=True,
296
- # time_prefix=False,
297
- # )
298
- # mock_to_csv.assert_called_once_with("path/to/messages.csv")
299
-
300
- # # Verify that messages are not cleared after exporting
301
- # assert not self.branch.messages.empty
302
-
303
- # @patch(
304
- # "lionagi.libs.sys_util.SysUtil.create_path",
305
- # return_value="path/to/messages.json",
306
- # )
307
- # @patch.object(pd.DataFrame, "to_json")
308
- # def test_to_json(self, mock_to_json, mock_create_path):
309
- # self.branch.datalogger = MagicMock()
310
- # self.branch.datalogger.persist_path = "data/logs/"
311
-
312
- # self.branch.to_json_file("messages.json", verbose=False, clear=False)
313
-
314
- # mock_create_path.assert_called_once_with(
315
- # self.branch.datalogger.persist_path,
316
- # "messages.json",
317
- # timestamp=True,
318
- # dir_exist_ok=True,
319
- # time_prefix=False,
320
- # )
321
- # mock_to_json.assert_called_once_with(
322
- # "path/to/messages.json", orient="records", lines=True, date_format="iso"
323
- # )
324
-
325
- # # Verify that messages are not cleared after exporting
326
- # assert not self.branch.messages.empty
327
-
328
- # # def test_log_to_csv(self):
329
- # # self.branch.log_to_csv('log.csv', verbose=False, clear=False)
330
-
331
- # # self.branch.datalogger.to_csv_file.assert_called_once_with(filename='log.csv', dir_exist_ok=True, timestamp=True,
332
- # # time_prefix=False, verbose=False, clear=False)
333
-
334
- # # def test_log_to_json(self):
335
- # # branch = BaseBranch()
336
- # # branch.log_to_json('log.json', verbose=False, clear=False)
337
-
338
- # # self.branch.datalogger.to_json_file.assert_called_once_with(filename='log.json', dir_exist_ok=True, timestamp=True,
339
- # # time_prefix=False, verbose=False, clear=False)
340
-
341
- # def test_remove_message(self):
342
- # """Test removing a message from the branch based on its node ID."""
343
- # initial_length = len(self.branch.messages)
344
- # node_id_to_remove = "2"
345
- # self.branch.remove_message(node_id_to_remove)
346
- # final_length = len(self.branch.messages)
347
- # self.assertNotIn(node_id_to_remove, self.branch.messages["node_id"].tolist())
348
- # self.assertEqual(final_length, initial_length - 1)
349
-
350
- # def test_update_message(self):
351
- # """Test updating a specific message's column identified by node_id with a new value."""
352
- # node_id_to_update = "2"
353
- # new_value = "Updated content"
354
- # self.branch.update_message(node_id_to_update, "content", new_value)
355
- # updated_value = self.branch.messages.loc[
356
- # self.branch.messages["node_id"] == node_id_to_update, "content"
357
- # ].values[0]
358
- # self.assertEqual(updated_value, new_value)
359
-
360
- # # def test_change_first_system_message(self):
361
- # # """Test updating the first system message with new content and/or sender."""
362
- # # new_system_content = {"system_info": "Updated system message"}
363
- # # self.branch.change_first_system_message(new_system_content['system_info'])
364
- # # first_system_message_content = self.branch.messages.loc[self.branch.messages['role'] == 'system', 'content'].iloc[0]
365
- # # self.assertIn(json.dumps({"system_info": "Updated system message"}), first_system_message_content)
366
-
367
- # def test_rollback(self):
368
- # """Test removing the last 'n' messages from the branch."""
369
- # steps_to_remove = 2
370
- # initial_length = len(self.branch.messages)
371
- # self.branch.rollback(steps_to_remove)
372
- # final_length = len(self.branch.messages)
373
- # self.assertEqual(final_length, initial_length - steps_to_remove)
374
-
375
- # def test_clear_messages(self):
376
- # """Test clearing all messages from the branch."""
377
- # self.branch.clear_messages()
378
- # self.assertTrue(self.branch.messages.empty)
379
-
380
- # def test_replace_keyword(self):
381
- # """Test replacing occurrences of a specified keyword with a replacement string."""
382
- # keyword = "Assistant response"
383
- # replacement = "Helper feedback"
384
- # self.branch.replace_keyword(keyword, replacement)
385
- # self.assertTrue(
386
- # any(replacement in message for message in self.branch.messages["content"])
387
- # )
388
-
389
- # def test_search_keywords(self):
390
- # """Test filtering messages by a specified keyword or list of keywords."""
391
- # keyword_to_search = "Assistant"
392
- # filtered_messages = self.branch.search_keywords(keyword_to_search)
393
- # self.assertTrue(
394
- # all(
395
- # keyword_to_search in content for content in filtered_messages["content"]
396
- # )
397
- # )
398
-
399
- # def test_extend(self):
400
- # """Test extending branch messages with additional messages."""
401
- # additional_messages = pd.DataFrame(
402
- # [
403
- # {
404
- # "node_id": "6",
405
- # "timestamp": datetime(2021, 1, 1),
406
- # "role": "user",
407
- # "sender": "user2",
408
- # "content": json.dumps({"instruction": "Another user message"}),
409
- # }
410
- # ]
411
- # )
412
- # initial_length = len(self.branch.messages)
413
- # self.branch.extend(additional_messages)
414
- # self.assertEqual(len(self.branch.messages), initial_length + 1)
415
-
416
- # def test_filter_by(self):
417
- # """Test filtering messages by various criteria."""
418
- # # Filtering by role
419
- # filtered_messages = self.branch.filter_by(role="user")
420
- # self.assertTrue(
421
- # all(msg["role"] == "user" for _, msg in filtered_messages.iterrows())
422
- # )
423
-
424
-
425
- # if __name__ == "__main__":
426
- # unittest.main()
@@ -1,63 +0,0 @@
1
- # from lionagi.core.flow.monoflow import
2
- # from lionagi.core.session.branch import Branch
3
- # from lionagi.core.action.libs import func_to_tool
4
-
5
- # import unittest
6
- # from unittest import IsolatedAsyncioTestCase
7
- # from unittest.mock import patch, MagicMock, AsyncMock
8
-
9
-
10
- # class TestChatFlowCallChatCompletion(IsolatedAsyncioTestCase):
11
- # async def asyncSetUp(self):
12
- # self.branch = MagicMock()
13
- # self.branch.service = MagicMock()
14
- # self.branch.datalogger = MagicMock()
15
- # self.branch.status_tracker = MagicMock(num_tasks_succeeded=0, num_tasks_failed=0)
16
- # self.branch.add_message = MagicMock()
17
-
18
- # # Mock chat completion service response
19
- # self.branch.service.serve_chat = AsyncMock(return_value=({}, {"choices": [{'messages':{"content": "test response"}}]}))
20
-
21
- # async def test_call_chatcompletion(self):
22
- # await ChatFlow.call_chatcompletion(self.branch, sender="user")
23
-
24
- # # Verify serve_chat was called with expected arguments
25
- # self.branch.service.serve_chat.assert_called_once()
26
-
27
- # # Verify the branch's datalogger and add_message were called appropriately
28
- # self.branch.datalogger.append.assert_called_once()
29
- # self.branch.add_message.assert_called_with(response={'messages': {'content': 'test response'}}, sender="user")
30
-
31
- # # Verify status tracker update
32
- # self.assertEqual(self.branch.status_tracker.num_tasks_succeeded, 1)
33
- # self.assertEqual(self.branch.status_tracker.num_tasks_failed, 0)
34
-
35
-
36
- # class TestChatFlowChat(IsolatedAsyncioTestCase):
37
-
38
- # async def asyncSetUp(self):
39
- # self.branch = MagicMock()
40
- # self.branch.add_message = MagicMock()
41
- # self.branch.change_first_system_message = MagicMock()
42
- # self.branch.service = AsyncMock()
43
- # self.branch.datalogger = MagicMock()
44
- # self.branch.call_chatcompletion = AsyncMock()
45
- # self.branch.tool_manager.invoke = AsyncMock()
46
-
47
- # self.branch.service.serve_chat = AsyncMock(
48
- # return_value=({}, {"choices": [{'messages': {"content": "test response"}}]}))
49
-
50
- # async def test_chat_with_system_and_instruction(self):
51
- # instruction = "Ask about user preferences"
52
- # system = "System ready"
53
- # sender = "user"
54
-
55
- # await ChatFlow.chat(self.branch, instruction=instruction, sender=sender)
56
-
57
- # self.branch.add_message.assert_called_with(instruction=instruction, context=None, sender=sender)
58
-
59
- # self.branch.call_chatcompletion.assert_called_once()
60
-
61
-
62
- # if __name__ == '__main__':
63
- # unittest.main()
@@ -1,75 +0,0 @@
1
- # from lionagi.core.mail.mail_manager import MailManager
2
- # from lionagi.core.mail.schema import BaseMail
3
-
4
- # import unittest
5
- # from unittest.mock import patch
6
- # from collections import deque
7
-
8
-
9
- # class MockSource:
10
- # def __init__(self):
11
- # self.pending_outs = deque()
12
- # self.pending_ins = {}
13
-
14
-
15
- # class TestMailManager(unittest.TestCase):
16
-
17
- # def setUp(self):
18
- # self.sources = {"source1": MockSource(), "source2": MockSource()}
19
- # self.manager = MailManager(sources=self.sources)
20
-
21
- # def test_add_source(self):
22
- # """Test adding a new source."""
23
- # self.manager.add_source({"new_source": MockSource()})
24
- # self.assertIn("new_source", self.manager.sources)
25
-
26
- # def test_add_source_existing_name(self):
27
- # """Test adding a source with an existing name raises ValueError."""
28
- # with self.assertRaises(ValueError):
29
- # self.manager.add_source({"source1": MockSource()})
30
-
31
- # def test_delete_source(self):
32
- # """Test deleting an existing source."""
33
- # self.manager.delete_source("source1")
34
- # self.assertNotIn("source1", self.manager.sources)
35
-
36
- # def test_delete_nonexistent_source(self):
37
- # """Test deleting a non-existent source raises ValueError."""
38
- # with self.assertRaises(ValueError):
39
- # self.manager.delete_source("nonexistent_source")
40
-
41
- # def test_collect_from_nonexistent_sender(self):
42
- # """Test collecting mail from a non-existent sender raises ValueError."""
43
- # with self.assertRaises(ValueError):
44
- # self.manager.collect("nonexistent_sender")
45
-
46
- # def test_send_to_nonexistent_recipient(self):
47
- # """Test sending mail to a non-existent recipient raises ValueError."""
48
- # with self.assertRaises(ValueError):
49
- # self.manager.send("nonexistent_recipient")
50
-
51
- # @patch("lionagi.core.mail.mail_manager.BaseMail")
52
- # def test_create_mail(self, mock_base_mail):
53
- # """Test creating mail using the static method."""
54
- # mail = MailManager.create_mail("sender", "recipient", "messages", "package")
55
- # mock_base_mail.assert_called_once_with(
56
- # "sender", "recipient", "messages", "package"
57
- # )
58
-
59
- # # def test_collect_and_send_mail(self):
60
- # # """Test collecting and sending mail between existing sources."""
61
- # # # Setup: Simulate pending outs in source1
62
- # # mock_mail = BaseMail("source1", "source2", "messages", "package")
63
- # # self.sources["source1"].pending_outs.append(mock_mail)
64
-
65
- # # # Collect mail from source1
66
- # # self.manager.collect("source1")
67
- # # # Send mail to source2
68
- # # self.manager.send("source2")
69
-
70
- # # # Verify that source2 received the mail
71
- # # self.assertTrue(any(self.sources["source2"].pending_ins))
72
-
73
-
74
- # if __name__ == "__main__":
75
- # unittest.main()
@@ -1,51 +0,0 @@
1
- # from to_do.base_prompt_field import *
2
- # from pydantic import ValidationError
3
-
4
- # import unittest
5
-
6
-
7
- # class TestPromptField(unittest.TestCase):
8
-
9
- # def test_numeric_field_valid(self):
10
- # try:
11
- # BasePromptField(name="Age", default="30", field_type=FieldType.NUMERIC)
12
- # self.fail(
13
- # "Expected ValidationError not raised for NUMERIC field with non-numeric default value."
14
- # )
15
- # except ValidationError:
16
- # pass # Expected
17
-
18
- # def test_boolean_field_valid(self):
19
- # try:
20
- # BasePromptField(
21
- # name="Is Adult", default="True", field_type=FieldType.BOOLEAN
22
- # )
23
- # self.fail(
24
- # "Expected ValidationError not raised for BOOLEAN field with non-boolean default value."
25
- # )
26
- # except ValidationError:
27
- # pass # Expected
28
-
29
- # def test_string_field_invalid(self):
30
- # try:
31
- # BasePromptField(name="Name", default=123, field_type=FieldType.STRING)
32
- # self.fail(
33
- # "Expected ValidationError not raised for STRING field with non-string default value."
34
- # )
35
- # except ValidationError:
36
- # pass # Expected
37
-
38
- # def test_datetime_field_invalid(self):
39
- # try:
40
- # BasePromptField(name="Date", default=123, field_type=FieldType.DATETIME)
41
- # self.fail(
42
- # "Expected ValidationError not raised for DATETIME field with non-datetime-compatible default value."
43
- # )
44
- # except ValidationError:
45
- # pass # Expected
46
-
47
-
48
- # if __name__ == "__main__":
49
- # # unittest.main()
50
- # # Running the adjusted tests
51
- # unittest.main(argv=[""], exit=False)