agentscope-runtime 1.0.0b2__py3-none-any.whl → 1.0.2__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/message.py +78 -10
- agentscope_runtime/adapters/agentscope/stream.py +155 -101
- agentscope_runtime/adapters/agentscope/tool/tool.py +1 -3
- agentscope_runtime/adapters/agno/__init__.py +0 -0
- agentscope_runtime/adapters/agno/message.py +30 -0
- agentscope_runtime/adapters/agno/stream.py +122 -0
- agentscope_runtime/adapters/langgraph/__init__.py +12 -0
- agentscope_runtime/adapters/langgraph/message.py +257 -0
- agentscope_runtime/adapters/langgraph/stream.py +205 -0
- agentscope_runtime/cli/__init__.py +7 -0
- agentscope_runtime/cli/cli.py +63 -0
- agentscope_runtime/cli/commands/__init__.py +2 -0
- agentscope_runtime/cli/commands/chat.py +815 -0
- agentscope_runtime/cli/commands/deploy.py +1062 -0
- agentscope_runtime/cli/commands/invoke.py +58 -0
- agentscope_runtime/cli/commands/list_cmd.py +103 -0
- agentscope_runtime/cli/commands/run.py +176 -0
- agentscope_runtime/cli/commands/sandbox.py +128 -0
- agentscope_runtime/cli/commands/status.py +60 -0
- agentscope_runtime/cli/commands/stop.py +185 -0
- agentscope_runtime/cli/commands/web.py +166 -0
- agentscope_runtime/cli/loaders/__init__.py +6 -0
- agentscope_runtime/cli/loaders/agent_loader.py +295 -0
- agentscope_runtime/cli/state/__init__.py +10 -0
- agentscope_runtime/cli/utils/__init__.py +18 -0
- agentscope_runtime/cli/utils/console.py +378 -0
- agentscope_runtime/cli/utils/validators.py +118 -0
- agentscope_runtime/engine/app/agent_app.py +15 -5
- agentscope_runtime/engine/deployers/__init__.py +1 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +154 -24
- agentscope_runtime/engine/deployers/base.py +27 -2
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +158 -31
- agentscope_runtime/engine/deployers/local_deployer.py +188 -25
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +109 -18
- agentscope_runtime/engine/deployers/state/__init__.py +9 -0
- agentscope_runtime/engine/deployers/state/manager.py +388 -0
- agentscope_runtime/engine/deployers/state/schema.py +96 -0
- agentscope_runtime/engine/deployers/utils/build_cache.py +736 -0
- agentscope_runtime/engine/deployers/utils/detached_app.py +105 -30
- agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +31 -10
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +15 -8
- agentscope_runtime/engine/deployers/utils/docker_image_utils/image_factory.py +30 -2
- agentscope_runtime/engine/deployers/utils/k8s_utils.py +241 -0
- agentscope_runtime/engine/deployers/utils/package.py +56 -6
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +68 -9
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +155 -5
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +107 -123
- agentscope_runtime/engine/runner.py +32 -12
- agentscope_runtime/engine/schemas/agent_schemas.py +21 -7
- agentscope_runtime/engine/schemas/exception.py +580 -0
- agentscope_runtime/engine/services/agent_state/__init__.py +2 -0
- agentscope_runtime/engine/services/agent_state/state_service_factory.py +55 -0
- agentscope_runtime/engine/services/memory/__init__.py +2 -0
- agentscope_runtime/engine/services/memory/memory_service_factory.py +126 -0
- agentscope_runtime/engine/services/sandbox/__init__.py +2 -0
- agentscope_runtime/engine/services/sandbox/sandbox_service_factory.py +49 -0
- agentscope_runtime/engine/services/service_factory.py +119 -0
- agentscope_runtime/engine/services/session_history/__init__.py +2 -0
- agentscope_runtime/engine/services/session_history/session_history_service_factory.py +73 -0
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +35 -10
- agentscope_runtime/engine/tracing/wrapper.py +49 -31
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +113 -39
- agentscope_runtime/sandbox/box/shared/routers/mcp_utils.py +20 -4
- agentscope_runtime/sandbox/utils.py +2 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/METADATA +82 -11
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/RECORD +71 -36
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/entry_points.txt +1 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/WHEEL +0 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.0b2.dist-info → agentscope_runtime-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Dict
|
|
4
|
+
|
|
5
|
+
from ..service_factory import ServiceFactory
|
|
6
|
+
from .memory_service import MemoryService, InMemoryMemoryService
|
|
7
|
+
from .redis_memory_service import RedisMemoryService
|
|
8
|
+
from .mem0_memory_service import Mem0MemoryService
|
|
9
|
+
from .reme_personal_memory_service import ReMePersonalMemoryService
|
|
10
|
+
from .reme_task_memory_service import ReMeTaskMemoryService
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from .tablestore_memory_service import (
|
|
14
|
+
TablestoreMemoryService,
|
|
15
|
+
SearchStrategy,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
TABLESTORE_AVAILABLE = True
|
|
19
|
+
except ImportError:
|
|
20
|
+
TABLESTORE_AVAILABLE = False
|
|
21
|
+
SearchStrategy = None # type: ignore
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MemoryServiceFactory(ServiceFactory[MemoryService]):
|
|
25
|
+
"""
|
|
26
|
+
Factory for MemoryService, supporting both environment variables and
|
|
27
|
+
kwargs.
|
|
28
|
+
|
|
29
|
+
Usage examples:
|
|
30
|
+
1. Startup using only environment variables:
|
|
31
|
+
export MEMORY_BACKEND=redis
|
|
32
|
+
export MEMORY_REDIS_REDIS_URL="redis://localhost:6379/5"
|
|
33
|
+
service = await MemoryServiceFactory.create()
|
|
34
|
+
|
|
35
|
+
2. Override environment variables using arguments:
|
|
36
|
+
export MEMORY_BACKEND=redis
|
|
37
|
+
export MEMORY_REDIS_REDIS_URL="redis://localhost:6379/5"
|
|
38
|
+
service = await MemoryServiceFactory.create(
|
|
39
|
+
redis_url="redis://otherhost:6379/1"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
3. Register a custom backend:
|
|
43
|
+
from my_backend import PostgresMemoryService
|
|
44
|
+
MemoryServiceFactory.register_backend(
|
|
45
|
+
"postgres",
|
|
46
|
+
PostgresMemoryService,
|
|
47
|
+
)
|
|
48
|
+
export MEMORY_BACKEND=postgres
|
|
49
|
+
export MEMORY_POSTGRES_DSN="postgresql://user:pass@localhost/db"
|
|
50
|
+
service = await MemoryServiceFactory.create()
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
_registry: Dict[str, Callable[..., MemoryService]] = {}
|
|
54
|
+
_env_prefix = "MEMORY_"
|
|
55
|
+
_default_backend = "in_memory"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# === Default built-in backend registration ===
|
|
59
|
+
|
|
60
|
+
MemoryServiceFactory.register_backend(
|
|
61
|
+
"in_memory",
|
|
62
|
+
lambda **kwargs: InMemoryMemoryService(),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
MemoryServiceFactory.register_backend(
|
|
66
|
+
"redis",
|
|
67
|
+
RedisMemoryService,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
MemoryServiceFactory.register_backend(
|
|
71
|
+
"mem0",
|
|
72
|
+
Mem0MemoryService,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
MemoryServiceFactory.register_backend(
|
|
76
|
+
"reme_personal",
|
|
77
|
+
ReMePersonalMemoryService,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
MemoryServiceFactory.register_backend(
|
|
81
|
+
"reme_task",
|
|
82
|
+
ReMeTaskMemoryService,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if TABLESTORE_AVAILABLE:
|
|
86
|
+
|
|
87
|
+
def _create_tablestore_memory_service(**kwargs):
|
|
88
|
+
"""Helper function to create a TablestoreMemoryService instance."""
|
|
89
|
+
search_strategy = kwargs.get("search_strategy")
|
|
90
|
+
if isinstance(search_strategy, str):
|
|
91
|
+
search_strategy = SearchStrategy(search_strategy.lower())
|
|
92
|
+
elif search_strategy is None:
|
|
93
|
+
search_strategy = SearchStrategy.FULL_TEXT
|
|
94
|
+
|
|
95
|
+
return TablestoreMemoryService(
|
|
96
|
+
tablestore_client=kwargs["tablestore_client"],
|
|
97
|
+
search_strategy=search_strategy,
|
|
98
|
+
embedding_model=kwargs.get("embedding_model"),
|
|
99
|
+
vector_dimension=int(kwargs.get("vector_dimension", 1536)),
|
|
100
|
+
table_name=kwargs.get("table_name", "agentscope_runtime_memory"),
|
|
101
|
+
search_index_schema=kwargs.get("search_index_schema"),
|
|
102
|
+
text_field=kwargs.get("text_field", "text"),
|
|
103
|
+
embedding_field=kwargs.get("embedding_field", "embedding"),
|
|
104
|
+
vector_metric_type=kwargs.get("vector_metric_type"),
|
|
105
|
+
**{
|
|
106
|
+
k: v
|
|
107
|
+
for k, v in kwargs.items()
|
|
108
|
+
if k
|
|
109
|
+
not in [
|
|
110
|
+
"tablestore_client",
|
|
111
|
+
"search_strategy",
|
|
112
|
+
"embedding_model",
|
|
113
|
+
"vector_dimension",
|
|
114
|
+
"table_name",
|
|
115
|
+
"search_index_schema",
|
|
116
|
+
"text_field",
|
|
117
|
+
"embedding_field",
|
|
118
|
+
"vector_metric_type",
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
MemoryServiceFactory.register_backend(
|
|
124
|
+
"tablestore",
|
|
125
|
+
_create_tablestore_memory_service,
|
|
126
|
+
)
|
|
@@ -4,10 +4,12 @@ from ....common.utils.lazy_loader import install_lazy_loader
|
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from .sandbox_service import SandboxService
|
|
7
|
+
from .sandbox_service_factory import SandboxServiceFactory
|
|
7
8
|
|
|
8
9
|
install_lazy_loader(
|
|
9
10
|
globals(),
|
|
10
11
|
{
|
|
11
12
|
"SandboxService": ".sandbox_service",
|
|
13
|
+
"SandboxServiceFactory": ".sandbox_service_factory",
|
|
12
14
|
},
|
|
13
15
|
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Dict
|
|
4
|
+
|
|
5
|
+
from ..service_factory import ServiceFactory
|
|
6
|
+
from .sandbox_service import SandboxService
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SandboxServiceFactory(ServiceFactory[SandboxService]):
|
|
10
|
+
"""
|
|
11
|
+
Factory for SandboxService, supporting both environment variables and
|
|
12
|
+
kwargs.
|
|
13
|
+
|
|
14
|
+
Usage examples:
|
|
15
|
+
1. Start with only environment variables:
|
|
16
|
+
export SANDBOX_BACKEND=default
|
|
17
|
+
export SANDBOX_DEFAULT_BASE_URL="http://localhost:8080"
|
|
18
|
+
export SANDBOX_DEFAULT_BEARER_TOKEN="token123"
|
|
19
|
+
service = await SandboxServiceFactory.create()
|
|
20
|
+
|
|
21
|
+
2. Override environment variables with arguments:
|
|
22
|
+
export SANDBOX_DEFAULT_BASE_URL="http://localhost:8080"
|
|
23
|
+
service = await SandboxServiceFactory.create(
|
|
24
|
+
base_url="http://otherhost:8080",
|
|
25
|
+
bearer_token="custom_token"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
3. Register a custom backend:
|
|
29
|
+
from my_backend import CustomSandboxService
|
|
30
|
+
SandboxServiceFactory.register_backend(
|
|
31
|
+
"custom",
|
|
32
|
+
CustomSandboxService,
|
|
33
|
+
)
|
|
34
|
+
export SANDBOX_BACKEND=custom
|
|
35
|
+
export SANDBOX_CUSTOM_ENDPOINT="https://api.example.com"
|
|
36
|
+
export SANDBOX_CUSTOM_API_KEY="key123"
|
|
37
|
+
service = await SandboxServiceFactory.create()
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_registry: Dict[str, Callable[..., SandboxService]] = {}
|
|
41
|
+
_env_prefix = "SANDBOX_"
|
|
42
|
+
_default_backend = "default"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# === Default backend registration ===
|
|
46
|
+
SandboxServiceFactory.register_backend(
|
|
47
|
+
"default",
|
|
48
|
+
SandboxService,
|
|
49
|
+
)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import inspect
|
|
5
|
+
|
|
6
|
+
from typing import Callable, Dict, Any, Optional, TypeVar, Generic
|
|
7
|
+
|
|
8
|
+
from .base import ServiceWithLifecycleManager
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T", bound=ServiceWithLifecycleManager)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ServiceFactory(Generic[T]):
|
|
14
|
+
"""
|
|
15
|
+
Generic Service Factory base class that supports environment variables
|
|
16
|
+
and kwargs.
|
|
17
|
+
|
|
18
|
+
This base class provides a generic factory pattern that supports:
|
|
19
|
+
- Loading configuration from environment variables
|
|
20
|
+
- Overriding environment variables with kwargs
|
|
21
|
+
- Registering custom backends
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_registry: Dict[str, Callable[..., T]] = {}
|
|
25
|
+
_env_prefix: str = ""
|
|
26
|
+
_default_backend: str = "in_memory"
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def register_backend(
|
|
30
|
+
cls,
|
|
31
|
+
backend_type: str,
|
|
32
|
+
constructor: Callable[..., T],
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Register a constructor function for a backend type.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
backend_type: Backend type name (case-insensitive)
|
|
38
|
+
constructor: Constructor function used to create the service
|
|
39
|
+
instance
|
|
40
|
+
"""
|
|
41
|
+
cls._registry[backend_type.lower()] = constructor
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def _load_env_kwargs(cls, backend_type: str) -> Dict[str, Any]:
|
|
45
|
+
"""Load backend-specific kwargs from environment variables.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
backend_type: Backend type name
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
A dictionary of parameters loaded from environment variables
|
|
52
|
+
"""
|
|
53
|
+
result = {}
|
|
54
|
+
prefix = f"{cls._env_prefix}{backend_type.upper()}_"
|
|
55
|
+
|
|
56
|
+
for key, value in os.environ.items():
|
|
57
|
+
if key.startswith(prefix):
|
|
58
|
+
# env var: SERVICE_TYPE_BACKEND_PARAM -> param
|
|
59
|
+
param_name = key[len(prefix) :].lower()
|
|
60
|
+
result[param_name] = value
|
|
61
|
+
|
|
62
|
+
return result
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
async def create(
|
|
66
|
+
cls,
|
|
67
|
+
backend_type: Optional[str] = None,
|
|
68
|
+
**kwargs: Any,
|
|
69
|
+
) -> T:
|
|
70
|
+
"""
|
|
71
|
+
Create and start a service instance, supporting environment
|
|
72
|
+
variables and kwargs.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
backend_type: Backend type, if None will read from environment
|
|
76
|
+
variables
|
|
77
|
+
**kwargs: Additional parameters, having higher priority than
|
|
78
|
+
environment variables
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
A started service instance
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
ValueError: If the backend_type is unsupported
|
|
85
|
+
"""
|
|
86
|
+
if backend_type is None:
|
|
87
|
+
backend_type = os.getenv(
|
|
88
|
+
f"{cls._env_prefix}BACKEND",
|
|
89
|
+
cls._default_backend,
|
|
90
|
+
)
|
|
91
|
+
backend_type = backend_type.lower()
|
|
92
|
+
|
|
93
|
+
constructor = cls._registry.get(backend_type)
|
|
94
|
+
if constructor is None:
|
|
95
|
+
raise ValueError(f"Unsupported backend type: {backend_type}")
|
|
96
|
+
|
|
97
|
+
# 1. Load kwargs for this backend from environment variables
|
|
98
|
+
env_kwargs = cls._load_env_kwargs(backend_type)
|
|
99
|
+
|
|
100
|
+
# 2. Merge priority: kwargs > environment variables
|
|
101
|
+
final_kwargs = {**env_kwargs, **kwargs}
|
|
102
|
+
|
|
103
|
+
# 3. Filter out kwargs that are not accepted by the constructor
|
|
104
|
+
sig = inspect.signature(constructor)
|
|
105
|
+
|
|
106
|
+
has_var_kwargs = any(
|
|
107
|
+
p.kind == inspect.Parameter.VAR_KEYWORD
|
|
108
|
+
for p in sig.parameters.values()
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if not has_var_kwargs:
|
|
112
|
+
accepted_keys = sig.parameters.keys()
|
|
113
|
+
final_kwargs = {
|
|
114
|
+
k: v for k, v in final_kwargs.items() if k in accepted_keys
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# 4. Create instance
|
|
118
|
+
service = constructor(**final_kwargs)
|
|
119
|
+
return service
|
|
@@ -11,6 +11,7 @@ if TYPE_CHECKING:
|
|
|
11
11
|
from .tablestore_session_history_service import (
|
|
12
12
|
TablestoreSessionHistoryService,
|
|
13
13
|
)
|
|
14
|
+
from .session_history_service_factory import SessionHistoryServiceFactory
|
|
14
15
|
|
|
15
16
|
install_lazy_loader(
|
|
16
17
|
globals(),
|
|
@@ -19,5 +20,6 @@ install_lazy_loader(
|
|
|
19
20
|
"InMemorySessionHistoryService": ".session_history_service",
|
|
20
21
|
"RedisSessionHistoryService": ".redis_session_history_service",
|
|
21
22
|
"TablestoreSessionHistoryService": ".tablestore_session_history_service", # noqa
|
|
23
|
+
"SessionHistoryServiceFactory": ".session_history_service_factory",
|
|
22
24
|
},
|
|
23
25
|
)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Dict
|
|
4
|
+
|
|
5
|
+
from ..service_factory import ServiceFactory
|
|
6
|
+
from .session_history_service import (
|
|
7
|
+
SessionHistoryService,
|
|
8
|
+
InMemorySessionHistoryService,
|
|
9
|
+
)
|
|
10
|
+
from .redis_session_history_service import RedisSessionHistoryService
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from .tablestore_session_history_service import (
|
|
14
|
+
TablestoreSessionHistoryService,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
TABLESTORE_AVAILABLE = True
|
|
18
|
+
except ImportError:
|
|
19
|
+
TABLESTORE_AVAILABLE = False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SessionHistoryServiceFactory(ServiceFactory[SessionHistoryService]):
|
|
23
|
+
"""
|
|
24
|
+
Factory for SessionHistoryService, supporting both environment variables
|
|
25
|
+
and keyword arguments.
|
|
26
|
+
|
|
27
|
+
Usage examples:
|
|
28
|
+
1. Start with only environment variables:
|
|
29
|
+
export SESSION_HISTORY_BACKEND=redis
|
|
30
|
+
export SESSION_HISTORY_REDIS_REDIS_URL="redis://localhost:6379/5"
|
|
31
|
+
service = await SessionHistoryServiceFactory.create()
|
|
32
|
+
|
|
33
|
+
2. Override environment variables with arguments:
|
|
34
|
+
export SESSION_HISTORY_BACKEND=redis
|
|
35
|
+
export SESSION_HISTORY_REDIS_REDIS_URL="redis://localhost:6379/5"
|
|
36
|
+
service = await SessionHistoryServiceFactory.create(
|
|
37
|
+
redis_url="redis://otherhost:6379/1"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
3. Register a custom backend:
|
|
41
|
+
from my_backend import PostgresSessionHistoryService
|
|
42
|
+
SessionHistoryServiceFactory.register_backend(
|
|
43
|
+
"postgres",
|
|
44
|
+
PostgresSessionHistoryService,
|
|
45
|
+
)
|
|
46
|
+
export SESSION_HISTORY_BACKEND=postgres
|
|
47
|
+
export SESSION_HISTORY_POSTGRES_DSN="postgresql://user:pass@localhost/db" # noqa
|
|
48
|
+
export SESSION_HISTORY_POSTGRES_POOL_SIZE="20"
|
|
49
|
+
service = await SessionHistoryServiceFactory.create()
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
_registry: Dict[str, Callable[..., SessionHistoryService]] = {}
|
|
53
|
+
_env_prefix = "SESSION_HISTORY_"
|
|
54
|
+
_default_backend = "in_memory"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# === Default built-in backend registration ===
|
|
58
|
+
|
|
59
|
+
SessionHistoryServiceFactory.register_backend(
|
|
60
|
+
"in_memory",
|
|
61
|
+
InMemorySessionHistoryService,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
SessionHistoryServiceFactory.register_backend(
|
|
65
|
+
"redis",
|
|
66
|
+
RedisSessionHistoryService,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if TABLESTORE_AVAILABLE:
|
|
70
|
+
SessionHistoryServiceFactory.register_backend(
|
|
71
|
+
"tablestore",
|
|
72
|
+
TablestoreSessionHistoryService,
|
|
73
|
+
)
|
|
@@ -56,6 +56,32 @@ def exclude_None_fields_in_place(obj: Dict):
|
|
|
56
56
|
del obj[key]
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
def stringify_values(d: dict) -> dict:
|
|
60
|
+
for k, v in d.items():
|
|
61
|
+
if v is None:
|
|
62
|
+
continue
|
|
63
|
+
if isinstance(v, (dict, list)):
|
|
64
|
+
d[k] = json.dumps(v, ensure_ascii=False)
|
|
65
|
+
elif not isinstance(v, str):
|
|
66
|
+
d[k] = str(v)
|
|
67
|
+
return d
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _json_loads_if_str(v):
|
|
71
|
+
if isinstance(v, str):
|
|
72
|
+
try:
|
|
73
|
+
return json.loads(v)
|
|
74
|
+
except Exception:
|
|
75
|
+
return v
|
|
76
|
+
return v
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def restore_json_strings(d: dict) -> dict:
|
|
80
|
+
for k, v in d.items():
|
|
81
|
+
d[k] = _json_loads_if_str(v)
|
|
82
|
+
return d
|
|
83
|
+
|
|
84
|
+
|
|
59
85
|
def tablestore_log(msg: str):
|
|
60
86
|
print(msg)
|
|
61
87
|
|
|
@@ -111,6 +137,7 @@ def convert_message_to_tablestore_message(
|
|
|
111
137
|
"""Convert Message to TablestoreMessage"""
|
|
112
138
|
content, content_list = _generate_tablestore_content_from_message(message)
|
|
113
139
|
tablestore_message_metadata = message.model_dump(exclude={"content", "id"})
|
|
140
|
+
tablestore_message_metadata = stringify_values(tablestore_message_metadata)
|
|
114
141
|
tablestore_message_metadata[content_list_name] = json.dumps(
|
|
115
142
|
content_list,
|
|
116
143
|
ensure_ascii=False,
|
|
@@ -241,6 +268,9 @@ def _generate_init_json_from_tablestore_message(
|
|
|
241
268
|
) -> Dict[str, Any]:
|
|
242
269
|
"""Generate initialization JSON from TablestoreMessage"""
|
|
243
270
|
tablestore_message = copy.deepcopy(tablestore_message)
|
|
271
|
+
tablestore_message.metadata = restore_json_strings(
|
|
272
|
+
tablestore_message.metadata,
|
|
273
|
+
)
|
|
244
274
|
tablestore_message_content_list = tablestore_message.metadata.pop(
|
|
245
275
|
content_list_name,
|
|
246
276
|
None,
|
|
@@ -249,11 +279,7 @@ def _generate_init_json_from_tablestore_message(
|
|
|
249
279
|
"id": tablestore_message.message_id,
|
|
250
280
|
"content": _generate_content_from_tablestore_content(
|
|
251
281
|
text=tablestore_message.content,
|
|
252
|
-
content_list=
|
|
253
|
-
json.loads(tablestore_message_content_list)
|
|
254
|
-
if tablestore_message_content_list
|
|
255
|
-
else None
|
|
256
|
-
),
|
|
282
|
+
content_list=tablestore_message_content_list,
|
|
257
283
|
),
|
|
258
284
|
}
|
|
259
285
|
init_json.update(tablestore_message.metadata)
|
|
@@ -265,6 +291,9 @@ def _generate_init_json_from_tablestore_document(
|
|
|
265
291
|
) -> Dict[str, Any]:
|
|
266
292
|
"""Generate initialization JSON from TablestoreDocument"""
|
|
267
293
|
tablestore_document = copy.deepcopy(tablestore_document)
|
|
294
|
+
tablestore_document.metadata = restore_json_strings(
|
|
295
|
+
tablestore_document.metadata,
|
|
296
|
+
)
|
|
268
297
|
tablestore_document_content_list = tablestore_document.metadata.pop(
|
|
269
298
|
content_list_name,
|
|
270
299
|
None,
|
|
@@ -273,11 +302,7 @@ def _generate_init_json_from_tablestore_document(
|
|
|
273
302
|
"id": tablestore_document.document_id,
|
|
274
303
|
"content": _generate_content_from_tablestore_content(
|
|
275
304
|
text=tablestore_document.text,
|
|
276
|
-
content_list=
|
|
277
|
-
json.loads(tablestore_document_content_list)
|
|
278
|
-
if tablestore_document_content_list
|
|
279
|
-
else None
|
|
280
|
-
),
|
|
305
|
+
content_list=tablestore_document_content_list,
|
|
281
306
|
),
|
|
282
307
|
}
|
|
283
308
|
init_json.update(tablestore_document.metadata)
|
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
9
|
import time
|
|
10
|
+
import threading
|
|
10
11
|
import uuid
|
|
11
12
|
from collections.abc import Callable
|
|
12
13
|
from copy import deepcopy
|
|
@@ -25,7 +26,7 @@ from typing import (
|
|
|
25
26
|
from pydantic import BaseModel
|
|
26
27
|
from opentelemetry.propagate import extract
|
|
27
28
|
from opentelemetry.context import attach
|
|
28
|
-
from opentelemetry.trace import StatusCode
|
|
29
|
+
from opentelemetry.trace import StatusCode, NoOpTracerProvider
|
|
29
30
|
from opentelemetry import trace as ot_trace
|
|
30
31
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
|
31
32
|
OTLPSpanExporter as OTLPSpanGrpcExporter,
|
|
@@ -177,7 +178,7 @@ def trace( # pylint: disable=too-many-statements
|
|
|
177
178
|
**common_attrs,
|
|
178
179
|
}
|
|
179
180
|
|
|
180
|
-
with
|
|
181
|
+
with _get_ot_tracer().start_as_current_span(
|
|
181
182
|
final_trace_name,
|
|
182
183
|
context=parent_ctx,
|
|
183
184
|
attributes=span_attributes,
|
|
@@ -280,7 +281,7 @@ def trace( # pylint: disable=too-many-statements
|
|
|
280
281
|
**common_attrs,
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
with
|
|
284
|
+
with _get_ot_tracer().start_as_current_span(
|
|
284
285
|
final_trace_name,
|
|
285
286
|
context=parent_ctx,
|
|
286
287
|
attributes=span_attributes,
|
|
@@ -385,7 +386,7 @@ def trace( # pylint: disable=too-many-statements
|
|
|
385
386
|
**common_attrs,
|
|
386
387
|
}
|
|
387
388
|
|
|
388
|
-
with
|
|
389
|
+
with _get_ot_tracer().start_as_current_span(
|
|
389
390
|
final_trace_name,
|
|
390
391
|
context=parent_ctx,
|
|
391
392
|
attributes=span_attributes,
|
|
@@ -518,7 +519,7 @@ def trace( # pylint: disable=too-many-statements
|
|
|
518
519
|
**common_attrs,
|
|
519
520
|
}
|
|
520
521
|
|
|
521
|
-
with
|
|
522
|
+
with _get_ot_tracer().start_as_current_span(
|
|
522
523
|
final_trace_name,
|
|
523
524
|
context=parent_ctx,
|
|
524
525
|
attributes=span_attributes,
|
|
@@ -897,13 +898,17 @@ def _get_service_name() -> str:
|
|
|
897
898
|
|
|
898
899
|
def _get_tracer() -> Tracer:
|
|
899
900
|
handlers: list[TracerHandler] = []
|
|
900
|
-
if _str_to_bool(os.getenv("TRACE_ENABLE_LOG", "
|
|
901
|
+
if _str_to_bool(os.getenv("TRACE_ENABLE_LOG", "false")):
|
|
901
902
|
handlers.append(LocalLogHandler(enable_console=True))
|
|
902
903
|
|
|
903
904
|
tracer = Tracer(handlers=handlers)
|
|
904
905
|
return tracer
|
|
905
906
|
|
|
906
907
|
|
|
908
|
+
_otel_tracer_lock = threading.Lock()
|
|
909
|
+
_otel_tracer = None
|
|
910
|
+
|
|
911
|
+
|
|
907
912
|
# TODO: support more tracing protocols and platforms
|
|
908
913
|
def _get_ot_tracer() -> ot_trace.Tracer:
|
|
909
914
|
"""Get the OpenTelemetry tracer.
|
|
@@ -912,35 +917,48 @@ def _get_ot_tracer() -> ot_trace.Tracer:
|
|
|
912
917
|
ot_trace.Tracer: The OpenTelemetry tracer instance.
|
|
913
918
|
"""
|
|
914
919
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
headers=f"Authentication="
|
|
928
|
-
f"{os.getenv('TRACE_AUTHENTICATION', '')}",
|
|
929
|
-
),
|
|
920
|
+
def _get_ot_tracer_inner() -> ot_trace.Tracer:
|
|
921
|
+
existing_provider = ot_trace.get_tracer_provider()
|
|
922
|
+
|
|
923
|
+
if not isinstance(existing_provider, NoOpTracerProvider):
|
|
924
|
+
return ot_trace.get_tracer("agentscope_runtime")
|
|
925
|
+
|
|
926
|
+
resource = Resource(
|
|
927
|
+
attributes={
|
|
928
|
+
SERVICE_NAME: _get_service_name(),
|
|
929
|
+
SERVICE_VERSION: os.getenv("SERVICE_VERSION", "1.0.0"),
|
|
930
|
+
"source": "agentscope_runtime-source",
|
|
931
|
+
},
|
|
930
932
|
)
|
|
931
|
-
provider
|
|
933
|
+
provider = TracerProvider(resource=resource)
|
|
934
|
+
if _str_to_bool(os.getenv("TRACE_ENABLE_REPORT", "false")):
|
|
935
|
+
span_exporter = BatchSpanProcessor(
|
|
936
|
+
OTLPSpanGrpcExporter(
|
|
937
|
+
endpoint=os.getenv("TRACE_ENDPOINT", ""),
|
|
938
|
+
headers=f"Authentication="
|
|
939
|
+
f"{os.getenv('TRACE_AUTHENTICATION', '')}",
|
|
940
|
+
),
|
|
941
|
+
)
|
|
942
|
+
provider.add_span_processor(span_exporter)
|
|
932
943
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
944
|
+
if _str_to_bool(os.getenv("TRACE_ENABLE_DEBUG", "false")):
|
|
945
|
+
span_logger = BatchSpanProcessor(ConsoleSpanExporter())
|
|
946
|
+
provider.add_span_processor(span_logger)
|
|
936
947
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
948
|
+
tracer = ot_trace.get_tracer(
|
|
949
|
+
"agentscope_runtime",
|
|
950
|
+
tracer_provider=provider,
|
|
951
|
+
)
|
|
952
|
+
return tracer
|
|
953
|
+
|
|
954
|
+
global _otel_tracer
|
|
955
|
+
|
|
956
|
+
if _otel_tracer is None:
|
|
957
|
+
with _otel_tracer_lock:
|
|
958
|
+
if _otel_tracer is None:
|
|
959
|
+
_otel_tracer = _get_ot_tracer_inner()
|
|
942
960
|
|
|
961
|
+
return _otel_tracer
|
|
943
962
|
|
|
944
|
-
_ot_tracer = _get_ot_tracer()
|
|
945
963
|
|
|
946
964
|
_tracer = _get_tracer()
|