lionagi 0.1.2__py3-none-any.whl → 0.2.1__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 +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)