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.
- lionagi/__init__.py +61 -3
- lionagi/core/__init__.py +0 -14
- lionagi/core/_setting/_setting.py +59 -0
- lionagi/core/action/__init__.py +14 -0
- lionagi/core/action/function_calling.py +136 -0
- lionagi/core/action/manual.py +1 -0
- lionagi/core/action/node.py +109 -0
- lionagi/core/action/tool.py +114 -0
- lionagi/core/action/tool_manager.py +356 -0
- lionagi/core/agent/__init__.py +0 -3
- lionagi/core/agent/base_agent.py +45 -36
- lionagi/core/agent/eval/evaluator.py +1 -0
- lionagi/core/agent/eval/vote.py +40 -0
- lionagi/core/agent/learn/learner.py +59 -0
- lionagi/core/agent/plan/unit_template.py +1 -0
- lionagi/core/collections/__init__.py +17 -0
- lionagi/core/collections/_logger.py +319 -0
- lionagi/core/collections/abc/__init__.py +53 -0
- lionagi/core/collections/abc/component.py +615 -0
- lionagi/core/collections/abc/concepts.py +297 -0
- lionagi/core/collections/abc/exceptions.py +150 -0
- lionagi/core/collections/abc/util.py +45 -0
- lionagi/core/collections/exchange.py +161 -0
- lionagi/core/collections/flow.py +426 -0
- lionagi/core/collections/model.py +419 -0
- lionagi/core/collections/pile.py +913 -0
- lionagi/core/collections/progression.py +236 -0
- lionagi/core/collections/util.py +64 -0
- lionagi/core/director/direct.py +314 -0
- lionagi/core/director/director.py +2 -0
- lionagi/core/engine/branch_engine.py +333 -0
- lionagi/core/engine/instruction_map_engine.py +204 -0
- lionagi/core/engine/sandbox_.py +14 -0
- lionagi/core/engine/script_engine.py +99 -0
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/executor/graph_executor.py +330 -0
- lionagi/core/executor/neo4j_executor.py +384 -0
- lionagi/core/generic/__init__.py +7 -0
- lionagi/core/generic/edge.py +112 -0
- lionagi/core/generic/edge_condition.py +16 -0
- lionagi/core/generic/graph.py +236 -0
- lionagi/core/generic/hyperedge.py +1 -0
- lionagi/core/generic/node.py +220 -0
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +7 -3
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +142 -58
- lionagi/core/mail/package.py +45 -0
- lionagi/core/mail/start_mail.py +36 -0
- lionagi/core/message/__init__.py +19 -0
- lionagi/core/message/action_request.py +133 -0
- lionagi/core/message/action_response.py +135 -0
- lionagi/core/message/assistant_response.py +95 -0
- lionagi/core/message/instruction.py +234 -0
- lionagi/core/message/message.py +101 -0
- lionagi/core/message/system.py +86 -0
- lionagi/core/message/util.py +283 -0
- lionagi/core/report/__init__.py +4 -0
- lionagi/core/report/base.py +217 -0
- lionagi/core/report/form.py +231 -0
- lionagi/core/report/report.py +166 -0
- lionagi/core/report/util.py +28 -0
- lionagi/core/rule/__init__.py +0 -0
- lionagi/core/rule/_default.py +16 -0
- lionagi/core/rule/action.py +99 -0
- lionagi/core/rule/base.py +238 -0
- lionagi/core/rule/boolean.py +56 -0
- lionagi/core/rule/choice.py +47 -0
- lionagi/core/rule/mapping.py +96 -0
- lionagi/core/rule/number.py +71 -0
- lionagi/core/rule/rulebook.py +109 -0
- lionagi/core/rule/string.py +52 -0
- lionagi/core/rule/util.py +35 -0
- lionagi/core/session/__init__.py +0 -3
- lionagi/core/session/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +230 -902
- lionagi/core/structure/__init__.py +1 -0
- lionagi/core/structure/chain.py +1 -0
- lionagi/core/structure/forest.py +1 -0
- lionagi/core/structure/graph.py +1 -0
- lionagi/core/structure/tree.py +1 -0
- lionagi/core/unit/__init__.py +5 -0
- lionagi/core/unit/parallel_unit.py +245 -0
- lionagi/core/unit/template/__init__.py +0 -0
- lionagi/core/unit/template/action.py +81 -0
- lionagi/core/unit/template/base.py +51 -0
- lionagi/core/unit/template/plan.py +84 -0
- lionagi/core/unit/template/predict.py +109 -0
- lionagi/core/unit/template/score.py +124 -0
- lionagi/core/unit/template/select.py +104 -0
- lionagi/core/unit/unit.py +362 -0
- lionagi/core/unit/unit_form.py +305 -0
- lionagi/core/unit/unit_mixin.py +1168 -0
- lionagi/core/unit/util.py +71 -0
- lionagi/core/validator/__init__.py +0 -0
- lionagi/core/validator/validator.py +364 -0
- lionagi/core/work/__init__.py +0 -0
- lionagi/core/work/work.py +76 -0
- lionagi/core/work/work_function.py +101 -0
- lionagi/core/work/work_queue.py +103 -0
- lionagi/core/work/worker.py +258 -0
- lionagi/core/work/worklog.py +120 -0
- lionagi/experimental/__init__.py +0 -0
- lionagi/experimental/compressor/__init__.py +0 -0
- lionagi/experimental/compressor/base.py +46 -0
- lionagi/experimental/compressor/llm_compressor.py +247 -0
- lionagi/experimental/compressor/llm_summarizer.py +61 -0
- lionagi/experimental/compressor/util.py +70 -0
- lionagi/experimental/directive/__init__.py +19 -0
- lionagi/experimental/directive/parser/__init__.py +0 -0
- lionagi/experimental/directive/parser/base_parser.py +282 -0
- lionagi/experimental/directive/template/__init__.py +0 -0
- lionagi/experimental/directive/template/base_template.py +79 -0
- lionagi/experimental/directive/template/schema.py +36 -0
- lionagi/experimental/directive/tokenizer.py +73 -0
- lionagi/experimental/evaluator/__init__.py +0 -0
- lionagi/experimental/evaluator/ast_evaluator.py +131 -0
- lionagi/experimental/evaluator/base_evaluator.py +218 -0
- lionagi/experimental/knowledge/__init__.py +0 -0
- lionagi/experimental/knowledge/base.py +10 -0
- lionagi/experimental/knowledge/graph.py +0 -0
- lionagi/experimental/memory/__init__.py +0 -0
- lionagi/experimental/strategies/__init__.py +0 -0
- lionagi/experimental/strategies/base.py +1 -0
- lionagi/integrations/bridge/autogen_/__init__.py +0 -0
- lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
- lionagi/integrations/bridge/langchain_/documents.py +4 -0
- lionagi/integrations/bridge/llamaindex_/index.py +30 -0
- lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +6 -0
- lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
- lionagi/integrations/bridge/llamaindex_/node_parser.py +6 -9
- lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +1 -0
- lionagi/integrations/bridge/transformers_/__init__.py +0 -0
- lionagi/integrations/bridge/transformers_/install_.py +36 -0
- lionagi/integrations/chunker/__init__.py +0 -0
- lionagi/integrations/chunker/chunk.py +312 -0
- lionagi/integrations/config/oai_configs.py +38 -7
- lionagi/integrations/config/ollama_configs.py +1 -1
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/__init__.py +0 -0
- lionagi/integrations/loader/load.py +253 -0
- lionagi/integrations/loader/load_util.py +195 -0
- lionagi/integrations/provider/_mapping.py +46 -0
- lionagi/integrations/provider/litellm.py +2 -1
- lionagi/integrations/provider/mlx_service.py +16 -9
- lionagi/integrations/provider/oai.py +91 -4
- lionagi/integrations/provider/ollama.py +7 -6
- lionagi/integrations/provider/openrouter.py +115 -8
- lionagi/integrations/provider/services.py +2 -2
- lionagi/integrations/provider/transformers.py +18 -22
- lionagi/integrations/storage/__init__.py +3 -0
- lionagi/integrations/storage/neo4j.py +665 -0
- lionagi/integrations/storage/storage_util.py +287 -0
- lionagi/integrations/storage/structure_excel.py +285 -0
- lionagi/integrations/storage/to_csv.py +63 -0
- lionagi/integrations/storage/to_excel.py +83 -0
- lionagi/libs/__init__.py +26 -1
- lionagi/libs/ln_api.py +78 -23
- lionagi/libs/ln_context.py +37 -0
- lionagi/libs/ln_convert.py +21 -9
- lionagi/libs/ln_func_call.py +69 -28
- lionagi/libs/ln_image.py +107 -0
- lionagi/libs/ln_knowledge_graph.py +405 -0
- lionagi/libs/ln_nested.py +26 -11
- lionagi/libs/ln_parse.py +110 -14
- lionagi/libs/ln_queue.py +117 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/{core/prompt/field_validator.py → libs/ln_validate.py} +79 -14
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +107 -2
- lionagi/lions/__init__.py +0 -0
- lionagi/lions/coder/__init__.py +0 -0
- lionagi/lions/coder/add_feature.py +20 -0
- lionagi/lions/coder/base_prompts.py +22 -0
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +168 -0
- lionagi/lions/coder/util.py +96 -0
- lionagi/lions/researcher/__init__.py +0 -0
- lionagi/lions/researcher/data_source/__init__.py +0 -0
- lionagi/lions/researcher/data_source/finhub_.py +191 -0
- lionagi/lions/researcher/data_source/google_.py +199 -0
- lionagi/lions/researcher/data_source/wiki_.py +96 -0
- lionagi/lions/researcher/data_source/yfinance_.py +21 -0
- lionagi/tests/integrations/__init__.py +0 -0
- lionagi/tests/libs/__init__.py +0 -0
- lionagi/tests/libs/test_field_validators.py +353 -0
- lionagi/tests/{test_libs → libs}/test_func_call.py +23 -21
- lionagi/tests/{test_libs → libs}/test_nested.py +36 -21
- lionagi/tests/{test_libs → libs}/test_parse.py +1 -1
- lionagi/tests/libs/test_queue.py +67 -0
- lionagi/tests/test_core/collections/__init__.py +0 -0
- lionagi/tests/test_core/collections/test_component.py +206 -0
- lionagi/tests/test_core/collections/test_exchange.py +138 -0
- lionagi/tests/test_core/collections/test_flow.py +145 -0
- lionagi/tests/test_core/collections/test_pile.py +171 -0
- lionagi/tests/test_core/collections/test_progression.py +129 -0
- lionagi/tests/test_core/generic/__init__.py +0 -0
- lionagi/tests/test_core/generic/test_edge.py +67 -0
- lionagi/tests/test_core/generic/test_graph.py +96 -0
- lionagi/tests/test_core/generic/test_node.py +106 -0
- lionagi/tests/test_core/generic/test_tree_node.py +73 -0
- lionagi/tests/test_core/test_branch.py +115 -292
- lionagi/tests/test_core/test_form.py +46 -0
- lionagi/tests/test_core/test_report.py +105 -0
- lionagi/tests/test_core/test_validator.py +111 -0
- lionagi/version.py +1 -1
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/LICENSE +12 -11
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/METADATA +19 -118
- lionagi-0.2.1.dist-info/RECORD +240 -0
- lionagi/core/branch/__init__.py +0 -4
- lionagi/core/branch/base_branch.py +0 -654
- lionagi/core/branch/branch.py +0 -471
- lionagi/core/branch/branch_flow_mixin.py +0 -96
- lionagi/core/branch/executable_branch.py +0 -347
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -6
- lionagi/core/direct/predict.py +0 -161
- lionagi/core/direct/score.py +0 -278
- lionagi/core/direct/select.py +0 -169
- lionagi/core/direct/utils.py +0 -87
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/flow/base/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -238
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -263
- lionagi/core/flow/monoflow/followup.py +0 -214
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -248
- lionagi/core/mail/schema.py +0 -56
- lionagi/core/messages/__init__.py +0 -3
- lionagi/core/messages/schema.py +0 -533
- lionagi/core/prompt/prompt_template.py +0 -316
- lionagi/core/schema/__init__.py +0 -22
- lionagi/core/schema/action_node.py +0 -29
- lionagi/core/schema/base_mixin.py +0 -296
- lionagi/core/schema/base_node.py +0 -199
- lionagi/core/schema/condition.py +0 -24
- lionagi/core/schema/data_logger.py +0 -354
- lionagi/core/schema/data_node.py +0 -93
- lionagi/core/schema/prompt_template.py +0 -67
- lionagi/core/schema/structure.py +0 -910
- lionagi/core/tool/__init__.py +0 -3
- lionagi/core/tool/tool_manager.py +0 -280
- lionagi/integrations/bridge/pydantic_/base_model.py +0 -7
- lionagi/tests/test_core/test_base_branch.py +0 -427
- lionagi/tests/test_core/test_chat_flow.py +0 -63
- lionagi/tests/test_core/test_mail_manager.py +0 -75
- lionagi/tests/test_core/test_prompts.py +0 -51
- lionagi/tests/test_core/test_session.py +0 -254
- lionagi/tests/test_core/test_session_base_util.py +0 -312
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.0.312.dist-info/RECORD +0 -111
- /lionagi/core/{branch/base → _setting}/__init__.py +0 -0
- /lionagi/core/{flow → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow/base → agent/learn}/__init__.py +0 -0
- /lionagi/core/{prompt → agent/plan}/__init__.py +0 -0
- /lionagi/core/{tool/manual.py → agent/plan/plan.py} +0 -0
- /lionagi/{tests/test_integrations → core/director}/__init__.py +0 -0
- /lionagi/{tests/test_libs → core/engine}/__init__.py +0 -0
- /lionagi/{tests/test_libs/test_async.py → core/executor/__init__.py} +0 -0
- /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
- /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
- {lionagi-0.0.312.dist-info → lionagi-0.2.1.dist-info}/WHEEL +0 -0
- {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
|
lionagi/core/agent/__init__.py
CHANGED
lionagi/core/agent/base_agent.py
CHANGED
@@ -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
|
6
|
-
from
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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__(
|
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 =
|
47
|
-
self.start = StartMail()
|
48
|
-
self.
|
49
|
-
|
50
|
-
|
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.
|
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.
|
77
|
-
executable_id=self.executable.
|
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.
|
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.
|
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
|
+
]
|