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

Sign up to get free protection for your applications and to get access to all the features.
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 +35 -38
  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.307.dist-info}/METADATA +4 -2
  72. lionagi-0.0.307.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.307.dist-info}/LICENSE +0 -0
  77. {lionagi-0.0.306.dist-info → lionagi-0.0.307.dist-info}/WHEEL +0 -0
  78. {lionagi-0.0.306.dist-info → lionagi-0.0.307.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
+ ]