lionagi 0.1.2__py3-none-any.whl → 0.2.0__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 +74 -0
  94. lionagi/core/work/work_function.py +92 -0
  95. lionagi/core/work/work_queue.py +81 -0
  96. lionagi/core/work/worker.py +195 -0
  97. lionagi/core/work/worklog.py +124 -0
  98. lionagi/experimental/compressor/base.py +46 -0
  99. lionagi/experimental/compressor/llm_compressor.py +247 -0
  100. lionagi/experimental/compressor/llm_summarizer.py +61 -0
  101. lionagi/experimental/compressor/util.py +70 -0
  102. lionagi/experimental/directive/__init__.py +19 -0
  103. lionagi/experimental/directive/parser/base_parser.py +69 -2
  104. lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
  105. lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
  106. lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
  107. lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
  108. lionagi/experimental/knowledge/base.py +10 -0
  109. lionagi/experimental/memory/__init__.py +0 -0
  110. lionagi/experimental/strategies/__init__.py +0 -0
  111. lionagi/experimental/strategies/base.py +1 -0
  112. lionagi/integrations/bridge/langchain_/documents.py +4 -0
  113. lionagi/integrations/bridge/llamaindex_/index.py +30 -0
  114. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
  115. lionagi/integrations/chunker/chunk.py +161 -24
  116. lionagi/integrations/config/oai_configs.py +34 -3
  117. lionagi/integrations/config/openrouter_configs.py +14 -2
  118. lionagi/integrations/loader/load.py +122 -21
  119. lionagi/integrations/loader/load_util.py +6 -77
  120. lionagi/integrations/provider/_mapping.py +46 -0
  121. lionagi/integrations/provider/litellm.py +2 -1
  122. lionagi/integrations/provider/mlx_service.py +16 -9
  123. lionagi/integrations/provider/oai.py +91 -4
  124. lionagi/integrations/provider/ollama.py +6 -5
  125. lionagi/integrations/provider/openrouter.py +115 -8
  126. lionagi/integrations/provider/services.py +2 -2
  127. lionagi/integrations/provider/transformers.py +18 -22
  128. lionagi/integrations/storage/__init__.py +3 -3
  129. lionagi/integrations/storage/neo4j.py +52 -60
  130. lionagi/integrations/storage/storage_util.py +44 -46
  131. lionagi/integrations/storage/structure_excel.py +43 -26
  132. lionagi/integrations/storage/to_excel.py +11 -4
  133. lionagi/libs/__init__.py +22 -1
  134. lionagi/libs/ln_api.py +75 -20
  135. lionagi/libs/ln_context.py +37 -0
  136. lionagi/libs/ln_convert.py +21 -9
  137. lionagi/libs/ln_func_call.py +69 -28
  138. lionagi/libs/ln_image.py +107 -0
  139. lionagi/libs/ln_nested.py +26 -11
  140. lionagi/libs/ln_parse.py +82 -23
  141. lionagi/libs/ln_queue.py +16 -0
  142. lionagi/libs/ln_tokenize.py +164 -0
  143. lionagi/libs/ln_validate.py +16 -0
  144. lionagi/libs/special_tokens.py +172 -0
  145. lionagi/libs/sys_util.py +95 -24
  146. lionagi/lions/coder/code_form.py +13 -0
  147. lionagi/lions/coder/coder.py +50 -3
  148. lionagi/lions/coder/util.py +30 -25
  149. lionagi/tests/libs/test_func_call.py +23 -21
  150. lionagi/tests/libs/test_nested.py +36 -21
  151. lionagi/tests/libs/test_parse.py +1 -1
  152. lionagi/tests/test_core/collections/__init__.py +0 -0
  153. lionagi/tests/test_core/collections/test_component.py +206 -0
  154. lionagi/tests/test_core/collections/test_exchange.py +138 -0
  155. lionagi/tests/test_core/collections/test_flow.py +145 -0
  156. lionagi/tests/test_core/collections/test_pile.py +171 -0
  157. lionagi/tests/test_core/collections/test_progression.py +129 -0
  158. lionagi/tests/test_core/generic/test_edge.py +67 -0
  159. lionagi/tests/test_core/generic/test_graph.py +96 -0
  160. lionagi/tests/test_core/generic/test_node.py +106 -0
  161. lionagi/tests/test_core/generic/test_tree_node.py +73 -0
  162. lionagi/tests/test_core/test_branch.py +115 -294
  163. lionagi/tests/test_core/test_form.py +46 -0
  164. lionagi/tests/test_core/test_report.py +105 -0
  165. lionagi/tests/test_core/test_validator.py +111 -0
  166. lionagi/version.py +1 -1
  167. lionagi-0.2.0.dist-info/LICENSE +202 -0
  168. lionagi-0.2.0.dist-info/METADATA +272 -0
  169. lionagi-0.2.0.dist-info/RECORD +240 -0
  170. lionagi/core/branch/base.py +0 -653
  171. lionagi/core/branch/branch.py +0 -474
  172. lionagi/core/branch/flow_mixin.py +0 -96
  173. lionagi/core/branch/util.py +0 -323
  174. lionagi/core/direct/__init__.py +0 -19
  175. lionagi/core/direct/cot.py +0 -123
  176. lionagi/core/direct/plan.py +0 -164
  177. lionagi/core/direct/predict.py +0 -166
  178. lionagi/core/direct/react.py +0 -171
  179. lionagi/core/direct/score.py +0 -279
  180. lionagi/core/direct/select.py +0 -170
  181. lionagi/core/direct/sentiment.py +0 -1
  182. lionagi/core/direct/utils.py +0 -110
  183. lionagi/core/direct/vote.py +0 -64
  184. lionagi/core/execute/base_executor.py +0 -47
  185. lionagi/core/flow/baseflow.py +0 -23
  186. lionagi/core/flow/monoflow/ReAct.py +0 -240
  187. lionagi/core/flow/monoflow/__init__.py +0 -9
  188. lionagi/core/flow/monoflow/chat.py +0 -95
  189. lionagi/core/flow/monoflow/chat_mixin.py +0 -253
  190. lionagi/core/flow/monoflow/followup.py +0 -215
  191. lionagi/core/flow/polyflow/__init__.py +0 -1
  192. lionagi/core/flow/polyflow/chat.py +0 -251
  193. lionagi/core/form/action_form.py +0 -26
  194. lionagi/core/form/field_validator.py +0 -287
  195. lionagi/core/form/form.py +0 -302
  196. lionagi/core/form/mixin.py +0 -214
  197. lionagi/core/form/scored_form.py +0 -13
  198. lionagi/core/generic/action.py +0 -26
  199. lionagi/core/generic/component.py +0 -532
  200. lionagi/core/generic/condition.py +0 -46
  201. lionagi/core/generic/mail.py +0 -90
  202. lionagi/core/generic/mailbox.py +0 -36
  203. lionagi/core/generic/relation.py +0 -70
  204. lionagi/core/generic/signal.py +0 -22
  205. lionagi/core/generic/structure.py +0 -362
  206. lionagi/core/generic/transfer.py +0 -20
  207. lionagi/core/generic/work.py +0 -40
  208. lionagi/core/graph/graph.py +0 -126
  209. lionagi/core/graph/tree.py +0 -190
  210. lionagi/core/mail/schema.py +0 -63
  211. lionagi/core/messages/schema.py +0 -325
  212. lionagi/core/tool/__init__.py +0 -5
  213. lionagi/core/tool/tool.py +0 -28
  214. lionagi/core/tool/tool_manager.py +0 -283
  215. lionagi/experimental/report/form.py +0 -64
  216. lionagi/experimental/report/report.py +0 -138
  217. lionagi/experimental/report/util.py +0 -47
  218. lionagi/experimental/tool/function_calling.py +0 -43
  219. lionagi/experimental/tool/manual.py +0 -66
  220. lionagi/experimental/tool/schema.py +0 -59
  221. lionagi/experimental/tool/tool_manager.py +0 -138
  222. lionagi/experimental/tool/util.py +0 -16
  223. lionagi/experimental/validator/rule.py +0 -139
  224. lionagi/experimental/validator/validator.py +0 -56
  225. lionagi/experimental/work/__init__.py +0 -10
  226. lionagi/experimental/work/async_queue.py +0 -54
  227. lionagi/experimental/work/schema.py +0 -73
  228. lionagi/experimental/work/work_function.py +0 -67
  229. lionagi/experimental/work/worker.py +0 -56
  230. lionagi/experimental/work2/form.py +0 -371
  231. lionagi/experimental/work2/report.py +0 -289
  232. lionagi/experimental/work2/schema.py +0 -30
  233. lionagi/experimental/work2/tests.py +0 -72
  234. lionagi/experimental/work2/work_function.py +0 -89
  235. lionagi/experimental/work2/worker.py +0 -12
  236. lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
  237. lionagi/tests/test_core/generic/test_component.py +0 -89
  238. lionagi/tests/test_core/test_base_branch.py +0 -426
  239. lionagi/tests/test_core/test_chat_flow.py +0 -63
  240. lionagi/tests/test_core/test_mail_manager.py +0 -75
  241. lionagi/tests/test_core/test_prompts.py +0 -51
  242. lionagi/tests/test_core/test_session.py +0 -254
  243. lionagi/tests/test_core/test_session_base_util.py +0 -313
  244. lionagi/tests/test_core/test_tool_manager.py +0 -95
  245. lionagi-0.1.2.dist-info/LICENSE +0 -9
  246. lionagi-0.1.2.dist-info/METADATA +0 -174
  247. lionagi-0.1.2.dist-info/RECORD +0 -206
  248. /lionagi/core/{branch → _setting}/__init__.py +0 -0
  249. /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
  250. /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
  251. /lionagi/core/{form → agent/plan}/__init__.py +0 -0
  252. /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
  253. /lionagi/core/{graph → director}/__init__.py +0 -0
  254. /lionagi/core/{messages → engine}/__init__.py +0 -0
  255. /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
  256. /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
  257. /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
  258. /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
  259. /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
  260. /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
  261. /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
  262. /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
  263. /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
  264. /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
  265. /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
  266. /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
  267. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/WHEEL +0 -0
  268. {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,356 @@
1
+ """
2
+ Copyright 2024 HaiyangLi
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
16
+
17
+ """
18
+ This module contains the ToolManager class, which manages tools in the system.
19
+ It allows registering, invoking, and retrieving schemas of tools. Tools can be
20
+ registered individually or in batches, and invoked using function names, JSON
21
+ strings, or specialized objects.
22
+ """
23
+
24
+ import inspect
25
+ from functools import singledispatchmethod
26
+ from typing import Any, Callable, List, Union, Tuple
27
+ from lionagi.libs import ParseUtil
28
+ from lionagi.libs.ln_convert import to_list, to_dict
29
+ from lionagi.libs.ln_func_call import lcall
30
+ from lionagi.core.collections.abc import Actionable
31
+ from lionagi.core.action.function_calling import FunctionCalling
32
+ from lionagi.core.action.tool import Tool, TOOL_TYPE
33
+
34
+
35
+ class ToolManager(Actionable):
36
+ """
37
+ Manages tools in the system. Provides functionality to register tools,
38
+ invoke them based on various input formats, and retrieve tool schemas.
39
+ """
40
+
41
+ def __init__(self, registry: dict[str, Tool] = None) -> None:
42
+ """
43
+ Initializes a new instance of ToolManager.
44
+
45
+ Args:
46
+ registry (dict[str, Tool], optional): A dictionary to store registered tools.
47
+ Defaults to an empty dictionary.
48
+ """
49
+ self.registry = registry or {}
50
+
51
+ def __contains__(self, tool) -> bool:
52
+ if isinstance(tool, Tool):
53
+ return tool.name in self.registry
54
+
55
+ elif isinstance(tool, str):
56
+ return tool in self.registry
57
+
58
+ elif inspect.isfunction(tool):
59
+ return tool.__name__ in self.registry
60
+
61
+ return False
62
+
63
+ def _register_tool(self, tool: Tool | Callable, update: bool = False) -> bool:
64
+ """
65
+ Registers a single tool or multiple tools based on the input type.
66
+
67
+ Args:
68
+ tool (Any): Can be a single Tool, a list of Tools, a callable, or other forms.
69
+
70
+ Raises:
71
+ TypeError: If the tools argument type is unsupported.
72
+ """
73
+ if not update and tool in self:
74
+ raise ValueError(f"Function {tool.name} is already registered.")
75
+ if isinstance(tool, Callable):
76
+ tool = func_to_tool(tool)
77
+ tool = tool[0] if isinstance(tool, list) and len(tool) == 1 else tool
78
+ if not isinstance(tool, Tool):
79
+ raise TypeError("Please register a Tool object.")
80
+ self.registry[tool.name] = tool
81
+ return True
82
+
83
+ def update_tools(self, tools: list | Tool | Callable):
84
+ if isinstance(tools, Tool) or isinstance(tools, Callable):
85
+ return self._register_tool(tools, update=True)
86
+ else:
87
+ return all(lcall(tools, self._register_tool, update=True))
88
+
89
+ def register_tools(self, tools: list | Tool | Callable):
90
+ """
91
+ Registers multiple Tools.
92
+
93
+ Args:
94
+ tools (list): The list of Tools to register.
95
+
96
+ Returns:
97
+ bool: True if all tools are successfully registered.
98
+ """
99
+ if isinstance(tools, Tool) or isinstance(tools, Callable):
100
+ return self._register_tool(tools)
101
+ else:
102
+ return all(lcall(tools, self._register_tool))
103
+
104
+ async def invoke(self, func_calling=None):
105
+ """
106
+ Invokes a function based on the provided function calling description.
107
+
108
+ Args:
109
+ func_calling (Any, optional): The function calling description, which can be:
110
+ - tuple: (name, kwargs)
111
+ - dict: {"function": name, "arguments": kwargs}
112
+ - str: JSON string of dict format
113
+ - ActionRequest object
114
+ - FunctionCalling object
115
+
116
+ Returns:
117
+ Any: The result of the function call.
118
+
119
+ Raises:
120
+ ValueError: If func_calling is None or the function is not registered.
121
+ """
122
+ if not func_calling:
123
+ raise ValueError("func_calling is required.")
124
+
125
+ if not isinstance(func_calling, FunctionCalling):
126
+ func_calling = FunctionCalling.create(func_calling)
127
+
128
+ if func_calling.func_name in self.registry:
129
+ return await self.registry[func_calling.func_name].invoke(
130
+ func_calling=func_calling
131
+ )
132
+
133
+ raise ValueError(f"Function {func_calling.func_name} is not registered.")
134
+
135
+ @property
136
+ def _schema_list(self) -> list[dict[str, Any]]:
137
+ """
138
+ Lists all tool schemas currently registered in the ToolManager.
139
+
140
+ Returns:
141
+ list[dict[str, Any]]: A list of tool schemas.
142
+ """
143
+ return [tool.schema_ for tool in self.registry.values()]
144
+
145
+ def get_tool_schema(self, tools: TOOL_TYPE, **kwargs) -> dict:
146
+ """
147
+ Retrieves the schema for a specific tool or all tools based on the input.
148
+
149
+ Args:
150
+ tools (TOOL_TYPE): Can be a boolean, specific tool name, Tool, or list of tools.
151
+ **kwargs: Additional keyword arguments to be merged with tool schema.
152
+
153
+ Returns:
154
+ dict: Combined tool schema and kwargs.
155
+ """
156
+ if isinstance(tools, bool):
157
+ tool_kwarg = {"tools": self._schema_list}
158
+ return tool_kwarg | kwargs
159
+
160
+ else:
161
+ tool_kwarg = {"tools": self._get_tool_schema(tools)}
162
+ return tool_kwarg | kwargs
163
+
164
+ @singledispatchmethod
165
+ def _get_tool_schema(self, tool: Any) -> dict:
166
+ """
167
+ Retrieves the schema for a specific tool based on its type.
168
+
169
+ Args:
170
+ tool (Any): The tool descriptor, can be a dict, Tool, str, or list.
171
+
172
+ Raises:
173
+ TypeError: If the tool type is unsupported.
174
+ """
175
+ raise TypeError(f"Unsupported type {type(tool)}")
176
+
177
+ @_get_tool_schema.register(dict)
178
+ def _(self, tool):
179
+ """
180
+ Assumes that the tool is a schema and returns it.
181
+
182
+ Args:
183
+ tool (dict): The tool schema.
184
+
185
+ Returns:
186
+ dict: The tool schema.
187
+ """
188
+ return tool
189
+
190
+ @_get_tool_schema.register(Tool)
191
+ def _(self, tool):
192
+ """
193
+ Retrieves the schema for a Tool object.
194
+
195
+ Args:
196
+ tool (Tool): The Tool object.
197
+
198
+ Returns:
199
+ dict: The tool schema.
200
+
201
+ Raises:
202
+ ValueError: If the Tool is not registered.
203
+ """
204
+ if tool.name in self.registry:
205
+ return self.registry[tool.name].schema_
206
+ else:
207
+ err_msg = f"Function {tool.name} is not registered."
208
+ raise ValueError(err_msg)
209
+
210
+ @_get_tool_schema.register(str)
211
+ def _(self, tool):
212
+ """
213
+ Assumes that the tool is a name and retrieves its schema.
214
+
215
+ Args:
216
+ tool (str): The tool name.
217
+
218
+ Returns:
219
+ dict: The tool schema.
220
+
221
+ Raises:
222
+ ValueError: If the tool name is not registered.
223
+ """
224
+ if tool in self.registry:
225
+ return self.registry[tool].schema_
226
+ else:
227
+ err_msg = f"Function {tool} is not registered."
228
+ raise ValueError(err_msg)
229
+
230
+ @_get_tool_schema.register(list)
231
+ def _(self, tools):
232
+ """
233
+ Retrieves the schema for a list of tools.
234
+
235
+ Args:
236
+ tools (list): The list of tools.
237
+
238
+ Returns:
239
+ list: A list of tool schemas.
240
+ """
241
+ return lcall(tools, self._get_tool_schema)
242
+
243
+ def parse_tool(self, tools: TOOL_TYPE, **kwargs) -> dict:
244
+ """
245
+ Parses and merges tool schemas based on the provided tool descriptors.
246
+
247
+ Args:
248
+ tools (TOOL_TYPE): The tools to parse, can be a single tool or list.
249
+ **kwargs: Additional keyword arguments to be merged with the tool schema.
250
+
251
+ Returns:
252
+ dict: The merged tool schema and additional arguments.
253
+ """
254
+ if tools:
255
+ if isinstance(tools, bool):
256
+ tool_kwarg = {"tools": self._schema_list}
257
+ kwargs = tool_kwarg | kwargs
258
+ else:
259
+ tools = to_list(tools) if not isinstance(tools, list) else [tools]
260
+ tool_kwarg = {"tools": lcall(tools, self._get_tool_schema)}
261
+ kwargs = tool_kwarg | kwargs
262
+
263
+ return kwargs
264
+
265
+ @staticmethod
266
+ def parse_tool_request(response: dict) -> Tuple[str, dict]:
267
+ """
268
+ Parses a tool request from a given response dictionary.
269
+
270
+ Args:
271
+ response (dict): The response data containing the tool request.
272
+
273
+ Returns:
274
+ Tuple[str, dict]: The function name and its arguments.
275
+
276
+ Raises:
277
+ ValueError: If the response is not a valid function call.
278
+ """
279
+ try:
280
+ func = response["action"][7:]
281
+ args = to_dict(response["arguments"])
282
+ return func, args
283
+ except Exception:
284
+ try:
285
+ func = response["recipient_name"].split(".")[-1]
286
+ args = response["parameters"]
287
+ return func, args
288
+ except:
289
+ raise ValueError("response is not a valid function call")
290
+
291
+
292
+ def func_to_tool(
293
+ func_: Union[Callable, List[Callable]],
294
+ parser: Union[Callable, List[Callable]] = None,
295
+ docstring_style: str = "google",
296
+ **kwargs,
297
+ ) -> List[Tool]:
298
+ """
299
+ Converts functions to Tool objects, optionally associating parsers with each function
300
+ and applying a specified docstring parsing style to generate tool schemas.
301
+
302
+ Args:
303
+ func_ (Callable | list[Callable]): The function(s) to convert into tool(s).
304
+ parser (Callable | list[Callable], optional): Parser(s) to associate with
305
+ the function(s). If a list is provided, it should match the length of func_.
306
+ docstring_style (str, optional): The style of the docstring parser to use when
307
+ generating tool schemas. Defaults to "google".
308
+
309
+ Returns:
310
+ list[Tool]: A list of Tool objects created from the provided function(s).
311
+
312
+ Raises:
313
+ ValueError: If the length of the parsers does not match the length of the
314
+ functions when both are provided as lists.
315
+
316
+ Examples:
317
+ # Convert a single function with a custom parser
318
+ tools = func_to_tool(my_function, my_parser)
319
+
320
+ # Convert multiple functions without parsers
321
+ tools = func_to_tool([func_one, func_two])
322
+
323
+ # Convert multiple functions with multiple parsers
324
+ tools = func_to_tool([func_one, func_two], [parser_one, parser_two])
325
+ """
326
+ fs = []
327
+ funcs = to_list(func_, flatten=True, dropna=True)
328
+ parsers = to_list(parser, flatten=True, dropna=True)
329
+
330
+ if parser:
331
+ if len(funcs) != len(parsers) != 1:
332
+ raise ValueError(
333
+ "Length of parser must match length of func. Except if you only pass one"
334
+ )
335
+
336
+ for idx in range(len(funcs)):
337
+ f_ = lambda _f: Tool(
338
+ function=_f,
339
+ schema_=ParseUtil._func_to_schema(_f, style=docstring_style),
340
+ parser=parsers[idx] if len(parsers) > 1 else parsers[0],
341
+ **kwargs,
342
+ )
343
+
344
+ fs.append(f_)
345
+
346
+ else:
347
+ fs = lcall(
348
+ funcs,
349
+ lambda _f: Tool(
350
+ function=_f,
351
+ schema_=ParseUtil._func_to_schema(_f, style=docstring_style),
352
+ **kwargs,
353
+ ),
354
+ )
355
+
356
+ return fs
@@ -1,3 +1,19 @@
1
+ """
2
+ Copyright 2024 HaiyangLi
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
16
+
1
17
  """
2
18
  This module contains the BaseAgent class, which serves as a base class for agents.
3
19
  """
@@ -8,11 +24,11 @@ from typing import Any, Callable
8
24
  from lionagi.libs import func_call, AsyncUtil
9
25
 
10
26
 
11
- from lionagi.core.mail.schema import StartMail
12
- from lionagi.core.generic import Node
27
+ from lionagi.core.mail.start_mail import StartMail
28
+ from lionagi.core.generic.node import Node
13
29
  from lionagi.core.mail.mail_manager import MailManager
14
- from lionagi.core.execute.base_executor import BaseExecutor
15
- from lionagi.core.execute.structure_executor import StructureExecutor
30
+ from lionagi.core.executor.base_executor import BaseExecutor
31
+ from lionagi.core.executor.graph_executor import GraphExecutor
16
32
 
17
33
 
18
34
  class BaseAgent(Node):
@@ -32,13 +48,11 @@ class BaseAgent(Node):
32
48
  executable_obj: The executable object of the agent.
33
49
  output_parser: A function for parsing the agent's output (optional).
34
50
  """
35
- super().__init__()
51
+ super().__init__(**kwargs)
36
52
  self.structure: BaseExecutor = structure
37
53
  self.executable: BaseExecutor = executable
38
- for v, k in kwargs.items():
39
- executable.__setattr__(v, k)
40
54
  self.start: StartMail = StartMail()
41
- self.mailManager: MailManager = MailManager(
55
+ self.mail_manager: MailManager = MailManager(
42
56
  [self.structure, self.executable, self.start]
43
57
  )
44
58
  self.output_parser: Callable | None = output_parser
@@ -53,7 +67,7 @@ class BaseAgent(Node):
53
67
  """
54
68
  while not self.structure.execute_stop or not self.executable.execute_stop:
55
69
  await AsyncUtil.sleep(refresh_time)
56
- self.mailManager.execute_stop = True
70
+ self.mail_manager.execute_stop = True
57
71
 
58
72
  async def execute(self, context=None):
59
73
  """
@@ -68,22 +82,22 @@ class BaseAgent(Node):
68
82
  self.start_context = context
69
83
  self.start.trigger(
70
84
  context=context,
71
- structure_id=self.structure.id_,
72
- executable_id=self.executable.id_,
85
+ structure_id=self.structure.ln_id,
86
+ executable_id=self.executable.ln_id,
73
87
  )
74
88
  await func_call.mcall(
75
89
  [0.1, 0.1, 0.1, 0.1],
76
90
  [
77
91
  self.structure.execute,
78
92
  self.executable.execute,
79
- self.mailManager.execute,
93
+ self.mail_manager.execute,
80
94
  self.mail_manager_control,
81
95
  ],
82
96
  )
83
97
 
84
98
  self.structure.execute_stop = False
85
99
  self.executable.execute_stop = False
86
- self.mailManager.execute_stop = False
100
+ self.mail_manager.execute_stop = False
87
101
 
88
102
  if self.output_parser:
89
103
  return self.output_parser(self)
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,40 @@
1
+ # TODO
2
+
3
+ # from lionagi.libs import func_call
4
+ # import numpy as np
5
+ # from lionagi.core.form.predict import predict
6
+ # from lionagi.core.form.score import score
7
+
8
+
9
+ # async def vote(
10
+ # sentence,
11
+ # directive=predict,
12
+ # num_generations=5,
13
+ # num_output=1,
14
+ # num_scorer=5,
15
+ # score_range=(0, 100),
16
+ # num_digit=2,
17
+ # scorer_instruction=None,
18
+ # **kwargs,
19
+ # ):
20
+ # async def _inner(i):
21
+ # out_ = await directive(sentence, **kwargs)
22
+ # score_ = await score(
23
+ # out_.answer,
24
+ # context=sentence,
25
+ # instruction=scorer_instruction,
26
+ # score_range=score_range,
27
+ # num_digit=num_digit,
28
+ # num_instances=num_scorer,
29
+ # return_template=False,
30
+ # )
31
+
32
+ # out_.__setattr__("score", score_)
33
+ # return out_
34
+
35
+ # _outs = await func_call.alcall(list(range(num_generations)), _inner)
36
+
37
+ # top_index = np.argsort([i.score for i in _outs])[-num_output:]
38
+ # final_output = list(np.array(_outs)[top_index])
39
+
40
+ # return final_output[0] if len(final_output) == 1 else final_output
@@ -0,0 +1,59 @@
1
+ # class LearningFramework:
2
+ # def __init__(self, learning_model: Any, learning_service: Any):
3
+ # self.learning_model = learning_model
4
+ # self.learning_service = learning_service
5
+
6
+ # async def learn_from_interaction(self, interaction_data: Dict[str, Any]) -> None:
7
+ # """
8
+ # Update the learning model based on interaction data.
9
+ # """
10
+ # # Update the embedded model
11
+ # self.learning_model.update(interaction_data)
12
+
13
+ # # Optionally send data to an external learning provider
14
+ # await self.learning_service.send_data_for_learning(interaction_data)
15
+
16
+ # async def adapt_response_strategy(self, context: Dict[str, Any]) -> Dict[str, Any]:
17
+ # """
18
+ # Adapt the assistant_response strategy based on learned patterns and context.
19
+ # """
20
+ # # Use the learning model to determine the adaptation strategy
21
+ # adaptation_strategy = self.learning_model.determine_strategy(context)
22
+ # return adaptation_strategy
23
+
24
+
25
+ # class LearningAgent(TaskAgent):
26
+ # def __init__(
27
+ # self, name: Optional[str] = None, learning_model: Optional[Any] = None
28
+ # ):
29
+ # super().__init__(name)
30
+ # self.learning_model = learning_model
31
+
32
+ # async def learn_from_interaction(self, interaction_data: Any):
33
+ # """
34
+ # Update the learning model based on interaction data.
35
+ # This method should be implemented to integrate specific learning algorithms.
36
+ # """
37
+ # if self.learning_model:
38
+ # # Placeholder for learning logic. Implement learning model updates based on interaction data.
39
+ # print("Learning from interaction...")
40
+
41
+ # async def adapt_response_strategy(self, instruction: Any) -> Any:
42
+ # """
43
+ # Adapt the assistant_response strategy based on what has been learned.
44
+ # Override this method to implement adaptive assistant_response strategies.
45
+ # """
46
+ # # Example implementation. Use the learning model to adapt the assistant_response strategy.
47
+ # print("Adapting assistant_response strategy based on learned patterns...")
48
+ # # Placeholder for demonstration. Implement adaptive assistant_response generation based on the learning model.
49
+ # return "Adapted assistant_response based on learning."
50
+
51
+ # async def process_instruction(self, instruction: Any) -> Any:
52
+ # """
53
+ # Process instruction with learning and adaptation.
54
+ # """
55
+ # # Incorporate learning into the instruction processing.
56
+ # response = await super().process_instruction(instruction)
57
+ # await self.learn_from_interaction(instruction)
58
+ # adapted_response = await self.adapt_response_strategy(instruction)
59
+ # return adapted_response
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,17 @@
1
+ from .model import iModel
2
+ from .pile import Pile, pile
3
+ from .progression import Progression, progression
4
+ from .flow import Flow, flow
5
+ from .exchange import Exchange
6
+
7
+
8
+ __all__ = [
9
+ "iModel",
10
+ "Pile",
11
+ "pile",
12
+ "Progression",
13
+ "progression",
14
+ "Flow",
15
+ "flow",
16
+ "Exchange",
17
+ ]