lionagi 0.0.316__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. lionagi/core/__init__.py +19 -8
  2. lionagi/core/agent/__init__.py +0 -3
  3. lionagi/core/agent/base_agent.py +25 -30
  4. lionagi/core/branch/__init__.py +0 -4
  5. lionagi/core/branch/{base_branch.py → base.py} +12 -13
  6. lionagi/core/branch/branch.py +22 -19
  7. lionagi/core/branch/executable_branch.py +0 -347
  8. lionagi/core/branch/{branch_flow_mixin.py → flow_mixin.py} +5 -5
  9. lionagi/core/direct/__init__.py +10 -1
  10. lionagi/core/direct/cot.py +61 -26
  11. lionagi/core/direct/plan.py +10 -8
  12. lionagi/core/direct/predict.py +5 -5
  13. lionagi/core/direct/react.py +8 -8
  14. lionagi/core/direct/score.py +4 -4
  15. lionagi/core/direct/select.py +4 -4
  16. lionagi/core/direct/utils.py +7 -4
  17. lionagi/core/direct/vote.py +2 -2
  18. lionagi/core/execute/base_executor.py +47 -0
  19. lionagi/core/execute/branch_executor.py +296 -0
  20. lionagi/core/execute/instruction_map_executor.py +179 -0
  21. lionagi/core/execute/neo4j_executor.py +381 -0
  22. lionagi/core/execute/structure_executor.py +314 -0
  23. lionagi/core/flow/monoflow/ReAct.py +20 -20
  24. lionagi/core/flow/monoflow/chat.py +6 -6
  25. lionagi/core/flow/monoflow/chat_mixin.py +23 -33
  26. lionagi/core/flow/monoflow/followup.py +14 -15
  27. lionagi/core/flow/polyflow/chat.py +15 -12
  28. lionagi/core/{prompt/action_template.py → form/action_form.py} +2 -2
  29. lionagi/core/{prompt → form}/field_validator.py +40 -31
  30. lionagi/core/form/form.py +302 -0
  31. lionagi/core/form/mixin.py +214 -0
  32. lionagi/core/{prompt/scored_template.py → form/scored_form.py} +2 -2
  33. lionagi/core/generic/__init__.py +37 -0
  34. lionagi/core/generic/action.py +26 -0
  35. lionagi/core/generic/component.py +455 -0
  36. lionagi/core/generic/condition.py +44 -0
  37. lionagi/core/generic/data_logger.py +305 -0
  38. lionagi/core/generic/edge.py +162 -0
  39. lionagi/core/generic/mail.py +90 -0
  40. lionagi/core/generic/mailbox.py +36 -0
  41. lionagi/core/generic/node.py +285 -0
  42. lionagi/core/generic/relation.py +70 -0
  43. lionagi/core/generic/signal.py +22 -0
  44. lionagi/core/generic/structure.py +362 -0
  45. lionagi/core/generic/transfer.py +20 -0
  46. lionagi/core/generic/work.py +40 -0
  47. lionagi/core/graph/graph.py +126 -0
  48. lionagi/core/graph/tree.py +190 -0
  49. lionagi/core/mail/__init__.py +0 -8
  50. lionagi/core/mail/mail_manager.py +15 -12
  51. lionagi/core/mail/schema.py +9 -2
  52. lionagi/core/messages/__init__.py +0 -3
  53. lionagi/core/messages/schema.py +17 -225
  54. lionagi/core/session/__init__.py +0 -3
  55. lionagi/core/session/session.py +24 -22
  56. lionagi/core/tool/__init__.py +3 -1
  57. lionagi/core/tool/tool.py +28 -0
  58. lionagi/core/tool/tool_manager.py +75 -75
  59. lionagi/experimental/directive/evaluator/__init__.py +0 -0
  60. lionagi/experimental/directive/evaluator/ast_evaluator.py +115 -0
  61. lionagi/experimental/directive/evaluator/base_evaluator.py +202 -0
  62. lionagi/experimental/directive/evaluator/sandbox_.py +14 -0
  63. lionagi/experimental/directive/evaluator/script_engine.py +83 -0
  64. lionagi/experimental/directive/parser/__init__.py +0 -0
  65. lionagi/experimental/directive/parser/base_parser.py +215 -0
  66. lionagi/experimental/directive/schema.py +36 -0
  67. lionagi/experimental/directive/template_/__init__.py +0 -0
  68. lionagi/experimental/directive/template_/base_template.py +63 -0
  69. lionagi/experimental/tool/__init__.py +0 -0
  70. lionagi/experimental/tool/function_calling.py +43 -0
  71. lionagi/experimental/tool/manual.py +66 -0
  72. lionagi/experimental/tool/schema.py +59 -0
  73. lionagi/experimental/tool/tool_manager.py +138 -0
  74. lionagi/experimental/tool/util.py +16 -0
  75. lionagi/experimental/work/__init__.py +0 -0
  76. lionagi/experimental/work/_logger.py +25 -0
  77. lionagi/experimental/work/exchange.py +0 -0
  78. lionagi/experimental/work/schema.py +30 -0
  79. lionagi/experimental/work/tests.py +72 -0
  80. lionagi/experimental/work/util.py +0 -0
  81. lionagi/experimental/work/work_function.py +89 -0
  82. lionagi/experimental/work/worker.py +12 -0
  83. lionagi/integrations/bridge/autogen_/__init__.py +0 -0
  84. lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
  85. lionagi/integrations/bridge/llamaindex_/get_index.py +294 -0
  86. lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
  87. lionagi/integrations/bridge/transformers_/__init__.py +0 -0
  88. lionagi/integrations/bridge/transformers_/install_.py +36 -0
  89. lionagi/integrations/chunker/chunk.py +7 -7
  90. lionagi/integrations/config/oai_configs.py +5 -5
  91. lionagi/integrations/config/ollama_configs.py +1 -1
  92. lionagi/integrations/config/openrouter_configs.py +1 -1
  93. lionagi/integrations/loader/load.py +6 -6
  94. lionagi/integrations/loader/load_util.py +8 -8
  95. lionagi/integrations/storage/__init__.py +3 -0
  96. lionagi/integrations/storage/neo4j.py +673 -0
  97. lionagi/integrations/storage/storage_util.py +289 -0
  98. lionagi/integrations/storage/to_csv.py +63 -0
  99. lionagi/integrations/storage/to_excel.py +67 -0
  100. lionagi/libs/ln_api.py +3 -3
  101. lionagi/libs/ln_knowledge_graph.py +405 -0
  102. lionagi/libs/ln_parse.py +43 -6
  103. lionagi/libs/ln_queue.py +101 -0
  104. lionagi/libs/ln_tokenizer.py +57 -0
  105. lionagi/libs/ln_validate.py +288 -0
  106. lionagi/libs/sys_util.py +29 -7
  107. lionagi/lions/__init__.py +0 -0
  108. lionagi/lions/coder/__init__.py +0 -0
  109. lionagi/lions/coder/add_feature.py +20 -0
  110. lionagi/lions/coder/base_prompts.py +22 -0
  111. lionagi/lions/coder/coder.py +121 -0
  112. lionagi/lions/coder/util.py +91 -0
  113. lionagi/lions/researcher/__init__.py +0 -0
  114. lionagi/lions/researcher/data_source/__init__.py +0 -0
  115. lionagi/lions/researcher/data_source/finhub_.py +191 -0
  116. lionagi/lions/researcher/data_source/google_.py +199 -0
  117. lionagi/lions/researcher/data_source/wiki_.py +96 -0
  118. lionagi/lions/researcher/data_source/yfinance_.py +21 -0
  119. lionagi/tests/integrations/__init__.py +0 -0
  120. lionagi/tests/libs/__init__.py +0 -0
  121. lionagi/tests/libs/test_async.py +0 -0
  122. lionagi/tests/libs/test_field_validators.py +353 -0
  123. lionagi/tests/libs/test_queue.py +67 -0
  124. lionagi/tests/test_core/test_base_branch.py +0 -1
  125. lionagi/tests/test_core/test_branch.py +2 -0
  126. lionagi/tests/test_core/test_session_base_util.py +1 -0
  127. lionagi/version.py +1 -1
  128. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/METADATA +1 -1
  129. lionagi-0.1.1.dist-info/RECORD +190 -0
  130. lionagi/core/prompt/prompt_template.py +0 -312
  131. lionagi/core/schema/__init__.py +0 -22
  132. lionagi/core/schema/action_node.py +0 -29
  133. lionagi/core/schema/base_mixin.py +0 -296
  134. lionagi/core/schema/base_node.py +0 -199
  135. lionagi/core/schema/condition.py +0 -24
  136. lionagi/core/schema/data_logger.py +0 -354
  137. lionagi/core/schema/data_node.py +0 -93
  138. lionagi/core/schema/prompt_template.py +0 -67
  139. lionagi/core/schema/structure.py +0 -912
  140. lionagi/core/tool/manual.py +0 -1
  141. lionagi-0.0.316.dist-info/RECORD +0 -121
  142. /lionagi/core/{branch/base → execute}/__init__.py +0 -0
  143. /lionagi/core/flow/{base/baseflow.py → baseflow.py} +0 -0
  144. /lionagi/core/flow/{base/__init__.py → mono_chat_mixin.py} +0 -0
  145. /lionagi/core/{prompt → form}/__init__.py +0 -0
  146. /lionagi/{tests/test_integrations → core/graph}/__init__.py +0 -0
  147. /lionagi/{tests/test_libs → experimental}/__init__.py +0 -0
  148. /lionagi/{tests/test_libs/test_async.py → experimental/directive/__init__.py} +0 -0
  149. /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
  150. /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
  151. /lionagi/tests/{test_libs → libs}/test_func_call.py +0 -0
  152. /lionagi/tests/{test_libs → libs}/test_nested.py +0 -0
  153. /lionagi/tests/{test_libs → libs}/test_parse.py +0 -0
  154. /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
  155. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/LICENSE +0 -0
  156. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/WHEEL +0 -0
  157. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/top_level.txt +0 -0
lionagi/core/__init__.py CHANGED
@@ -1,15 +1,26 @@
1
1
  from . import *
2
2
 
3
- from .branch import Branch, ExecutableBranch
4
- from .session import Session
5
- from .schema import (
6
- Tool,
7
- Structure,
3
+ from .branch.branch import Branch
4
+ from .session.session import Session
5
+ from .generic import (
8
6
  ActionNode,
9
- Relationship,
10
7
  ActionSelection,
11
8
  Condition,
12
9
  )
13
- from .agent import BaseAgent
14
- from .messages import Instruction, System, Response
10
+ from .agent.base_agent import BaseAgent
11
+ from .messages.schema import Instruction, System, Response
15
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
+ ]
@@ -1,3 +0,0 @@
1
- from .base_agent import BaseAgent
2
-
3
- __all__ = ["BaseAgent"]
@@ -2,37 +2,28 @@
2
2
  This module contains the BaseAgent class, which serves as a base class for agents.
3
3
  """
4
4
 
5
- from lionagi.core.mail.schema import StartMail
6
- from lionagi.core.schema.base_node import BaseRelatableNode
7
- from lionagi.core.mail.mail_manager import MailManager
5
+ from pydantic import Field
6
+ from typing import Any, Callable
8
7
 
9
8
  from lionagi.libs import func_call, AsyncUtil
10
9
 
11
10
 
12
- class BaseAgent(BaseRelatableNode):
13
- """
14
- A base class for agents.
15
-
16
- Attributes:
17
- structure: The structure of the agent.
18
- executable: The executable object of the agent.
19
- start: The StartMail object for triggering the agent.
20
- mailManager: The MailManager object for managing agent communication.
21
- output_parser: A function for parsing the agent's output (optional).
22
- start_context: The initial context for the agent (optional).
23
-
24
- Methods:
25
- __init__(self, structure, executable_obj, output_parser=None) -> None:
26
- Initializes the BaseAgent instance.
11
+ from lionagi.core.mail.schema import StartMail
12
+ from lionagi.core.generic import Node
13
+ from lionagi.core.mail.mail_manager import MailManager
14
+ from lionagi.core.execute.base_executor import BaseExecutor
15
+ from lionagi.core.execute.structure_executor import StructureExecutor
27
16
 
28
- async mail_manager_control(self, refresh_time=1) -> None:
29
- Controls the mail manager execution based on the structure and executable states.
30
17
 
31
- async execute(self, context=None) -> Any:
32
- Executes the agent with the given context and returns the parsed output (if available).
33
- """
18
+ class BaseAgent(Node):
34
19
 
35
- def __init__(self, structure, executable_obj, output_parser=None) -> None:
20
+ def __init__(
21
+ self,
22
+ structure: BaseExecutor,
23
+ executable: BaseExecutor,
24
+ output_parser=None,
25
+ **kwargs,
26
+ ) -> None:
36
27
  """
37
28
  Initializes the BaseAgent instance.
38
29
 
@@ -42,12 +33,16 @@ class BaseAgent(BaseRelatableNode):
42
33
  output_parser: A function for parsing the agent's output (optional).
43
34
  """
44
35
  super().__init__()
45
- self.structure = structure
46
- self.executable = executable_obj
47
- self.start = StartMail()
48
- self.mailManager = MailManager([self.structure, self.executable, self.start])
49
- self.output_parser = output_parser
50
- self.start_context = None
36
+ self.structure: BaseExecutor = structure
37
+ self.executable: BaseExecutor = executable
38
+ for v, k in kwargs.items():
39
+ executable.__setattr__(v, k)
40
+ self.start: StartMail = StartMail()
41
+ self.mailManager: MailManager = MailManager(
42
+ [self.structure, self.executable, self.start]
43
+ )
44
+ self.output_parser: Callable | None = output_parser
45
+ self.start_context: Any | None = None
51
46
 
52
47
  async def mail_manager_control(self, refresh_time=1):
53
48
  """
@@ -1,4 +0,0 @@
1
- from .branch import Branch
2
- from .executable_branch import ExecutableBranch
3
-
4
- __all__ = ["Branch", "ExecutableBranch"]
@@ -1,22 +1,21 @@
1
1
  from abc import ABC
2
2
  from typing import Any
3
3
 
4
- from lionagi.libs.sys_util import PATH_TYPE
4
+ from pathlib import Path
5
5
  from lionagi.libs import convert, dataframe, SysUtil
6
6
 
7
- from ..schema.base_node import BaseRelatableNode
8
- from ..schema.data_logger import DataLogger, DLog
9
- from ..messages.schema import (
7
+ from lionagi.core.generic import BaseNode, DataLogger, DLog
8
+ from lionagi.core.messages.schema import (
10
9
  BranchColumns,
11
10
  System,
12
11
  Response,
13
12
  Instruction,
14
13
  BaseMessage,
15
14
  )
16
- from .util import MessageUtil
15
+ from lionagi.core.branch.util import MessageUtil
17
16
 
18
17
 
19
- class BaseBranch(BaseRelatableNode, ABC):
18
+ class BaseBranch(BaseNode, ABC):
20
19
  """
21
20
  Base class for managing branches of conversation, incorporating messages
22
21
  and logging functionality.
@@ -24,7 +23,7 @@ class BaseBranch(BaseRelatableNode, ABC):
24
23
  Attributes:
25
24
  messages (dataframe.ln_DataFrame): Holds the messages in the branch.
26
25
  datalogger (DataLogger): Logs data related to the branch's operation.
27
- persist_path (PATH_TYPE): Filesystem path for data persistence.
26
+ persist_path (str | Path): Filesystem path for data persistence.
28
27
  """
29
28
 
30
29
  _columns: list[str] = BranchColumns.COLUMNS.value
@@ -33,7 +32,7 @@ class BaseBranch(BaseRelatableNode, ABC):
33
32
  self,
34
33
  messages: dataframe.ln_DataFrame | None = None,
35
34
  datalogger: DataLogger | None = None,
36
- persist_path: PATH_TYPE | None = None,
35
+ persist_path: str | Path | None = None,
37
36
  name=None,
38
37
  **kwargs,
39
38
  ) -> None:
@@ -97,6 +96,7 @@ class BaseBranch(BaseRelatableNode, ABC):
97
96
  if self.name is not None:
98
97
  _msg.sender = self.name
99
98
 
99
+ setattr(_msg, "node_id", _msg.id_)
100
100
  _msg.content = _msg.msg_content
101
101
  self.messages.loc[len(self.messages)] = _msg.to_pd_series()
102
102
 
@@ -332,7 +332,7 @@ class BaseBranch(BaseRelatableNode, ABC):
332
332
 
333
333
  def to_csv_file(
334
334
  self,
335
- filename: PATH_TYPE = "messages.csv",
335
+ filename: str | Path = "messages.csv",
336
336
  dir_exist_ok: bool = True,
337
337
  timestamp: bool = True,
338
338
  time_prefix: bool = False,
@@ -375,7 +375,7 @@ class BaseBranch(BaseRelatableNode, ABC):
375
375
 
376
376
  def to_json_file(
377
377
  self,
378
- filename: PATH_TYPE = "messages.json",
378
+ filename: str | Path = "messages.json",
379
379
  dir_exist_ok: bool = True,
380
380
  timestamp: bool = True,
381
381
  time_prefix: bool = False,
@@ -420,7 +420,7 @@ class BaseBranch(BaseRelatableNode, ABC):
420
420
 
421
421
  def log_to_csv(
422
422
  self,
423
- filename: PATH_TYPE = "log.csv",
423
+ filename: str | Path = "log.csv",
424
424
  dir_exist_ok: bool = True,
425
425
  timestamp: bool = True,
426
426
  time_prefix: bool = False,
@@ -456,7 +456,7 @@ class BaseBranch(BaseRelatableNode, ABC):
456
456
 
457
457
  def log_to_json(
458
458
  self,
459
- filename: PATH_TYPE = "log.json",
459
+ filename: str | Path = "log.json",
460
460
  dir_exist_ok: bool = True,
461
461
  timestamp: bool = True,
462
462
  time_prefix: bool = False,
@@ -636,7 +636,6 @@ class BaseBranch(BaseRelatableNode, ABC):
636
636
  case_sensitive=case_sensitive,
637
637
  )
638
638
 
639
- # noinspection PyTestUnpassedFixture
640
639
  def _info(self, use_sender: bool = False) -> dict[str, int]:
641
640
  """
642
641
  Helper method to generate summaries of messages either by role or sender.
@@ -4,19 +4,18 @@ This module contains the Branch class, which represents a branch in a conversati
4
4
 
5
5
  from collections import deque
6
6
  from typing import Any, Union, TypeVar, Callable
7
+ from pathlib import Path
7
8
 
8
- from lionagi.libs.sys_util import PATH_TYPE
9
9
  from lionagi.libs import StatusTracker, BaseService, convert, dataframe
10
10
 
11
- from ..schema import TOOL_TYPE, Tool, DataLogger
12
- from ..tool import ToolManager, func_to_tool
11
+ from lionagi.core.generic import DataLogger
12
+ from lionagi.core.tool import ToolManager, func_to_tool, Tool, TOOL_TYPE
13
+ from lionagi.core.messages.schema import System
14
+ from lionagi.core.mail.schema import BaseMail
13
15
 
14
- from ..messages import System
15
- from ..mail import BaseMail
16
-
17
- from .util import MessageUtil
18
- from .base_branch import BaseBranch
19
- from .branch_flow_mixin import BranchFlowMixin
16
+ from lionagi.core.branch.util import MessageUtil
17
+ from lionagi.core.branch.base import BaseBranch
18
+ from lionagi.core.branch.flow_mixin import BranchFlowMixin
20
19
 
21
20
  from dotenv import load_dotenv
22
21
 
@@ -95,7 +94,7 @@ class Branch(BaseBranch, BranchFlowMixin):
95
94
  llmconfig: dict[str, str | int | dict] | None = None,
96
95
  tools: list[Callable | Tool] | None = None,
97
96
  datalogger: None | DataLogger = None,
98
- persist_path: PATH_TYPE | None = None, # instruction_sets=None,
97
+ persist_path: str | Path | None = None, # instruction_sets=None,
99
98
  tool_manager: ToolManager | None = None,
100
99
  **kwargs,
101
100
  ):
@@ -111,7 +110,7 @@ class Branch(BaseBranch, BranchFlowMixin):
111
110
  llmconfig (dict[str, str | int | dict]): The configuration for the language model (optional).
112
111
  tools (list[Callable | Tool]): The tools to register in the branch (optional).
113
112
  datalogger (DataLogger): The data logger for the branch (optional).
114
- persist_path (PATH_TYPE): The path to persist the branch data (optional).
113
+ persist_path (str | Path): The path to persist the branch data (optional).
115
114
  tool_manager (ToolManager): The tool manager for the branch (optional).
116
115
  **kwargs: Additional keyword arguments.
117
116
 
@@ -165,7 +164,7 @@ class Branch(BaseBranch, BranchFlowMixin):
165
164
  llmconfig: dict[str, str | int | dict] | None = None,
166
165
  tools: TOOL_TYPE | None = None,
167
166
  datalogger: None | DataLogger = None,
168
- persist_path: PATH_TYPE | None = None, # instruction_sets=None,
167
+ persist_path: str | Path | None = None, # instruction_sets=None,
169
168
  tool_manager: ToolManager | None = None,
170
169
  read_kwargs=None,
171
170
  **kwargs,
@@ -180,7 +179,7 @@ class Branch(BaseBranch, BranchFlowMixin):
180
179
  llmconfig (dict[str, str | int | dict]): The configuration for the language model (optional).
181
180
  tools (TOOL_TYPE): The tools to register in the branch (optional).
182
181
  datalogger (DataLogger): The data logger for the branch (optional).
183
- persist_path (PATH_TYPE): The path to persist the branch data (optional).
182
+ persist_path (str | Path): The path to persist the branch data (optional).
184
183
  tool_manager (ToolManager): The tool manager for the branch (optional).
185
184
  read_kwargs: Additional keyword arguments for reading the CSV file (optional).
186
185
  **kwargs: Additional keyword arguments.
@@ -211,7 +210,7 @@ class Branch(BaseBranch, BranchFlowMixin):
211
210
  llmconfig: dict[str, str | int | dict] | None = None,
212
211
  tools: TOOL_TYPE | None = None,
213
212
  datalogger: None | DataLogger = None,
214
- persist_path: PATH_TYPE | None = None, # instruction_sets=None,
213
+ persist_path: str | Path | None = None, # instruction_sets=None,
215
214
  tool_manager: ToolManager | None = None,
216
215
  read_kwargs=None,
217
216
  **kwargs,
@@ -226,7 +225,7 @@ class Branch(BaseBranch, BranchFlowMixin):
226
225
  llmconfig (dict[str, str | int | dict]): The configuration for the language model (optional).
227
226
  tools (TOOL_TYPE): The tools to register in the branch (optional).
228
227
  datalogger (DataLogger): The data logger for the branch (optional).
229
- persist_path (PATH_TYPE): The path to persist the branch data (optional).
228
+ persist_path (str | Path): The path to persist the branch data (optional).
230
229
  tool_manager (ToolManager): The tool manager for the branch (optional).
231
230
  read_kwargs: Additional keyword arguments for reading the JSON string file (optional).
232
231
  **kwargs: Additional keyword arguments.
@@ -348,7 +347,7 @@ class Branch(BaseBranch, BranchFlowMixin):
348
347
  print("tools deletion failed")
349
348
  return False
350
349
 
351
- def send(self, recipient: str, category: str, package: Any) -> None:
350
+ def send(self, recipient_id: str, category: str, package: Any) -> None:
352
351
  """
353
352
  Sends a mail to a recipient.
354
353
 
@@ -357,10 +356,13 @@ class Branch(BaseBranch, BranchFlowMixin):
357
356
  category (str): The category of the mail.
358
357
  package (Any): The package to send in the mail.
359
358
  """
360
- mail_ = BaseMail(
361
- sender=self.sender, recipient=recipient, category=category, package=package
359
+ mail = BaseMail(
360
+ sender_id=self.id_,
361
+ recipient_id=recipient_id,
362
+ category=category,
363
+ package=package,
362
364
  )
363
- self.pending_outs.append(mail_)
365
+ self.pending_outs.append(mail)
364
366
 
365
367
  def receive(
366
368
  self,
@@ -469,3 +471,4 @@ class Branch(BaseBranch, BranchFlowMixin):
469
471
  return True
470
472
  except Exception:
471
473
  return False
474
+ return False
@@ -1,347 +0,0 @@
1
- """
2
- This module contains the ExecutableBranch class, which represents an executable branch in a conversation tree.
3
- """
4
-
5
- import contextlib
6
- from collections import deque
7
- from typing import Any
8
-
9
- from lionagi.libs import convert, AsyncUtil, ParseUtil
10
-
11
- from ..schema import BaseRelatableNode, ActionNode
12
- from ..mail import BaseMail
13
- from ..messages import System, Instruction
14
- from ..agent import BaseAgent
15
-
16
- from .branch import Branch
17
-
18
-
19
- class ExecutableBranch(BaseRelatableNode):
20
- """
21
- Represents an executable branch in a conversation tree.
22
-
23
- Attributes:
24
- branch (Branch): The branch associated with the executable branch.
25
- pending_ins (dict): The pending incoming mails for the executable branch.
26
- pending_outs (deque): The pending outgoing mails for the executable branch.
27
- responses (list): The responses generated by the executable branch.
28
- execute_stop (bool): A flag indicating whether the execution should stop.
29
- context (Any): The context of the executable branch.
30
- context_log (list): The log of contexts for the executable branch.
31
- verbose (bool): A flag indicating whether to provide verbose output.
32
-
33
- Methods:
34
- __init__(self, verbose=True, **kwargs) -> None:
35
- Initializes the ExecutableBranch instance.
36
-
37
- send(self, recipient_id: str, category: str, package: Any) -> None:
38
- Sends a mail to a recipient.
39
-
40
- async forward(self) -> None:
41
- Forwards the pending incoming mails to the appropriate processing methods.
42
-
43
- async execute(self, refresh_time=1) -> None:
44
- Executes the executable branch.
45
-
46
- async _process_node(self, mail: BaseMail) -> None:
47
- Processes a node mail.
48
-
49
- _process_node_list(self, mail: BaseMail) -> None:
50
- Processes a node list mail.
51
-
52
- _process_condition(self, mail: BaseMail) -> None:
53
- Processes a condition mail.
54
-
55
- _system_process(self, system: System, verbose=True, context_verbose=False) -> None:
56
- Processes a system message.
57
-
58
- async _instruction_process(self, instruction: Instruction, verbose=True, **kwargs) -> None:
59
- Processes an instruction message.
60
-
61
- async _action_process(self, action: ActionNode, verbose=True) -> None:
62
- Processes an action node.
63
-
64
- async _agent_process(self, agent, verbose=True) -> None:
65
- Processes an agent.
66
-
67
- _process_start(self, mail: BaseMail) -> None:
68
- Processes a start mail.
69
-
70
- _process_end(self, mail: BaseMail) -> None:
71
- Processes an end mail.
72
- """
73
-
74
- def __init__(self, verbose=True, **kwargs):
75
- """
76
- Initializes the ExecutableBranch instance.
77
-
78
- Args:
79
- verbose (bool): A flag indicating whether to provide verbose output (default: True).
80
- **kwargs: Additional keyword arguments for initializing the branch.
81
- """
82
- super().__init__()
83
- self.branch: Branch = Branch(**kwargs)
84
- self.pending_ins = {} # needed
85
- self.pending_outs = deque() # needed
86
- self.responses = []
87
- self.execute_stop = False # needed
88
- self.context = None # needed
89
- self.context_log = []
90
- self.verbose = verbose
91
-
92
- def send(self, recipient_id: str, category: str, package: Any) -> None:
93
- """
94
- Sends a mail to a recipient.
95
-
96
- Args:
97
- recipient_id (str): The ID of the recipient.
98
- category (str): The category of the mail.
99
- package (Any): The package to send in the mail.
100
- """
101
- mail = BaseMail(
102
- sender_id=self.id_,
103
- recipient_id=recipient_id,
104
- category=category,
105
- package=package,
106
- )
107
- self.pending_outs.append(mail)
108
-
109
- async def forward(self) -> None:
110
- """
111
- Forwards the pending incoming mails to the appropriate processing methods.
112
- """
113
- for key in list(self.pending_ins.keys()):
114
- while self.pending_ins[key]:
115
- mail = self.pending_ins[key].popleft()
116
- if mail.category == "start":
117
- self._process_start(mail)
118
- elif mail.category == "node":
119
- await self._process_node(mail)
120
- elif mail.category == "node_list":
121
- self._process_node_list(mail)
122
- elif mail.category == "condition":
123
- self._process_condition(mail)
124
- elif mail.category == "end":
125
- self._process_end(mail)
126
-
127
- async def execute(self, refresh_time=1) -> None:
128
- """
129
- Executes the executable branch.
130
-
131
- Args:
132
- refresh_time (int): The refresh time for execution (default: 1).
133
- """
134
- while not self.execute_stop:
135
- await self.forward()
136
- await AsyncUtil.sleep(refresh_time)
137
-
138
- async def _process_node(self, mail: BaseMail):
139
- """
140
- Processes a node mail.
141
-
142
- Args:
143
- mail (BaseMail): The node mail to process.
144
-
145
- Raises:
146
- ValueError: If the mail package is invalid.
147
- """
148
- if isinstance(mail.package, System):
149
- self._system_process(mail.package, verbose=self.verbose)
150
- self.send(mail.sender_id, "node_id", mail.package.id_)
151
-
152
- elif isinstance(mail.package, Instruction):
153
- await self._instruction_process(mail.package, verbose=self.verbose)
154
- self.send(mail.sender_id, "node_id", mail.package.id_)
155
-
156
- elif isinstance(mail.package, ActionNode):
157
- await self._action_process(mail.package, verbose=self.verbose)
158
- self.send(mail.sender_id, "node_id", mail.package.instruction.id_)
159
- else:
160
- try:
161
- await self._agent_process(mail.package, verbose=self.verbose)
162
- self.send(mail.sender_id, "node_id", mail.package.id_)
163
- except:
164
- raise ValueError(f"Invalid mail to process. Mail:{mail}")
165
-
166
- def _process_node_list(self, mail: BaseMail):
167
- """
168
- Processes a node list mail.
169
-
170
- Args:
171
- mail (BaseMail): The node list mail to process.
172
-
173
- Raises:
174
- ValueError: If multiple path selection is not supported.
175
- """
176
- self.send(mail.sender_id, "end", "end")
177
- self.execute_stop = True
178
- raise ValueError("Multiple path selection is currently not supported")
179
-
180
- def _process_condition(self, mail: BaseMail):
181
- """
182
- Processes a condition mail.
183
-
184
- Args:
185
- mail (BaseMail): The condition mail to process.
186
- """
187
- relationship = mail.package
188
- check_result = relationship.condition(self)
189
- back_mail = {"relationship_id": mail.package.id_, "check_result": check_result}
190
- self.send(mail.sender_id, "condition", back_mail)
191
-
192
- def _system_process(self, system: System, verbose=True, context_verbose=False):
193
- """
194
- Processes a system message.
195
-
196
- Args:
197
- system (System): The system message to process.
198
- verbose (bool): A flag indicating whether to provide verbose output (default: True).
199
- context_verbose (bool): A flag indicating whether to display the context (default: False).
200
- """
201
- from lionagi.libs import SysUtil
202
-
203
- SysUtil.check_import("IPython")
204
- from IPython.display import Markdown, display
205
-
206
- if verbose:
207
- print(f"------------------Welcome: {system.sender}--------------------")
208
- display(Markdown(f"system: {convert.to_str(system.system_info)}"))
209
- if self.context and context_verbose:
210
- display(Markdown(f"context: {convert.to_str(self.context)}"))
211
-
212
- self.branch.add_message(system=system)
213
-
214
- async def _instruction_process(
215
- self, instruction: Instruction, verbose=True, **kwargs
216
- ):
217
- """
218
- Processes an instruction message.
219
-
220
- Args:
221
- instruction (Instruction): The instruction message to process.
222
- verbose (bool): A flag indicating whether to provide verbose output (default: True).
223
- **kwargs: Additional keyword arguments for processing the instruction.
224
- """
225
- from lionagi.libs import SysUtil
226
-
227
- SysUtil.check_import("IPython")
228
- from IPython.display import Markdown, display
229
-
230
- if verbose:
231
- display(
232
- Markdown(
233
- f"{instruction.sender}: {convert.to_str(instruction.instruct)}"
234
- )
235
- )
236
-
237
- if self.context:
238
- instruction.content.update({"context": self.context})
239
- self.context = None
240
-
241
- result = await self.branch.chat(instruction, **kwargs)
242
- with contextlib.suppress(Exception):
243
- result = ParseUtil.fuzzy_parse_json(result)
244
- if "response" in result.keys():
245
- result = result["response"]
246
- if verbose and len(self.branch.assistant_responses) != 0:
247
- display(
248
- Markdown(
249
- f"{self.branch.last_assistant_response.sender}: {convert.to_str(result)}"
250
- )
251
- )
252
- print("-----------------------------------------------------")
253
-
254
- self.responses.append(result)
255
-
256
- async def _action_process(self, action: ActionNode, verbose=True):
257
- """
258
- Processes an action node.
259
-
260
- Args:
261
- action (ActionNode): The action node to process.
262
- verbose (bool): A flag indicating whether to provide verbose output (default: True).
263
-
264
- Raises:
265
- ValueError: If the action is not valid.
266
- """
267
- from lionagi.libs import SysUtil
268
-
269
- SysUtil.check_import("IPython")
270
- from IPython.display import Markdown, display
271
-
272
- try:
273
- func = getattr(self.branch, action.action)
274
- except:
275
- raise ValueError(f"{action.action} is not a valid action")
276
-
277
- if verbose:
278
- display(
279
- Markdown(
280
- f"{action.instruction.sender}: {convert.to_str(action.instruction.instruct)}"
281
- )
282
- )
283
-
284
- if action.tools:
285
- self.branch.register_tools(action.tools)
286
- if self.context:
287
- result = await func(
288
- action.instruction.content["instruction"],
289
- context=self.context,
290
- tools=action.tools,
291
- **action.action_kwargs,
292
- )
293
- self.context = None
294
- else:
295
- result = await func(
296
- action.instruction.content, tools=action.tools, **action.action_kwargs
297
- )
298
-
299
- if verbose and len(self.branch.assistant_responses) != 0:
300
- display(
301
- Markdown(
302
- f"{self.branch.last_assistant_response.sender}: {convert.to_str(result)}"
303
- )
304
- )
305
- print("-----------------------------------------------------")
306
-
307
- self.responses.append(result)
308
-
309
- async def _agent_process(self, agent, verbose=True):
310
- """
311
- Processes an agent.
312
-
313
- Args:
314
- agent: The agent to process.
315
- verbose (bool): A flag indicating whether to provide verbose output (default: True).
316
- """
317
- context = self.responses
318
- if verbose:
319
- print("*****************************************************")
320
- result = await agent.execute(context)
321
-
322
- if verbose:
323
- print("*****************************************************")
324
-
325
- self.context = result
326
- self.responses.append(result)
327
-
328
- def _process_start(self, mail):
329
- """
330
- Processes a start mail.
331
-
332
- Args:
333
- mail (BaseMail): The start mail to process.
334
- """
335
- start_mail_content = mail.package
336
- self.context = start_mail_content["context"]
337
- self.send(start_mail_content["structure_id"], "start", "start")
338
-
339
- def _process_end(self, mail):
340
- """
341
- Processes an end mail.
342
-
343
- Args:
344
- mail (BaseMail): The end mail to process.
345
- """
346
- self.execute_stop = True
347
- self.send(mail.sender_id, "end", "end")