agentscope-runtime 1.0.4a1__py3-none-any.whl → 1.0.5.post1__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.
- agentscope_runtime/adapters/agentscope/stream.py +2 -8
- agentscope_runtime/adapters/langgraph/stream.py +120 -70
- agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
- agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
- agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
- agentscope_runtime/adapters/utils.py +6 -0
- agentscope_runtime/cli/commands/deploy.py +836 -1
- agentscope_runtime/cli/commands/stop.py +16 -0
- agentscope_runtime/common/container_clients/__init__.py +52 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +6 -4
- agentscope_runtime/common/container_clients/boxlite_client.py +442 -0
- agentscope_runtime/common/container_clients/docker_client.py +0 -20
- agentscope_runtime/common/container_clients/fc_client.py +6 -4
- agentscope_runtime/common/container_clients/gvisor_client.py +38 -0
- agentscope_runtime/common/container_clients/knative_client.py +467 -0
- agentscope_runtime/common/utils/deprecation.py +164 -0
- agentscope_runtime/engine/__init__.py +4 -0
- agentscope_runtime/engine/app/agent_app.py +16 -4
- agentscope_runtime/engine/constant.py +1 -0
- agentscope_runtime/engine/deployers/__init__.py +34 -11
- agentscope_runtime/engine/deployers/adapter/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +26 -51
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +23 -13
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +4 -201
- agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +152 -25
- agentscope_runtime/engine/deployers/adapter/agui/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_adapter_utils.py +652 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_protocol_adapter.py +225 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
- agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
- agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
- agentscope_runtime/engine/deployers/pai_deployer.py +2335 -0
- agentscope_runtime/engine/deployers/utils/net_utils.py +37 -0
- agentscope_runtime/engine/deployers/utils/oss_utils.py +38 -0
- agentscope_runtime/engine/deployers/utils/package.py +46 -42
- agentscope_runtime/engine/helpers/agent_api_client.py +372 -0
- agentscope_runtime/engine/runner.py +13 -0
- agentscope_runtime/engine/schemas/agent_schemas.py +9 -3
- agentscope_runtime/engine/services/agent_state/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/redis_memory_service.py +15 -16
- agentscope_runtime/engine/services/session_history/__init__.py +7 -0
- agentscope_runtime/engine/tracing/local_logging_handler.py +2 -3
- agentscope_runtime/engine/tracing/wrapper.py +18 -4
- agentscope_runtime/sandbox/__init__.py +14 -6
- agentscope_runtime/sandbox/box/base/__init__.py +2 -2
- agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
- agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
- agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
- agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
- agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
- agentscope_runtime/sandbox/box/sandbox.py +102 -65
- agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
- agentscope_runtime/sandbox/client/__init__.py +6 -1
- agentscope_runtime/sandbox/client/async_http_client.py +339 -0
- agentscope_runtime/sandbox/client/base.py +74 -0
- agentscope_runtime/sandbox/client/http_client.py +108 -329
- agentscope_runtime/sandbox/enums.py +7 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +275 -29
- agentscope_runtime/sandbox/manager/server/app.py +7 -1
- agentscope_runtime/sandbox/manager/server/config.py +3 -1
- agentscope_runtime/sandbox/model/manager_config.py +11 -9
- agentscope_runtime/tools/modelstudio_memory/__init__.py +106 -0
- agentscope_runtime/tools/modelstudio_memory/base.py +220 -0
- agentscope_runtime/tools/modelstudio_memory/config.py +86 -0
- agentscope_runtime/tools/modelstudio_memory/core.py +594 -0
- agentscope_runtime/tools/modelstudio_memory/exceptions.py +60 -0
- agentscope_runtime/tools/modelstudio_memory/schemas.py +253 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/METADATA +187 -74
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/RECORD +79 -55
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/WHEEL +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/top_level.txt +0 -0
|
@@ -9,6 +9,7 @@ from urllib.parse import urlparse
|
|
|
9
9
|
from agentscope import setup_logger
|
|
10
10
|
from agentscope.message import Msg
|
|
11
11
|
|
|
12
|
+
from ..utils import _update_obj_attrs
|
|
12
13
|
from ...engine.schemas.agent_schemas import (
|
|
13
14
|
Message,
|
|
14
15
|
Content,
|
|
@@ -26,13 +27,6 @@ from ...engine.schemas.agent_schemas import (
|
|
|
26
27
|
setup_logger("ERROR")
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
def _update_obj_attrs(obj, **attrs):
|
|
30
|
-
for key, value in attrs.items():
|
|
31
|
-
if hasattr(obj, key):
|
|
32
|
-
setattr(obj, key, value)
|
|
33
|
-
return obj
|
|
34
|
-
|
|
35
|
-
|
|
36
30
|
async def adapt_agentscope_message_stream(
|
|
37
31
|
source_stream: AsyncIterator[Tuple[Msg, bool]],
|
|
38
32
|
) -> AsyncIterator[Union[Message, Content]]:
|
|
@@ -277,7 +271,7 @@ async def adapt_agentscope_message_stream(
|
|
|
277
271
|
role="assistant",
|
|
278
272
|
)
|
|
279
273
|
data_delta_content = DataContent(
|
|
280
|
-
index=0,
|
|
274
|
+
index=None if last else 0,
|
|
281
275
|
data=fc_cls(
|
|
282
276
|
call_id=element["id"],
|
|
283
277
|
name=element.get("name"),
|
|
@@ -62,79 +62,121 @@ async def adapt_langgraph_message_stream(
|
|
|
62
62
|
yield message.completed()
|
|
63
63
|
elif isinstance(msg, AIMessage):
|
|
64
64
|
role = "assistant"
|
|
65
|
+
tool_calls = getattr(msg, "tool_calls", [])
|
|
65
66
|
has_tool_call_chunk = (
|
|
66
|
-
True if getattr(msg, "tool_call_chunks") else False
|
|
67
|
+
True if getattr(msg, "tool_call_chunks", "") else False
|
|
67
68
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
data_content
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
if tool_calls and not has_tool_call_chunk:
|
|
70
|
+
plugin_call_message = Message(
|
|
71
|
+
type=MessageType.PLUGIN_CALL,
|
|
72
|
+
role=role,
|
|
73
|
+
)
|
|
74
|
+
for tool_call in tool_calls:
|
|
75
|
+
tool_call_args = (
|
|
76
|
+
tool_call.get("args")
|
|
77
|
+
if isinstance(tool_call.get("args"), str)
|
|
78
|
+
else json.dumps(tool_call.get("args"))
|
|
79
|
+
)
|
|
80
|
+
data_content = DataContent(
|
|
81
|
+
index=index,
|
|
82
|
+
data=FunctionCall(
|
|
83
|
+
call_id=tool_call.get("id"),
|
|
84
|
+
name=tool_call.get("name"),
|
|
85
|
+
arguments=tool_call_args,
|
|
86
|
+
).model_dump(),
|
|
87
|
+
)
|
|
88
|
+
plugin_call_message.add_content(
|
|
89
|
+
data_content,
|
|
90
|
+
)
|
|
91
|
+
yield data_content.completed()
|
|
92
|
+
yield plugin_call_message.completed()
|
|
93
|
+
else:
|
|
94
|
+
has_tool_call_chunk = (
|
|
95
|
+
True if getattr(msg, "tool_call_chunks", "") else False
|
|
96
|
+
)
|
|
97
|
+
is_last_chunk = (
|
|
98
|
+
True
|
|
99
|
+
if getattr(msg, "chunk_position", "") == "last"
|
|
100
|
+
else False
|
|
101
|
+
)
|
|
102
|
+
# Extract tool calls if present
|
|
103
|
+
if tool_started:
|
|
104
|
+
if has_tool_call_chunk:
|
|
105
|
+
tool_call_chunk_msgs.append(msg)
|
|
106
|
+
if is_last_chunk:
|
|
107
|
+
# tool call finished
|
|
108
|
+
tool_started = False
|
|
109
|
+
result = reduce(
|
|
110
|
+
lambda x, y: x + y,
|
|
111
|
+
tool_call_chunk_msgs,
|
|
99
112
|
)
|
|
113
|
+
tool_calls = result.tool_call_chunks
|
|
114
|
+
for tool_call in tool_calls:
|
|
115
|
+
call_id = tool_call.get("id", "")
|
|
116
|
+
# Create new tool call message
|
|
117
|
+
plugin_call_message = Message(
|
|
118
|
+
type=MessageType.PLUGIN_CALL,
|
|
119
|
+
role=role,
|
|
120
|
+
)
|
|
121
|
+
tool_call_args = (
|
|
122
|
+
tool_call.get("args")
|
|
123
|
+
if isinstance(tool_call.get("args"), str)
|
|
124
|
+
else json.dumps(tool_call.get("args"))
|
|
125
|
+
)
|
|
100
126
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
tool_started = True
|
|
110
|
-
tool_call_chunk_msgs.append(msg)
|
|
111
|
-
else:
|
|
112
|
-
# normal message
|
|
113
|
-
content = msg.content if hasattr(msg, "content") else None
|
|
114
|
-
if msg_id != getattr(msg, "id"):
|
|
115
|
-
index = None
|
|
116
|
-
message = Message(type=MessageType.MESSAGE, role=role)
|
|
117
|
-
msg_id = getattr(msg, "id")
|
|
118
|
-
yield message.in_progress()
|
|
127
|
+
data_content = DataContent(
|
|
128
|
+
index=index,
|
|
129
|
+
data=FunctionCall(
|
|
130
|
+
call_id=call_id,
|
|
131
|
+
name=tool_call.get("name"),
|
|
132
|
+
arguments=tool_call_args,
|
|
133
|
+
).model_dump(),
|
|
134
|
+
)
|
|
119
135
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
data_content = (
|
|
137
|
+
plugin_call_message.add_delta_content(
|
|
138
|
+
new_content=data_content,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
yield data_content.completed()
|
|
142
|
+
yield plugin_call_message.completed()
|
|
143
|
+
else:
|
|
144
|
+
if has_tool_call_chunk:
|
|
145
|
+
# tool call start, collect chunks and continue
|
|
146
|
+
tool_started = True
|
|
147
|
+
tool_call_chunk_msgs.append(msg)
|
|
148
|
+
else:
|
|
149
|
+
# normal message
|
|
150
|
+
content = (
|
|
151
|
+
msg.content if hasattr(msg, "content") else None
|
|
129
152
|
)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
if msg_id != getattr(msg, "id"):
|
|
154
|
+
index = None
|
|
155
|
+
message = Message(
|
|
156
|
+
type=MessageType.MESSAGE,
|
|
157
|
+
role=role,
|
|
158
|
+
)
|
|
159
|
+
msg_id = getattr(msg, "id")
|
|
160
|
+
yield message.in_progress()
|
|
161
|
+
|
|
162
|
+
if content:
|
|
163
|
+
# todo support non str content
|
|
164
|
+
text_delta_content = TextContent(
|
|
165
|
+
delta=True,
|
|
166
|
+
index=index,
|
|
167
|
+
text=content,
|
|
168
|
+
)
|
|
169
|
+
text_delta_content = message.add_delta_content(
|
|
170
|
+
new_content=text_delta_content,
|
|
171
|
+
)
|
|
172
|
+
index = text_delta_content.index
|
|
173
|
+
yield text_delta_content
|
|
174
|
+
# Handle final completion
|
|
175
|
+
if last:
|
|
176
|
+
# completed_content = message.content[index]
|
|
177
|
+
# if completed_content.text:
|
|
178
|
+
# yield completed_content.completed()
|
|
179
|
+
yield message.completed()
|
|
138
180
|
elif isinstance(msg, SystemMessage):
|
|
139
181
|
role = "system"
|
|
140
182
|
content = msg.content if hasattr(msg, "content") else None
|
|
@@ -163,18 +205,26 @@ async def adapt_langgraph_message_stream(
|
|
|
163
205
|
type=MessageType.PLUGIN_CALL_OUTPUT,
|
|
164
206
|
role="tool",
|
|
165
207
|
)
|
|
208
|
+
tool_call_output = (
|
|
209
|
+
msg.content
|
|
210
|
+
if isinstance(msg.content, str)
|
|
211
|
+
else json.dumps(msg.content, ensure_ascii=False)
|
|
212
|
+
)
|
|
166
213
|
# Create function call output data
|
|
167
214
|
function_output_data = FunctionCallOutput(
|
|
168
215
|
call_id=msg.tool_call_id,
|
|
169
216
|
name=msg.name,
|
|
170
|
-
output=
|
|
217
|
+
output=tool_call_output,
|
|
171
218
|
)
|
|
172
219
|
|
|
173
220
|
data_content = DataContent(
|
|
174
|
-
index=None,
|
|
175
221
|
data=function_output_data.model_dump(),
|
|
222
|
+
msg_id=plugin_output_message.id,
|
|
223
|
+
)
|
|
224
|
+
yield data_content.completed()
|
|
225
|
+
plugin_output_message.add_content(
|
|
226
|
+
data_content,
|
|
176
227
|
)
|
|
177
|
-
plugin_output_message.content = [data_content]
|
|
178
228
|
yield plugin_output_message.completed()
|
|
179
229
|
else:
|
|
180
230
|
role = "assistant"
|
|
File without changes
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=too-many-branches,too-many-statements
|
|
3
|
+
import json
|
|
4
|
+
from typing import Union, List
|
|
5
|
+
from collections import OrderedDict
|
|
6
|
+
|
|
7
|
+
from agent_framework import (
|
|
8
|
+
ChatMessage,
|
|
9
|
+
TextContent as MSTextContent,
|
|
10
|
+
DataContent as MSDataContent,
|
|
11
|
+
TextReasoningContent,
|
|
12
|
+
UriContent,
|
|
13
|
+
FunctionCallContent,
|
|
14
|
+
FunctionResultContent,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from ...engine.schemas.agent_schemas import (
|
|
18
|
+
Message,
|
|
19
|
+
MessageType,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def message_to_ms_agent_framework_message(
|
|
24
|
+
messages: Union[Message, List[Message]],
|
|
25
|
+
) -> Union[ChatMessage, List[ChatMessage]]:
|
|
26
|
+
"""
|
|
27
|
+
Convert AgentScope runtime Message(s) to Microsoft agent framework
|
|
28
|
+
Message(s).
|
|
29
|
+
|
|
30
|
+
Reference:
|
|
31
|
+
https://learn.microsoft.com/en-us/agent-framework/user-guide/agents
|
|
32
|
+
/running-agents?pivots=programming-language-python
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
messages: A single AgentScope runtime Message or list of Messages.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
A single Microsoft agent framework Message object or a list of
|
|
39
|
+
Microsoft agent framework Message objects.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def _try_loads(v, default, keep_original=False):
|
|
43
|
+
if isinstance(v, (dict, list)):
|
|
44
|
+
return v
|
|
45
|
+
if isinstance(v, str) and v.strip():
|
|
46
|
+
try:
|
|
47
|
+
return json.loads(v)
|
|
48
|
+
except Exception:
|
|
49
|
+
return v if keep_original else default
|
|
50
|
+
return default
|
|
51
|
+
|
|
52
|
+
def _convert_one(message: Message) -> ChatMessage:
|
|
53
|
+
result = {
|
|
54
|
+
"author_name": getattr(message, "name", message.role),
|
|
55
|
+
"role": message.role or "assistant",
|
|
56
|
+
}
|
|
57
|
+
_id = getattr(message, "id")
|
|
58
|
+
|
|
59
|
+
# if meta exists, prefer original id/name from meta
|
|
60
|
+
if hasattr(message, "metadata") and isinstance(message.metadata, dict):
|
|
61
|
+
if "original_id" in message.metadata:
|
|
62
|
+
_id = message.metadata["original_id"]
|
|
63
|
+
if "original_name" in message.metadata:
|
|
64
|
+
result["author_name"] = message.metadata["original_name"]
|
|
65
|
+
if "metadata" in message.metadata:
|
|
66
|
+
result["additional_properties"] = message.metadata["metadata"]
|
|
67
|
+
result["message_id"] = _id
|
|
68
|
+
|
|
69
|
+
if message.type in (
|
|
70
|
+
MessageType.PLUGIN_CALL,
|
|
71
|
+
MessageType.MCP_TOOL_CALL,
|
|
72
|
+
MessageType.FUNCTION_CALL,
|
|
73
|
+
):
|
|
74
|
+
# convert CALL to ToolUseBlock
|
|
75
|
+
tool_args = None
|
|
76
|
+
for cnt in reversed(message.content):
|
|
77
|
+
if hasattr(cnt, "data"):
|
|
78
|
+
v = cnt.data.get("arguments")
|
|
79
|
+
if isinstance(v, (dict, list)) or (
|
|
80
|
+
isinstance(v, str) and v.strip()
|
|
81
|
+
):
|
|
82
|
+
tool_args = _try_loads(v, {}, keep_original=False)
|
|
83
|
+
break
|
|
84
|
+
if tool_args is None:
|
|
85
|
+
tool_args = {}
|
|
86
|
+
result["contents"] = [
|
|
87
|
+
FunctionCallContent(
|
|
88
|
+
call_id=message.content[0].data["call_id"],
|
|
89
|
+
name=message.content[0].data.get("name"),
|
|
90
|
+
arguments=tool_args,
|
|
91
|
+
),
|
|
92
|
+
]
|
|
93
|
+
elif message.type in (
|
|
94
|
+
MessageType.PLUGIN_CALL_OUTPUT,
|
|
95
|
+
MessageType.MCP_TOOL_CALL_OUTPUT,
|
|
96
|
+
MessageType.FUNCTION_CALL_OUTPUT,
|
|
97
|
+
):
|
|
98
|
+
result["role"] = "tool"
|
|
99
|
+
out = None
|
|
100
|
+
for cnt in reversed(message.content):
|
|
101
|
+
if hasattr(cnt, "data"):
|
|
102
|
+
v = cnt.data.get("output")
|
|
103
|
+
if isinstance(v, (dict, list)) or (
|
|
104
|
+
isinstance(v, str) and v.strip()
|
|
105
|
+
):
|
|
106
|
+
out = _try_loads(v, "", keep_original=True)
|
|
107
|
+
break
|
|
108
|
+
if out is None:
|
|
109
|
+
out = ""
|
|
110
|
+
blk = out
|
|
111
|
+
|
|
112
|
+
result["contents"] = [
|
|
113
|
+
FunctionResultContent(
|
|
114
|
+
call_id=message.content[0].data["call_id"],
|
|
115
|
+
result=blk,
|
|
116
|
+
),
|
|
117
|
+
]
|
|
118
|
+
elif message.type in (MessageType.REASONING,):
|
|
119
|
+
result["contents"] = [
|
|
120
|
+
TextReasoningContent(
|
|
121
|
+
text=message.content[0].text,
|
|
122
|
+
),
|
|
123
|
+
]
|
|
124
|
+
else:
|
|
125
|
+
type_mapping = {
|
|
126
|
+
"text": (MSTextContent, "text"),
|
|
127
|
+
"image": (UriContent, "image_url"),
|
|
128
|
+
"audio": (UriContent, "data"),
|
|
129
|
+
"data": (MSDataContent, "data"),
|
|
130
|
+
"file": (MSDataContent, "file_url"), # Support file_url
|
|
131
|
+
# "video": (VideoBlock, "video_url", True),
|
|
132
|
+
# TODO: support video
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
msg_content = []
|
|
136
|
+
for cnt in message.content:
|
|
137
|
+
cnt_type = cnt.type or "text"
|
|
138
|
+
|
|
139
|
+
if cnt_type not in type_mapping:
|
|
140
|
+
raise ValueError(f"Unsupported message type: {cnt_type}")
|
|
141
|
+
|
|
142
|
+
block_cls, attr_name = type_mapping[cnt_type]
|
|
143
|
+
value = getattr(cnt, attr_name)
|
|
144
|
+
|
|
145
|
+
if cnt_type in ("image", "audio", "file", "data"):
|
|
146
|
+
msg_content.append(
|
|
147
|
+
block_cls(
|
|
148
|
+
data=value,
|
|
149
|
+
type=cnt.type,
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
else:
|
|
154
|
+
# text
|
|
155
|
+
if isinstance(value, str):
|
|
156
|
+
msg_content.append(
|
|
157
|
+
MSTextContent(text=value),
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
try:
|
|
161
|
+
json_str = json.dumps(value, ensure_ascii=False)
|
|
162
|
+
except Exception:
|
|
163
|
+
json_str = str(value)
|
|
164
|
+
msg_content.append(MSTextContent(text=json_str))
|
|
165
|
+
|
|
166
|
+
result["contents"] = msg_content
|
|
167
|
+
_msg = ChatMessage(**result)
|
|
168
|
+
return _msg
|
|
169
|
+
|
|
170
|
+
# Handle single or list input
|
|
171
|
+
if isinstance(messages, Message):
|
|
172
|
+
return _convert_one(messages)
|
|
173
|
+
elif isinstance(messages, list):
|
|
174
|
+
converted_list = [_convert_one(m) for m in messages]
|
|
175
|
+
|
|
176
|
+
# Group by original_id
|
|
177
|
+
grouped = OrderedDict()
|
|
178
|
+
for msg, orig_msg in zip(messages, converted_list):
|
|
179
|
+
metadata = getattr(msg, "metadata")
|
|
180
|
+
if metadata:
|
|
181
|
+
orig_id = metadata.get(
|
|
182
|
+
"original_id",
|
|
183
|
+
orig_msg.message_id,
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
# In case metadata is not provided, use the original id
|
|
187
|
+
orig_id = msg.id
|
|
188
|
+
|
|
189
|
+
if orig_id not in grouped:
|
|
190
|
+
ms_msg = ChatMessage(
|
|
191
|
+
author_name=orig_msg.author_name,
|
|
192
|
+
role=orig_msg.role,
|
|
193
|
+
additional_properties=orig_msg.additional_properties,
|
|
194
|
+
contents=list(orig_msg.contents),
|
|
195
|
+
)
|
|
196
|
+
ms_msg.message_id = orig_id
|
|
197
|
+
grouped[orig_id] = ms_msg
|
|
198
|
+
else:
|
|
199
|
+
grouped[orig_id].contents.extend(orig_msg.contents)
|
|
200
|
+
|
|
201
|
+
return list(grouped.values())
|
|
202
|
+
else:
|
|
203
|
+
raise TypeError(
|
|
204
|
+
f"Expected Message or list[Message], got {type(messages)}",
|
|
205
|
+
)
|