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
@@ -0,0 +1,35 @@
|
|
1
|
+
# from lionagi.libs.ln_convert import is_same_dtype
|
2
|
+
# from collections.abc import Mapping, Generator
|
3
|
+
|
4
|
+
|
5
|
+
# def validate_keys(keys):
|
6
|
+
# """
|
7
|
+
# choices can be provided from various sources:
|
8
|
+
# - mapping such as dict, their keys will be used as choices
|
9
|
+
# - iterables including list, tuple, set, generator, enum, etc.
|
10
|
+
# - strings, comma separated values
|
11
|
+
# """
|
12
|
+
|
13
|
+
# try:
|
14
|
+
# if isinstance(keys, Mapping):
|
15
|
+
# keys = list(keys.keys())
|
16
|
+
|
17
|
+
# elif isinstance(keys, (list, tuple, set, Generator)):
|
18
|
+
# keys = set(keys)
|
19
|
+
|
20
|
+
# elif isinstance(keys, str):
|
21
|
+
# if "," in keys:
|
22
|
+
# keys = list({i.strip() for i in keys.split(",")})
|
23
|
+
# else:
|
24
|
+
# keys = [keys.strip()]
|
25
|
+
|
26
|
+
# else:
|
27
|
+
# keys = [i.value for i in keys]
|
28
|
+
|
29
|
+
# except Exception as e:
|
30
|
+
# raise ValueError(f"invalid choices {keys}") from e
|
31
|
+
|
32
|
+
# if not is_same_dtype(keys):
|
33
|
+
# raise ValueError(f"choices must be of the same type, got {keys}")
|
34
|
+
|
35
|
+
# return keys
|
@@ -0,0 +1,431 @@
|
|
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 Any
|
18
|
+
from lionagi.libs.ln_convert import is_same_dtype, to_df
|
19
|
+
from lionagi.core.collections.abc import Field
|
20
|
+
from lionagi.core.collections import (
|
21
|
+
pile,
|
22
|
+
progression,
|
23
|
+
Pile,
|
24
|
+
Progression,
|
25
|
+
iModel,
|
26
|
+
Exchange,
|
27
|
+
)
|
28
|
+
from lionagi.core.generic.node import Node
|
29
|
+
from lionagi.core.action import Tool, ToolManager
|
30
|
+
from lionagi.core.mail import Mail, Package
|
31
|
+
from lionagi.core.message import (
|
32
|
+
create_message,
|
33
|
+
System,
|
34
|
+
Instruction,
|
35
|
+
AssistantResponse,
|
36
|
+
ActionRequest,
|
37
|
+
ActionResponse,
|
38
|
+
RoledMessage,
|
39
|
+
)
|
40
|
+
|
41
|
+
from lionagi.core.session.directive_mixin import DirectiveMixin
|
42
|
+
|
43
|
+
|
44
|
+
class Branch(Node, DirectiveMixin):
|
45
|
+
"""
|
46
|
+
A class representing a branch in a messaging system.
|
47
|
+
|
48
|
+
Attributes:
|
49
|
+
messages (Pile): A pile of messages.
|
50
|
+
progress (Progression): A progression of messages.
|
51
|
+
tool_manager (ToolManager): A manager for handling tools.
|
52
|
+
system (System): The system associated with the branch.
|
53
|
+
user (str): The user associated with the branch.
|
54
|
+
mailbox (Exchange): An exchange for managing mail.
|
55
|
+
imodel (iModel): The model associated with the branch.
|
56
|
+
"""
|
57
|
+
|
58
|
+
messages: Pile = Field(None)
|
59
|
+
progress: Progression = Field(None)
|
60
|
+
tool_manager: ToolManager = Field(None)
|
61
|
+
system: System = Field(None)
|
62
|
+
user: str = Field(None)
|
63
|
+
mailbox: Exchange[Mail] = Field(None)
|
64
|
+
imodel: iModel = Field(None)
|
65
|
+
|
66
|
+
def __init__(
|
67
|
+
self,
|
68
|
+
system: System | None = None,
|
69
|
+
system_sender: str | None = None,
|
70
|
+
user: str | None = None,
|
71
|
+
messages: Pile = None,
|
72
|
+
progress: Progression = None,
|
73
|
+
tool_manager: ToolManager = None,
|
74
|
+
tools: Any = None,
|
75
|
+
imodel=None,
|
76
|
+
):
|
77
|
+
"""
|
78
|
+
Initializes a new instance of the Branch class.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
system (System, optional): The system associated with the branch.
|
82
|
+
system_sender (str, optional): The sender of the system message.
|
83
|
+
user (str, optional): The user associated with the branch.
|
84
|
+
messages (Pile, optional): A pile of messages.
|
85
|
+
progress (Progression, optional): A progression of messages.
|
86
|
+
tool_manager (ToolManager, optional): A manager for handling tools.
|
87
|
+
tools (Any, optional): Tools to be registered with the tool manager.
|
88
|
+
imodel (iModel, optional): The model associated with the branch.
|
89
|
+
"""
|
90
|
+
super().__init__()
|
91
|
+
self.system = None
|
92
|
+
|
93
|
+
self.user = user or "user"
|
94
|
+
self.messages = messages or pile({})
|
95
|
+
self.progress = progress or progression()
|
96
|
+
self.tool_manager = tool_manager or ToolManager()
|
97
|
+
self.mailbox = Exchange()
|
98
|
+
self.imodel = imodel or iModel()
|
99
|
+
if tools:
|
100
|
+
self.tool_manager.register_tools(tools)
|
101
|
+
self.set_system(system=system, sender=system_sender)
|
102
|
+
# system = system or "You are a helpful assistant, let's think step by step"
|
103
|
+
# self.add_message(system=system, sender=system_sender)
|
104
|
+
|
105
|
+
def set_system(self, system=None, sender=None) -> None:
|
106
|
+
"""
|
107
|
+
Sets the system message.
|
108
|
+
|
109
|
+
Args:
|
110
|
+
system (System): The system message to set.
|
111
|
+
sender (str, optional): The sender of the system message.
|
112
|
+
"""
|
113
|
+
system = system or "You are a helpful assistant."
|
114
|
+
if len(self.progress) == 0:
|
115
|
+
self.add_message(system=system, sender=sender)
|
116
|
+
else:
|
117
|
+
_msg = System(system=system, sender=sender)
|
118
|
+
_msg.recipient = self.ln_id
|
119
|
+
self._remove_system()
|
120
|
+
self.system = _msg
|
121
|
+
|
122
|
+
def add_message(
|
123
|
+
self,
|
124
|
+
*,
|
125
|
+
system=None, # system node - JSON serializable
|
126
|
+
instruction=None, # Instruction node - JSON serializable
|
127
|
+
context=None, # JSON serializable
|
128
|
+
assistant_response=None, # JSON
|
129
|
+
function=None,
|
130
|
+
arguments=None,
|
131
|
+
func_outputs=None,
|
132
|
+
action_request=None, # ActionRequest node
|
133
|
+
action_response=None, # ActionResponse node
|
134
|
+
images=None,
|
135
|
+
sender=None, # str
|
136
|
+
recipient=None, # str
|
137
|
+
requested_fields=None, # dict[str, str]
|
138
|
+
metadata: dict | None = None, # extra metadata
|
139
|
+
**kwargs, # additional context fields
|
140
|
+
) -> bool:
|
141
|
+
"""
|
142
|
+
Adds a message to the branch.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
system (Any, optional): The system node (JSON serializable).
|
146
|
+
instruction (Any, optional): The instruction node (JSON serializable).
|
147
|
+
context (Any, optional): Additional context (JSON serializable).
|
148
|
+
assistant_response (Any, optional): The assistant's response (JSON serializable).
|
149
|
+
function (Any, optional): The function associated with the message.
|
150
|
+
arguments (Any, optional): The arguments for the function.
|
151
|
+
func_outputs (Any, optional): The outputs of the function.
|
152
|
+
action_request (Any, optional): The action request node.
|
153
|
+
action_response (Any, optional): The action response node.
|
154
|
+
sender (str, optional): The sender of the message.
|
155
|
+
recipient (str, optional): The recipient of the message.
|
156
|
+
requested_fields (dict[str, str], optional): Requested fields for the message.
|
157
|
+
metadata (dict, optional): Extra metadata for the message.
|
158
|
+
**kwargs: Additional context fields.
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
bool: True if the message was successfully added, else False.
|
162
|
+
"""
|
163
|
+
if assistant_response:
|
164
|
+
sender = self.ln_id
|
165
|
+
|
166
|
+
_msg = create_message(
|
167
|
+
system=system,
|
168
|
+
instruction=instruction,
|
169
|
+
context=context,
|
170
|
+
assistant_response=assistant_response,
|
171
|
+
function=function,
|
172
|
+
arguments=arguments,
|
173
|
+
func_outputs=func_outputs,
|
174
|
+
action_request=action_request,
|
175
|
+
action_response=action_response,
|
176
|
+
sender=sender,
|
177
|
+
images=images,
|
178
|
+
recipient=recipient,
|
179
|
+
requested_fields=requested_fields,
|
180
|
+
**kwargs,
|
181
|
+
)
|
182
|
+
|
183
|
+
if isinstance(_msg, System):
|
184
|
+
_msg.recipient = self.ln_id # the branch itself, system is to the branch
|
185
|
+
self._remove_system()
|
186
|
+
self.system = _msg
|
187
|
+
|
188
|
+
if isinstance(_msg, Instruction):
|
189
|
+
_msg.sender = sender or self.user
|
190
|
+
_msg.recipient = recipient or self.ln_id
|
191
|
+
|
192
|
+
if isinstance(_msg, AssistantResponse):
|
193
|
+
_msg.sender = sender or self.ln_id
|
194
|
+
_msg.recipient = recipient or "user"
|
195
|
+
|
196
|
+
if isinstance(_msg, ActionRequest):
|
197
|
+
_msg.sender = sender or self.ln_id
|
198
|
+
_msg.recipient = recipient or "N/A"
|
199
|
+
|
200
|
+
if isinstance(_msg, ActionResponse):
|
201
|
+
_msg.sender = sender or "N/A"
|
202
|
+
_msg.recipient = recipient or self.ln_id
|
203
|
+
|
204
|
+
if metadata:
|
205
|
+
_msg._meta_insert(["extra"], metadata)
|
206
|
+
|
207
|
+
return self.messages.include(_msg) and self.progress.include(_msg)
|
208
|
+
|
209
|
+
def to_chat_messages(self) -> list[dict[str, Any]]:
|
210
|
+
"""
|
211
|
+
Converts the messages to chat message format.
|
212
|
+
|
213
|
+
Returns:
|
214
|
+
list[dict[str, Any]]: A list of chat messages.
|
215
|
+
"""
|
216
|
+
return [self.messages[j].chat_msg for j in self.progress]
|
217
|
+
|
218
|
+
def _remove_system(self) -> None:
|
219
|
+
"""
|
220
|
+
Removes the system message from the branch.
|
221
|
+
"""
|
222
|
+
self.messages.exclude(self.system)
|
223
|
+
self.progress.exclude(self.system)
|
224
|
+
self.system = None
|
225
|
+
|
226
|
+
def clear(self) -> None:
|
227
|
+
"""
|
228
|
+
Clears all messages and progression in the branch.
|
229
|
+
"""
|
230
|
+
self.messages.clear()
|
231
|
+
self.progress.clear()
|
232
|
+
|
233
|
+
@property
|
234
|
+
def has_tools(self) -> bool:
|
235
|
+
"""
|
236
|
+
Checks if the branch has tools.
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
bool: True if the branch has tools, else False.
|
240
|
+
"""
|
241
|
+
return self.tool_manager.registry != {}
|
242
|
+
|
243
|
+
def register_tools(self, tools) -> None:
|
244
|
+
"""
|
245
|
+
Registers tools with the tool manager.
|
246
|
+
|
247
|
+
Args:
|
248
|
+
tools (Any): The tools to register.
|
249
|
+
"""
|
250
|
+
self.tool_manager.register_tools(tools=tools)
|
251
|
+
|
252
|
+
def delete_tools(self, tools, verbose: bool = True) -> bool:
|
253
|
+
"""
|
254
|
+
Deletes tools from the tool manager.
|
255
|
+
|
256
|
+
Args:
|
257
|
+
tools (Any): The tools to delete.
|
258
|
+
verbose (bool, optional): Whether to print deletion status.
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
bool: True if tools were successfully deleted, else False.
|
262
|
+
"""
|
263
|
+
if not isinstance(tools, list):
|
264
|
+
tools = [tools]
|
265
|
+
if is_same_dtype(tools, str):
|
266
|
+
for act_ in tools:
|
267
|
+
if act_ in self.tool_manager.registry:
|
268
|
+
self.tool_manager.registry.pop(act_)
|
269
|
+
if verbose:
|
270
|
+
print("tools successfully deleted")
|
271
|
+
return True
|
272
|
+
elif is_same_dtype(tools, Tool):
|
273
|
+
for act_ in tools:
|
274
|
+
if act_.schema_["function"]["name"] in self.tool_manager.registry:
|
275
|
+
self.tool_manager.registry.pop(act_.schema_["function"]["name"])
|
276
|
+
if verbose:
|
277
|
+
print("tools successfully deleted")
|
278
|
+
return True
|
279
|
+
if verbose:
|
280
|
+
print("tools deletion failed")
|
281
|
+
return False
|
282
|
+
|
283
|
+
def update_last_instruction_meta(self, meta):
|
284
|
+
"""
|
285
|
+
Updates metadata of the last instruction.
|
286
|
+
|
287
|
+
Args:
|
288
|
+
meta (dict): The metadata to update.
|
289
|
+
"""
|
290
|
+
|
291
|
+
for i in reversed(self.progress):
|
292
|
+
if isinstance(self.messages[i], Instruction):
|
293
|
+
self.messages[i]._meta_insert(["extra"], meta)
|
294
|
+
return
|
295
|
+
|
296
|
+
@property
|
297
|
+
def last_response(self):
|
298
|
+
for i in reversed(self.progress):
|
299
|
+
if isinstance(self.messages[i], AssistantResponse):
|
300
|
+
return self.messages[i]
|
301
|
+
|
302
|
+
@property
|
303
|
+
def assistant_responses(self):
|
304
|
+
return pile(
|
305
|
+
[
|
306
|
+
self.messages[i]
|
307
|
+
for i in self.progress
|
308
|
+
if isinstance(self.messages[i], AssistantResponse)
|
309
|
+
]
|
310
|
+
)
|
311
|
+
|
312
|
+
def to_df(self) -> Any:
|
313
|
+
"""
|
314
|
+
Converts the messages to a DataFrame.
|
315
|
+
|
316
|
+
Returns:
|
317
|
+
Any: A DataFrame representation of the messages.
|
318
|
+
"""
|
319
|
+
fields = [
|
320
|
+
"ln_id",
|
321
|
+
"message_type",
|
322
|
+
"timestamp",
|
323
|
+
"role",
|
324
|
+
"content",
|
325
|
+
"metadata",
|
326
|
+
"sender",
|
327
|
+
"recipient",
|
328
|
+
]
|
329
|
+
dicts_ = []
|
330
|
+
for i in self.progress:
|
331
|
+
_d = {}
|
332
|
+
for j in fields:
|
333
|
+
_d.update({j: getattr(self.messages[i], j, None)})
|
334
|
+
_d["message_type"] = self.messages[i].class_name
|
335
|
+
dicts_.append(_d)
|
336
|
+
|
337
|
+
return to_df(dicts_)
|
338
|
+
|
339
|
+
def _is_invoked(self) -> bool:
|
340
|
+
"""
|
341
|
+
Checks if the last message is an ActionResponse.
|
342
|
+
|
343
|
+
Returns:
|
344
|
+
bool: True if the last message is an ActionResponse, else False.
|
345
|
+
"""
|
346
|
+
return isinstance(self.messages[-1], ActionResponse)
|
347
|
+
|
348
|
+
def send(
|
349
|
+
self, recipient: str, category: str, package: Any, request_source: str = None
|
350
|
+
) -> None:
|
351
|
+
"""
|
352
|
+
Sends a mail to a recipient.
|
353
|
+
|
354
|
+
Args:
|
355
|
+
recipient (str): The ID of the recipient.
|
356
|
+
category (str): The category of the mail.
|
357
|
+
package (Any): The package to send in the mail.
|
358
|
+
request_source (str): The source of the request.
|
359
|
+
"""
|
360
|
+
pack = Package(
|
361
|
+
category=category, package=package, request_source=request_source
|
362
|
+
)
|
363
|
+
mail = Mail(
|
364
|
+
sender=self.ln_id,
|
365
|
+
recipient=recipient,
|
366
|
+
package=pack,
|
367
|
+
)
|
368
|
+
self.mailbox.include(mail, "out")
|
369
|
+
|
370
|
+
def receive(
|
371
|
+
self,
|
372
|
+
sender: str,
|
373
|
+
message: bool = True,
|
374
|
+
tool: bool = True,
|
375
|
+
imodel: bool = True,
|
376
|
+
) -> None:
|
377
|
+
"""
|
378
|
+
Receives mail from a sender.
|
379
|
+
|
380
|
+
Args:
|
381
|
+
sender (str): The ID of the sender.
|
382
|
+
message (bool, optional): Whether to process message mails. Defaults to True.
|
383
|
+
tool (bool, optional): Whether to process tool mails. Defaults to True.
|
384
|
+
imodel (bool, optional): Whether to process imodel mails. Defaults to True.
|
385
|
+
|
386
|
+
Raises:
|
387
|
+
ValueError: If the sender does not exist or the mail category is invalid.
|
388
|
+
"""
|
389
|
+
skipped_requests = progression()
|
390
|
+
if sender not in self.mailbox.pending_ins.keys():
|
391
|
+
raise ValueError(f"No package from {sender}")
|
392
|
+
while self.mailbox.pending_ins[sender].size() > 0:
|
393
|
+
mail_id = self.mailbox.pending_ins[sender].popleft()
|
394
|
+
mail: Mail = self.mailbox.pile[mail_id]
|
395
|
+
|
396
|
+
if mail.category == "message" and message:
|
397
|
+
if not isinstance(mail.package.package, RoledMessage):
|
398
|
+
raise ValueError("Invalid message format")
|
399
|
+
new_message = mail.package.package.clone()
|
400
|
+
new_message.sender = mail.sender
|
401
|
+
new_message.recipient = self.ln_id
|
402
|
+
self.messages.include(new_message)
|
403
|
+
self.progress.include(new_message)
|
404
|
+
self.mailbox.pile.pop(mail_id)
|
405
|
+
|
406
|
+
elif mail.category == "tool" and tool:
|
407
|
+
if not isinstance(mail.package.package, Tool):
|
408
|
+
raise ValueError("Invalid tools format")
|
409
|
+
self.tool_manager.register_tools(mail.package.package)
|
410
|
+
self.mailbox.pile.pop(mail_id)
|
411
|
+
|
412
|
+
elif mail.category == "imodel" and imodel:
|
413
|
+
if not isinstance(mail.package.package, iModel):
|
414
|
+
raise ValueError("Invalid iModel format")
|
415
|
+
self.imodel = mail.package.package
|
416
|
+
self.mailbox.pile.pop(mail_id)
|
417
|
+
|
418
|
+
else:
|
419
|
+
skipped_requests.append(mail)
|
420
|
+
|
421
|
+
self.mailbox.pending_ins[sender] = skipped_requests
|
422
|
+
|
423
|
+
if self.mailbox.pending_ins[sender].size() == 0:
|
424
|
+
self.mailbox.pending_ins.pop(sender)
|
425
|
+
|
426
|
+
def receive_all(self) -> None:
|
427
|
+
"""
|
428
|
+
Receives mail from all senders.
|
429
|
+
"""
|
430
|
+
for key in list(self.mailbox.pending_ins.keys()):
|
431
|
+
self.receive(key)
|