lionagi 0.0.305__tar.gz → 0.0.307__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. {lionagi-0.0.305 → lionagi-0.0.307}/PKG-INFO +4 -2
  2. {lionagi-0.0.305 → lionagi-0.0.307}/README.md +3 -1
  3. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/__init__.py +2 -5
  4. lionagi-0.0.307/lionagi/core/__init__.py +8 -0
  5. lionagi-0.0.307/lionagi/core/agent/__init__.py +3 -0
  6. lionagi-0.0.307/lionagi/core/agent/base_agent.py +46 -0
  7. lionagi-0.0.307/lionagi/core/branch/__init__.py +4 -0
  8. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/branch/base_branch.py +100 -78
  9. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/branch/branch.py +22 -34
  10. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/branch/branch_flow_mixin.py +3 -7
  11. lionagi-0.0.307/lionagi/core/branch/executable_branch.py +192 -0
  12. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/branch/util.py +77 -162
  13. lionagi-0.0.307/lionagi/core/direct/__init__.py +13 -0
  14. lionagi-0.0.307/lionagi/core/direct/parallel_predict.py +127 -0
  15. lionagi-0.0.307/lionagi/core/direct/predict.py +174 -0
  16. lionagi-0.0.307/lionagi/core/direct/react.py +33 -0
  17. lionagi-0.0.307/lionagi/core/direct/score.py +163 -0
  18. lionagi-0.0.307/lionagi/core/direct/select.py +144 -0
  19. lionagi-0.0.307/lionagi/core/direct/sentiment.py +51 -0
  20. lionagi-0.0.307/lionagi/core/direct/utils.py +83 -0
  21. lionagi-0.0.305/lionagi/core/flow/monoflow/mono_react.py → lionagi-0.0.307/lionagi/core/flow/monoflow/ReAct.py +52 -9
  22. lionagi-0.0.307/lionagi/core/flow/monoflow/__init__.py +9 -0
  23. lionagi-0.0.305/lionagi/core/flow/monoflow/mono_chat.py → lionagi-0.0.307/lionagi/core/flow/monoflow/chat.py +11 -11
  24. lionagi-0.0.305/lionagi/core/flow/monoflow/mono_chat_mixin.py → lionagi-0.0.307/lionagi/core/flow/monoflow/chat_mixin.py +33 -27
  25. lionagi-0.0.305/lionagi/core/flow/monoflow/mono_followup.py → lionagi-0.0.307/lionagi/core/flow/monoflow/followup.py +7 -6
  26. lionagi-0.0.307/lionagi/core/flow/polyflow/__init__.py +1 -0
  27. lionagi-0.0.305/lionagi/core/flow/polyflow/polychat.py → lionagi-0.0.307/lionagi/core/flow/polyflow/chat.py +15 -3
  28. lionagi-0.0.307/lionagi/core/mail/__init__.py +8 -0
  29. lionagi-0.0.307/lionagi/core/mail/mail_manager.py +97 -0
  30. lionagi-0.0.307/lionagi/core/mail/schema.py +56 -0
  31. lionagi-0.0.307/lionagi/core/messages/__init__.py +3 -0
  32. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/messages/schema.py +56 -25
  33. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/schema/__init__.py +7 -5
  34. lionagi-0.0.307/lionagi/core/schema/action_node.py +29 -0
  35. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/schema/base_mixin.py +56 -59
  36. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/schema/base_node.py +35 -38
  37. lionagi-0.0.307/lionagi/core/schema/condition.py +24 -0
  38. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/schema/data_logger.py +98 -98
  39. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/schema/data_node.py +19 -19
  40. lionagi-0.0.307/lionagi/core/schema/structure.py +604 -0
  41. lionagi-0.0.307/lionagi/core/session/__init__.py +3 -0
  42. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/session/session.py +196 -214
  43. lionagi-0.0.307/lionagi/core/tool/tool_manager.py +280 -0
  44. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/langchain_/documents.py +17 -18
  45. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
  46. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
  47. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
  48. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
  49. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
  50. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/config/openrouter_configs.py +0 -1
  51. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/oai.py +26 -26
  52. lionagi-0.0.307/lionagi/integrations/provider/services.py +136 -0
  53. lionagi-0.0.307/lionagi/libs/__init__.py +34 -0
  54. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_api.py +211 -221
  55. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_async.py +53 -60
  56. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_convert.py +118 -120
  57. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_dataframe.py +32 -33
  58. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_func_call.py +334 -342
  59. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_nested.py +99 -107
  60. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/ln_parse.py +175 -158
  61. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/libs/sys_util.py +52 -52
  62. lionagi-0.0.307/lionagi/tests/test_core/__init__.py +0 -0
  63. lionagi-0.0.307/lionagi/tests/test_core/test_base_branch.py +427 -0
  64. lionagi-0.0.307/lionagi/tests/test_core/test_branch.py +292 -0
  65. lionagi-0.0.307/lionagi/tests/test_core/test_mail_manager.py +75 -0
  66. lionagi-0.0.307/lionagi/tests/test_core/test_session.py +254 -0
  67. lionagi-0.0.307/lionagi/tests/test_core/test_session_base_util.py +312 -0
  68. lionagi-0.0.307/lionagi/tests/test_core/test_tool_manager.py +95 -0
  69. lionagi-0.0.307/lionagi/tests/test_integrations/__init__.py +0 -0
  70. lionagi-0.0.307/lionagi/tests/test_libs/__init__.py +0 -0
  71. lionagi-0.0.307/lionagi/tests/test_libs/test_async.py +0 -0
  72. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_nested.py +2 -7
  73. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_parse.py +2 -2
  74. lionagi-0.0.307/lionagi/version.py +1 -0
  75. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi.egg-info/PKG-INFO +4 -2
  76. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi.egg-info/SOURCES.txt +26 -5
  77. lionagi-0.0.305/lionagi/core/__init__.py +0 -5
  78. lionagi-0.0.305/lionagi/core/flow/__init__.py +0 -3
  79. lionagi-0.0.305/lionagi/core/mail/mail_manager.py +0 -49
  80. lionagi-0.0.305/lionagi/core/mail/schema.py +0 -30
  81. lionagi-0.0.305/lionagi/core/schema/structure.py +0 -501
  82. lionagi-0.0.305/lionagi/core/session/__init__.py +0 -5
  83. lionagi-0.0.305/lionagi/core/tool/tool_manager.py +0 -288
  84. lionagi-0.0.305/lionagi/integrations/__init__.py +0 -3
  85. lionagi-0.0.305/lionagi/integrations/provider/services.py +0 -136
  86. lionagi-0.0.305/lionagi/tests/test_core/test_base_branch.py +0 -427
  87. lionagi-0.0.305/lionagi/tests/test_core/test_branch.py +0 -292
  88. lionagi-0.0.305/lionagi/tests/test_core/test_mail_manager.py +0 -75
  89. lionagi-0.0.305/lionagi/tests/test_core/test_session.py +0 -266
  90. lionagi-0.0.305/lionagi/tests/test_core/test_session_base_util.py +0 -313
  91. lionagi-0.0.305/lionagi/tests/test_core/test_tool_manager.py +0 -99
  92. lionagi-0.0.305/lionagi/version.py +0 -1
  93. {lionagi-0.0.305 → lionagi-0.0.307}/LICENSE +0 -0
  94. {lionagi-0.0.305 → lionagi-0.0.307}/README.rst +0 -0
  95. {lionagi-0.0.305/lionagi/core/branch → lionagi-0.0.307/lionagi/core/branch/base}/__init__.py +0 -0
  96. /lionagi-0.0.305/lionagi/core/flow/base/__init__.py → /lionagi-0.0.307/lionagi/core/direct/parallel_react.py +0 -0
  97. /lionagi-0.0.305/lionagi/core/flow/monoflow/__init__.py → /lionagi-0.0.307/lionagi/core/direct/parallel_score.py +0 -0
  98. /lionagi-0.0.305/lionagi/core/flow/polyflow/__init__.py → /lionagi-0.0.307/lionagi/core/direct/parallel_select.py +0 -0
  99. /lionagi-0.0.305/lionagi/core/mail/__init__.py → /lionagi-0.0.307/lionagi/core/direct/parallel_sentiment.py +0 -0
  100. {lionagi-0.0.305/lionagi/core/messages → lionagi-0.0.307/lionagi/core/flow}/__init__.py +0 -0
  101. {lionagi-0.0.305/lionagi/integrations/bridge/langchain_ → lionagi-0.0.307/lionagi/core/flow/base}/__init__.py +0 -0
  102. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/flow/base/baseflow.py +0 -0
  103. {lionagi-0.0.305/lionagi/integrations/bridge/llamaindex_ → lionagi-0.0.307/lionagi/core/prompt}/__init__.py +0 -0
  104. /lionagi-0.0.305/lionagi/core/tool/manual.py → /lionagi-0.0.307/lionagi/core/prompt/prompt_template.py +0 -0
  105. /lionagi-0.0.305/lionagi/integrations/bridge/llamaindex_/index.py → /lionagi-0.0.307/lionagi/core/schema/prompt_template.py +0 -0
  106. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/core/tool/__init__.py +0 -0
  107. /lionagi-0.0.305/lionagi/integrations/bridge/pydantic_/__init__.py → /lionagi-0.0.307/lionagi/core/tool/manual.py +0 -0
  108. {lionagi-0.0.305/lionagi/libs → lionagi-0.0.307/lionagi/integrations}/__init__.py +0 -0
  109. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/__init__.py +0 -0
  110. {lionagi-0.0.305/lionagi/tests → lionagi-0.0.307/lionagi/integrations/bridge/langchain_}/__init__.py +0 -0
  111. {lionagi-0.0.305/lionagi/tests/test_core → lionagi-0.0.307/lionagi/integrations/bridge/llamaindex_}/__init__.py +0 -0
  112. /lionagi-0.0.305/lionagi/integrations/bridge/pydantic_/pydantic_bridge.py → /lionagi-0.0.307/lionagi/integrations/bridge/llamaindex_/index.py +0 -0
  113. {lionagi-0.0.305/lionagi/tests/test_integrations → lionagi-0.0.307/lionagi/integrations/bridge/pydantic_}/__init__.py +0 -0
  114. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/bridge/pydantic_/base_model.py +0 -0
  115. /lionagi-0.0.305/lionagi/tests/test_libs/__init__.py → /lionagi-0.0.307/lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +0 -0
  116. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/config/__init__.py +0 -0
  117. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/config/mlx_configs.py +0 -0
  118. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/config/oai_configs.py +0 -0
  119. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/config/ollama_configs.py +0 -0
  120. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/__init__.py +0 -0
  121. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/litellm.py +0 -0
  122. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/mistralai.py +0 -0
  123. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/mlx_service.py +0 -0
  124. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/ollama.py +0 -0
  125. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/openrouter.py +0 -0
  126. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/integrations/provider/transformers.py +0 -0
  127. /lionagi-0.0.305/lionagi/tests/test_libs/test_async.py → /lionagi-0.0.307/lionagi/tests/__init__.py +0 -0
  128. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_core/test_chat_flow.py +0 -0
  129. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_api.py +0 -0
  130. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_convert.py +0 -0
  131. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_func_call.py +0 -0
  132. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi/tests/test_libs/test_sys_util.py +0 -0
  133. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi.egg-info/dependency_links.txt +0 -0
  134. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi.egg-info/requires.txt +0 -0
  135. {lionagi-0.0.305 → lionagi-0.0.307}/lionagi.egg-info/top_level.txt +0 -0
  136. {lionagi-0.0.305 → lionagi-0.0.307}/pyproject.toml +0 -0
  137. {lionagi-0.0.305 → lionagi-0.0.307}/setup.cfg +0 -0
  138. {lionagi-0.0.305 → lionagi-0.0.307}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.0.305
3
+ Version: 0.0.307
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -229,7 +229,9 @@ Requires-Dist: pandas>=2.1.0
229
229
  [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/xCkA5ErGmV)
230
230
 
231
231
  ```
232
- Documentation for v0.0.302 is in progress
232
+ Documentation for v0.0.300+ is in progress
233
+
234
+ To contribute, you need to make a fork first, and then make pull request from your fork.
233
235
  ```
234
236
 
235
237
  # LionAGI
@@ -5,7 +5,9 @@
5
5
  [PyPI](https://pypi.org/project/lionagi/) | [Documentation](https://ocean-lion.com/Welcome) | [Discord](https://discord.gg/xCkA5ErGmV)
6
6
 
7
7
  ```
8
- Documentation for v0.0.302 is in progress
8
+ Documentation for v0.0.300+ is in progress
9
+
10
+ To contribute, you need to make a fork first, and then make pull request from your fork.
9
11
  ```
10
12
 
11
13
  # LionAGI
@@ -6,11 +6,8 @@ import logging
6
6
  from .version import __version__
7
7
  from dotenv import load_dotenv
8
8
 
9
-
10
- from .libs import *
11
- from .core import *
12
- from .integrations import *
13
-
9
+ from .core import direct, Branch, Session, Structure, Tool, BaseAgent
10
+ from .integrations.provider.services import Services
14
11
 
15
12
  logger = logging.getLogger(__name__)
16
13
  logger.setLevel(logging.INFO)
@@ -0,0 +1,8 @@
1
+ from . import *
2
+
3
+ from .branch import Branch, ExecutableBranch
4
+ from .session import Session
5
+ from .schema import Tool, Structure, ActionNode, Relationship
6
+ from .agent import BaseAgent
7
+ from .messages import Instruction, System, Response
8
+ from .tool import func_to_tool
@@ -0,0 +1,3 @@
1
+ from .base_agent import BaseAgent
2
+
3
+ __all__ = ["BaseAgent"]
@@ -0,0 +1,46 @@
1
+ from lionagi.core.mail.schema import StartMail
2
+ from lionagi.core.schema.base_node import BaseRelatableNode
3
+ from lionagi.core.mail.mail_manager import MailManager
4
+
5
+ from lionagi.libs import func_call, AsyncUtil
6
+
7
+
8
+ class BaseAgent(BaseRelatableNode):
9
+ def __init__(self, structure, executable_obj, output_parser=None) -> None:
10
+
11
+ super().__init__()
12
+ self.structure = structure
13
+ self.executable = executable_obj
14
+ self.start = StartMail()
15
+ self.mailManager = MailManager([self.structure, self.executable, self.start])
16
+ self.output_parser = output_parser
17
+ self.start_context = None
18
+
19
+ async def mail_manager_control(self, refresh_time=1):
20
+ while not self.structure.execute_stop or not self.executable.execute_stop:
21
+ await AsyncUtil.sleep(refresh_time)
22
+ self.mailManager.execute_stop = True
23
+
24
+ async def execute(self, context=None):
25
+ self.start_context = context
26
+ self.start.trigger(
27
+ context=context,
28
+ structure_id=self.structure.id_,
29
+ executable_id=self.executable.id_,
30
+ )
31
+ await func_call.mcall(
32
+ [0.1, 0.1, 0.1, 0.1],
33
+ [
34
+ self.structure.execute,
35
+ self.executable.execute,
36
+ self.mailManager.execute,
37
+ self.mail_manager_control,
38
+ ],
39
+ )
40
+
41
+ self.structure.execute_stop = False
42
+ self.executable.execute_stop = False
43
+ self.mailManager.execute_stop = False
44
+
45
+ if self.output_parser:
46
+ return self.output_parser(self)
@@ -0,0 +1,4 @@
1
+ from .branch import Branch
2
+ from .executable_branch import ExecutableBranch
3
+
4
+ __all__ = ["Branch", "ExecutableBranch"]
@@ -1,21 +1,19 @@
1
1
  from abc import ABC
2
2
  from typing import Any
3
3
 
4
- from lionagi.libs.sys_util import SysUtil, PATH_TYPE
4
+ from lionagi.libs.sys_util import PATH_TYPE
5
+ from lionagi.libs import convert, dataframe, SysUtil
5
6
 
6
- import lionagi.libs.ln_convert as convert
7
- import lionagi.libs.ln_dataframe as dataframe
8
-
9
- from lionagi.core.schema.base_node import BaseRelatableNode
10
- from lionagi.core.schema.data_logger import DataLogger, DLog
11
- from lionagi.core.messages.schema import (
7
+ from ..schema.base_node import BaseRelatableNode
8
+ from ..schema.data_logger import DataLogger, DLog
9
+ from ..messages.schema import (
12
10
  BranchColumns,
13
11
  System,
12
+ Response,
14
13
  Instruction,
15
14
  BaseMessage,
16
15
  )
17
- from lionagi.core.branch.util import MessageUtil
18
- from lionagi.libs.ln_parse import ParseUtil
16
+ from .util import MessageUtil
19
17
 
20
18
 
21
19
  class BaseBranch(BaseRelatableNode, ABC):
@@ -24,9 +22,9 @@ class BaseBranch(BaseRelatableNode, ABC):
24
22
  and logging functionality.
25
23
 
26
24
  Attributes:
27
- messages (dataframe.ln_DataFrame): Holds the messages in the branch.
28
- datalogger (DataLogger): Logs data related to the branch's operation.
29
- persist_path (PATH_TYPE): Filesystem path for data persistence.
25
+ messages (dataframe.ln_DataFrame): Holds the messages in the branch.
26
+ datalogger (DataLogger): Logs data related to the branch's operation.
27
+ persist_path (PATH_TYPE): Filesystem path for data persistence.
30
28
  """
31
29
 
32
30
  _columns: list[str] = BranchColumns.COLUMNS.value
@@ -36,6 +34,7 @@ class BaseBranch(BaseRelatableNode, ABC):
36
34
  messages: dataframe.ln_DataFrame | None = None,
37
35
  datalogger: DataLogger | None = None,
38
36
  persist_path: PATH_TYPE | None = None,
37
+ name=None,
39
38
  **kwargs,
40
39
  ) -> None:
41
40
  super().__init__(**kwargs)
@@ -47,9 +46,8 @@ class BaseBranch(BaseRelatableNode, ABC):
47
46
  else:
48
47
  self.messages = dataframe.ln_DataFrame(columns=self._columns)
49
48
 
50
- self.datalogger = (
51
- datalogger if datalogger else DataLogger(persist_path=persist_path)
52
- )
49
+ self.datalogger = datalogger or DataLogger(persist_path=persist_path)
50
+ self.name = name
53
51
 
54
52
  def add_message(
55
53
  self,
@@ -58,17 +56,18 @@ class BaseBranch(BaseRelatableNode, ABC):
58
56
  context: str | dict[str, Any] | None = None,
59
57
  response: dict | list | BaseMessage | None = None,
60
58
  output_fields=None,
59
+ recipient=None,
61
60
  **kwargs,
62
61
  ) -> None:
63
62
  """
64
63
  Adds a message to the branch.
65
64
 
66
65
  Args:
67
- system: Information for creating a System message.
68
- instruction: Information for creating an Instruction message.
69
- context: Context information for the message.
70
- response: Response data for creating a message.
71
- **kwargs: Additional keyword arguments for message creation.
66
+ system: Information for creating a System message.
67
+ instruction: Information for creating an Instruction message.
68
+ context: Context information for the message.
69
+ response: Response data for creating a message.
70
+ **kwargs: Additional keyword arguments for message creation.
72
71
  """
73
72
  _msg = MessageUtil.create_message(
74
73
  system=system,
@@ -76,9 +75,28 @@ class BaseBranch(BaseRelatableNode, ABC):
76
75
  context=context,
77
76
  response=response,
78
77
  output_fields=output_fields,
78
+ recipient=recipient,
79
79
  **kwargs,
80
80
  )
81
81
 
82
+ if isinstance(_msg, System):
83
+ self.system_node = _msg
84
+
85
+ # sourcery skip: merge-nested-ifs
86
+ if isinstance(_msg, Instruction):
87
+ if recipient is None and self.name is not None:
88
+ _msg.recipient = self.name
89
+
90
+ if isinstance(_msg, Response):
91
+ if "action_response" in _msg.content.keys():
92
+ if recipient is None and self.name is not None:
93
+ _msg.recipient = self.name
94
+ if recipient is not None and self.name is None:
95
+ _msg.recipient = recipient
96
+ if "response" in _msg.content.keys():
97
+ if self.name is not None:
98
+ _msg.sender = self.name
99
+
82
100
  _msg.content = _msg.msg_content
83
101
  self.messages.loc[len(self.messages)] = _msg.to_pd_series()
84
102
 
@@ -90,11 +108,11 @@ class BaseBranch(BaseRelatableNode, ABC):
90
108
  optionally including sender information.
91
109
 
92
110
  Args:
93
- with_sender: Flag to include sender information in the output.
111
+ with_sender: Flag to include sender information in the output.
94
112
 
95
113
  Returns:
96
- A list of message dictionaries, each with 'role' and 'content' keys,
97
- and optionally prefixed by 'Sender' if with_sender is True.
114
+ A list of message dictionaries, each with 'role' and 'content' keys,
115
+ and optionally prefixed by 'Sender' if with_sender is True.
98
116
  """
99
117
 
100
118
  message = []
@@ -125,7 +143,7 @@ class BaseBranch(BaseRelatableNode, ABC):
125
143
  Retrieves all chat messages without sender information.
126
144
 
127
145
  Returns:
128
- A list of dictionaries representing chat messages.
146
+ A list of dictionaries representing chat messages.
129
147
  """
130
148
 
131
149
  return self._to_chatcompletion_message()
@@ -136,7 +154,7 @@ class BaseBranch(BaseRelatableNode, ABC):
136
154
  Retrieves all chat messages, including sender information.
137
155
 
138
156
  Returns:
139
- A list of dictionaries representing chat messages, each prefixed with its sender.
157
+ A list of dictionaries representing chat messages, each prefixed with its sender.
140
158
  """
141
159
 
142
160
  return self._to_chatcompletion_message(with_sender=True)
@@ -147,7 +165,7 @@ class BaseBranch(BaseRelatableNode, ABC):
147
165
  Retrieves the last message from the branch as a pandas Series.
148
166
 
149
167
  Returns:
150
- A pandas Series representing the last message in the branch.
168
+ A pandas Series representing the last message in the branch.
151
169
  """
152
170
 
153
171
  return MessageUtil.get_message_rows(self.messages, n=1, from_="last")
@@ -158,7 +176,7 @@ class BaseBranch(BaseRelatableNode, ABC):
158
176
  Extracts the content of the last message in the branch.
159
177
 
160
178
  Returns:
161
- A dictionary representing the content of the last message.
179
+ A dictionary representing the content of the last message.
162
180
  """
163
181
 
164
182
  return convert.to_dict(self.messages.content.iloc[-1])
@@ -169,7 +187,7 @@ class BaseBranch(BaseRelatableNode, ABC):
169
187
  Retrieves the first message marked with the 'system' role.
170
188
 
171
189
  Returns:
172
- A pandas Series representing the first 'system' message in the branch.
190
+ A pandas Series representing the first 'system' message in the branch.
173
191
  """
174
192
 
175
193
  return MessageUtil.get_message_rows(
@@ -182,7 +200,7 @@ class BaseBranch(BaseRelatableNode, ABC):
182
200
  Retrieves the last message marked with the 'assistant' role.
183
201
 
184
202
  Returns:
185
- A pandas Series representing the last 'assistant' (response) message in the branch.
203
+ A pandas Series representing the last 'assistant' (response) message in the branch.
186
204
  """
187
205
 
188
206
  return MessageUtil.get_message_rows(
@@ -195,7 +213,7 @@ class BaseBranch(BaseRelatableNode, ABC):
195
213
  Extracts the content of the last 'assistant' (response) message.
196
214
 
197
215
  Returns:
198
- A dictionary representing the content of the last 'assistant' message.
216
+ A dictionary representing the content of the last 'assistant' message.
199
217
  """
200
218
 
201
219
  return convert.to_dict(self.last_response.content.iloc[-1])
@@ -206,7 +224,7 @@ class BaseBranch(BaseRelatableNode, ABC):
206
224
  Filters and retrieves all messages sent by 'action_request'.
207
225
 
208
226
  Returns:
209
- A pandas DataFrame containing all 'action_request' messages.
227
+ A pandas DataFrame containing all 'action_request' messages.
210
228
  """
211
229
 
212
230
  return convert.to_df(self.messages[self.messages.sender == "action_request"])
@@ -217,7 +235,7 @@ class BaseBranch(BaseRelatableNode, ABC):
217
235
  Filters and retrieves all messages sent by 'action_response'.
218
236
 
219
237
  Returns:
220
- A pandas DataFrame containing all 'action_response' messages.
238
+ A pandas DataFrame containing all 'action_response' messages.
221
239
  """
222
240
 
223
241
  return convert.to_df(self.messages[self.messages.sender == "action_response"])
@@ -228,7 +246,7 @@ class BaseBranch(BaseRelatableNode, ABC):
228
246
  Retrieves all messages marked with the 'assistant' role.
229
247
 
230
248
  Returns:
231
- A pandas DataFrame containing all messages with an 'assistant' role.
249
+ A pandas DataFrame containing all messages with an 'assistant' role.
232
250
  """
233
251
 
234
252
  return convert.to_df(self.messages[self.messages.role == "assistant"])
@@ -239,20 +257,24 @@ class BaseBranch(BaseRelatableNode, ABC):
239
257
  Filters 'assistant' role messages excluding 'action_request' and 'action_response'.
240
258
 
241
259
  Returns:
242
- A pandas DataFrame of 'assistant' messages excluding action requests/responses.
260
+ A pandas DataFrame of 'assistant' messages excluding action requests/responses.
243
261
  """
244
262
 
245
263
  a_responses = self.responses[self.responses.sender != "action_response"]
246
264
  a_responses = a_responses[a_responses.sender != "action_request"]
247
265
  return convert.to_df(a_responses)
248
266
 
267
+ @property
268
+ def last_assistant_response(self):
269
+ return self.assistant_responses.iloc[-1]
270
+
249
271
  @property
250
272
  def info(self) -> dict[str, Any]:
251
273
  """
252
274
  Summarizes branch information, including message counts by role.
253
275
 
254
276
  Returns:
255
- A dictionary containing counts of messages categorized by their role.
277
+ A dictionary containing counts of messages categorized by their role.
256
278
  """
257
279
 
258
280
  return self._info()
@@ -263,7 +285,7 @@ class BaseBranch(BaseRelatableNode, ABC):
263
285
  Provides a summary of message counts categorized by sender.
264
286
 
265
287
  Returns:
266
- A dictionary with senders as keys and counts of their messages as values.
288
+ A dictionary with senders as keys and counts of their messages as values.
267
289
  """
268
290
 
269
291
  return self._info(use_sender=True)
@@ -274,8 +296,8 @@ class BaseBranch(BaseRelatableNode, ABC):
274
296
  Provides a detailed description of the branch, including a summary of messages.
275
297
 
276
298
  Returns:
277
- A dictionary with a summary of total messages, a breakdown by role, and
278
- a preview of the first five messages.
299
+ A dictionary with a summary of total messages, a breakdown by role, and
300
+ a preview of the first five messages.
279
301
  """
280
302
 
281
303
  return {
@@ -322,13 +344,13 @@ class BaseBranch(BaseRelatableNode, ABC):
322
344
  Exports the branch messages to a CSV file.
323
345
 
324
346
  Args:
325
- filepath: Destination path for the CSV file. Defaults to 'messages.csv'.
326
- dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
327
- timestamp: If True, appends a timestamp to the filename. Defaults to True.
328
- time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
329
- verbose: If True, prints a message upon successful export. Defaults to True.
330
- clear: If True, clears the messages after exporting. Defaults to True.
331
- **kwargs: Additional keyword arguments for pandas.DataFrame.to_csv().
347
+ filepath: Destination path for the CSV file. Defaults to 'messages.csv'.
348
+ dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
349
+ timestamp: If True, appends a timestamp to the filename. Defaults to True.
350
+ time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
351
+ verbose: If True, prints a message upon successful export. Defaults to True.
352
+ clear: If True, clears the messages after exporting. Defaults to True.
353
+ **kwargs: Additional keyword arguments for pandas.DataFrame.to_csv().
332
354
  """
333
355
 
334
356
  if not filename.endswith(".csv"):
@@ -349,7 +371,7 @@ class BaseBranch(BaseRelatableNode, ABC):
349
371
  if clear:
350
372
  self.clear_messages()
351
373
  except Exception as e:
352
- raise ValueError(f"Error in saving to csv: {e}")
374
+ raise ValueError(f"Error in saving to csv: {e}") from e
353
375
 
354
376
  def to_json_file(
355
377
  self,
@@ -365,13 +387,13 @@ class BaseBranch(BaseRelatableNode, ABC):
365
387
  Exports the branch messages to a JSON file.
366
388
 
367
389
  Args:
368
- filename: Destination path for the JSON file. Defaults to 'messages.json'.
369
- dir_exist_ok: If False, an error is raised if the dirctory exists. Defaults to True.
370
- timestamp: If True, appends a timestamp to the filename. Defaults to True.
371
- time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
372
- verbose: If True, prints a message upon successful export. Defaults to True.
373
- clear: If True, clears the messages after exporting. Defaults to True.
374
- **kwargs: Additional keyword arguments for pandas.DataFrame.to_json().
390
+ filename: Destination path for the JSON file. Defaults to 'messages.json'.
391
+ dir_exist_ok: If False, an error is raised if the dirctory exists. Defaults to True.
392
+ timestamp: If True, appends a timestamp to the filename. Defaults to True.
393
+ time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
394
+ verbose: If True, prints a message upon successful export. Defaults to True.
395
+ clear: If True, clears the messages after exporting. Defaults to True.
396
+ **kwargs: Additional keyword arguments for pandas.DataFrame.to_json().
375
397
  """
376
398
 
377
399
  if not filename.endswith(".json"):
@@ -394,7 +416,7 @@ class BaseBranch(BaseRelatableNode, ABC):
394
416
  if clear:
395
417
  self.clear_messages()
396
418
  except Exception as e:
397
- raise ValueError(f"Error in saving to json: {e}")
419
+ raise ValueError(f"Error in saving to json: {e}") from e
398
420
 
399
421
  def log_to_csv(
400
422
  self,
@@ -412,13 +434,13 @@ class BaseBranch(BaseRelatableNode, ABC):
412
434
  Exports the data logger contents to a CSV file.
413
435
 
414
436
  Args:
415
- filename: Destination path for the CSV file. Defaults to 'log.csv'.
416
- dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
417
- timestamp: If True, appends a timestamp to the filename. Defaults to True.
418
- time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
419
- verbose: If True, prints a message upon successful export. Defaults to True.
420
- clear: If True, clears the logger after exporting. Defaults to True.
421
- **kwargs: Additional keyword arguments for pandas.DataFrame.to_csv().
437
+ filename: Destination path for the CSV file. Defaults to 'log.csv'.
438
+ dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
439
+ timestamp: If True, appends a timestamp to the filename. Defaults to True.
440
+ time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
441
+ verbose: If True, prints a message upon successful export. Defaults to True.
442
+ clear: If True, clears the logger after exporting. Defaults to True.
443
+ **kwargs: Additional keyword arguments for pandas.DataFrame.to_csv().
422
444
  """
423
445
  self.datalogger.to_csv_file(
424
446
  filename=filename,
@@ -448,13 +470,13 @@ class BaseBranch(BaseRelatableNode, ABC):
448
470
  Exports the data logger contents to a JSON file.
449
471
 
450
472
  Args:
451
- filename: Destination path for the JSON file. Defaults to 'log.json'.
452
- dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
453
- timestamp: If True, appends a timestamp to the filename. Defaults to True.
454
- time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
455
- verbose: If True, prints a message upon successful export. Defaults to True.
456
- clear: If True, clears the logger after exporting. Defaults to True.
457
- **kwargs: Additional keyword arguments for pandas.DataFrame.to_json().
473
+ filename: Destination path for the JSON file. Defaults to 'log.json'.
474
+ dir_exist_ok: If False, an error is raised if the directory exists. Defaults to True.
475
+ timestamp: If True, appends a timestamp to the filename. Defaults to True.
476
+ time_prefix: If True, prefixes the filename with a timestamp. Defaults to False.
477
+ verbose: If True, prints a message upon successful export. Defaults to True.
478
+ clear: If True, clears the logger after exporting. Defaults to True.
479
+ **kwargs: Additional keyword arguments for pandas.DataFrame.to_json().
458
480
  """
459
481
 
460
482
  self.datalogger.to_json_file(
@@ -491,14 +513,14 @@ class BaseBranch(BaseRelatableNode, ABC):
491
513
  if verbose:
492
514
  print(f"Loaded {len(df)} logs from {filename}")
493
515
  except Exception as e:
494
- raise ValueError(f"Error in loading log: {e}")
516
+ raise ValueError(f"Error in loading log: {e}") from e
495
517
 
496
518
  def remove_message(self, node_id: str) -> None:
497
519
  """
498
520
  Removes a message from the branch based on its node ID.
499
521
 
500
522
  Args:
501
- node_id: The unique identifier of the message to be removed.
523
+ node_id: The unique identifier of the message to be removed.
502
524
  """
503
525
  MessageUtil.remove_message(self.messages, node_id)
504
526
 
@@ -507,9 +529,9 @@ class BaseBranch(BaseRelatableNode, ABC):
507
529
  Updates a specific column of a message identified by node_id with a new value.
508
530
 
509
531
  Args:
510
- value: The new value to update the message with.
511
- node_id: The unique identifier of the message to update.
512
- column: The column of the message to update.
532
+ value: The new value to update the message with.
533
+ node_id: The unique identifier of the message to update.
534
+ column: The column of the message to update.
513
535
  """
514
536
 
515
537
  index = self.messages[self.messages["node_id"] == node_id].index[0]
@@ -525,8 +547,8 @@ class BaseBranch(BaseRelatableNode, ABC):
525
547
  Updates the first system message with new content and/or sender.
526
548
 
527
549
  Args:
528
- system: The new system message content or a System object.
529
- sender: The identifier of the sender for the system message.
550
+ system: The new system message content or a System object.
551
+ sender: The identifier of the sender for the system message.
530
552
  """
531
553
 
532
554
  if len(self.messages[self.messages["role"] == "system"]) == 0:
@@ -548,7 +570,7 @@ class BaseBranch(BaseRelatableNode, ABC):
548
570
  Removes the last 'n' messages from the branch.
549
571
 
550
572
  Args:
551
- steps: The number of messages to remove from the end.
573
+ steps: The number of messages to remove from the end.
552
574
  """
553
575
 
554
576
  self.messages = dataframe.remove_last_n_rows(self.messages, steps)
@@ -620,10 +642,10 @@ class BaseBranch(BaseRelatableNode, ABC):
620
642
  Helper method to generate summaries of messages either by role or sender.
621
643
 
622
644
  Args:
623
- use_sender: If True, summary is categorized by sender. Otherwise, by role.
645
+ use_sender: If True, summary is categorized by sender. Otherwise, by role.
624
646
 
625
647
  Returns:
626
- A dictionary summarizing the count of messages either by role or sender.
648
+ A dictionary summarizing the count of messages either by role or sender.
627
649
  """
628
650
 
629
651
  messages = self.messages["sender"] if use_sender else self.messages["role"]