lionagi 0.1.2__py3-none-any.whl → 0.2.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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 +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/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.1.dist-info/LICENSE +202 -0
- lionagi-0.2.1.dist-info/METADATA +272 -0
- lionagi-0.2.1.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.1.dist-info}/WHEEL +0 -0
- {lionagi-0.1.2.dist-info → lionagi-0.2.1.dist-info}/top_level.txt +0 -0
lionagi/core/session/session.py
CHANGED
@@ -1,985 +1,311 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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 lionagi.core.collections import (
|
18
|
+
Pile,
|
19
|
+
Progression,
|
20
|
+
progression,
|
21
|
+
pile,
|
22
|
+
iModel,
|
23
|
+
)
|
24
|
+
from lionagi.core.message import System
|
25
|
+
from typing import Any
|
26
|
+
from lionagi.core.action.tool_manager import ToolManager
|
27
|
+
|
28
|
+
from lionagi.libs import SysUtil
|
29
|
+
from lionagi.core.session.branch import Branch
|
30
|
+
from lionagi.core.collections import pile, Pile, Exchange
|
31
|
+
from lionagi.core.collections.abc import get_lion_id
|
32
|
+
from lionagi.core.collections.util import to_list_type
|
9
33
|
from lionagi.core.mail.mail_manager import MailManager
|
10
|
-
from lionagi.core.messages.schema import System, Instruction
|
11
|
-
from lionagi.core.branch.branch import Branch
|
12
|
-
from lionagi.core.flow.polyflow import PolyChat
|
13
34
|
|
14
35
|
|
15
36
|
class Session:
|
16
37
|
"""
|
17
|
-
|
18
|
-
|
19
|
-
A `Session` encapsulates the state and behavior for managing conversations and their branches.
|
20
|
-
It provides functionality for initializing and managing conversation sessions, including setting up default
|
21
|
-
branches, configuring language learning models, managing tools, and handling session data logging.
|
38
|
+
A session for managing branches, mail transfer, and interactions with a model.
|
22
39
|
|
23
40
|
Attributes:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
41
|
+
ln_id (str): The unique identifier for the session.
|
42
|
+
timestamp (str): The timestamp when the session was created.
|
43
|
+
system (System): The default system message for the session.
|
44
|
+
system_sender (str): The sender of the system message.
|
45
|
+
branches (Pile[Branch]): The pile of branches in the session.
|
46
|
+
mail_transfer (Exchange): The exchange for managing mail transfer.
|
47
|
+
mail_manager (MailManager): The manager for handling mail.
|
48
|
+
imodel (iModel): The model associated with the session.
|
49
|
+
user (str): The user associated with the session.
|
50
|
+
default_branch (Branch): The default branch of the session.
|
28
51
|
"""
|
29
52
|
|
30
53
|
def __init__(
|
31
54
|
self,
|
32
|
-
system
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
default_branch_name: str | None = None,
|
39
|
-
tools: TOOL_TYPE | None = None,
|
40
|
-
# instruction_sets: Optional[List[Instruction]] = None,
|
41
|
-
tool_manager: ToolManager | None = None,
|
42
|
-
messages: dataframe.ln_DataFrame | None = None,
|
43
|
-
datalogger: None | DataLogger = None,
|
44
|
-
persist_path: Path | str | None = None,
|
55
|
+
system=None, # the default system message for the session
|
56
|
+
branches: Any | None = None,
|
57
|
+
system_sender: str | None = None,
|
58
|
+
user: str | None = None,
|
59
|
+
imodel=None,
|
60
|
+
tools=None,
|
45
61
|
):
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
Examples:
|
64
|
-
>>> session = Session(system="you are a helpful assistant", sender="researcher")
|
65
|
-
"""
|
66
|
-
self.branches = branches if isinstance(branches, dict) else {}
|
67
|
-
self.service = service
|
68
|
-
self.setup_default_branch(
|
69
|
-
system=system,
|
70
|
-
sender=sender,
|
71
|
-
default_branch=default_branch,
|
72
|
-
default_branch_name=default_branch_name,
|
73
|
-
messages=messages,
|
74
|
-
# instruction_sets=instruction_sets,
|
75
|
-
tool_manager=tool_manager,
|
76
|
-
service=service,
|
77
|
-
llmconfig=llmconfig,
|
78
|
-
tools=tools,
|
79
|
-
persist_path=persist_path,
|
80
|
-
datalogger=datalogger,
|
81
|
-
)
|
82
|
-
self.mail_manager = MailManager(self.branches)
|
83
|
-
self.datalogger = self.default_branch.datalogger
|
84
|
-
for key, branch in self.branches.items():
|
85
|
-
branch.name = key
|
86
|
-
|
87
|
-
# --- default branch methods ---- #
|
88
|
-
|
89
|
-
@property
|
90
|
-
def messages(self):
|
91
|
-
return self.default_branch.messages
|
92
|
-
|
93
|
-
@property
|
94
|
-
def messages_describe(self):
|
95
|
-
"""
|
96
|
-
Provides a descriptive summary of all messages in the branch.
|
97
|
-
|
98
|
-
Returns:
|
99
|
-
dict[str, Any]: A dictionary containing summaries of messages by role and sender, total message count,
|
100
|
-
instruction sets, registered tools, and message details.
|
101
|
-
|
102
|
-
Examples:
|
103
|
-
>>> session.messages_describe
|
104
|
-
{'total_messages': 100, 'by_sender': {'User123': 60, 'Bot': 40}}
|
105
|
-
"""
|
106
|
-
return self.default_branch.messages_describe
|
107
|
-
|
108
|
-
@property
|
109
|
-
def has_tools(self) -> bool:
|
110
|
-
"""
|
111
|
-
Checks if there are any tools registered in the tool manager.
|
112
|
-
|
113
|
-
Returns:
|
114
|
-
bool: True if there are tools registered, False otherwise.
|
115
|
-
|
116
|
-
Examples:
|
117
|
-
>>> session.has_tools
|
118
|
-
True
|
119
|
-
"""
|
120
|
-
return self.default_branch.has_tools
|
121
|
-
|
122
|
-
@property
|
123
|
-
def last_message(self) -> dataframe.ln_DataFrame:
|
124
|
-
"""
|
125
|
-
Retrieves the last message from the conversation.
|
126
|
-
|
127
|
-
Returns:
|
128
|
-
pd.Series: The last message as a pandas Series.
|
129
|
-
"""
|
130
|
-
return self.default_branch.last_message
|
131
|
-
|
132
|
-
@property
|
133
|
-
def first_system(self) -> dataframe.ln_DataFrame:
|
134
|
-
"""
|
135
|
-
Retrieves the first system message from the conversation.
|
136
|
-
|
137
|
-
Returns:
|
138
|
-
pd.Series: The first system message as a pandas Series.
|
139
|
-
"""
|
140
|
-
return self.default_branch.first_system
|
141
|
-
|
142
|
-
@property
|
143
|
-
def last_response(self) -> dataframe.ln_DataFrame:
|
144
|
-
"""
|
145
|
-
Retrieves the last response message from the conversation.
|
146
|
-
|
147
|
-
Returns:
|
148
|
-
pd.Series: The last response message as a pandas Series.
|
149
|
-
"""
|
150
|
-
return self.default_branch.last_response
|
151
|
-
|
152
|
-
@property
|
153
|
-
def last_response_content(self) -> dict:
|
154
|
-
"""
|
155
|
-
Retrieves the content of the last response message from the conversation.
|
156
|
-
|
157
|
-
Returns:
|
158
|
-
dict: The content of the last response message as a dictionary
|
159
|
-
"""
|
160
|
-
return self.default_branch.last_response_content
|
161
|
-
|
162
|
-
@property
|
163
|
-
def tool_request(self) -> dataframe.ln_DataFrame:
|
164
|
-
"""
|
165
|
-
Retrieves all tool request messages from the conversation.
|
166
|
-
|
167
|
-
Returns:
|
168
|
-
dataframe.ln_DataFrame: A DataFrame containing all tool request messages.
|
169
|
-
"""
|
170
|
-
return self.default_branch.tool_request
|
171
|
-
|
172
|
-
@property
|
173
|
-
def tool_response(self) -> dataframe.ln_DataFrame:
|
174
|
-
"""
|
175
|
-
Retrieves all tool response messages from the conversation.
|
176
|
-
|
177
|
-
Returns:
|
178
|
-
dataframe.ln_DataFrame: A DataFrame containing all tool response messages.
|
179
|
-
"""
|
180
|
-
return self.default_branch.tool_response
|
181
|
-
|
182
|
-
@property
|
183
|
-
def responses(self) -> dataframe.ln_DataFrame:
|
184
|
-
"""
|
185
|
-
Retrieves all response messages from the conversation.
|
186
|
-
|
187
|
-
Returns:
|
188
|
-
dataframe.ln_DataFrame: A DataFrame containing all response messages.
|
189
|
-
"""
|
190
|
-
return self.default_branch.responses
|
191
|
-
|
192
|
-
@property
|
193
|
-
def assistant_responses(self) -> dataframe.ln_DataFrame:
|
194
|
-
"""
|
195
|
-
Retrieves all assistant responses from the conversation, excluding tool requests and responses.
|
196
|
-
|
197
|
-
Returns:
|
198
|
-
dataframe.ln_DataFrame: A DataFrame containing assistant responses excluding tool requests and responses.
|
199
|
-
"""
|
200
|
-
return self.default_branch.assistant_responses
|
201
|
-
|
202
|
-
@property
|
203
|
-
def info(self) -> dict[str, int]:
|
204
|
-
"""
|
205
|
-
Get a summary of the conversation messages categorized by role.
|
206
|
-
|
207
|
-
Returns:
|
208
|
-
dict[str, int]: A dictionary with keys as message roles and values as counts.
|
209
|
-
"""
|
210
|
-
|
211
|
-
return self.default_branch.info
|
212
|
-
|
213
|
-
@property
|
214
|
-
def sender_info(self) -> dict[str, int]:
|
215
|
-
"""
|
216
|
-
Provides a descriptive summary of the conversation, including total message count and summary by sender.
|
217
|
-
|
218
|
-
Returns:
|
219
|
-
dict[str, Any]: A dictionary containing the total number of messages and a summary categorized by sender.
|
220
|
-
"""
|
221
|
-
return self.default_branch.sender_info
|
222
|
-
|
223
|
-
def register_tools(self, tools):
|
224
|
-
self.default_branch.register_tools(tools)
|
225
|
-
|
226
|
-
@classmethod
|
227
|
-
def from_csv(
|
228
|
-
cls,
|
229
|
-
filepath: Path | str,
|
230
|
-
system: dict | list | System | None = None,
|
231
|
-
sender: str | None = None,
|
232
|
-
llmconfig: dict[str, str | int | dict] | None = None,
|
233
|
-
service: BaseService = None,
|
234
|
-
default_branch_name: str = "main",
|
235
|
-
tools: TOOL_TYPE = False, # instruction_sets=None,
|
236
|
-
tool_manager=None,
|
237
|
-
**kwargs,
|
238
|
-
) -> "Session":
|
239
|
-
"""
|
240
|
-
Creates a Session instance from a CSV file containing messages.
|
241
|
-
|
242
|
-
Args:
|
243
|
-
filepath (str): Path to the CSV file.
|
244
|
-
name (str | None): Name of the branch, default is None.
|
245
|
-
instruction_sets (Optional[dict[str, InstructionSet]]): Instruction sets, default is None.
|
246
|
-
tool_manager (Optional[ToolManager]): Tool manager for the branch, default is None.
|
247
|
-
service (BaseService]): External service for the branch, default | Noneis None.
|
248
|
-
llmconfig (Optional[dict]): Configuration for language learning models, default is None.
|
249
|
-
tools (TOOL_TYPE | None): Initial list of tools to register, default is None.
|
250
|
-
**kwargs: Additional keyword arguments for pd.read_csv().
|
251
|
-
|
252
|
-
Returns:
|
253
|
-
Branch: A new Branch instance created from the CSV data.
|
254
|
-
|
255
|
-
Examples:
|
256
|
-
>>> branch = Branch.from_csv("path/to/messages.csv", name="ImportedBranch")
|
257
|
-
"""
|
258
|
-
df = dataframe.read_csv(filepath, **kwargs)
|
259
|
-
|
260
|
-
return cls(
|
261
|
-
system=system,
|
262
|
-
sender=sender,
|
263
|
-
llmconfig=llmconfig,
|
264
|
-
service=service,
|
265
|
-
default_branch_name=default_branch_name,
|
266
|
-
tools=tools,
|
267
|
-
tool_manager=tool_manager,
|
268
|
-
messages=df,
|
269
|
-
**kwargs,
|
270
|
-
)
|
62
|
+
self.ln_id = SysUtil.create_id()
|
63
|
+
self.timestamp = SysUtil.get_timestamp(sep=None)[:-6]
|
64
|
+
system = system or "You are a helpful assistant, let's think step by step"
|
65
|
+
self.system = System(system=system, sender=system_sender)
|
66
|
+
self.system_sender = system_sender
|
67
|
+
self.branches: Pile[Branch] = self._validate_branches(branches)
|
68
|
+
self.mail_transfer = Exchange()
|
69
|
+
self.mail_manager = MailManager([self.mail_transfer])
|
70
|
+
self.imodel = imodel or iModel()
|
71
|
+
self.user = user
|
72
|
+
self.default_branch = None
|
73
|
+
if self.branches.size() == 0:
|
74
|
+
self.new_branch(system=self.system.clone())
|
75
|
+
else:
|
76
|
+
self.default_branch = self.branches[0]
|
77
|
+
if tools:
|
78
|
+
self.default_branch.tool_manager.register_tools(tools)
|
271
79
|
|
272
|
-
|
273
|
-
def from_json(
|
274
|
-
cls,
|
275
|
-
filepath: Path | str,
|
276
|
-
system: dict | list | System | None = None,
|
277
|
-
sender: str | None = None,
|
278
|
-
llmconfig: dict[str, str | int | dict] | None = None,
|
279
|
-
service: BaseService = None,
|
280
|
-
default_branch_name: str = "main",
|
281
|
-
tools: TOOL_TYPE = False, # instruction_sets=None,
|
282
|
-
tool_manager=None,
|
283
|
-
**kwargs,
|
284
|
-
) -> "Session":
|
80
|
+
def _validate_branches(self, value):
|
285
81
|
"""
|
286
|
-
|
82
|
+
Validates and converts the branches input to a Pile of Branch objects.
|
287
83
|
|
288
84
|
Args:
|
289
|
-
|
290
|
-
name (str | None): Name of the branch, default is None.
|
291
|
-
instruction_sets (Optional[dict[str, InstructionSet]]): Instruction sets, default is None.
|
292
|
-
tool_manager (Optional[ToolManager]): Tool manager for the branch, default is None.
|
293
|
-
service (BaseService]): External service for the branch, default | Noneis None.
|
294
|
-
llmconfig (Optional[dict]): Configuration for language learning models, default is None.
|
295
|
-
**kwargs: Additional keyword arguments for pd.read_json().
|
85
|
+
value (Any): The input value to validate and convert.
|
296
86
|
|
297
87
|
Returns:
|
298
|
-
|
299
|
-
|
300
|
-
Examples:
|
301
|
-
>>> branch = Branch.from_json_string("path/to/messages.json", name="JSONBranch")
|
302
|
-
"""
|
303
|
-
df = dataframe.read_json(filepath, **kwargs)
|
304
|
-
return cls(
|
305
|
-
system=system,
|
306
|
-
sender=sender,
|
307
|
-
llmconfig=llmconfig,
|
308
|
-
service=service,
|
309
|
-
default_branch_name=default_branch_name,
|
310
|
-
tools=tools, # instruction_sets=instruction_sets,
|
311
|
-
tool_manager=tool_manager,
|
312
|
-
messages=df,
|
313
|
-
**kwargs,
|
314
|
-
)
|
315
|
-
|
316
|
-
def to_csv_file(
|
317
|
-
self,
|
318
|
-
filename: str = "messages.csv",
|
319
|
-
dir_exist_ok: bool = True,
|
320
|
-
timestamp: bool = True,
|
321
|
-
time_prefix: bool = False,
|
322
|
-
verbose: bool = True,
|
323
|
-
clear: bool = True,
|
324
|
-
**kwargs,
|
325
|
-
):
|
326
|
-
"""
|
327
|
-
Saves the branch's messages to a CSV file.
|
328
|
-
|
329
|
-
Args:
|
330
|
-
filename (str): The name of the output CSV file, default is 'messages.csv'.
|
331
|
-
dir_exist_ok (bool): If True, does not raise an error if the directory already exists, default is True.
|
332
|
-
timestamp (bool): If True, appends a timestamp to the filename, default is True.
|
333
|
-
time_prefix (bool): If True, adds a timestamp prefix to the filename, default is False.
|
334
|
-
verbose (bool): If True, prints a message upon successful save, default is True.
|
335
|
-
clear (bool): If True, clears the messages after saving, default is True.
|
336
|
-
**kwargs: Additional keyword arguments for DataFrame.to_csv().
|
337
|
-
|
338
|
-
Examples:
|
339
|
-
>>> branch.to_csv_file("exported_messages.csv")
|
340
|
-
>>> branch.to_csv_file("timed_export.csv", timestamp=True, time_prefix=True)
|
341
|
-
"""
|
342
|
-
for name, branch in self.branches.items():
|
343
|
-
f_name = f"{name}_{filename}"
|
344
|
-
branch.to_csv_file(
|
345
|
-
filename=f_name,
|
346
|
-
dir_exist_ok=dir_exist_ok,
|
347
|
-
timestamp=timestamp,
|
348
|
-
time_prefix=time_prefix,
|
349
|
-
verbose=verbose,
|
350
|
-
clear=clear,
|
351
|
-
**kwargs,
|
352
|
-
)
|
353
|
-
|
354
|
-
def to_json_file(
|
355
|
-
self,
|
356
|
-
filename: str = "messages.json",
|
357
|
-
dir_exist_ok: bool = False,
|
358
|
-
timestamp: bool = True,
|
359
|
-
time_prefix: bool = False,
|
360
|
-
verbose: bool = True,
|
361
|
-
clear: bool = True,
|
362
|
-
**kwargs,
|
363
|
-
):
|
364
|
-
"""
|
365
|
-
Saves the branch's messages to a JSON file.
|
366
|
-
|
367
|
-
Args:
|
368
|
-
filename (str): The name of the output JSON file, default is 'messages.json'.
|
369
|
-
dir_exist_ok (bool): If True, does not raise an error if the directory already exists, default is True.
|
370
|
-
timestamp (bool): If True, appends a timestamp to the filename, default is True.
|
371
|
-
time_prefix (bool): If True, adds a timestamp prefix to the filename, default is False.
|
372
|
-
verbose (bool): If True, prints a message upon successful save, default is True.
|
373
|
-
clear (bool): If True, clears the messages after saving, default is True.
|
374
|
-
**kwargs: Additional keyword arguments for DataFrame.to_json().
|
375
|
-
|
376
|
-
Examples:
|
377
|
-
>>> branch.to_json_file("exported_messages.json")
|
378
|
-
>>> branch.to_json_file("timed_export.json", timestamp=True, time_prefix=True)
|
379
|
-
"""
|
380
|
-
|
381
|
-
for name, branch in self.branches.items():
|
382
|
-
f_name = f"{name}_{filename}"
|
383
|
-
branch.to_json_file(
|
384
|
-
filename=f_name,
|
385
|
-
dir_exist_ok=dir_exist_ok,
|
386
|
-
timestamp=timestamp,
|
387
|
-
time_prefix=time_prefix,
|
388
|
-
verbose=verbose,
|
389
|
-
clear=clear,
|
390
|
-
**kwargs,
|
391
|
-
)
|
392
|
-
|
393
|
-
def log_to_csv(
|
394
|
-
self,
|
395
|
-
filename: str = "log.csv",
|
396
|
-
dir_exist_ok: bool = True,
|
397
|
-
timestamp: bool = True,
|
398
|
-
time_prefix: bool = False,
|
399
|
-
verbose: bool = True,
|
400
|
-
clear: bool = True,
|
401
|
-
**kwargs,
|
402
|
-
):
|
403
|
-
"""
|
404
|
-
Saves the branch's log data to a CSV file.
|
405
|
-
|
406
|
-
This method is designed to export log data, potentially including operations and intertools,
|
407
|
-
to a CSV file for analysis or record-keeping.
|
88
|
+
Pile[Branch]: A pile of validated branches.
|
408
89
|
|
409
|
-
|
410
|
-
|
411
|
-
dir_exist_ok (bool): If True, will not raise an error if the directory already exists. Defaults to True.
|
412
|
-
timestamp (bool): If True, appends a timestamp to the filename for uniqueness. Defaults to True.
|
413
|
-
time_prefix (bool): If True, adds a timestamp prefix to the filename. Defaults to False.
|
414
|
-
verbose (bool): If True, prints a success message upon completion. Defaults to True.
|
415
|
-
clear (bool): If True, clears the log after saving. Defaults to True.
|
416
|
-
**kwargs: Additional keyword arguments for `DataFrame.to_csv()`.
|
417
|
-
|
418
|
-
Examples:
|
419
|
-
>>> branch.log_to_csv("branch_log.csv")
|
420
|
-
>>> branch.log_to_csv("detailed_branch_log.csv", timestamp=True, verbose=True)
|
421
|
-
"""
|
422
|
-
for name, branch in self.branches.items():
|
423
|
-
f_name = f"{name}_{filename}"
|
424
|
-
branch.log_to_csv(
|
425
|
-
filename=f_name,
|
426
|
-
dir_exist_ok=dir_exist_ok,
|
427
|
-
timestamp=timestamp,
|
428
|
-
time_prefix=time_prefix,
|
429
|
-
verbose=verbose,
|
430
|
-
clear=clear,
|
431
|
-
**kwargs,
|
432
|
-
)
|
433
|
-
|
434
|
-
def log_to_json(
|
435
|
-
self,
|
436
|
-
filename: str = "log.json",
|
437
|
-
dir_exist_ok: bool = True,
|
438
|
-
timestamp: bool = True,
|
439
|
-
time_prefix: bool = False,
|
440
|
-
verbose: bool = True,
|
441
|
-
clear: bool = True,
|
442
|
-
**kwargs,
|
443
|
-
):
|
444
|
-
"""
|
445
|
-
Saves the branch's log data to a JSON file.
|
446
|
-
|
447
|
-
Useful for exporting log data in JSON format, allowing for easy integration with web applications
|
448
|
-
and services that consume JSON.
|
449
|
-
|
450
|
-
Args:
|
451
|
-
filename (str): The name of the output JSON file. Defaults to 'log.json'.
|
452
|
-
dir_exist_ok (bool): If directory existence should not raise an error. Defaults to True.
|
453
|
-
timestamp (bool): If True, appends a timestamp to the filename. Defaults to True.
|
454
|
-
time_prefix (bool): If True, adds a timestamp prefix to the filename. Defaults to False.
|
455
|
-
verbose (bool): If True, prints a success message upon completion. Defaults to True.
|
456
|
-
clear (bool): If True, clears the log after saving. Defaults to True.
|
457
|
-
**kwargs: Additional keyword arguments for `DataFrame.to_json()`.
|
458
|
-
|
459
|
-
Examples:
|
460
|
-
>>> branch.log_to_json("branch_log.json")
|
461
|
-
>>> branch.log_to_json("detailed_branch_log.json", verbose=True, timestamp=True)
|
462
|
-
"""
|
463
|
-
for name, branch in self.branches.items():
|
464
|
-
f_name = f"{name}_{filename}"
|
465
|
-
branch.log_to_json(
|
466
|
-
filename=f_name,
|
467
|
-
dir_exist_ok=dir_exist_ok,
|
468
|
-
timestamp=timestamp,
|
469
|
-
time_prefix=time_prefix,
|
470
|
-
verbose=verbose,
|
471
|
-
clear=clear,
|
472
|
-
**kwargs,
|
473
|
-
)
|
474
|
-
|
475
|
-
@property
|
476
|
-
def all_messages(self) -> dataframe.ln_DataFrame:
|
477
|
-
"""
|
478
|
-
return all messages across branches
|
90
|
+
Raises:
|
91
|
+
ValueError: If the input value contains non-Branch objects.
|
479
92
|
"""
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
93
|
+
if isinstance(value, Pile):
|
94
|
+
for branch in value:
|
95
|
+
if not isinstance(branch, Branch):
|
96
|
+
raise ValueError("The branches pile contains non-Branch object")
|
97
|
+
return value
|
98
|
+
else:
|
99
|
+
try:
|
100
|
+
value = pile(items=value, item_type=Branch)
|
101
|
+
return value
|
102
|
+
except Exception as e:
|
103
|
+
raise ValueError(f"Invalid branches value. Error:{e}")
|
484
104
|
|
485
|
-
#
|
486
|
-
|
105
|
+
# ---- branch manipulation ---- #
|
106
|
+
def new_branch(
|
487
107
|
self,
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
108
|
+
system: System | None = None,
|
109
|
+
system_sender: str | None = None,
|
110
|
+
user: str | None = None,
|
111
|
+
messages: Pile = None,
|
112
|
+
progress: Progression = None,
|
113
|
+
tool_manager: ToolManager = None,
|
114
|
+
tools: Any = None,
|
115
|
+
imodel=None,
|
492
116
|
):
|
493
117
|
"""
|
494
|
-
|
495
|
-
|
496
|
-
This method prepares the messages for chat completion, sends the request to the configured service, and handles the response. The method supports additional keyword arguments that are passed directly to the service.
|
118
|
+
Creates a new branch and adds it to the session.
|
497
119
|
|
498
120
|
Args:
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
await branch.call_chatcompletion(
|
508
|
-
sender=sender,
|
509
|
-
with_sender=with_sender,
|
510
|
-
**kwargs,
|
511
|
-
)
|
512
|
-
|
513
|
-
async def chat(
|
514
|
-
self,
|
515
|
-
instruction: dict | list | Instruction | str,
|
516
|
-
branch: Branch | str | None = None,
|
517
|
-
context: dict | list | str = None,
|
518
|
-
sender: str | None = None,
|
519
|
-
system: dict | list | System | None = None,
|
520
|
-
tools: TOOL_TYPE = False,
|
521
|
-
out: bool = True,
|
522
|
-
invoke: bool = True,
|
523
|
-
output_fields=None,
|
524
|
-
**kwargs,
|
525
|
-
) -> str | None:
|
526
|
-
"""
|
527
|
-
a chat conversation with LLM, processing instructions and system messages, optionally invoking tools.
|
121
|
+
system (System, optional): The system message for the branch.
|
122
|
+
system_sender (str, optional): The sender of the system message.
|
123
|
+
user (str, optional): The user associated with the branch.
|
124
|
+
messages (Pile, optional): The pile of messages for the branch.
|
125
|
+
progress (Progression, optional): The progression of messages.
|
126
|
+
tool_manager (ToolManager, optional): The tool manager for the branch.
|
127
|
+
tools (Any, optional): The tools to register with the tool manager.
|
128
|
+
imodel (iModel, optional): The model associated with the branch.
|
528
129
|
|
529
|
-
|
530
|
-
|
531
|
-
instruction (dict | list | Instruction | str): The instruction for the chat.
|
532
|
-
context (Optional[Any]): Additional context for the chat.
|
533
|
-
sender (str | None): The sender of the chat message.
|
534
|
-
system (Optional[Union[System, str, dict[str, Any]]]): System message to be processed.
|
535
|
-
tools (Union[bool, Tool, List[Tool], str, List[str]]): Specifies tools to be invoked.
|
536
|
-
out (bool): If True, outputs the chat response.
|
537
|
-
invoke (bool): If True, invokes tools as part of the chat.
|
538
|
-
**kwargs: Arbitrary keyword arguments for chat completion.
|
539
|
-
|
540
|
-
Examples:
|
541
|
-
>>> await ChatFlow.chat(branch, "Ask about user preferences")
|
130
|
+
Returns:
|
131
|
+
Branch: The created branch.
|
542
132
|
"""
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
sender=sender,
|
133
|
+
if system is None:
|
134
|
+
system = self.system.clone()
|
135
|
+
system.sender = self.ln_id
|
136
|
+
system_sender = self.ln_id
|
137
|
+
branch = Branch(
|
549
138
|
system=system,
|
139
|
+
system_sender=system_sender,
|
140
|
+
user=user,
|
141
|
+
messages=messages,
|
142
|
+
progress=progress,
|
143
|
+
tool_manager=tool_manager,
|
550
144
|
tools=tools,
|
551
|
-
|
552
|
-
invoke=invoke,
|
553
|
-
output_fields=output_fields,
|
554
|
-
**kwargs,
|
145
|
+
imodel=imodel or self.imodel,
|
555
146
|
)
|
147
|
+
self.branches.append(branch)
|
148
|
+
self.mail_manager.add_sources(branch)
|
149
|
+
if self.default_branch is None:
|
150
|
+
self.default_branch = branch
|
151
|
+
return branch
|
556
152
|
|
557
|
-
|
558
|
-
self,
|
559
|
-
instruction: dict | list | Instruction | str,
|
560
|
-
branch: Branch | str | None = None,
|
561
|
-
context=None,
|
562
|
-
sender=None,
|
563
|
-
system=None,
|
564
|
-
tools=None,
|
565
|
-
auto=False,
|
566
|
-
num_rounds: int = 1,
|
567
|
-
reason_prompt=None,
|
568
|
-
action_prompt=None,
|
569
|
-
output_prompt=None,
|
570
|
-
**kwargs,
|
571
|
-
):
|
153
|
+
def delete_branch(self, branch):
|
572
154
|
"""
|
573
|
-
|
155
|
+
Deletes a branch from the session.
|
574
156
|
|
575
157
|
Args:
|
576
|
-
|
577
|
-
instruction (dict | list | Instruction | str): Initial instruction for the cycle.
|
578
|
-
context: Context relevant to the instruction.
|
579
|
-
sender (str | None): Identifier for the message sender.
|
580
|
-
system: Initial system message or configuration.
|
581
|
-
tools: Tools to be registered or used during the cycle.
|
582
|
-
num_rounds (int): Number of reason-tool cycles to perform.
|
583
|
-
**kwargs: Additional keyword arguments for customization.
|
584
|
-
|
585
|
-
Examples:
|
586
|
-
>>> await ChatFlow.ReAct(branch, "Analyze user feedback", num_rounds=2)
|
158
|
+
branch (Branch | str): The branch or its ID to delete.
|
587
159
|
"""
|
588
|
-
|
160
|
+
branch_id = get_lion_id(branch)
|
161
|
+
self.branches.pop(branch_id)
|
162
|
+
self.mail_manager.delete_source(branch_id)
|
589
163
|
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
tools=tools,
|
596
|
-
auto=auto,
|
597
|
-
num_rounds=num_rounds,
|
598
|
-
reason_prompt=reason_prompt,
|
599
|
-
action_prompt=action_prompt,
|
600
|
-
output_prompt=output_prompt,
|
601
|
-
**kwargs,
|
602
|
-
)
|
164
|
+
if self.default_branch == branch:
|
165
|
+
if self.branches.size() == 0:
|
166
|
+
self.default_branch = None
|
167
|
+
else:
|
168
|
+
self.default_branch = self.branches[0]
|
603
169
|
|
604
|
-
|
605
|
-
self,
|
606
|
-
instruction: dict | list | Instruction | str,
|
607
|
-
branch=None,
|
608
|
-
context=None,
|
609
|
-
sender=None,
|
610
|
-
system=None,
|
611
|
-
tools=None,
|
612
|
-
max_followup: int = 1,
|
613
|
-
auto=False,
|
614
|
-
followup_prompt=None,
|
615
|
-
output_prompt=None,
|
616
|
-
out=True,
|
617
|
-
**kwargs,
|
618
|
-
):
|
170
|
+
def split_branch(self, branch):
|
619
171
|
"""
|
620
|
-
|
172
|
+
Splits a branch, creating a new branch with the same messages and tools.
|
621
173
|
|
622
174
|
Args:
|
623
|
-
|
624
|
-
instruction (dict | list | Instruction | str): The initial instruction for follow-up.
|
625
|
-
context: Context relevant to the instruction.
|
626
|
-
sender (str | None): Identifier for the message sender.
|
627
|
-
system: Initial system message or configuration.
|
628
|
-
tools: Specifies tools to be considered for follow-up tools.
|
629
|
-
max_followup (int): Maximum number of follow-up chats allowed.
|
630
|
-
out (bool): If True, outputs the result of the follow-up tool.
|
631
|
-
**kwargs: Additional keyword arguments for follow-up customization.
|
632
|
-
|
633
|
-
Examples:
|
634
|
-
>>> await ChatFlow.auto_followup(branch, "Finalize report", max_followup=2)
|
635
|
-
"""
|
636
|
-
branch = self.get_branch(branch)
|
637
|
-
return await branch.followup(
|
638
|
-
instruction=instruction,
|
639
|
-
context=context,
|
640
|
-
sender=sender,
|
641
|
-
system=system,
|
642
|
-
tools=tools,
|
643
|
-
max_followup=max_followup,
|
644
|
-
auto=auto,
|
645
|
-
followup_prompt=followup_prompt,
|
646
|
-
output_prompt=output_prompt,
|
647
|
-
out=out,
|
648
|
-
**kwargs,
|
649
|
-
)
|
175
|
+
branch (Branch | str): The branch or its ID to split.
|
650
176
|
|
651
|
-
|
652
|
-
|
653
|
-
instruction: Instruction | str,
|
654
|
-
num_instances=1,
|
655
|
-
context=None,
|
656
|
-
sender=None,
|
657
|
-
branch_system=None,
|
658
|
-
messages=None,
|
659
|
-
tools=False,
|
660
|
-
out=True,
|
661
|
-
invoke: bool = True,
|
662
|
-
output_fields=None,
|
663
|
-
persist_path=None,
|
664
|
-
branch_config=None,
|
665
|
-
explode=False,
|
666
|
-
include_mapping=False,
|
667
|
-
**kwargs,
|
668
|
-
):
|
669
|
-
"""
|
670
|
-
parallel chat
|
177
|
+
Returns:
|
178
|
+
Branch: The newly created branch.
|
671
179
|
"""
|
672
|
-
|
673
|
-
if
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
persist_path=persist_path,
|
689
|
-
branch_config=branch_config,
|
690
|
-
explode=explode,
|
691
|
-
include_mapping=include_mapping,
|
692
|
-
**kwargs,
|
180
|
+
branch = self.branches[branch]
|
181
|
+
system = branch.system.clone() if branch.system else None
|
182
|
+
if system:
|
183
|
+
system.sender = branch.ln_id
|
184
|
+
progress = progression()
|
185
|
+
messages = pile()
|
186
|
+
|
187
|
+
for id_ in branch.progress:
|
188
|
+
clone_message = branch.messages[id_].clone()
|
189
|
+
progress.append(clone_message.ln_id)
|
190
|
+
messages.append(clone_message)
|
191
|
+
|
192
|
+
tools = (
|
193
|
+
list(branch.tool_manager.registry.values())
|
194
|
+
if branch.tool_manager.registry
|
195
|
+
else None
|
693
196
|
)
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
system: dict | list | System | None = None,
|
700
|
-
sender: str | None = None,
|
701
|
-
messages: dataframe.ln_DataFrame | None = None,
|
702
|
-
tool_manager=None,
|
703
|
-
service=None,
|
704
|
-
llmconfig=None,
|
705
|
-
tools: TOOL_TYPE = False,
|
706
|
-
) -> None:
|
707
|
-
"""Create a new branch with the specified configurations.
|
708
|
-
|
709
|
-
Args:
|
710
|
-
branch_name (str | None): Name of the new branch.
|
711
|
-
system (Optional[Union[System, str]]): System or context identifier for the new branch.
|
712
|
-
sender (str | None): Default sender identifier for the new branch.
|
713
|
-
messages (Optional[dataframe.ln_DataFrame]): Initial set of messages for the new branch.
|
714
|
-
instruction_sets (Optional[Any]): Instruction sets for the new branch.
|
715
|
-
tool_manager (Optional[Any]): Tool manager for handling tools in the new branch.
|
716
|
-
service (BaseService]): External service instance for the ne | None branch.
|
717
|
-
llmconfig (dict[str, Any] | None): Configuration for language learning models in the new branch.
|
718
|
-
tools (TOOL_TYPE | None): List of tools available for the new branch.
|
719
|
-
|
720
|
-
Raises:
|
721
|
-
ValueError: If the branch name already exists.
|
722
|
-
|
723
|
-
Examples:
|
724
|
-
>>> session.new_branch("new_branch_name")
|
725
|
-
"""
|
726
|
-
if branch_name in self.branches.keys():
|
727
|
-
raise ValueError(
|
728
|
-
f"Invalid new branch name {branch_name}. Branch already existed."
|
729
|
-
)
|
730
|
-
if isinstance(tools, Tool):
|
731
|
-
tools = [tools]
|
732
|
-
new_branch = Branch(
|
733
|
-
name=branch_name,
|
197
|
+
branch_clone = Branch(
|
198
|
+
system=system,
|
199
|
+
system_sender=branch.ln_id,
|
200
|
+
user=branch.user,
|
201
|
+
progress=progress,
|
734
202
|
messages=messages,
|
735
|
-
tool_manager=tool_manager,
|
736
|
-
service=service,
|
737
|
-
llmconfig=llmconfig,
|
738
203
|
tools=tools,
|
739
204
|
)
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
self.branches
|
744
|
-
self.mail_manager.
|
745
|
-
|
746
|
-
|
747
|
-
def get_branch(
|
748
|
-
self, branch: Branch | str | None = None, get_name: bool = False
|
749
|
-
) -> Branch | Tuple[Branch, str]:
|
750
|
-
"""
|
751
|
-
Retrieve a branch by name or instance.
|
752
|
-
|
753
|
-
Args:
|
754
|
-
branch (Optional[Branch | str]): The branch name or instance to retrieve.
|
755
|
-
get_name (bool): If True, returns a tuple of the branch instance and its name.
|
756
|
-
|
757
|
-
Returns:
|
758
|
-
Union[Branch, Tuple[Branch, str]]: The branch instance or a tuple of the branch instance and its name.
|
759
|
-
|
760
|
-
Raises:
|
761
|
-
ValueError: If the branch name does not exist or the branch input is invalid.
|
205
|
+
for message in branch_clone.messages:
|
206
|
+
message.sender = branch.ln_id
|
207
|
+
message.recipient = branch_clone.ln_id
|
208
|
+
self.branches.append(branch_clone)
|
209
|
+
self.mail_manager.add_sources(branch_clone)
|
210
|
+
return branch_clone
|
762
211
|
|
763
|
-
|
764
|
-
>>> branch_instance = session.get_branch("existing_branch_name")
|
765
|
-
>>> branch_instance, branch_name = session.get_branch("existing_branch_name", get_name=True)
|
212
|
+
def change_default_branch(self, branch):
|
766
213
|
"""
|
767
|
-
|
768
|
-
if branch not in self.branches.keys():
|
769
|
-
raise ValueError(f"Invalid branch name {branch}. Not exist.")
|
770
|
-
return (
|
771
|
-
(self.branches[branch], branch) if get_name else self.branches[branch]
|
772
|
-
)
|
773
|
-
elif isinstance(branch, Branch) and branch in self.branches.values():
|
774
|
-
return (branch, branch.name) if get_name else branch
|
775
|
-
elif branch is None:
|
776
|
-
if get_name:
|
777
|
-
return self.default_branch, self.default_branch_name
|
778
|
-
return self.default_branch
|
779
|
-
|
780
|
-
else:
|
781
|
-
raise ValueError(f"Invalid branch input {branch}.")
|
782
|
-
|
783
|
-
def change_default_branch(self, branch: str | Branch) -> None:
|
784
|
-
"""Change the default branch of the session.
|
785
|
-
|
786
|
-
Args:
|
787
|
-
branch (str | Branch): The branch name or instance to set as the new default.
|
788
|
-
|
789
|
-
Examples:
|
790
|
-
>>> session.change_default_branch("new_default_branch")
|
791
|
-
"""
|
792
|
-
branch_, name_ = self.get_branch(branch, get_name=True)
|
793
|
-
self.default_branch = branch_
|
794
|
-
self.default_branch_name = name_
|
795
|
-
|
796
|
-
def delete_branch(self, branch: Branch | str, verbose: bool = True) -> bool:
|
797
|
-
"""Delete a branch from the session.
|
214
|
+
Changes the default branch of the session.
|
798
215
|
|
799
216
|
Args:
|
800
|
-
|
801
|
-
verbose (bool): If True, prints a message upon deletion.
|
802
|
-
|
803
|
-
Returns:
|
804
|
-
bool: True if the branch was successfully deleted.
|
805
|
-
|
806
|
-
Raises:
|
807
|
-
ValueError: If attempting to delete the current default branch.
|
808
|
-
|
809
|
-
Examples:
|
810
|
-
>>> session.delete_branch("branch_to_delete")
|
217
|
+
branch (Branch | str): The branch or its ID to set as the default.
|
811
218
|
"""
|
812
|
-
|
813
|
-
|
814
|
-
if branch_name == self.default_branch_name:
|
815
|
-
raise ValueError(
|
816
|
-
f"{branch_name} is the current default branch, please switch to another branch before delete it."
|
817
|
-
)
|
818
|
-
self.branches.pop(branch_name)
|
819
|
-
# self.mail_manager.sources.pop(branch_name)
|
820
|
-
self.mail_manager.mails.pop(branch_name)
|
821
|
-
if verbose:
|
822
|
-
print(f"Branch {branch_name} is deleted.")
|
823
|
-
return True
|
824
|
-
|
825
|
-
def merge_branch(
|
826
|
-
self,
|
827
|
-
from_: str | Branch,
|
828
|
-
to_branch: str | Branch,
|
829
|
-
update: bool = True,
|
830
|
-
del_: bool = False,
|
831
|
-
) -> None:
|
832
|
-
"""Merge messages and settings from one branch to another.
|
833
|
-
|
834
|
-
Args:
|
835
|
-
from_ (str | Branch): The source branch name or instance.
|
836
|
-
to_branch (str | Branch): The target branch name or instance where the merge will happen.
|
837
|
-
update (bool): If True, updates the target branch with the source branch's settings.
|
838
|
-
del_ (bool): If True, deletes the source branch after merging.
|
219
|
+
branch = self.branches[branch]
|
220
|
+
self.default_branch = branch
|
839
221
|
|
840
|
-
|
841
|
-
>>> session.merge_branch("source_branch", "target_branch", del_=True)
|
842
|
-
"""
|
843
|
-
from_ = self.get_branch(branch=from_)
|
844
|
-
to_branch, to_name = self.get_branch(branch=to_branch, get_name=True)
|
845
|
-
to_branch.merge_branch(from_, update=update)
|
846
|
-
|
847
|
-
if del_:
|
848
|
-
if from_ == self.default_branch:
|
849
|
-
self.default_branch_name = to_name
|
850
|
-
self.default_branch = to_branch
|
851
|
-
self.delete_branch(from_, verbose=False)
|
852
|
-
|
853
|
-
def take_branch(self, branch):
|
854
|
-
self.branches[branch.branch_name] = branch
|
855
|
-
self.mail_manager.sources[branch.id_] = branch
|
856
|
-
self.mail_manager.mails[branch.id_] = {}
|
857
|
-
|
858
|
-
def collect(self, from_: str | Branch | list[str | Branch] | None = None):
|
222
|
+
def collect(self, from_: Branch | str | Pile[Branch] | None = None):
|
859
223
|
"""
|
860
|
-
Collects
|
861
|
-
|
862
|
-
This method is intended to aggregate data or requests from one or more branches for processing or analysis.
|
224
|
+
Collects mail from specified branches.
|
863
225
|
|
864
226
|
Args:
|
865
|
-
|
866
|
-
|
867
|
-
If None, requests are collected from all branches.
|
868
|
-
|
869
|
-
Examples:
|
870
|
-
>>> session.collect("branch_name")
|
871
|
-
>>> session.collect([branch_instance_1, "branch_name_2"])
|
872
|
-
>>> session.collect() # Collects from all branches
|
227
|
+
from_ (Branch | str | Pile[Branch], optional): The branches to collect mail from.
|
228
|
+
If None, collects mail from all branches.
|
873
229
|
"""
|
874
230
|
if from_ is None:
|
875
|
-
|
876
|
-
self.mail_manager.collect(branch.id_)
|
231
|
+
self.mail_manager.collect_all()
|
877
232
|
else:
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
elif isinstance(branch, Branch):
|
885
|
-
self.mail_manager.collect(branch.id_)
|
886
|
-
|
887
|
-
def send(self, to_: str | Branch | list[str | Branch] | None = None):
|
888
|
-
"""
|
889
|
-
Sends requests or data to specified branches or to all branches if none are specified.
|
233
|
+
try:
|
234
|
+
sources = to_list_type(from_)
|
235
|
+
for source in sources:
|
236
|
+
self.mail_manager.collect(get_lion_id(source))
|
237
|
+
except Exception as e:
|
238
|
+
raise ValueError(f"Failed to collect mail. Error: {e}")
|
890
239
|
|
891
|
-
|
240
|
+
def send(self, to_: Branch | str | Pile[Branch] | None = None):
|
241
|
+
"""
|
242
|
+
Sends mail to specified branches.
|
892
243
|
|
893
244
|
Args:
|
894
|
-
|
895
|
-
|
896
|
-
If None, requests are sent to all branches.
|
897
|
-
|
898
|
-
Examples:
|
899
|
-
>>> session.send("target_branch")
|
900
|
-
>>> session.send([branch_instance_1, "target_branch_2"])
|
901
|
-
>>> session.send() # Sends to all branches
|
245
|
+
to_ (Branch | str | Pile[Branch], optional): The branches to send mail to.
|
246
|
+
If None, sends mail to all branches.
|
902
247
|
"""
|
903
248
|
if to_ is None:
|
904
|
-
|
905
|
-
self.mail_manager.send(branch.id_)
|
249
|
+
self.mail_manager.send_all()
|
906
250
|
else:
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
if isinstance(branch, Branch):
|
914
|
-
self.mail_manager.send(branch.id_)
|
251
|
+
try:
|
252
|
+
sources = to_list_type(to_)
|
253
|
+
for source in sources:
|
254
|
+
self.mail_manager.send(get_lion_id(source))
|
255
|
+
except Exception as e:
|
256
|
+
raise ValueError(f"Failed to send mail. Error: {e}")
|
915
257
|
|
916
258
|
def collect_send_all(self, receive_all=False):
|
917
259
|
"""
|
918
|
-
Collects and sends
|
919
|
-
|
920
|
-
This method is a convenience function for performing a full cycle of collect and send operations across all branches,
|
921
|
-
useful in scenarios where data or requests need to be aggregated and then distributed uniformly.
|
260
|
+
Collects and sends mail for all branches, optionally receiving all mail.
|
922
261
|
|
923
262
|
Args:
|
924
|
-
|
925
|
-
which can be used to process or acknowledge the received data.
|
926
|
-
|
927
|
-
Examples:
|
928
|
-
>>> session.collect_send_all()
|
929
|
-
>>> session.collect_send_all(receive_all=True)
|
263
|
+
receive_all (bool, optional): Whether to receive all mail for all branches.
|
930
264
|
"""
|
931
265
|
self.collect()
|
932
266
|
self.send()
|
933
267
|
if receive_all:
|
934
|
-
for branch in self.branches
|
268
|
+
for branch in self.branches:
|
935
269
|
branch.receive_all()
|
936
270
|
|
937
|
-
def
|
938
|
-
|
939
|
-
|
271
|
+
async def chat(self, *args, branch=None, **kwargs):
|
272
|
+
"""
|
273
|
+
Initiates a chat interaction with a branch.
|
940
274
|
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
if self.default_branch is not self.branches[self.default_branch_name]:
|
946
|
-
raise ValueError(
|
947
|
-
f"default branch does not match Branch object under {self.default_branch_name}"
|
948
|
-
)
|
275
|
+
Args:
|
276
|
+
*args: Positional arguments to pass to the chat method.
|
277
|
+
branch (Branch, optional): The branch to chat with. Defaults to the default branch.
|
278
|
+
**kwargs: Keyword arguments to pass to the chat method.
|
949
279
|
|
950
|
-
|
951
|
-
|
280
|
+
Returns:
|
281
|
+
Any: The result of the chat interaction.
|
952
282
|
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
service,
|
962
|
-
llmconfig,
|
963
|
-
tools,
|
964
|
-
persist_path,
|
965
|
-
datalogger,
|
966
|
-
):
|
283
|
+
Raises:
|
284
|
+
ValueError: If the specified branch is not found in the session branches.
|
285
|
+
"""
|
286
|
+
if branch is None:
|
287
|
+
branch = self.default_branch
|
288
|
+
if branch not in self.branches:
|
289
|
+
raise ValueError("Branch not found in session branches")
|
290
|
+
return await self.branches[branch].chat(*args, **kwargs)
|
967
291
|
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
llmconfig=llmconfig,
|
972
|
-
tools=tools,
|
973
|
-
tool_manager=tool_manager,
|
974
|
-
# instruction_sets=instruction_sets,
|
975
|
-
messages=messages,
|
976
|
-
persist_path=persist_path,
|
977
|
-
datalogger=datalogger,
|
978
|
-
)
|
292
|
+
async def direct(self, *args, branch=None, **kwargs):
|
293
|
+
"""
|
294
|
+
Initiates a direct interaction with a branch.
|
979
295
|
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
296
|
+
Args:
|
297
|
+
*args: Positional arguments to pass to the direct method.
|
298
|
+
branch (Branch, optional): The branch to interact with. Defaults to the default branch.
|
299
|
+
**kwargs: Keyword arguments to pass to the direct method.
|
984
300
|
|
985
|
-
|
301
|
+
Returns:
|
302
|
+
Any: The result of the direct interaction.
|
303
|
+
|
304
|
+
Raises:
|
305
|
+
ValueError: If the specified branch is not found in the session branches.
|
306
|
+
"""
|
307
|
+
if branch is None:
|
308
|
+
branch = self.default_branch
|
309
|
+
if branch not in self.branches:
|
310
|
+
raise ValueError("Branch not found in session branches")
|
311
|
+
return await self.branches[branch].direct(*args, **kwargs)
|