lionagi 0.0.306__py3-none-any.whl → 0.0.308__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. lionagi/__init__.py +2 -5
  2. lionagi/core/__init__.py +7 -5
  3. lionagi/core/agent/__init__.py +3 -0
  4. lionagi/core/agent/base_agent.py +10 -12
  5. lionagi/core/branch/__init__.py +4 -0
  6. lionagi/core/branch/base_branch.py +81 -81
  7. lionagi/core/branch/branch.py +16 -28
  8. lionagi/core/branch/branch_flow_mixin.py +3 -7
  9. lionagi/core/branch/executable_branch.py +86 -56
  10. lionagi/core/branch/util.py +77 -162
  11. lionagi/core/{flow/direct → direct}/__init__.py +1 -1
  12. lionagi/core/{flow/direct/predict.py → direct/parallel_predict.py} +39 -17
  13. lionagi/core/direct/parallel_react.py +0 -0
  14. lionagi/core/direct/parallel_score.py +0 -0
  15. lionagi/core/direct/parallel_select.py +0 -0
  16. lionagi/core/direct/parallel_sentiment.py +0 -0
  17. lionagi/core/direct/predict.py +174 -0
  18. lionagi/core/{flow/direct → direct}/react.py +2 -2
  19. lionagi/core/{flow/direct → direct}/score.py +28 -23
  20. lionagi/core/{flow/direct → direct}/select.py +48 -45
  21. lionagi/core/direct/utils.py +83 -0
  22. lionagi/core/flow/monoflow/ReAct.py +6 -5
  23. lionagi/core/flow/monoflow/__init__.py +9 -0
  24. lionagi/core/flow/monoflow/chat.py +10 -10
  25. lionagi/core/flow/monoflow/chat_mixin.py +11 -10
  26. lionagi/core/flow/monoflow/followup.py +6 -5
  27. lionagi/core/flow/polyflow/__init__.py +1 -0
  28. lionagi/core/flow/polyflow/chat.py +15 -3
  29. lionagi/core/mail/mail_manager.py +18 -19
  30. lionagi/core/mail/schema.py +5 -4
  31. lionagi/core/messages/schema.py +18 -20
  32. lionagi/core/prompt/__init__.py +0 -0
  33. lionagi/core/prompt/prompt_template.py +0 -0
  34. lionagi/core/schema/__init__.py +2 -2
  35. lionagi/core/schema/action_node.py +11 -3
  36. lionagi/core/schema/base_mixin.py +56 -59
  37. lionagi/core/schema/base_node.py +34 -37
  38. lionagi/core/schema/condition.py +24 -0
  39. lionagi/core/schema/data_logger.py +96 -99
  40. lionagi/core/schema/data_node.py +19 -19
  41. lionagi/core/schema/prompt_template.py +0 -0
  42. lionagi/core/schema/structure.py +171 -169
  43. lionagi/core/session/__init__.py +1 -3
  44. lionagi/core/session/session.py +196 -214
  45. lionagi/core/tool/tool_manager.py +95 -103
  46. lionagi/integrations/__init__.py +1 -3
  47. lionagi/integrations/bridge/langchain_/documents.py +17 -18
  48. lionagi/integrations/bridge/langchain_/langchain_bridge.py +14 -14
  49. lionagi/integrations/bridge/llamaindex_/llama_index_bridge.py +22 -22
  50. lionagi/integrations/bridge/llamaindex_/node_parser.py +12 -12
  51. lionagi/integrations/bridge/llamaindex_/reader.py +11 -11
  52. lionagi/integrations/bridge/llamaindex_/textnode.py +7 -7
  53. lionagi/integrations/config/openrouter_configs.py +0 -1
  54. lionagi/integrations/provider/oai.py +26 -26
  55. lionagi/integrations/provider/services.py +38 -38
  56. lionagi/libs/__init__.py +34 -1
  57. lionagi/libs/ln_api.py +211 -221
  58. lionagi/libs/ln_async.py +53 -60
  59. lionagi/libs/ln_convert.py +118 -120
  60. lionagi/libs/ln_dataframe.py +32 -33
  61. lionagi/libs/ln_func_call.py +334 -342
  62. lionagi/libs/ln_nested.py +99 -107
  63. lionagi/libs/ln_parse.py +161 -165
  64. lionagi/libs/sys_util.py +52 -52
  65. lionagi/tests/test_core/test_session.py +254 -266
  66. lionagi/tests/test_core/test_session_base_util.py +299 -300
  67. lionagi/tests/test_core/test_tool_manager.py +70 -74
  68. lionagi/tests/test_libs/test_nested.py +2 -7
  69. lionagi/tests/test_libs/test_parse.py +2 -2
  70. lionagi/version.py +1 -1
  71. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/METADATA +4 -2
  72. lionagi-0.0.308.dist-info/RECORD +115 -0
  73. lionagi/core/flow/direct/utils.py +0 -43
  74. lionagi-0.0.306.dist-info/RECORD +0 -106
  75. /lionagi/core/{flow/direct → direct}/sentiment.py +0 -0
  76. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/LICENSE +0 -0
  77. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/WHEEL +0 -0
  78. {lionagi-0.0.306.dist-info → lionagi-0.0.308.dist-info}/top_level.txt +0 -0
@@ -1,27 +1,20 @@
1
+ import contextlib
1
2
  from collections import deque
2
3
  from typing import Any
3
4
 
4
- from IPython.display import Markdown, display
5
+ from lionagi.libs import convert, AsyncUtil, ParseUtil
5
6
 
6
- import lionagi.libs.ln_convert as convert
7
- from lionagi.libs.ln_async import AsyncUtil
8
- from lionagi.libs.ln_parse import ParseUtil
7
+ from ..schema import BaseRelatableNode, ActionNode
8
+ from ..mail import BaseMail
9
+ from ..messages import System, Instruction
10
+ from ..agent import BaseAgent
9
11
 
10
- from lionagi.core.schema.base_node import BaseRelatableNode
11
- from lionagi.core.schema.action_node import ActionNode
12
-
13
- from lionagi.core.mail.schema import BaseMail
14
-
15
- from lionagi.core.messages.schema import System, Instruction
16
-
17
-
18
- from lionagi import Branch
19
- from lionagi.core.agent.base_agent import BaseAgent
12
+ from .branch import Branch
20
13
 
21
14
 
22
15
  class ExecutableBranch(BaseRelatableNode):
23
16
 
24
- def __init__(self, **kwargs):
17
+ def __init__(self, verbose=True, **kwargs):
25
18
  super().__init__()
26
19
  self.branch: Branch = Branch(**kwargs)
27
20
  self.pending_ins = {} # needed
@@ -29,6 +22,8 @@ class ExecutableBranch(BaseRelatableNode):
29
22
  self.responses = []
30
23
  self.execute_stop = False # needed
31
24
  self.context = None # needed
25
+ self.context_log = []
26
+ self.verbose = verbose
32
27
 
33
28
  def send(self, recipient_id: str, category: str, package: Any) -> None:
34
29
  mail = BaseMail(
@@ -45,8 +40,12 @@ class ExecutableBranch(BaseRelatableNode):
45
40
  mail = self.pending_ins[key].popleft()
46
41
  if mail.category == "start": # needed
47
42
  self._process_start(mail)
48
- if mail.category == "node":
43
+ elif mail.category == "node":
49
44
  await self._process_node(mail)
45
+ elif mail.category == "node_list":
46
+ self._process_node_list(mail)
47
+ elif mail.category == "condition":
48
+ self._process_condition(mail)
50
49
  elif mail.category == "end": # needed
51
50
  self._process_end(mail)
52
51
 
@@ -58,28 +57,40 @@ class ExecutableBranch(BaseRelatableNode):
58
57
  async def _process_node(self, mail: BaseMail):
59
58
 
60
59
  if isinstance(mail.package, System):
61
- self._system_process(mail.package)
60
+ self._system_process(mail.package, verbose=self.verbose)
62
61
  self.send(mail.sender_id, "node_id", mail.package.id_)
63
- return
64
62
 
65
63
  elif isinstance(mail.package, Instruction):
66
- await self._instruction_process(mail.package)
64
+ await self._instruction_process(mail.package, verbose=self.verbose)
67
65
  self.send(mail.sender_id, "node_id", mail.package.id_)
68
- return
69
66
 
70
67
  elif isinstance(mail.package, ActionNode):
71
- await self._action_process(mail.package)
68
+ await self._action_process(mail.package, verbose=self.verbose)
72
69
  self.send(mail.sender_id, "node_id", mail.package.instruction.id_)
73
- return
70
+ else:
71
+ try:
72
+ await self._agent_process(mail.package, verbose=self.verbose)
73
+ self.send(mail.sender_id, "node_id", mail.package.id_)
74
+ except:
75
+ raise ValueError(f"Invalid mail to process. Mail:{mail}")
74
76
 
75
- elif isinstance(mail.package, BaseAgent):
76
- await self._agent_process(mail.package)
77
- self.send(mail.sender_id, "node_id", mail.package.id_)
78
- return
77
+ def _process_node_list(self, mail: BaseMail):
78
+ self.send(mail.sender_id, "end", "end")
79
+ self.execute_stop = True
80
+ raise ValueError("Multiple path selection is currently not supported")
81
+
82
+ def _process_condition(self, mail: BaseMail):
83
+ relationship = mail.package
84
+ check_result = relationship.condition(self)
85
+ back_mail = {"relationship_id": mail.package.id_, "check_result": check_result}
86
+ self.send(mail.sender_id, "condition", back_mail)
79
87
 
80
88
  def _system_process(self, system: System, verbose=True, context_verbose=False):
89
+ from lionagi.libs import SysUtil
90
+ SysUtil.check_import('IPython')
91
+ from IPython.display import Markdown, display
81
92
  if verbose:
82
- print(f"---------------Welcome: {system.recipient}------------------")
93
+ print(f"------------------Welcome: {system.sender}--------------------")
83
94
  display(Markdown(f"system: {convert.to_str(system.system_info)}"))
84
95
  if self.context and context_verbose:
85
96
  display(Markdown(f"context: {convert.to_str(self.context)}"))
@@ -89,6 +100,9 @@ class ExecutableBranch(BaseRelatableNode):
89
100
  async def _instruction_process(
90
101
  self, instruction: Instruction, verbose=True, **kwargs
91
102
  ):
103
+ from lionagi.libs import SysUtil
104
+ SysUtil.check_import('IPython')
105
+ from IPython.display import Markdown, display
92
106
  if verbose:
93
107
  display(
94
108
  Markdown(
@@ -101,54 +115,41 @@ class ExecutableBranch(BaseRelatableNode):
101
115
  self.context = None
102
116
 
103
117
  result = await self.branch.chat(instruction, **kwargs)
104
- try:
118
+ with contextlib.suppress(Exception):
105
119
  result = ParseUtil.fuzzy_parse_json(result)
106
120
  if "response" in result.keys():
107
121
  result = result["response"]
108
- except:
109
- pass
110
-
111
- if verbose:
122
+ if verbose and len(self.branch.assistant_responses) != 0:
112
123
  display(
113
124
  Markdown(
114
125
  f"{self.branch.last_assistant_response.sender}: {convert.to_str(result)}"
115
126
  )
116
127
  )
128
+ print("-----------------------------------------------------")
117
129
 
118
130
  self.responses.append(result)
119
131
 
120
- async def _agent_process(self, agent):
121
- context = self.responses
122
- result = await agent.execute(context)
123
-
124
- self.context = result
125
- self.responses.append(result)
126
-
127
- def _process_start(self, mail):
128
- start_mail_content = mail.package
129
- self.context = start_mail_content["context"]
130
- self.send(start_mail_content["structure_id"], "start", "start")
131
-
132
- def _process_end(self, mail):
133
- self.execute_stop = True
134
- self.send(mail.sender_id, "end", "end")
135
-
136
- async def _action_process(self, action: ActionNode):
137
- # instruction = action.instruction
138
- # if self.context:
139
- # instruction.content.update({"context": self.context})
140
- # self.context=None
132
+ async def _action_process(self, action: ActionNode, verbose=True):
133
+ from lionagi.libs import SysUtil
134
+ SysUtil.check_import('IPython')
135
+ from IPython.display import Markdown, display
141
136
  try:
142
137
  func = getattr(self.branch, action.action)
143
138
  except:
144
139
  raise ValueError(f"{action.action} is not a valid action")
145
140
 
141
+ if verbose:
142
+ display(
143
+ Markdown(
144
+ f"{action.instruction.sender}: {convert.to_str(action.instruction.instruct)}"
145
+ )
146
+ )
147
+
146
148
  if action.tools:
147
149
  self.branch.register_tools(action.tools)
148
- # result = await func(instruction, tools=action.tools, **action.action_kwargs)
149
150
  if self.context:
150
151
  result = await func(
151
- action.instruction.content,
152
+ action.instruction.content["instruction"],
152
153
  context=self.context,
153
154
  tools=action.tools,
154
155
  **action.action_kwargs,
@@ -158,5 +159,34 @@ class ExecutableBranch(BaseRelatableNode):
158
159
  result = await func(
159
160
  action.instruction.content, tools=action.tools, **action.action_kwargs
160
161
  )
161
- print("action calls:", result)
162
+
163
+ if verbose and len(self.branch.assistant_responses) != 0:
164
+ display(
165
+ Markdown(
166
+ f"{self.branch.last_assistant_response.sender}: {convert.to_str(result)}"
167
+ )
168
+ )
169
+ print("-----------------------------------------------------")
170
+
162
171
  self.responses.append(result)
172
+
173
+ async def _agent_process(self, agent, verbose=True):
174
+ context = self.responses
175
+ if verbose:
176
+ print("*****************************************************")
177
+ result = await agent.execute(context)
178
+
179
+ if verbose:
180
+ print("*****************************************************")
181
+
182
+ self.context = result
183
+ self.responses.append(result)
184
+
185
+ def _process_start(self, mail):
186
+ start_mail_content = mail.package
187
+ self.context = start_mail_content["context"]
188
+ self.send(start_mail_content["structure_id"], "start", "start")
189
+
190
+ def _process_end(self, mail):
191
+ self.execute_stop = True
192
+ self.send(mail.sender_id, "end", "end")
@@ -1,10 +1,8 @@
1
+ import contextlib
1
2
  from datetime import datetime
2
3
  from typing import Any
3
4
 
4
- from lionagi.libs import ln_convert as convert
5
- from lionagi.libs import ln_nested as nested
6
- from lionagi.libs import ln_func_call as func_call
7
- from lionagi.libs import ln_dataframe as dataframe
5
+ from lionagi.libs import convert, nested, func_call, dataframe
8
6
 
9
7
  from lionagi.core.messages.schema import (
10
8
  System,
@@ -14,7 +12,6 @@ from lionagi.core.messages.schema import (
14
12
  BranchColumns,
15
13
  )
16
14
 
17
-
18
15
  CUSTOM_TYPE = dict[str, Any] | str | list[Any] | None
19
16
 
20
17
 
@@ -33,42 +30,41 @@ class MessageUtil:
33
30
  Creates a message object based on the input parameters, ensuring only one message role is present.
34
31
 
35
32
  Args:
36
- system: Information for creating a System message.
37
- instruction: Information for creating an Instruction message.
38
- context: Context information for the message.
39
- response: Response data for creating a message.
40
- **kwargs: Additional keyword arguments for message creation.
33
+ system: Information for creating a System message.
34
+ instruction: Information for creating an Instruction message.
35
+ context: Context information for the message.
36
+ response: Response data for creating a message.
37
+ **kwargs: Additional keyword arguments for message creation.
41
38
 
42
39
  Returns:
43
- A message object of the appropriate type based on provided inputs.
40
+ A message object of the appropriate type based on provided inputs.
44
41
 
45
42
  Raises:
46
- ValueError: If more than one of the role-specific parameters are provided.
43
+ ValueError: If more than one of the role-specific parameters are provided.
47
44
  """
48
45
  if sum(func_call.lcall([system, instruction, response], bool)) != 1:
49
46
  raise ValueError("Error: Message must have one and only one role.")
50
47
 
51
- else:
52
- if isinstance(system, System):
53
- return system
54
- elif isinstance(instruction, Instruction):
55
- return instruction
56
- elif isinstance(response, Response):
57
- return response
58
-
59
- msg = 0
60
- if response:
61
- msg = Response(response=response, **kwargs)
62
- elif instruction:
63
- msg = Instruction(
64
- instruction=instruction,
65
- context=context,
66
- output_fields=output_fields,
67
- **kwargs,
68
- )
69
- elif system:
70
- msg = System(system=system, **kwargs)
71
- return msg
48
+ if isinstance(system, System):
49
+ return system
50
+ elif isinstance(instruction, Instruction):
51
+ return instruction
52
+ elif isinstance(response, Response):
53
+ return response
54
+
55
+ msg = 0
56
+ if response:
57
+ msg = Response(response=response, **kwargs)
58
+ elif instruction:
59
+ msg = Instruction(
60
+ instruction=instruction,
61
+ context=context,
62
+ output_fields=output_fields,
63
+ **kwargs,
64
+ )
65
+ elif system:
66
+ msg = System(system=system, **kwargs)
67
+ return msg
72
68
 
73
69
  @staticmethod
74
70
  def validate_messages(messages: dataframe.ln_DataFrame) -> bool:
@@ -76,21 +72,21 @@ class MessageUtil:
76
72
  Validates the format and content of a DataFrame containing messages.
77
73
 
78
74
  Args:
79
- messages: A DataFrame with message information.
75
+ messages: A DataFrame with message information.
80
76
 
81
77
  Returns:
82
- True if the messages DataFrame is correctly formatted, False otherwise.
78
+ True if the messages DataFrame is correctly formatted, False otherwise.
83
79
 
84
80
  Raises:
85
- ValueError: If the DataFrame does not match expected schema or content requirements.
81
+ ValueError: If the DataFrame does not match expected schema or content requirements.
86
82
  """
87
83
 
88
84
  if list(messages.columns) != BranchColumns.COLUMNS.value:
89
85
  raise ValueError("Invalid messages dataframe. Unmatched columns.")
90
86
  if messages.isnull().values.any():
91
87
  raise ValueError("Invalid messages dataframe. Cannot have null.")
92
- if not all(
93
- role in ["system", "user", "assistant"]
88
+ if any(
89
+ role not in ["system", "user", "assistant"]
94
90
  for role in messages["role"].unique()
95
91
  ):
96
92
  raise ValueError(
@@ -115,14 +111,14 @@ class MessageUtil:
115
111
  Appends a sender prefix to the 'content' field of each message in a DataFrame.
116
112
 
117
113
  Args:
118
- messages: A DataFrame containing message data.
119
- sender: The identifier of the sender to prefix to message contents.
114
+ messages: A DataFrame containing message data.
115
+ sender: The identifier of the sender to prefix to message contents.
120
116
 
121
117
  Returns:
122
- A DataFrame with sender-prefixed message contents.
118
+ A DataFrame with sender-prefixed message contents.
123
119
 
124
120
  Raises:
125
- ValueError: If the sender is None or the value is 'none'.
121
+ ValueError: If the sender is None or the value is 'none'.
126
122
  """
127
123
 
128
124
  if sender is None or convert.strip_lower(sender) == "none":
@@ -152,16 +148,16 @@ class MessageUtil:
152
148
  Filters messages in a DataFrame based on specified criteria.
153
149
 
154
150
  Args:
155
- messages: The DataFrame to filter.
156
- role: The role to filter by.
157
- sender: The sender to filter by.
158
- start_time: The minimum timestamp for messages.
159
- end_time: The maximum timestamp for messages.
160
- content_keywords: Keywords to look for in message content.
161
- case_sensitive: Whether the keyword search should be case-sensitive.
151
+ messages: The DataFrame to filter.
152
+ role: The role to filter by.
153
+ sender: The sender to filter by.
154
+ start_time: The minimum timestamp for messages.
155
+ end_time: The maximum timestamp for messages.
156
+ content_keywords: Keywords to look for in message content.
157
+ case_sensitive: Whether the keyword search should be case-sensitive.
162
158
 
163
159
  Returns:
164
- A filtered DataFrame based on the specified criteria.
160
+ A filtered DataFrame based on the specified criteria.
165
161
  """
166
162
 
167
163
  try:
@@ -180,7 +176,7 @@ class MessageUtil:
180
176
  return convert.to_df(outs)
181
177
 
182
178
  except Exception as e:
183
- raise ValueError(f"Error in filtering messages: {e}")
179
+ raise ValueError(f"Error in filtering messages: {e}") from e
184
180
 
185
181
  @staticmethod
186
182
  def remove_message(messages: dataframe.ln_DataFrame, node_id: str) -> bool:
@@ -188,15 +184,15 @@ class MessageUtil:
188
184
  Removes a message from the DataFrame based on its node ID.
189
185
 
190
186
  Args:
191
- messages: The DataFrame containing messages.
192
- node_id: The unique identifier of the message to be removed.
187
+ messages: The DataFrame containing messages.
188
+ node_id: The unique identifier of the message to be removed.
193
189
 
194
190
  Returns:
195
- If any messages are removed.
191
+ If any messages are removed.
196
192
 
197
193
  Examples:
198
- >>> messages = dataframe.ln_DataFrame([...])
199
- >>> updated_messages = MessageUtil.remove_message(messages, "node_id_123")
194
+ >>> messages = dataframe.ln_DataFrame([...])
195
+ >>> updated_messages = MessageUtil.remove_message(messages, "node_id_123")
200
196
  """
201
197
 
202
198
  initial_length = len(messages)
@@ -218,15 +214,15 @@ class MessageUtil:
218
214
  Retrieves a specified number of message rows based on sender and role.
219
215
 
220
216
  Args:
221
- messages: The DataFrame containing messages.
222
- sender: Filter messages by the sender.
223
- role: Filter messages by the role.
224
- n: The number of messages to retrieve.
225
- sign_: If True, sign the message with the sender.
226
- from_: Specify retrieval from the 'front' or 'last' of the DataFrame.
217
+ messages: The DataFrame containing messages.
218
+ sender: Filter messages by the sender.
219
+ role: Filter messages by the role.
220
+ n: The number of messages to retrieve.
221
+ sign_: If True, sign the message with the sender.
222
+ from_: Specify retrieval from the 'front' or 'last' of the DataFrame.
227
223
 
228
224
  Returns:
229
- A DataFrame containing the filtered messages.
225
+ A DataFrame containing the filtered messages.
230
226
  """
231
227
 
232
228
  outs = ""
@@ -266,17 +262,17 @@ class MessageUtil:
266
262
  Extends a DataFrame with another DataFrame's rows, ensuring no duplicate 'node_id'.
267
263
 
268
264
  Args:
269
- df1: The primary DataFrame.
270
- df2: The DataFrame to merge with the primary DataFrame.
271
- **kwargs: Additional keyword arguments for `drop_duplicates`.
265
+ df1: The primary DataFrame.
266
+ df2: The DataFrame to merge with the primary DataFrame.
267
+ **kwargs: Additional keyword arguments for `drop_duplicates`.
272
268
 
273
269
  Returns:
274
- A DataFrame combined from df1 and df2 with duplicates removed based on 'node_id'.
270
+ A DataFrame combined from df1 and df2 with duplicates removed based on 'node_id'.
275
271
 
276
272
  Examples:
277
- >>> df_main = dataframe.ln_DataFrame([...])
278
- >>> df_additional = dataframe.ln_DataFrame([...])
279
- >>> combined_df = MessageUtil.extend(df_main, df_additional, keep='first')
273
+ >>> df_main = dataframe.ln_DataFrame([...])
274
+ >>> df_additional = dataframe.ln_DataFrame([...])
275
+ >>> combined_df = MessageUtil.extend(df_main, df_additional, keep='first')
280
276
  """
281
277
 
282
278
  MessageUtil.validate_messages(df2)
@@ -288,7 +284,7 @@ class MessageUtil:
288
284
  )
289
285
  return convert.to_df(df)
290
286
  except Exception as e:
291
- raise ValueError(f"Error in extending messages: {e}")
287
+ raise ValueError(f"Error in extending messages: {e}") from e
292
288
 
293
289
  @staticmethod
294
290
  def to_markdown_string(messages: dataframe.ln_DataFrame) -> str:
@@ -296,11 +292,11 @@ class MessageUtil:
296
292
  Converts messages in a DataFrame to a Markdown-formatted string for easy reading.
297
293
 
298
294
  Args:
299
- messages: A DataFrame containing messages with columns for 'role' and 'content'.
295
+ messages: A DataFrame containing messages with columns for 'role' and 'content'.
300
296
 
301
297
  Returns:
302
- A string formatted in Markdown, where each message's content is presented
303
- according to its role in a readable format.
298
+ A string formatted in Markdown, where each message's content is presented
299
+ according to its role in a readable format.
304
300
  """
305
301
 
306
302
  answers = []
@@ -308,101 +304,20 @@ class MessageUtil:
308
304
  content = convert.to_dict(i.content)
309
305
 
310
306
  if i.role == "assistant":
311
- try:
307
+ with contextlib.suppress(Exception):
312
308
  a = nested.nget(content, ["action_response", "func"])
313
309
  b = nested.nget(content, ["action_response", "arguments"])
314
310
  c = nested.nget(content, ["action_response", "output"])
315
311
  if a is not None:
316
- answers.append(f"Function: {a}")
317
- answers.append(f"Arguments: {b}")
318
- answers.append(f"Output: {c}")
312
+ answers.extend(
313
+ (f"Function: {a}", f"Arguments: {b}", f"Output: {c}")
314
+ )
319
315
  else:
320
316
  answers.append(nested.nget(content, ["assistant_response"]))
321
- except:
322
- pass
323
317
  elif i.role == "user":
324
- try:
318
+ with contextlib.suppress(Exception):
325
319
  answers.append(nested.nget(content, ["instruction"]))
326
- except:
327
- pass
328
320
  else:
329
- try:
321
+ with contextlib.suppress(Exception):
330
322
  answers.append(nested.nget(content, ["system_info"]))
331
- except:
332
- pass
333
-
334
- out_ = "\n".join(answers)
335
- return out_
336
-
337
- # @staticmethod
338
- # def to_json_content(value):
339
- # if isinstance(value, dict):
340
- # for key, val in value.items():
341
- # value[key] = MessageUtil.to_json_content(val)
342
- # value = json.dumps(value)
343
- # if isinstance(value, list):
344
- # for i in range(len(value)):
345
- # value[i] = MessageUtil.to_json_content(value[i])
346
- # return value
347
-
348
- # @staticmethod
349
- # def to_dict_content(value):
350
- # try:
351
- # value = json.loads(value)
352
- # if isinstance(value, dict):
353
- # for key, val in value.items():
354
- # value[key] = MessageUtil.to_dict_content(val)
355
- # if isinstance(value, list):
356
- # for i in range(len(value)):
357
- # value[i] = MessageUtil.to_dict_content(value[i])
358
- # return value
359
- # except:
360
- # return value
361
-
362
- # @staticmethod
363
- # def response_to_message(response: dict[str, Any], **kwargs) -> Any:
364
- # """
365
- # Processes a message response dictionary to generate an appropriate message object.
366
-
367
- # Args:
368
- # response: A dictionary potentially containing message information.
369
- # **kwargs: Additional keyword arguments to pass to the message constructors.
370
-
371
- # Returns:
372
- # An instance of a message class, such as ActionRequest or AssistantResponse,
373
- # depending on the content of the response.
374
- # """
375
- # try:
376
- # response = response["message"]
377
- # if .strip_lower(response['content']) == "none":
378
-
379
- # content = ActionRequest._handle_action_request(response)
380
- # return ActionRequest(action_request=content, **kwargs)
381
-
382
- # else:
383
-
384
- # try:
385
- # if 'tool_uses' in to_dict(response[MessageField.CONTENT.value]):
386
- # content_ = to_dict(response[MessageField.CONTENT.value])[
387
- # 'tool_uses']
388
- # return ActionRequest(action_request=content_, **kwargs)
389
-
390
- # elif MessageContentKey.RESPONSE.value in to_dict(
391
- # response[MessageField.CONTENT.value]):
392
- # content_ = to_dict(response[MessageField.CONTENT.value])[
393
- # MessageContentKey.RESPONSE.value]
394
- # return AssistantResponse(assistant_response=content_, **kwargs)
395
-
396
- # elif MessageContentKey.ACTION_REQUEST.value in to_dict(
397
- # response[MessageField.CONTENT.value]):
398
- # content_ = to_dict(response[MessageField.CONTENT.value])[
399
- # MessageContentKey.ACTION_REQUEST.value]
400
- # return ActionRequest(action_request=content_, **kwargs)
401
-
402
- # else:
403
- # return AssistantResponse(assistant_response=response, **kwargs)
404
-
405
- # except:
406
- # return AssistantResponse(assistant_response=response, **kwargs)
407
- # except:
408
- # return ActionResponse(action_response=response, **kwargs)
323
+ return "\n".join(answers)
@@ -10,4 +10,4 @@ __all__ = [
10
10
  "score",
11
11
  "sentiment",
12
12
  "react",
13
- ]
13
+ ]