agentscope-runtime 0.1.5b2__py3-none-any.whl → 0.2.0__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/common/__init__.py +0 -0
- agentscope_runtime/common/collections/in_memory_mapping.py +27 -0
- agentscope_runtime/common/collections/redis_mapping.py +42 -0
- agentscope_runtime/common/container_clients/__init__.py +0 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +1098 -0
- agentscope_runtime/common/container_clients/docker_client.py +250 -0
- agentscope_runtime/{sandbox/manager → common}/container_clients/kubernetes_client.py +6 -13
- agentscope_runtime/engine/__init__.py +12 -0
- agentscope_runtime/engine/agents/agentscope_agent.py +567 -0
- agentscope_runtime/engine/agents/agno_agent.py +26 -27
- agentscope_runtime/engine/agents/autogen_agent.py +13 -8
- agentscope_runtime/engine/agents/langgraph_agent.py +52 -9
- agentscope_runtime/engine/agents/utils.py +53 -0
- agentscope_runtime/engine/app/__init__.py +6 -0
- agentscope_runtime/engine/app/agent_app.py +239 -0
- agentscope_runtime/engine/app/base_app.py +181 -0
- agentscope_runtime/engine/app/celery_mixin.py +92 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -1
- agentscope_runtime/engine/deployers/base.py +1 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +39 -20
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +12 -5
- agentscope_runtime/engine/deployers/local_deployer.py +61 -3
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +201 -40
- agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +9 -0
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +234 -3
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +567 -7
- agentscope_runtime/engine/deployers/utils/service_utils/standalone_main.py.j2 +211 -0
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +1 -1
- agentscope_runtime/engine/helpers/helper.py +60 -41
- agentscope_runtime/engine/runner.py +40 -24
- agentscope_runtime/engine/schemas/agent_schemas.py +42 -0
- agentscope_runtime/engine/schemas/modelstudio_llm.py +14 -14
- agentscope_runtime/engine/services/sandbox_service.py +62 -70
- agentscope_runtime/engine/services/tablestore_memory_service.py +307 -0
- agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
- agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
- agentscope_runtime/engine/services/utils/__init__.py +0 -0
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
- agentscope_runtime/engine/tracing/__init__.py +9 -3
- agentscope_runtime/engine/tracing/asyncio_util.py +24 -0
- agentscope_runtime/engine/tracing/base.py +66 -34
- agentscope_runtime/engine/tracing/local_logging_handler.py +45 -31
- agentscope_runtime/engine/tracing/message_util.py +528 -0
- agentscope_runtime/engine/tracing/tracing_metric.py +20 -8
- agentscope_runtime/engine/tracing/tracing_util.py +130 -0
- agentscope_runtime/engine/tracing/wrapper.py +794 -169
- agentscope_runtime/sandbox/__init__.py +2 -0
- agentscope_runtime/sandbox/box/base/__init__.py +4 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +6 -4
- agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +10 -14
- agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
- agentscope_runtime/sandbox/box/dummy/dummy_sandbox.py +2 -1
- agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +10 -7
- agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
- agentscope_runtime/sandbox/box/gui/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +81 -0
- agentscope_runtime/sandbox/box/sandbox.py +5 -2
- agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
- agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +7 -54
- agentscope_runtime/sandbox/build.py +143 -58
- agentscope_runtime/sandbox/client/http_client.py +87 -59
- agentscope_runtime/sandbox/client/training_client.py +0 -1
- agentscope_runtime/sandbox/constant.py +27 -1
- agentscope_runtime/sandbox/custom/custom_sandbox.py +7 -6
- agentscope_runtime/sandbox/custom/example.py +4 -3
- agentscope_runtime/sandbox/enums.py +1 -1
- agentscope_runtime/sandbox/manager/sandbox_manager.py +212 -106
- agentscope_runtime/sandbox/manager/server/app.py +82 -14
- agentscope_runtime/sandbox/manager/server/config.py +50 -3
- agentscope_runtime/sandbox/model/container.py +12 -23
- agentscope_runtime/sandbox/model/manager_config.py +93 -5
- agentscope_runtime/sandbox/registry.py +1 -1
- agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
- agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
- agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
- agentscope_runtime/sandbox/tools/tool.py +4 -0
- agentscope_runtime/sandbox/utils.py +124 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/METADATA +246 -111
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/RECORD +96 -80
- agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
- agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
- agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
- agentscope_runtime/engine/agents/llm_agent.py +0 -51
- agentscope_runtime/engine/llms/__init__.py +0 -3
- agentscope_runtime/engine/llms/base_llm.py +0 -60
- agentscope_runtime/engine/llms/qwen_llm.py +0 -47
- agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +0 -22
- agentscope_runtime/sandbox/manager/collections/redis_mapping.py +0 -26
- agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
- agentscope_runtime/sandbox/manager/container_clients/docker_client.py +0 -422
- /agentscope_runtime/{sandbox/manager → common}/collections/__init__.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_mapping.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/base_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/in_memory_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/redis_queue.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/collections/redis_set.py +0 -0
- /agentscope_runtime/{sandbox/manager → common}/container_clients/base_client.py +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.1.5b2.dist-info → agentscope_runtime-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint: disable=redefined-outer-name
|
|
3
|
+
import asyncio
|
|
4
|
+
import uuid
|
|
5
|
+
from typing import Any, Dict, List, Optional, Union
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import tablestore
|
|
9
|
+
from tablestore import AsyncOTSClient as AsyncTablestoreClient
|
|
10
|
+
from tablestore_for_agent_memory.base.base_memory_store import (
|
|
11
|
+
Session as TablestoreSession,
|
|
12
|
+
)
|
|
13
|
+
from tablestore_for_agent_memory.base.common import MetaType, Order
|
|
14
|
+
from tablestore_for_agent_memory.memory.async_memory_store import (
|
|
15
|
+
AsyncMemoryStore,
|
|
16
|
+
)
|
|
17
|
+
except ImportError as e:
|
|
18
|
+
raise ImportError(
|
|
19
|
+
"aliyun_tablestore is not available. "
|
|
20
|
+
"Please run pip install agentscope-runtime[aliyun_tablestore_ext]",
|
|
21
|
+
) from e
|
|
22
|
+
|
|
23
|
+
from ..schemas.agent_schemas import Message
|
|
24
|
+
from .session_history_service import Session, SessionHistoryService
|
|
25
|
+
from .utils.tablestore_service_utils import (
|
|
26
|
+
convert_message_to_tablestore_message,
|
|
27
|
+
convert_tablestore_session_to_session,
|
|
28
|
+
tablestore_log,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TablestoreSessionHistoryService(SessionHistoryService):
|
|
33
|
+
"""An aliyun tablestore implementation of the SessionHistoryService
|
|
34
|
+
based on tablestore_for_agent_memory
|
|
35
|
+
(https://github.com/aliyun/
|
|
36
|
+
alibabacloud-tablestore-for-agent-memory/blob/main/python/docs/memory_store_tutorial.ipynb).
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
_SESSION_SECONDARY_INDEX_NAME = (
|
|
40
|
+
"agentscope_runtime_session_secondary_index"
|
|
41
|
+
)
|
|
42
|
+
_SESSION_SEARCH_INDEX_NAME = "agentscope_runtime_session_search_index"
|
|
43
|
+
_MESSAGE_SECONDARY_INDEX_NAME = (
|
|
44
|
+
"agentscope_runtime_message_secondary_index"
|
|
45
|
+
)
|
|
46
|
+
_MESSAGE_SEARCH_INDEX_NAME = "agentscope_runtime_message_search_index"
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
tablestore_client: AsyncTablestoreClient,
|
|
51
|
+
session_table_name: Optional[str] = "agentscope_runtime_session",
|
|
52
|
+
message_table_name: Optional[str] = "agentscope_runtime_message",
|
|
53
|
+
session_secondary_index_meta: Optional[Dict[str, MetaType]] = None,
|
|
54
|
+
session_search_index_schema: Optional[
|
|
55
|
+
List[tablestore.FieldSchema]
|
|
56
|
+
] = None,
|
|
57
|
+
message_search_index_schema: Optional[
|
|
58
|
+
List[tablestore.FieldSchema]
|
|
59
|
+
] = None,
|
|
60
|
+
**kwargs: Any,
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Initializes the TablestoreSessionHistoryService."""
|
|
63
|
+
self._tablestore_client = tablestore_client
|
|
64
|
+
self._session_table_name = session_table_name
|
|
65
|
+
self._message_table_name = message_table_name
|
|
66
|
+
self._session_secondary_index_meta = session_secondary_index_meta
|
|
67
|
+
self._session_search_index_schema = session_search_index_schema
|
|
68
|
+
self._message_search_index_schema = message_search_index_schema
|
|
69
|
+
self._memory_store: Optional[AsyncMemoryStore] = None
|
|
70
|
+
self._memory_store_init_parameter_kwargs = kwargs
|
|
71
|
+
|
|
72
|
+
async def _init_memory_store(self) -> None:
|
|
73
|
+
self._memory_store = AsyncMemoryStore(
|
|
74
|
+
tablestore_client=self._tablestore_client,
|
|
75
|
+
session_table_name=self._session_table_name,
|
|
76
|
+
message_table_name=self._message_table_name,
|
|
77
|
+
session_secondary_index_name=self._SESSION_SECONDARY_INDEX_NAME,
|
|
78
|
+
session_search_index_name=self._SESSION_SEARCH_INDEX_NAME,
|
|
79
|
+
message_secondary_index_name=self._MESSAGE_SECONDARY_INDEX_NAME,
|
|
80
|
+
message_search_index_name=self._MESSAGE_SEARCH_INDEX_NAME,
|
|
81
|
+
session_secondary_index_meta=self._session_secondary_index_meta,
|
|
82
|
+
session_search_index_schema=self._session_search_index_schema,
|
|
83
|
+
message_search_index_schema=self._message_search_index_schema,
|
|
84
|
+
**self._memory_store_init_parameter_kwargs,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
await self._memory_store.init_table()
|
|
88
|
+
await self._memory_store.init_search_index()
|
|
89
|
+
|
|
90
|
+
async def start(self) -> None:
|
|
91
|
+
"""Start the tablestore service"""
|
|
92
|
+
if self._memory_store:
|
|
93
|
+
return
|
|
94
|
+
await self._init_memory_store()
|
|
95
|
+
|
|
96
|
+
async def stop(self) -> None:
|
|
97
|
+
"""Close the tablestore service"""
|
|
98
|
+
if self._memory_store is None:
|
|
99
|
+
return
|
|
100
|
+
memory_store = self._memory_store
|
|
101
|
+
self._memory_store = None
|
|
102
|
+
await memory_store.close()
|
|
103
|
+
|
|
104
|
+
async def health(self) -> bool:
|
|
105
|
+
"""Checks the health of the service."""
|
|
106
|
+
if self._memory_store is None:
|
|
107
|
+
tablestore_log(
|
|
108
|
+
"Tablestore session history service is not started.",
|
|
109
|
+
)
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
async for _ in await self._memory_store.list_all_sessions():
|
|
114
|
+
return True
|
|
115
|
+
return True
|
|
116
|
+
except Exception as e:
|
|
117
|
+
tablestore_log(
|
|
118
|
+
f"Tablestore session history service "
|
|
119
|
+
f"cannot access Tablestore, error: {str(e)}.",
|
|
120
|
+
)
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
async def create_session(
|
|
124
|
+
self,
|
|
125
|
+
user_id: str,
|
|
126
|
+
session_id: Optional[str] = None,
|
|
127
|
+
) -> Session:
|
|
128
|
+
"""Creates a new session for a given user and stores it.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
user_id: The identifier for the user creating the session.
|
|
132
|
+
session_id: The identifier for the session to delete.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
A newly created Session object.
|
|
136
|
+
"""
|
|
137
|
+
session_id = (
|
|
138
|
+
session_id.strip()
|
|
139
|
+
if session_id and session_id.strip()
|
|
140
|
+
else str(uuid.uuid4())
|
|
141
|
+
)
|
|
142
|
+
tablestore_session = TablestoreSession(
|
|
143
|
+
session_id=session_id,
|
|
144
|
+
user_id=user_id,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
await self._memory_store.put_session(tablestore_session)
|
|
148
|
+
return convert_tablestore_session_to_session(tablestore_session)
|
|
149
|
+
|
|
150
|
+
async def get_session(
|
|
151
|
+
self,
|
|
152
|
+
user_id: str,
|
|
153
|
+
session_id: str,
|
|
154
|
+
) -> Session | None:
|
|
155
|
+
"""Retrieves a specific session from memory.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
user_id: The identifier for the user.
|
|
159
|
+
session_id: The identifier for the session to retrieve.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
A Session object if found, otherwise None.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
tablestore_session = await self._memory_store.get_session(
|
|
166
|
+
user_id=user_id,
|
|
167
|
+
session_id=session_id,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if not tablestore_session:
|
|
171
|
+
tablestore_session = TablestoreSession(
|
|
172
|
+
session_id=session_id,
|
|
173
|
+
user_id=user_id,
|
|
174
|
+
)
|
|
175
|
+
await self._memory_store.put_session(tablestore_session)
|
|
176
|
+
tablestore_messages = None
|
|
177
|
+
else:
|
|
178
|
+
messages_iterator = await self._memory_store.list_messages(
|
|
179
|
+
session_id=session_id,
|
|
180
|
+
order=Order.ASC,
|
|
181
|
+
# Sort by timestamp,
|
|
182
|
+
# keeping the most recent information at the end of the list.
|
|
183
|
+
)
|
|
184
|
+
tablestore_messages = [
|
|
185
|
+
message async for message in messages_iterator
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
return convert_tablestore_session_to_session(
|
|
189
|
+
tablestore_session,
|
|
190
|
+
tablestore_messages,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
async def delete_session(self, user_id: str, session_id: str) -> None:
|
|
194
|
+
"""Deletes a specific session from memory.
|
|
195
|
+
|
|
196
|
+
If the session does not exist, the method does nothing.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
user_id: The identifier for the user.
|
|
200
|
+
session_id: The identifier for the session to delete.
|
|
201
|
+
"""
|
|
202
|
+
await self._memory_store.delete_session_and_messages(
|
|
203
|
+
user_id=user_id,
|
|
204
|
+
session_id=session_id,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
async def list_sessions(self, user_id: str) -> list[Session]:
|
|
208
|
+
"""Lists all sessions for a given user.
|
|
209
|
+
|
|
210
|
+
To improve performance and reduce data transfer, the returned session
|
|
211
|
+
objects do not contain the detailed response history.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
user_id: The identifier of the user whose sessions to list.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
A list of Session objects belonging to the user, without history.
|
|
218
|
+
"""
|
|
219
|
+
tablestore_sessions = await self._memory_store.list_sessions(user_id)
|
|
220
|
+
return [
|
|
221
|
+
convert_tablestore_session_to_session(tablestore_session)
|
|
222
|
+
async for tablestore_session in tablestore_sessions
|
|
223
|
+
]
|
|
224
|
+
|
|
225
|
+
async def append_message(
|
|
226
|
+
self,
|
|
227
|
+
session: Session,
|
|
228
|
+
message: Union[
|
|
229
|
+
Message,
|
|
230
|
+
List[Message],
|
|
231
|
+
Dict[str, Any],
|
|
232
|
+
List[Dict[str, Any]],
|
|
233
|
+
],
|
|
234
|
+
) -> None:
|
|
235
|
+
"""Appends message to a session's history in memory.
|
|
236
|
+
|
|
237
|
+
This method finds the authoritative session object in the in-memory
|
|
238
|
+
storage and appends the message to its history. It supports both
|
|
239
|
+
dictionary format messages and Message objects.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
session: The session object, typically from the context. The
|
|
243
|
+
user_id and id from this object are used for lookup.
|
|
244
|
+
message: The message or list of messages to append to the
|
|
245
|
+
session's history.
|
|
246
|
+
"""
|
|
247
|
+
# Normalize to list
|
|
248
|
+
if not isinstance(message, list):
|
|
249
|
+
message = [message]
|
|
250
|
+
|
|
251
|
+
norm_message = []
|
|
252
|
+
for msg in message:
|
|
253
|
+
if msg is None:
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
if not isinstance(msg, Message):
|
|
257
|
+
msg = Message.model_validate(msg)
|
|
258
|
+
norm_message.append(msg)
|
|
259
|
+
session.messages.extend(norm_message)
|
|
260
|
+
|
|
261
|
+
tablestore_session = await self._memory_store.get_session(
|
|
262
|
+
session_id=session.id,
|
|
263
|
+
user_id=session.user_id,
|
|
264
|
+
)
|
|
265
|
+
if tablestore_session:
|
|
266
|
+
put_tasks = [
|
|
267
|
+
self._memory_store.put_message(
|
|
268
|
+
convert_message_to_tablestore_message(message, session),
|
|
269
|
+
)
|
|
270
|
+
for message in norm_message
|
|
271
|
+
]
|
|
272
|
+
await asyncio.gather(*put_tasks)
|
|
273
|
+
|
|
274
|
+
else:
|
|
275
|
+
tablestore_log(
|
|
276
|
+
f"Warning: Session {session.id} not found "
|
|
277
|
+
f"in tablestore storage for "
|
|
278
|
+
f"append_message.",
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
async def delete_user_sessions(self, user_id: str) -> None:
|
|
282
|
+
"""
|
|
283
|
+
Deletes all session history data for a specific user.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
user_id (str): The ID of the user whose session history data should
|
|
287
|
+
be deleted
|
|
288
|
+
"""
|
|
289
|
+
delete_tasks = [
|
|
290
|
+
self.delete_session(user_id, session.id)
|
|
291
|
+
for session in (await self.list_sessions(user_id=user_id))
|
|
292
|
+
]
|
|
293
|
+
await asyncio.gather(*delete_tasks)
|
|
File without changes
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import copy
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
import tablestore
|
|
7
|
+
from langchain_core.embeddings import Embeddings
|
|
8
|
+
from tablestore import AsyncOTSClient as AsyncTablestoreClient
|
|
9
|
+
from tablestore.credentials import CredentialsProvider
|
|
10
|
+
from tablestore_for_agent_memory.base.base_knowledge_store import (
|
|
11
|
+
Document as TablestoreDocument,
|
|
12
|
+
)
|
|
13
|
+
from tablestore_for_agent_memory.base.base_memory_store import (
|
|
14
|
+
Message as TablestoreMessage,
|
|
15
|
+
)
|
|
16
|
+
from tablestore_for_agent_memory.base.base_memory_store import (
|
|
17
|
+
Session as TablestoreSession,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from ...schemas.agent_schemas import ContentType, MessageType
|
|
21
|
+
from ..session_history_service import Message, Session
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def create_tablestore_client(
|
|
25
|
+
end_point: str,
|
|
26
|
+
access_key_id: str,
|
|
27
|
+
access_key_secret: str,
|
|
28
|
+
instance_name: str,
|
|
29
|
+
sts_token: Optional[str] = None,
|
|
30
|
+
region: Optional[str] = None,
|
|
31
|
+
credentials_provider: Optional[CredentialsProvider] = None,
|
|
32
|
+
retry_policy: tablestore.RetryPolicy = tablestore.WriteRetryPolicy(),
|
|
33
|
+
**kwargs: Any,
|
|
34
|
+
) -> AsyncTablestoreClient:
|
|
35
|
+
return AsyncTablestoreClient(
|
|
36
|
+
end_point=end_point,
|
|
37
|
+
access_key_id=access_key_id,
|
|
38
|
+
access_key_secret=access_key_secret,
|
|
39
|
+
instance_name=instance_name,
|
|
40
|
+
region=region,
|
|
41
|
+
credentials_provider=credentials_provider,
|
|
42
|
+
sts_token=None if sts_token == "" else sts_token,
|
|
43
|
+
retry_policy=retry_policy,
|
|
44
|
+
**kwargs,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
content_list_name = "content_list"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def exclude_None_fields_in_place(obj: Dict):
|
|
52
|
+
"""Remove fields with None values from dictionary in-place"""
|
|
53
|
+
obj_copy = copy.deepcopy(obj)
|
|
54
|
+
for key, value in obj_copy.items():
|
|
55
|
+
if value is None:
|
|
56
|
+
del obj[key]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def tablestore_log(msg: str):
|
|
60
|
+
print(msg)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def convert_tablestore_session_to_session(
|
|
64
|
+
tablestore_session: TablestoreSession,
|
|
65
|
+
tablestore_messages: Optional[List[TablestoreMessage]] = None,
|
|
66
|
+
) -> Session:
|
|
67
|
+
"""Convert TablestoreSession to Session"""
|
|
68
|
+
init_json = _generate_init_json_from_tablestore_session(
|
|
69
|
+
tablestore_session,
|
|
70
|
+
tablestore_messages,
|
|
71
|
+
)
|
|
72
|
+
return Session.model_validate(init_json)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# now, the func is not be used,
|
|
76
|
+
# because the interface of session history service don't need this func,
|
|
77
|
+
# just for future
|
|
78
|
+
def convert_session_to_tablestore_session(
|
|
79
|
+
session: Session,
|
|
80
|
+
) -> Tuple[TablestoreSession, List[TablestoreMessage]]:
|
|
81
|
+
"""Convert Session to TablestoreSession and list of TablestoreMessage"""
|
|
82
|
+
tablestore_session_metadata = session.model_dump(
|
|
83
|
+
exclude={"id", "user_id", "messages"},
|
|
84
|
+
)
|
|
85
|
+
exclude_None_fields_in_place(tablestore_session_metadata)
|
|
86
|
+
tablestore_session = TablestoreSession(
|
|
87
|
+
user_id=session.user_id,
|
|
88
|
+
session_id=session.id,
|
|
89
|
+
metadata=tablestore_session_metadata,
|
|
90
|
+
)
|
|
91
|
+
tablestore_messages = [
|
|
92
|
+
convert_message_to_tablestore_message(message, session)
|
|
93
|
+
for message in session.messages
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
return tablestore_session, tablestore_messages
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def convert_tablestore_message_to_message(
|
|
100
|
+
tablestore_message: TablestoreMessage,
|
|
101
|
+
) -> Message:
|
|
102
|
+
"""Convert TablestoreMessage to Message"""
|
|
103
|
+
init_json = _generate_init_json_from_tablestore_message(tablestore_message)
|
|
104
|
+
return Message.model_validate(init_json)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def convert_message_to_tablestore_message(
|
|
108
|
+
message: Message,
|
|
109
|
+
session: Session,
|
|
110
|
+
) -> TablestoreMessage:
|
|
111
|
+
"""Convert Message to TablestoreMessage"""
|
|
112
|
+
content, content_list = _generate_tablestore_content_from_message(message)
|
|
113
|
+
tablestore_message_metadata = message.model_dump(exclude={"content", "id"})
|
|
114
|
+
tablestore_message_metadata[content_list_name] = json.dumps(
|
|
115
|
+
content_list,
|
|
116
|
+
ensure_ascii=False,
|
|
117
|
+
)
|
|
118
|
+
exclude_None_fields_in_place(tablestore_message_metadata)
|
|
119
|
+
tablestore_message = TablestoreMessage(
|
|
120
|
+
session_id=session.id,
|
|
121
|
+
message_id=message.id,
|
|
122
|
+
content=content,
|
|
123
|
+
metadata=tablestore_message_metadata,
|
|
124
|
+
)
|
|
125
|
+
return tablestore_message
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# This function is designed to
|
|
129
|
+
# facilitate batch embedding computation for better performance.
|
|
130
|
+
def convert_messages_to_tablestore_documents(
|
|
131
|
+
messages: List[Message],
|
|
132
|
+
user_id: str,
|
|
133
|
+
session_id: str,
|
|
134
|
+
embedding_model: Optional[Embeddings] = None,
|
|
135
|
+
) -> List[TablestoreDocument]:
|
|
136
|
+
"""Convert list of messages
|
|
137
|
+
to TablestoreDocuments with optional batch embedding"""
|
|
138
|
+
if not embedding_model:
|
|
139
|
+
return [
|
|
140
|
+
convert_message_to_tablestore_document(
|
|
141
|
+
message,
|
|
142
|
+
user_id,
|
|
143
|
+
session_id,
|
|
144
|
+
)
|
|
145
|
+
for message in messages
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
# Batch embed messages: extract content, filter non-empty,
|
|
149
|
+
# compute embeddings, and align results with original messages
|
|
150
|
+
contents = [
|
|
151
|
+
_generate_tablestore_content_from_message(message)[0]
|
|
152
|
+
for message in messages
|
|
153
|
+
]
|
|
154
|
+
contents_not_none = [
|
|
155
|
+
content for content in contents if content is not None
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
embeddings_not_none = embedding_model.embed_documents(contents_not_none)
|
|
159
|
+
embeddings = []
|
|
160
|
+
index = 0
|
|
161
|
+
for content in contents:
|
|
162
|
+
if content is not None:
|
|
163
|
+
embeddings.append(embeddings_not_none[index])
|
|
164
|
+
index += 1
|
|
165
|
+
continue
|
|
166
|
+
embeddings.append(None)
|
|
167
|
+
|
|
168
|
+
return [
|
|
169
|
+
convert_message_to_tablestore_document(
|
|
170
|
+
message,
|
|
171
|
+
user_id,
|
|
172
|
+
session_id,
|
|
173
|
+
embedding,
|
|
174
|
+
)
|
|
175
|
+
for message, embedding in zip(messages, embeddings)
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def convert_message_to_tablestore_document(
|
|
180
|
+
message: Message,
|
|
181
|
+
user_id: str,
|
|
182
|
+
session_id: str,
|
|
183
|
+
embedding: Optional[List[float]] = None,
|
|
184
|
+
) -> TablestoreDocument:
|
|
185
|
+
"""Convert Message to TablestoreDocument"""
|
|
186
|
+
content, content_list = _generate_tablestore_content_from_message(message)
|
|
187
|
+
tablestore_document_metadata = message.model_dump(
|
|
188
|
+
exclude={"content", "id"},
|
|
189
|
+
)
|
|
190
|
+
tablestore_document_metadata.update(
|
|
191
|
+
{
|
|
192
|
+
"user_id": user_id,
|
|
193
|
+
"session_id": session_id,
|
|
194
|
+
content_list_name: json.dumps(content_list, ensure_ascii=False),
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
exclude_None_fields_in_place(tablestore_document_metadata)
|
|
198
|
+
tablestore_document = TablestoreDocument(
|
|
199
|
+
document_id=message.id,
|
|
200
|
+
text=content,
|
|
201
|
+
embedding=embedding if embedding else None,
|
|
202
|
+
metadata=tablestore_document_metadata,
|
|
203
|
+
)
|
|
204
|
+
return tablestore_document
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def convert_tablestore_document_to_message(
|
|
208
|
+
tablestore_document: TablestoreDocument,
|
|
209
|
+
) -> Message:
|
|
210
|
+
"""Convert TablestoreDocument to Message"""
|
|
211
|
+
init_json = _generate_init_json_from_tablestore_document(
|
|
212
|
+
tablestore_document,
|
|
213
|
+
)
|
|
214
|
+
return Message.model_validate(init_json)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _generate_init_json_from_tablestore_session(
|
|
218
|
+
tablestore_session: TablestoreSession,
|
|
219
|
+
tablestore_messages: Optional[List[TablestoreMessage]] = None,
|
|
220
|
+
) -> Dict[str, Any]:
|
|
221
|
+
"""Generate initialization JSON from TablestoreSession"""
|
|
222
|
+
init_json = {
|
|
223
|
+
"id": tablestore_session.session_id,
|
|
224
|
+
"user_id": tablestore_session.user_id,
|
|
225
|
+
"messages": (
|
|
226
|
+
[
|
|
227
|
+
convert_tablestore_message_to_message(tablestore_message)
|
|
228
|
+
for tablestore_message in tablestore_messages
|
|
229
|
+
]
|
|
230
|
+
if tablestore_messages is not None
|
|
231
|
+
else []
|
|
232
|
+
),
|
|
233
|
+
}
|
|
234
|
+
# for fit future, having more fields in Session
|
|
235
|
+
init_json.update(tablestore_session.metadata)
|
|
236
|
+
return init_json
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def _generate_init_json_from_tablestore_message(
|
|
240
|
+
tablestore_message: TablestoreMessage,
|
|
241
|
+
) -> Dict[str, Any]:
|
|
242
|
+
"""Generate initialization JSON from TablestoreMessage"""
|
|
243
|
+
tablestore_message = copy.deepcopy(tablestore_message)
|
|
244
|
+
tablestore_message_content_list = tablestore_message.metadata.pop(
|
|
245
|
+
content_list_name,
|
|
246
|
+
None,
|
|
247
|
+
)
|
|
248
|
+
init_json = {
|
|
249
|
+
"id": tablestore_message.message_id,
|
|
250
|
+
"content": _generate_content_from_tablestore_content(
|
|
251
|
+
text=tablestore_message.content,
|
|
252
|
+
content_list=(
|
|
253
|
+
json.loads(tablestore_message_content_list)
|
|
254
|
+
if tablestore_message_content_list
|
|
255
|
+
else None
|
|
256
|
+
),
|
|
257
|
+
),
|
|
258
|
+
}
|
|
259
|
+
init_json.update(tablestore_message.metadata)
|
|
260
|
+
return init_json
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _generate_init_json_from_tablestore_document(
|
|
264
|
+
tablestore_document: TablestoreDocument,
|
|
265
|
+
) -> Dict[str, Any]:
|
|
266
|
+
"""Generate initialization JSON from TablestoreDocument"""
|
|
267
|
+
tablestore_document = copy.deepcopy(tablestore_document)
|
|
268
|
+
tablestore_document_content_list = tablestore_document.metadata.pop(
|
|
269
|
+
content_list_name,
|
|
270
|
+
None,
|
|
271
|
+
)
|
|
272
|
+
init_json = {
|
|
273
|
+
"id": tablestore_document.document_id,
|
|
274
|
+
"content": _generate_content_from_tablestore_content(
|
|
275
|
+
text=tablestore_document.text,
|
|
276
|
+
content_list=(
|
|
277
|
+
json.loads(tablestore_document_content_list)
|
|
278
|
+
if tablestore_document_content_list
|
|
279
|
+
else None
|
|
280
|
+
),
|
|
281
|
+
),
|
|
282
|
+
}
|
|
283
|
+
init_json.update(tablestore_document.metadata)
|
|
284
|
+
return init_json
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _generate_content_from_tablestore_content(
|
|
288
|
+
text: str,
|
|
289
|
+
content_list: List[Dict[str, Any]],
|
|
290
|
+
) -> Optional[List[Dict[str, Any]]]:
|
|
291
|
+
"""Generate final content from text and content list"""
|
|
292
|
+
content_list = copy.deepcopy(content_list)
|
|
293
|
+
|
|
294
|
+
if text is None:
|
|
295
|
+
return content_list
|
|
296
|
+
|
|
297
|
+
for content in content_list:
|
|
298
|
+
if content["type"] == ContentType.TEXT:
|
|
299
|
+
content["text"] = text
|
|
300
|
+
break
|
|
301
|
+
return content_list
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _generate_tablestore_content_from_message(
|
|
305
|
+
message: Message,
|
|
306
|
+
) -> Tuple[Optional[str], Optional[List[Dict[str, Any]]]]:
|
|
307
|
+
"""Generate Tablestore content (text and content list) from Message"""
|
|
308
|
+
if message.content is None:
|
|
309
|
+
return None, None
|
|
310
|
+
|
|
311
|
+
content_json_list = [content.model_dump() for content in message.content]
|
|
312
|
+
content = None
|
|
313
|
+
|
|
314
|
+
if message.type != MessageType.MESSAGE:
|
|
315
|
+
return content, content_json_list
|
|
316
|
+
|
|
317
|
+
for content_json in content_json_list:
|
|
318
|
+
if content_json["type"] == ContentType.TEXT:
|
|
319
|
+
content = content_json.pop("text")
|
|
320
|
+
break
|
|
321
|
+
|
|
322
|
+
return content, content_json_list
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# This global variable will be cached to reduce computation time overhead
|
|
326
|
+
message_metadata_names: Optional[List[str]] = None
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def get_message_metadata_names():
|
|
330
|
+
"""Get list of message metadata field names"""
|
|
331
|
+
global message_metadata_names
|
|
332
|
+
|
|
333
|
+
if message_metadata_names is not None:
|
|
334
|
+
return message_metadata_names
|
|
335
|
+
|
|
336
|
+
message_metadata_names = list(Message.model_fields.keys())
|
|
337
|
+
|
|
338
|
+
message_metadata_exclude_names = ("id", "content")
|
|
339
|
+
message_metadata_extra_names = (
|
|
340
|
+
"document_id",
|
|
341
|
+
"text",
|
|
342
|
+
"user_id",
|
|
343
|
+
"session_id",
|
|
344
|
+
content_list_name,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
for exclude_name in message_metadata_exclude_names:
|
|
348
|
+
message_metadata_names.remove(exclude_name)
|
|
349
|
+
for extra_name in message_metadata_extra_names:
|
|
350
|
+
message_metadata_names.append(extra_name)
|
|
351
|
+
|
|
352
|
+
return message_metadata_names
|
|
@@ -3,6 +3,14 @@ from typing import Any, List, Union
|
|
|
3
3
|
|
|
4
4
|
from .base import BaseLogHandler, Tracer, TracerHandler
|
|
5
5
|
from .tracing_metric import TraceType
|
|
6
|
+
from .tracing_util import TracingUtil
|
|
7
|
+
from .wrapper import trace
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"trace",
|
|
11
|
+
"TraceType",
|
|
12
|
+
"TracingUtil",
|
|
13
|
+
]
|
|
6
14
|
|
|
7
15
|
|
|
8
16
|
def create_handler(
|
|
@@ -15,9 +23,7 @@ def create_handler(
|
|
|
15
23
|
if "default" in eval_mode:
|
|
16
24
|
handlers.append(BaseLogHandler())
|
|
17
25
|
elif "local_logging" in eval_mode:
|
|
18
|
-
from .local_logging_handler import
|
|
19
|
-
LocalLogHandler,
|
|
20
|
-
)
|
|
26
|
+
from .local_logging_handler import LocalLogHandler
|
|
21
27
|
|
|
22
28
|
handlers.append(LocalLogHandler(**eval_params))
|
|
23
29
|
return handlers
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from typing import AsyncIterable, AsyncIterator, Tuple, TypeVar
|
|
3
|
+
|
|
4
|
+
T_co = TypeVar("T_co", covariant=True)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async def aenumerate(
|
|
8
|
+
asequence: AsyncIterable[T_co],
|
|
9
|
+
start: int = 0,
|
|
10
|
+
) -> AsyncIterator[Tuple[int, T_co]]:
|
|
11
|
+
"""Asynchronously enumerate an async iterator from a given start value.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
asequence (AsyncIterable[T_co]): The async iterable to enumerate.
|
|
15
|
+
start (int): The starting value for enumeration. Defaults to 0.
|
|
16
|
+
|
|
17
|
+
Yields:
|
|
18
|
+
Tuple[int, T_co]: A tuple containing the index and the item from the
|
|
19
|
+
async iterable.
|
|
20
|
+
"""
|
|
21
|
+
n = start
|
|
22
|
+
async for elem in asequence:
|
|
23
|
+
yield n, elem
|
|
24
|
+
n += 1
|