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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. lionagi/__init__.py +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
@@ -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 +0,0 @@
1
- from .base_agent import BaseAgent
2
-
3
- __all__ = ["BaseAgent"]
@@ -1,38 +1,45 @@
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
  """
4
20
 
5
- from lionagi.core.mail.schema import StartMail
6
- from lionagi.core.schema.base_node import BaseRelatableNode
7
- from lionagi.core.mail.mail_manager import MailManager
21
+ from pydantic import Field
22
+ from typing import Any, Callable
8
23
 
9
24
  from lionagi.libs import func_call, AsyncUtil
10
25
 
11
26
 
12
- class BaseAgent(BaseRelatableNode):
13
- """
14
- A base class for agents.
15
-
16
- Attributes:
17
- structure: The structure of the agent.
18
- executable: The executable object of the agent.
19
- start: The StartMail object for triggering the agent.
20
- mailManager: The MailManager object for managing agent communication.
21
- output_parser: A function for parsing the agent's output (optional).
22
- start_context: The initial context for the agent (optional).
23
-
24
- Methods:
25
- __init__(self, structure, executable_obj, output_parser=None) -> None:
26
- Initializes the BaseAgent instance.
27
+ from lionagi.core.mail.start_mail import StartMail
28
+ from lionagi.core.generic.node import Node
29
+ from lionagi.core.mail.mail_manager import MailManager
30
+ from lionagi.core.executor.base_executor import BaseExecutor
31
+ from lionagi.core.executor.graph_executor import GraphExecutor
27
32
 
28
- async mail_manager_control(self, refresh_time=1) -> None:
29
- Controls the mail manager execution based on the structure and executable states.
30
33
 
31
- async execute(self, context=None) -> Any:
32
- Executes the agent with the given context and returns the parsed output (if available).
33
- """
34
+ class BaseAgent(Node):
34
35
 
35
- def __init__(self, structure, executable_obj, output_parser=None) -> None:
36
+ def __init__(
37
+ self,
38
+ structure: BaseExecutor,
39
+ executable: BaseExecutor,
40
+ output_parser=None,
41
+ **kwargs,
42
+ ) -> None:
36
43
  """
37
44
  Initializes the BaseAgent instance.
38
45
 
@@ -41,13 +48,15 @@ class BaseAgent(BaseRelatableNode):
41
48
  executable_obj: The executable object of the agent.
42
49
  output_parser: A function for parsing the agent's output (optional).
43
50
  """
44
- super().__init__()
45
- self.structure = structure
46
- self.executable = executable_obj
47
- self.start = StartMail()
48
- self.mailManager = MailManager([self.structure, self.executable, self.start])
49
- self.output_parser = output_parser
50
- self.start_context = None
51
+ super().__init__(**kwargs)
52
+ self.structure: BaseExecutor = structure
53
+ self.executable: BaseExecutor = executable
54
+ self.start: StartMail = StartMail()
55
+ self.mail_manager: MailManager = MailManager(
56
+ [self.structure, self.executable, self.start]
57
+ )
58
+ self.output_parser: Callable | None = output_parser
59
+ self.start_context: Any | None = None
51
60
 
52
61
  async def mail_manager_control(self, refresh_time=1):
53
62
  """
@@ -58,7 +67,7 @@ class BaseAgent(BaseRelatableNode):
58
67
  """
59
68
  while not self.structure.execute_stop or not self.executable.execute_stop:
60
69
  await AsyncUtil.sleep(refresh_time)
61
- self.mailManager.execute_stop = True
70
+ self.mail_manager.execute_stop = True
62
71
 
63
72
  async def execute(self, context=None):
64
73
  """
@@ -73,22 +82,22 @@ class BaseAgent(BaseRelatableNode):
73
82
  self.start_context = context
74
83
  self.start.trigger(
75
84
  context=context,
76
- structure_id=self.structure.id_,
77
- executable_id=self.executable.id_,
85
+ structure_id=self.structure.ln_id,
86
+ executable_id=self.executable.ln_id,
78
87
  )
79
88
  await func_call.mcall(
80
89
  [0.1, 0.1, 0.1, 0.1],
81
90
  [
82
91
  self.structure.execute,
83
92
  self.executable.execute,
84
- self.mailManager.execute,
93
+ self.mail_manager.execute,
85
94
  self.mail_manager_control,
86
95
  ],
87
96
  )
88
97
 
89
98
  self.structure.execute_stop = False
90
99
  self.executable.execute_stop = False
91
- self.mailManager.execute_stop = False
100
+ self.mail_manager.execute_stop = False
92
101
 
93
102
  if self.output_parser:
94
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
+ ]