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.
- lionagi/__init__.py +60 -5
- lionagi/core/__init__.py +0 -25
- 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/base_agent.py +27 -13
- 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/{generic/data_logger.py → collections/_logger.py} +69 -55
- 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/{execute/branch_executor.py → engine/branch_engine.py} +134 -97
- lionagi/core/{execute/instruction_map_executor.py → engine/instruction_map_engine.py} +80 -55
- lionagi/{experimental/directive/evaluator → core/engine}/script_engine.py +17 -1
- lionagi/core/executor/base_executor.py +90 -0
- lionagi/core/{execute/structure_executor.py → executor/graph_executor.py} +62 -66
- lionagi/core/{execute → executor}/neo4j_executor.py +70 -67
- lionagi/core/generic/__init__.py +3 -33
- lionagi/core/generic/edge.py +29 -79
- 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 +156 -221
- lionagi/core/generic/tree.py +48 -0
- lionagi/core/generic/tree_node.py +79 -0
- lionagi/core/mail/__init__.py +12 -0
- lionagi/core/mail/mail.py +25 -0
- lionagi/core/mail/mail_manager.py +139 -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/_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/branch.py +431 -0
- lionagi/core/session/directive_mixin.py +287 -0
- lionagi/core/session/session.py +229 -903
- 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/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/validator.py +364 -0
- lionagi/core/work/work.py +74 -0
- lionagi/core/work/work_function.py +92 -0
- lionagi/core/work/work_queue.py +81 -0
- lionagi/core/work/worker.py +195 -0
- lionagi/core/work/worklog.py +124 -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/base_parser.py +69 -2
- lionagi/experimental/directive/{template_ → template}/base_template.py +17 -1
- lionagi/{libs/ln_tokenizer.py → experimental/directive/tokenizer.py} +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/ast_evaluator.py +16 -0
- lionagi/experimental/{directive/evaluator → evaluator}/base_evaluator.py +16 -0
- lionagi/experimental/knowledge/base.py +10 -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/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/chunker/chunk.py +161 -24
- lionagi/integrations/config/oai_configs.py +34 -3
- lionagi/integrations/config/openrouter_configs.py +14 -2
- lionagi/integrations/loader/load.py +122 -21
- lionagi/integrations/loader/load_util.py +6 -77
- 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 +6 -5
- 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 -3
- lionagi/integrations/storage/neo4j.py +52 -60
- lionagi/integrations/storage/storage_util.py +44 -46
- lionagi/integrations/storage/structure_excel.py +43 -26
- lionagi/integrations/storage/to_excel.py +11 -4
- lionagi/libs/__init__.py +22 -1
- lionagi/libs/ln_api.py +75 -20
- 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_nested.py +26 -11
- lionagi/libs/ln_parse.py +82 -23
- lionagi/libs/ln_queue.py +16 -0
- lionagi/libs/ln_tokenize.py +164 -0
- lionagi/libs/ln_validate.py +16 -0
- lionagi/libs/special_tokens.py +172 -0
- lionagi/libs/sys_util.py +95 -24
- lionagi/lions/coder/code_form.py +13 -0
- lionagi/lions/coder/coder.py +50 -3
- lionagi/lions/coder/util.py +30 -25
- lionagi/tests/libs/test_func_call.py +23 -21
- lionagi/tests/libs/test_nested.py +36 -21
- lionagi/tests/libs/test_parse.py +1 -1
- 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/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 -294
- 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.2.0.dist-info/LICENSE +202 -0
- lionagi-0.2.0.dist-info/METADATA +272 -0
- lionagi-0.2.0.dist-info/RECORD +240 -0
- lionagi/core/branch/base.py +0 -653
- lionagi/core/branch/branch.py +0 -474
- lionagi/core/branch/flow_mixin.py +0 -96
- lionagi/core/branch/util.py +0 -323
- lionagi/core/direct/__init__.py +0 -19
- lionagi/core/direct/cot.py +0 -123
- lionagi/core/direct/plan.py +0 -164
- lionagi/core/direct/predict.py +0 -166
- lionagi/core/direct/react.py +0 -171
- lionagi/core/direct/score.py +0 -279
- lionagi/core/direct/select.py +0 -170
- lionagi/core/direct/sentiment.py +0 -1
- lionagi/core/direct/utils.py +0 -110
- lionagi/core/direct/vote.py +0 -64
- lionagi/core/execute/base_executor.py +0 -47
- lionagi/core/flow/baseflow.py +0 -23
- lionagi/core/flow/monoflow/ReAct.py +0 -240
- lionagi/core/flow/monoflow/__init__.py +0 -9
- lionagi/core/flow/monoflow/chat.py +0 -95
- lionagi/core/flow/monoflow/chat_mixin.py +0 -253
- lionagi/core/flow/monoflow/followup.py +0 -215
- lionagi/core/flow/polyflow/__init__.py +0 -1
- lionagi/core/flow/polyflow/chat.py +0 -251
- lionagi/core/form/action_form.py +0 -26
- lionagi/core/form/field_validator.py +0 -287
- lionagi/core/form/form.py +0 -302
- lionagi/core/form/mixin.py +0 -214
- lionagi/core/form/scored_form.py +0 -13
- lionagi/core/generic/action.py +0 -26
- lionagi/core/generic/component.py +0 -532
- lionagi/core/generic/condition.py +0 -46
- lionagi/core/generic/mail.py +0 -90
- lionagi/core/generic/mailbox.py +0 -36
- lionagi/core/generic/relation.py +0 -70
- lionagi/core/generic/signal.py +0 -22
- lionagi/core/generic/structure.py +0 -362
- lionagi/core/generic/transfer.py +0 -20
- lionagi/core/generic/work.py +0 -40
- lionagi/core/graph/graph.py +0 -126
- lionagi/core/graph/tree.py +0 -190
- lionagi/core/mail/schema.py +0 -63
- lionagi/core/messages/schema.py +0 -325
- lionagi/core/tool/__init__.py +0 -5
- lionagi/core/tool/tool.py +0 -28
- lionagi/core/tool/tool_manager.py +0 -283
- lionagi/experimental/report/form.py +0 -64
- lionagi/experimental/report/report.py +0 -138
- lionagi/experimental/report/util.py +0 -47
- lionagi/experimental/tool/function_calling.py +0 -43
- lionagi/experimental/tool/manual.py +0 -66
- lionagi/experimental/tool/schema.py +0 -59
- lionagi/experimental/tool/tool_manager.py +0 -138
- lionagi/experimental/tool/util.py +0 -16
- lionagi/experimental/validator/rule.py +0 -139
- lionagi/experimental/validator/validator.py +0 -56
- lionagi/experimental/work/__init__.py +0 -10
- lionagi/experimental/work/async_queue.py +0 -54
- lionagi/experimental/work/schema.py +0 -73
- lionagi/experimental/work/work_function.py +0 -67
- lionagi/experimental/work/worker.py +0 -56
- lionagi/experimental/work2/form.py +0 -371
- lionagi/experimental/work2/report.py +0 -289
- lionagi/experimental/work2/schema.py +0 -30
- lionagi/experimental/work2/tests.py +0 -72
- lionagi/experimental/work2/work_function.py +0 -89
- lionagi/experimental/work2/worker.py +0 -12
- lionagi/integrations/bridge/llamaindex_/get_index.py +0 -294
- lionagi/tests/test_core/generic/test_component.py +0 -89
- lionagi/tests/test_core/test_base_branch.py +0 -426
- 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 -313
- lionagi/tests/test_core/test_tool_manager.py +0 -95
- lionagi-0.1.2.dist-info/LICENSE +0 -9
- lionagi-0.1.2.dist-info/METADATA +0 -174
- lionagi-0.1.2.dist-info/RECORD +0 -206
- /lionagi/core/{branch → _setting}/__init__.py +0 -0
- /lionagi/core/{execute → agent/eval}/__init__.py +0 -0
- /lionagi/core/{flow → agent/learn}/__init__.py +0 -0
- /lionagi/core/{form → agent/plan}/__init__.py +0 -0
- /lionagi/core/{branch/executable_branch.py → agent/plan/plan.py} +0 -0
- /lionagi/core/{graph → director}/__init__.py +0 -0
- /lionagi/core/{messages → engine}/__init__.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/engine}/sandbox_.py +0 -0
- /lionagi/{experimental/directive/evaluator → core/executor}/__init__.py +0 -0
- /lionagi/{experimental/directive/template_ → core/rule}/__init__.py +0 -0
- /lionagi/{experimental/report → core/unit/template}/__init__.py +0 -0
- /lionagi/{experimental/tool → core/validator}/__init__.py +0 -0
- /lionagi/{experimental/validator → core/work}/__init__.py +0 -0
- /lionagi/experimental/{work2 → compressor}/__init__.py +0 -0
- /lionagi/{core/flow/mono_chat_mixin.py → experimental/directive/template/__init__.py} +0 -0
- /lionagi/experimental/directive/{schema.py → template/schema.py} +0 -0
- /lionagi/experimental/{work2/util.py → evaluator/__init__.py} +0 -0
- /lionagi/experimental/{work2/work.py → knowledge/__init__.py} +0 -0
- /lionagi/{tests/libs/test_async.py → experimental/knowledge/graph.py} +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/WHEEL +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.0.dist-info}/top_level.txt +0 -0
lionagi/__init__.py
CHANGED
@@ -1,15 +1,70 @@
|
|
1
1
|
"""
|
2
|
-
|
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.
|
3
15
|
"""
|
4
16
|
|
5
17
|
import logging
|
6
18
|
from .version import __version__
|
7
19
|
from dotenv import load_dotenv
|
8
20
|
|
9
|
-
from .
|
10
|
-
from .
|
11
|
-
from .
|
12
|
-
from .
|
21
|
+
from lionagi.libs.ln_convert import to_list, to_dict, to_df, to_readable_dict
|
22
|
+
from lionagi.libs.ln_func_call import alcall, bcall, lcall, CallDecorator as cd, tcall
|
23
|
+
from lionagi.core.collections.abc import Field
|
24
|
+
from lionagi.core.collections import progression, flow, pile, iModel
|
25
|
+
from lionagi.core.generic import Node, Graph, Tree, Edge
|
26
|
+
from lionagi.core.action import func_to_tool
|
27
|
+
from lionagi.core.report import Form, Report
|
28
|
+
from lionagi.core.session.branch import Branch
|
29
|
+
from lionagi.core.session.session import Session
|
30
|
+
from lionagi.core.work.worker import work, Worker
|
31
|
+
from lionagi.integrations.provider.services import Services
|
32
|
+
from lionagi.integrations.chunker.chunk import chunk
|
33
|
+
from lionagi.integrations.loader.load import load
|
34
|
+
import lionagi.core.director.direct as direct
|
35
|
+
|
36
|
+
|
37
|
+
__all__ = [
|
38
|
+
"Field",
|
39
|
+
"progression",
|
40
|
+
"flow",
|
41
|
+
"pile",
|
42
|
+
"iModel",
|
43
|
+
"work",
|
44
|
+
"Worker",
|
45
|
+
"Branch",
|
46
|
+
"Session",
|
47
|
+
"Form",
|
48
|
+
"Report",
|
49
|
+
"Services",
|
50
|
+
"direct",
|
51
|
+
"Node",
|
52
|
+
"Graph",
|
53
|
+
"Tree",
|
54
|
+
"Edge",
|
55
|
+
"chunk",
|
56
|
+
"load",
|
57
|
+
"func_to_tool",
|
58
|
+
"cd",
|
59
|
+
"alcall",
|
60
|
+
"bcall",
|
61
|
+
"to_list",
|
62
|
+
"to_dict",
|
63
|
+
"lcall",
|
64
|
+
"to_df",
|
65
|
+
"tcall",
|
66
|
+
"to_readable_dict",
|
67
|
+
]
|
13
68
|
|
14
69
|
|
15
70
|
logger = logging.getLogger(__name__)
|
lionagi/core/__init__.py
CHANGED
@@ -1,26 +1 @@
|
|
1
1
|
from . import *
|
2
|
-
|
3
|
-
from .branch.branch import Branch
|
4
|
-
from .session.session import Session
|
5
|
-
from .generic import (
|
6
|
-
ActionNode,
|
7
|
-
ActionSelection,
|
8
|
-
Condition,
|
9
|
-
)
|
10
|
-
from .agent.base_agent import BaseAgent
|
11
|
-
from .messages.schema import Instruction, System, Response
|
12
|
-
from .tool import func_to_tool
|
13
|
-
|
14
|
-
|
15
|
-
__all__ = [
|
16
|
-
"ActionNode",
|
17
|
-
"ActionSelection",
|
18
|
-
"Branch",
|
19
|
-
"Condition",
|
20
|
-
"Session",
|
21
|
-
"System",
|
22
|
-
"Instruction",
|
23
|
-
"Response",
|
24
|
-
"BaseAgent",
|
25
|
-
"func_to_tool",
|
26
|
-
]
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
# import csv
|
4
|
+
# import json
|
5
|
+
# import threading
|
6
|
+
# from contextlib import contextmanager
|
7
|
+
|
8
|
+
|
9
|
+
# class Settings:
|
10
|
+
# def __init__(self):
|
11
|
+
# self._lock = threading.Lock()
|
12
|
+
# self._config = {}
|
13
|
+
# self._default_service = None
|
14
|
+
|
15
|
+
# def load_from_json(self, file_path):
|
16
|
+
# with self._lock:
|
17
|
+
# with open(file_path, "r") as file:
|
18
|
+
# self._config = json.load(file)
|
19
|
+
|
20
|
+
# def save_to_json(self, file_path):
|
21
|
+
# with self._lock:
|
22
|
+
# with open(file_path, "w") as file:
|
23
|
+
# json.dump(self._config, file, indent=4)
|
24
|
+
|
25
|
+
# def load_default_service(self, file_path):
|
26
|
+
# with self._lock:
|
27
|
+
# with open(file_path, "r") as file:
|
28
|
+
# reader = csv.DictReader(file)
|
29
|
+
# self._default_service = next(reader)
|
30
|
+
|
31
|
+
# def save_default_service(self, file_path):
|
32
|
+
# with self._lock:
|
33
|
+
# fieldnames = ["provider", "api_key", "rate_limit"]
|
34
|
+
# with open(file_path, "w", newline="") as file:
|
35
|
+
# writer = csv.DictWriter(file, fieldnames=fieldnames)
|
36
|
+
# writer.writeheader()
|
37
|
+
# writer.writerow(self._default_service)
|
38
|
+
|
39
|
+
# @contextmanager
|
40
|
+
# def service_context(self, provider=None, api_key=None, rate_limit=None):
|
41
|
+
# with self._lock:
|
42
|
+
# service_config = {
|
43
|
+
# "provider": provider or self._default_service["provider"],
|
44
|
+
# "api_key": api_key or self._default_service["api_key"],
|
45
|
+
# "rate_limit": rate_limit or self._default_service["rate_limit"],
|
46
|
+
# }
|
47
|
+
# yield service_config
|
48
|
+
|
49
|
+
# def get_config(self, key):
|
50
|
+
# with self._lock:
|
51
|
+
# return self._config.get(key)
|
52
|
+
|
53
|
+
# def set_config(self, key, value):
|
54
|
+
# with self._lock:
|
55
|
+
# self._config[key] = value
|
56
|
+
|
57
|
+
|
58
|
+
# # Singleton instance
|
59
|
+
# lionagi_settings = Settings()
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from .function_calling import FunctionCalling
|
2
|
+
from .tool import Tool
|
3
|
+
from .tool_manager import ToolManager, func_to_tool
|
4
|
+
from .node import ActionNode, DirectiveSelection
|
5
|
+
|
6
|
+
|
7
|
+
__all__ = [
|
8
|
+
"FunctionCalling",
|
9
|
+
"Tool",
|
10
|
+
"ToolManager",
|
11
|
+
"func_to_tool",
|
12
|
+
"ActionNode",
|
13
|
+
"DirectiveSelection",
|
14
|
+
]
|
@@ -0,0 +1,136 @@
|
|
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 defines the FunctionCalling class, which facilitates dynamic
|
19
|
+
invocation of functions based on various input types. It supports initializing
|
20
|
+
function calls from tuples, dictionaries, ActionRequest objects, or JSON strings.
|
21
|
+
|
22
|
+
Note:
|
23
|
+
Function Calling object is the only way for AI system to call functions.
|
24
|
+
"""
|
25
|
+
|
26
|
+
from functools import singledispatchmethod
|
27
|
+
from typing import Any, Callable, Dict
|
28
|
+
|
29
|
+
from lionagi.libs import ParseUtil
|
30
|
+
from lionagi.libs.ln_func_call import call_handler
|
31
|
+
from lionagi.core.collections.abc import Actionable
|
32
|
+
from lionagi.core.message.action_request import ActionRequest
|
33
|
+
|
34
|
+
|
35
|
+
class FunctionCalling(Actionable):
|
36
|
+
"""
|
37
|
+
A class for dynamically invoking functions based on various input types,
|
38
|
+
allowing for specification of the function and arguments through multiple
|
39
|
+
formats including tuples, dictionaries, ActionRequests, or JSON strings.
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(self, function: Callable, arguments: Dict[str, Any] = None):
|
43
|
+
"""
|
44
|
+
Initializes a new instance of FunctionCalling with the given function
|
45
|
+
and optional arguments.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
function (Callable): The function to be called.
|
49
|
+
arguments (Dict[str, Any]): Arguments to pass to the function.
|
50
|
+
Defaults to an empty dictionary.
|
51
|
+
"""
|
52
|
+
self.function = function
|
53
|
+
self.arguments = arguments or {}
|
54
|
+
|
55
|
+
@property
|
56
|
+
def func_name(self) -> str:
|
57
|
+
"""
|
58
|
+
Returns the name of the function.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
str: The function's name.
|
62
|
+
"""
|
63
|
+
return self.function.__name__
|
64
|
+
|
65
|
+
@singledispatchmethod
|
66
|
+
@classmethod
|
67
|
+
def create(cls, func_call: Any) -> "FunctionCalling":
|
68
|
+
"""
|
69
|
+
Creates an instance of FunctionCalling based on the type of input.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
func_call (Any): The function call description, which can be a tuple, dict,
|
73
|
+
ActionRequest, or JSON string.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
FunctionCalling: An instance of FunctionCalling prepared to invoke
|
77
|
+
the specified function.
|
78
|
+
|
79
|
+
Raises:
|
80
|
+
TypeError: If the input type is not supported.
|
81
|
+
"""
|
82
|
+
raise TypeError(f"Unsupported type {type(func_call)}")
|
83
|
+
|
84
|
+
@create.register(tuple)
|
85
|
+
def _(cls, function_calling: tuple) -> "FunctionCalling":
|
86
|
+
if len(function_calling) == 2:
|
87
|
+
return cls(function=function_calling[0], arguments=function_calling[1])
|
88
|
+
else:
|
89
|
+
raise ValueError(f"Invalid function call {function_calling}")
|
90
|
+
|
91
|
+
@create.register(dict)
|
92
|
+
def _(cls, function_calling: Dict[str, Any]) -> "FunctionCalling":
|
93
|
+
if len(function_calling) == 2 and (
|
94
|
+
{"function", "arguments"} <= function_calling.keys()
|
95
|
+
):
|
96
|
+
return cls.create(
|
97
|
+
(function_calling["function"], function_calling["arguments"])
|
98
|
+
)
|
99
|
+
raise ValueError(f"Invalid function call {function_calling}")
|
100
|
+
|
101
|
+
@create.register(ActionRequest)
|
102
|
+
def _(cls, function_calling: ActionRequest) -> "FunctionCalling":
|
103
|
+
return cls.create((function_calling.function, function_calling.arguments))
|
104
|
+
|
105
|
+
@create.register(str)
|
106
|
+
def _(cls, function_calling: str) -> "FunctionCalling":
|
107
|
+
_call = None
|
108
|
+
try:
|
109
|
+
_call = ParseUtil.fuzzy_parse_json(function_calling)
|
110
|
+
except Exception as e:
|
111
|
+
raise ValueError(f"Invalid function call {function_calling}") from e
|
112
|
+
|
113
|
+
if isinstance(_call, dict):
|
114
|
+
return cls.create(_call)
|
115
|
+
raise ValueError(f"Invalid function call {function_calling}")
|
116
|
+
|
117
|
+
async def invoke(self) -> Any:
|
118
|
+
"""
|
119
|
+
Asynchronously invokes the stored function with the provided arguments.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
Any: The result of the function call.
|
123
|
+
"""
|
124
|
+
return await call_handler(self.function, **self.arguments)
|
125
|
+
|
126
|
+
def __str__(self) -> str:
|
127
|
+
"""
|
128
|
+
Returns a string representation of the function call.
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
str: String representation of the function call.
|
132
|
+
"""
|
133
|
+
return f"{self.func_name}({self.arguments})"
|
134
|
+
|
135
|
+
def __repr__(self) -> str:
|
136
|
+
return self.__str__()
|
@@ -0,0 +1 @@
|
|
1
|
+
# TODO
|
@@ -0,0 +1,109 @@
|
|
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
|
+
from pydantic import Field
|
18
|
+
|
19
|
+
from lionagi.core.collections.abc import Actionable
|
20
|
+
from lionagi.core.generic.node import Node
|
21
|
+
from .tool import Tool
|
22
|
+
|
23
|
+
|
24
|
+
class DirectiveSelection(Node, Actionable):
|
25
|
+
"""
|
26
|
+
Represents a directive selection node which can be invoked to perform an action.
|
27
|
+
|
28
|
+
Attributes:
|
29
|
+
directive (str): The action to be performed, with a default value of "chat".
|
30
|
+
directive_kwargs (dict): The arguments for the action.
|
31
|
+
|
32
|
+
Methods:
|
33
|
+
invoke(): An asynchronous method to perform the action defined by the directive.
|
34
|
+
"""
|
35
|
+
|
36
|
+
directive: str = Field(
|
37
|
+
"chat", description="The action to be performed", alias="action_type"
|
38
|
+
)
|
39
|
+
directive_kwargs: dict = Field(
|
40
|
+
default_factory=dict,
|
41
|
+
description="The arguments for the action",
|
42
|
+
alias="action_arguments",
|
43
|
+
)
|
44
|
+
|
45
|
+
async def invoke(self):
|
46
|
+
"""
|
47
|
+
Perform the action defined by the directive.
|
48
|
+
|
49
|
+
This method is intended to be overridden by subclasses to provide specific
|
50
|
+
implementation details for the action.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class ActionNode(DirectiveSelection):
|
56
|
+
"""
|
57
|
+
Represents an action node that can invoke actions within a branch using tools and instructions.
|
58
|
+
|
59
|
+
Attributes:
|
60
|
+
tools (list[Tool] | Tool | None): The tools to be used in the action.
|
61
|
+
instruction (Node): The instruction for the action.
|
62
|
+
|
63
|
+
Methods:
|
64
|
+
invoke(branch, context=None): An asynchronous method to invoke the action
|
65
|
+
within the given branch.
|
66
|
+
"""
|
67
|
+
|
68
|
+
tools: list[Tool] | Tool | None = Field(
|
69
|
+
default_factory=list,
|
70
|
+
description="The tools to be used in the action",
|
71
|
+
alias="tool",
|
72
|
+
)
|
73
|
+
instruction: Node = Field(
|
74
|
+
..., description="The instruction for the action", alias="instruct"
|
75
|
+
)
|
76
|
+
|
77
|
+
async def invoke(self, branch, context=None):
|
78
|
+
"""
|
79
|
+
Invoke the action within the given branch.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
branch: The branch in which to perform the action.
|
83
|
+
context: Optional; Additional context for the action.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
The result of the action, depending on the directive.
|
87
|
+
|
88
|
+
Raises:
|
89
|
+
ValueError: If the directive is not "chat" or "direct".
|
90
|
+
"""
|
91
|
+
if self.directive == "chat":
|
92
|
+
return await branch.chat(
|
93
|
+
instruction=self.instruction.instruct,
|
94
|
+
tools=self.tools,
|
95
|
+
**self.directive_kwargs,
|
96
|
+
)
|
97
|
+
elif self.directive == "direct":
|
98
|
+
if self.tools:
|
99
|
+
self.directive_kwargs["allow_action"] = True
|
100
|
+
return await branch.direct(
|
101
|
+
instruction=self.instruction.instruct,
|
102
|
+
context=context,
|
103
|
+
tools=self.tools,
|
104
|
+
**self.directive_kwargs,
|
105
|
+
)
|
106
|
+
else:
|
107
|
+
raise ValueError(
|
108
|
+
'Invalid directive, valid directives are: "chat", "direct"'
|
109
|
+
)
|
@@ -0,0 +1,114 @@
|
|
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
|
+
from typing import Callable, Union, List, Dict, Any
|
18
|
+
from pydantic import Field, field_serializer
|
19
|
+
from lionagi.libs.ln_func_call import call_handler
|
20
|
+
from lionagi.core.collections.abc import Actionable
|
21
|
+
from lionagi.core.generic.node import Node
|
22
|
+
from .function_calling import FunctionCalling
|
23
|
+
|
24
|
+
|
25
|
+
class Tool(Node, Actionable):
|
26
|
+
"""
|
27
|
+
Class representing a Tool with capabilities for pre-processing, post-processing,
|
28
|
+
and parsing function results.
|
29
|
+
|
30
|
+
Attributes:
|
31
|
+
function (Callable): The callable function or capability of the tool.
|
32
|
+
schema_ (Union[Dict, None]): Schema in OpenAI format.
|
33
|
+
pre_processor (Union[Callable, None]): Function to preprocess input arguments.
|
34
|
+
pre_processor_kwargs (Union[Dict, None]): Keyword arguments for the pre-processor.
|
35
|
+
post_processor (Union[Callable, None]): Function to post-process the result.
|
36
|
+
post_processor_kwargs (Union[Dict, None]): Keyword arguments for the post-processor.
|
37
|
+
parser (Union[Callable, None]): Function to parse the result to a JSON serializable format.
|
38
|
+
"""
|
39
|
+
|
40
|
+
function: Callable = Field(
|
41
|
+
...,
|
42
|
+
description="The callable function or capability of the tool.",
|
43
|
+
)
|
44
|
+
|
45
|
+
schema_: Union[Dict, None] = Field(
|
46
|
+
None,
|
47
|
+
description="Schema in OpenAI format.",
|
48
|
+
)
|
49
|
+
|
50
|
+
pre_processor: Union[Callable, None] = None
|
51
|
+
pre_processor_kwargs: Union[Dict, None] = None
|
52
|
+
|
53
|
+
post_processor: Union[Callable, None] = None
|
54
|
+
post_processor_kwargs: Union[Dict, None] = None
|
55
|
+
|
56
|
+
parser: Union[Callable, None] = None # Parse result to JSON serializable format
|
57
|
+
|
58
|
+
@field_serializer("function", check_fields=False)
|
59
|
+
def serialize_func(self, func: Callable) -> str:
|
60
|
+
"""
|
61
|
+
Serialize the function for storage or transmission.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
func (Callable): The function to serialize.
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
str: The name of the function.
|
68
|
+
"""
|
69
|
+
return func.__name__
|
70
|
+
|
71
|
+
@property
|
72
|
+
def name(self) -> str:
|
73
|
+
"""
|
74
|
+
Get the name of the function from the schema.
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
str: The name of the function.
|
78
|
+
"""
|
79
|
+
return self.schema_["function"]["name"]
|
80
|
+
|
81
|
+
async def invoke(self, kwargs: Dict = {}) -> Any:
|
82
|
+
"""
|
83
|
+
Invoke the tool's function with optional pre-processing and post-processing.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
kwargs (Dict): The arguments to pass to the function.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
Any: The result of the function call.
|
90
|
+
"""
|
91
|
+
if self.pre_processor:
|
92
|
+
pre_process_kwargs = self.pre_processor_kwargs or {}
|
93
|
+
kwargs = await call_handler(
|
94
|
+
self.pre_processor(kwargs, **pre_process_kwargs)
|
95
|
+
)
|
96
|
+
if not isinstance(kwargs, dict):
|
97
|
+
raise ValueError("Pre-processor must return a dictionary.")
|
98
|
+
|
99
|
+
func_call_ = FunctionCalling(function=self.function, arguments=kwargs)
|
100
|
+
try:
|
101
|
+
result = await func_call_.invoke()
|
102
|
+
except Exception:
|
103
|
+
return None
|
104
|
+
|
105
|
+
if self.post_processor:
|
106
|
+
post_process_kwargs = self.post_processor_kwargs or {}
|
107
|
+
result = await call_handler(
|
108
|
+
self.post_processor(result, **post_process_kwargs)
|
109
|
+
)
|
110
|
+
|
111
|
+
return result if not self.parser else self.parser(result)
|
112
|
+
|
113
|
+
|
114
|
+
TOOL_TYPE = Union[bool, Tool, str, List[Union[Tool, str, Dict]], Dict]
|