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