agentscope-runtime 0.2.0b2__py3-none-any.whl → 1.0.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/adapters/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/__init__.py +0 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/long_term_memory/_long_term_memory_adapter.py +258 -0
- agentscope_runtime/adapters/agentscope/memory/__init__.py +6 -0
- agentscope_runtime/adapters/agentscope/memory/_memory_adapter.py +152 -0
- agentscope_runtime/adapters/agentscope/message.py +535 -0
- agentscope_runtime/adapters/agentscope/stream.py +506 -0
- agentscope_runtime/adapters/agentscope/tool/__init__.py +9 -0
- agentscope_runtime/adapters/agentscope/tool/sandbox_tool.py +69 -0
- agentscope_runtime/adapters/agentscope/tool/tool.py +233 -0
- agentscope_runtime/adapters/autogen/__init__.py +0 -0
- agentscope_runtime/adapters/autogen/tool/__init__.py +7 -0
- agentscope_runtime/adapters/autogen/tool/tool.py +211 -0
- agentscope_runtime/adapters/text/__init__.py +0 -0
- agentscope_runtime/adapters/text/stream.py +29 -0
- agentscope_runtime/common/collections/redis_mapping.py +4 -1
- agentscope_runtime/common/container_clients/fc_client.py +855 -0
- agentscope_runtime/common/utils/__init__.py +0 -0
- agentscope_runtime/common/utils/lazy_loader.py +57 -0
- agentscope_runtime/engine/__init__.py +25 -18
- agentscope_runtime/engine/app/agent_app.py +161 -91
- agentscope_runtime/engine/app/base_app.py +4 -118
- agentscope_runtime/engine/constant.py +8 -0
- agentscope_runtime/engine/deployers/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
- agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
- agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
- agentscope_runtime/engine/deployers/local_deployer.py +47 -74
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
- agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
- agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
- agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
- agentscope_runtime/engine/deployers/utils/package.py +693 -0
- agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +301 -282
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
- agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
- agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
- agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
- agentscope_runtime/engine/helpers/runner.py +40 -0
- agentscope_runtime/engine/runner.py +171 -130
- agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
- agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
- agentscope_runtime/engine/schemas/oai_llm.py +23 -23
- agentscope_runtime/engine/schemas/response_api.py +65 -0
- agentscope_runtime/engine/schemas/session.py +24 -0
- agentscope_runtime/engine/services/__init__.py +0 -9
- agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
- agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
- agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
- agentscope_runtime/engine/services/memory/__init__.py +24 -0
- agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
- agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
- agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
- agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
- agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
- agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
- agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
- agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
- agentscope_runtime/engine/services/session_history/__init__.py +23 -0
- agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
- agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
- agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
- agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
- agentscope_runtime/engine/tracing/base.py +10 -9
- agentscope_runtime/engine/tracing/message_util.py +1 -1
- agentscope_runtime/engine/tracing/tracing_util.py +7 -2
- agentscope_runtime/engine/tracing/wrapper.py +49 -31
- agentscope_runtime/sandbox/__init__.py +10 -2
- agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
- agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
- agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
- agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
- agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
- agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
- agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
- agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
- agentscope_runtime/sandbox/client/http_client.py +1 -0
- agentscope_runtime/sandbox/enums.py +2 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +15 -2
- agentscope_runtime/sandbox/manager/server/app.py +12 -0
- agentscope_runtime/sandbox/manager/server/config.py +19 -0
- agentscope_runtime/sandbox/model/manager_config.py +79 -2
- agentscope_runtime/sandbox/utils.py +0 -18
- agentscope_runtime/tools/RAGs/__init__.py +0 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
- agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
- agentscope_runtime/tools/__init__.py +119 -0
- agentscope_runtime/tools/_constants.py +18 -0
- agentscope_runtime/tools/alipay/__init__.py +4 -0
- agentscope_runtime/tools/alipay/base.py +334 -0
- agentscope_runtime/tools/alipay/payment.py +835 -0
- agentscope_runtime/tools/alipay/subscribe.py +551 -0
- agentscope_runtime/tools/base.py +264 -0
- agentscope_runtime/tools/cli/__init__.py +0 -0
- agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
- agentscope_runtime/tools/generations/__init__.py +75 -0
- agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
- agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
- agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
- agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
- agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
- agentscope_runtime/tools/generations/image_edit.py +208 -0
- agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
- agentscope_runtime/tools/generations/image_generation.py +202 -0
- agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
- agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
- agentscope_runtime/tools/generations/image_to_video.py +233 -0
- agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
- agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
- agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
- agentscope_runtime/tools/generations/speech_to_text.py +260 -0
- agentscope_runtime/tools/generations/speech_to_video.py +314 -0
- agentscope_runtime/tools/generations/text_to_video.py +221 -0
- agentscope_runtime/tools/mcp_wrapper.py +215 -0
- agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
- agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
- agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
- agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
- agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
- agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
- agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
- agentscope_runtime/tools/searches/__init__.py +3 -0
- agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
- agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
- agentscope_runtime/tools/utils/__init__.py +0 -0
- agentscope_runtime/tools/utils/api_key_util.py +45 -0
- agentscope_runtime/tools/utils/crypto_utils.py +99 -0
- agentscope_runtime/tools/utils/mcp_util.py +35 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/METADATA +240 -168
- agentscope_runtime-1.0.0.dist-info/RECORD +240 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/entry_points.txt +1 -0
- agentscope_runtime/engine/agents/__init__.py +0 -2
- agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
- agentscope_runtime/engine/agents/agno_agent.py +0 -220
- agentscope_runtime/engine/agents/autogen_agent.py +0 -250
- agentscope_runtime/engine/agents/base_agent.py +0 -29
- agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
- agentscope_runtime/engine/agents/utils.py +0 -53
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
- agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
- agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
- agentscope_runtime/engine/helpers/helper.py +0 -179
- agentscope_runtime/engine/schemas/context.py +0 -54
- agentscope_runtime/engine/services/context_manager.py +0 -164
- agentscope_runtime/engine/services/environment_manager.py +0 -50
- agentscope_runtime/engine/services/manager.py +0 -174
- agentscope_runtime/engine/services/rag_service.py +0 -195
- agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
- agentscope_runtime/sandbox/tools/__init__.py +0 -12
- agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
- agentscope_runtime/sandbox/tools/base/tool.py +0 -52
- agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
- agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
- agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
- agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
- agentscope_runtime/sandbox/tools/function_tool.py +0 -321
- agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
- agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
- agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
- agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
- agentscope_runtime/sandbox/tools/tool.py +0 -238
- agentscope_runtime/sandbox/tools/utils.py +0 -68
- agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint:disable=abstract-method, redefined-builtin, too-many-branches
|
|
3
|
+
# pylint:disable=unused-import
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import uuid
|
|
7
|
+
from http import HTTPStatus
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
from dashscope.client.base_api import BaseAsyncAioApi
|
|
11
|
+
from mcp.server.fastmcp import Context
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
|
|
14
|
+
from ..base import Tool
|
|
15
|
+
from ..utils.api_key_util import get_api_key, ApiNames
|
|
16
|
+
from ...engine.tracing import trace, TracingUtil
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SpeechToVideoSubmitInput(BaseModel):
|
|
20
|
+
"""
|
|
21
|
+
Speech to video generation input model
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
image_url: str = Field(
|
|
25
|
+
...,
|
|
26
|
+
description="上传的图片URL。图像格式:支持jpg,jpeg,png,bmp,webp。"
|
|
27
|
+
"图像分辨率:图像的宽度和高度范围为[400, 7000]像素。"
|
|
28
|
+
"上传图片仅支持公网可访问的HTTP/HTTPS链接。",
|
|
29
|
+
)
|
|
30
|
+
audio_url: str = Field(
|
|
31
|
+
...,
|
|
32
|
+
description="上传的音频文件URL。音频格式:格式为wav、mp3。"
|
|
33
|
+
"音频限制:文件<15M,时长<20s。"
|
|
34
|
+
"音频内容:音频中需包含清晰、响亮的人声语音,并去除了环境噪音、"
|
|
35
|
+
"背景音乐等声音干扰信息。上传音频仅支持公网可访问的HTTP/HTTPS链接。",
|
|
36
|
+
)
|
|
37
|
+
resolution: Optional[str] = Field(
|
|
38
|
+
default=None,
|
|
39
|
+
description="视频分辨率,默认不设置",
|
|
40
|
+
)
|
|
41
|
+
ctx: Optional[Context] = Field(
|
|
42
|
+
default=None,
|
|
43
|
+
description="HTTP request context containing headers for mcp only, "
|
|
44
|
+
"don't generate it",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class SpeechToVideoSubmitOutput(BaseModel):
|
|
49
|
+
"""
|
|
50
|
+
Speech to video generation output model
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
task_id: str = Field(
|
|
54
|
+
title="Task ID",
|
|
55
|
+
description="语音生成视频的任务ID",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
task_status: str = Field(
|
|
59
|
+
title="Task Status",
|
|
60
|
+
description="语音生成视频的任务状态,PENDING:任务排队中,RUNNING:任务处理中,"
|
|
61
|
+
"SUCCEEDED:任务执行成功,FAILED:任务执行失败,CANCELED:任务取消成功,"
|
|
62
|
+
"UNKNOWN:任务不存在或状态未知",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
request_id: Optional[str] = Field(
|
|
66
|
+
default=None,
|
|
67
|
+
title="Request ID",
|
|
68
|
+
description="请求ID",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SpeechToVideoSubmit(
|
|
73
|
+
Tool[SpeechToVideoSubmitInput, SpeechToVideoSubmitOutput],
|
|
74
|
+
):
|
|
75
|
+
"""
|
|
76
|
+
Speech to video generation service that converts speech and image into
|
|
77
|
+
videos using DashScope's wan2.2-s2v API.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
name: str = "modelstudio_speech_to_video_submit_task"
|
|
81
|
+
description: str = (
|
|
82
|
+
"数字人wan2.2-s2v模型的异步任务提交工具。能基于单张图片和音频,生成动作自然的说话、"
|
|
83
|
+
"唱歌或表演视频。通过输入的人声音频,驱动静态图片中的人物实现口型、表情和动作与音频同步。"
|
|
84
|
+
"支持说话、唱歌、表演三种对口型场景,支持真人及卡通人物,提供480P、720P两档分辨率选项。"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
async def _async_call(
|
|
89
|
+
model: str,
|
|
90
|
+
api_key: str,
|
|
91
|
+
image_url: str,
|
|
92
|
+
audio_url: str,
|
|
93
|
+
**parameters: Any,
|
|
94
|
+
) -> Any:
|
|
95
|
+
"""
|
|
96
|
+
Submit async task for speech to video generation using BaseAsyncAioApi
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
model: Model name to use
|
|
100
|
+
api_key: DashScope API key for authentication
|
|
101
|
+
image_url: URL of the input image
|
|
102
|
+
audio_url: URL of the input audio
|
|
103
|
+
**parameters: Additional parameters like resolution
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Response containing task_id for polling
|
|
107
|
+
"""
|
|
108
|
+
# Prepare input data
|
|
109
|
+
input = {
|
|
110
|
+
"image_url": image_url,
|
|
111
|
+
"audio_url": audio_url,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
result = await BaseAsyncAioApi.async_call(
|
|
115
|
+
model=model,
|
|
116
|
+
input=input,
|
|
117
|
+
task_group="aigc",
|
|
118
|
+
task="image2video",
|
|
119
|
+
function="video-synthesis",
|
|
120
|
+
api_key=api_key,
|
|
121
|
+
**parameters,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return result
|
|
125
|
+
|
|
126
|
+
@trace(trace_type="AIGC", trace_name="speech_to_video_submit")
|
|
127
|
+
async def arun(
|
|
128
|
+
self,
|
|
129
|
+
args: SpeechToVideoSubmitInput,
|
|
130
|
+
**kwargs: Any,
|
|
131
|
+
) -> SpeechToVideoSubmitOutput:
|
|
132
|
+
"""
|
|
133
|
+
Submit speech to video generation task using DashScope wan2.2-s2v API
|
|
134
|
+
|
|
135
|
+
This method wraps DashScope's wan2.2-s2v service to submit video
|
|
136
|
+
generation tasks based on input image and audio. It uses async call
|
|
137
|
+
pattern for better performance.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
args: SpeechToVideoSubmitInput containing image_url, audio_url and
|
|
141
|
+
optional parameters
|
|
142
|
+
**kwargs: Additional keyword arguments including:
|
|
143
|
+
- request_id: Optional request ID for tracking
|
|
144
|
+
- model_name: Model name to use (defaults to wan2.2-s2v)
|
|
145
|
+
- api_key: DashScope API key for authentication
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
SpeechToVideoSubmitOutput containing the task ID, status and
|
|
149
|
+
request ID
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
ValueError: If DASHSCOPE_API_KEY is not set or invalid
|
|
153
|
+
RuntimeError: If task submission fails
|
|
154
|
+
"""
|
|
155
|
+
trace_event = kwargs.pop("trace_event", None)
|
|
156
|
+
request_id = TracingUtil.get_request_id()
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
api_key = get_api_key(ApiNames.dashscope_api_key, **kwargs)
|
|
160
|
+
except AssertionError as e:
|
|
161
|
+
raise ValueError("Please set valid DASHSCOPE_API_KEY!") from e
|
|
162
|
+
|
|
163
|
+
model_name = kwargs.get(
|
|
164
|
+
"model_name",
|
|
165
|
+
os.getenv("SPEECH_TO_VIDEO_MODEL_NAME", "wan2.2-s2v"),
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
parameters = {}
|
|
169
|
+
if args.resolution:
|
|
170
|
+
parameters["resolution"] = args.resolution
|
|
171
|
+
|
|
172
|
+
# Submit async task
|
|
173
|
+
response = await self._async_call(
|
|
174
|
+
model=model_name,
|
|
175
|
+
api_key=api_key,
|
|
176
|
+
image_url=args.image_url,
|
|
177
|
+
audio_url=args.audio_url,
|
|
178
|
+
**parameters,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Log trace event if provided
|
|
182
|
+
if trace_event:
|
|
183
|
+
trace_event.on_log(
|
|
184
|
+
"",
|
|
185
|
+
**{
|
|
186
|
+
"step_suffix": "results",
|
|
187
|
+
"payload": {
|
|
188
|
+
"request_id": request_id,
|
|
189
|
+
"submit_task": response,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if (
|
|
195
|
+
response.status_code != HTTPStatus.OK
|
|
196
|
+
or not response.output
|
|
197
|
+
or response.output.get("task_status", "UNKNOWN")
|
|
198
|
+
in ["FAILED", "CANCELED"]
|
|
199
|
+
):
|
|
200
|
+
raise RuntimeError(f"Failed to submit task: {response}")
|
|
201
|
+
|
|
202
|
+
if not request_id:
|
|
203
|
+
request_id = (
|
|
204
|
+
response.request_id
|
|
205
|
+
if response.request_id
|
|
206
|
+
else str(uuid.uuid4())
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Extract task information from response
|
|
210
|
+
task_id = response.output.get("task_id", "")
|
|
211
|
+
task_status = response.output.get("task_status", "UNKNOWN")
|
|
212
|
+
|
|
213
|
+
result = SpeechToVideoSubmitOutput(
|
|
214
|
+
request_id=request_id,
|
|
215
|
+
task_id=task_id,
|
|
216
|
+
task_status=task_status,
|
|
217
|
+
)
|
|
218
|
+
return result
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class SpeechToVideoFetchInput(BaseModel):
|
|
222
|
+
"""
|
|
223
|
+
Speech to video fetch task input model
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
task_id: str = Field(
|
|
227
|
+
title="Task ID",
|
|
228
|
+
description="语音生成视频的任务ID",
|
|
229
|
+
)
|
|
230
|
+
ctx: Optional[Context] = Field(
|
|
231
|
+
default=None,
|
|
232
|
+
description="HTTP request context containing headers for mcp only, "
|
|
233
|
+
"don't generate it",
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class SpeechToVideoFetchOutput(BaseModel):
|
|
238
|
+
"""
|
|
239
|
+
Speech to video fetch task output model
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
video_url: Optional[str] = Field(
|
|
243
|
+
default=None,
|
|
244
|
+
title="Video URL",
|
|
245
|
+
description="生成的视频文件URL,仅在任务成功完成时有值",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
task_id: str = Field(
|
|
249
|
+
title="Task ID",
|
|
250
|
+
description="语音生成视频的任务ID",
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
task_status: str = Field(
|
|
254
|
+
title="Task Status",
|
|
255
|
+
description="语音生成视频的任务状态,PENDING:任务排队中,RUNNING:任务处理中,"
|
|
256
|
+
"SUCCEEDED:任务执行成功,FAILED:任务执行失败,CANCELED:任务取消成功,"
|
|
257
|
+
"UNKNOWN:任务不存在或状态未知",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
request_id: Optional[str] = Field(
|
|
261
|
+
default=None,
|
|
262
|
+
title="Request ID",
|
|
263
|
+
description="请求ID",
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
video_duration: Optional[float] = Field(
|
|
267
|
+
default=None,
|
|
268
|
+
title="Video Duration",
|
|
269
|
+
description="视频时长(秒),用于计费",
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class SpeechToVideoFetch(
|
|
274
|
+
Tool[SpeechToVideoFetchInput, SpeechToVideoFetchOutput],
|
|
275
|
+
):
|
|
276
|
+
"""
|
|
277
|
+
Speech to video fetch service that retrieves video generation results
|
|
278
|
+
using DashScope's wan2.2-s2v API.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
name: str = "modelstudio_speech_to_video_fetch_result"
|
|
282
|
+
description: str = "数字人wan2.2-s2v模型的异步任务结果查询工具,根据Task ID查询任务结果。"
|
|
283
|
+
|
|
284
|
+
@staticmethod
|
|
285
|
+
async def _fetch(
|
|
286
|
+
api_key: str,
|
|
287
|
+
task: Any,
|
|
288
|
+
) -> Any:
|
|
289
|
+
"""
|
|
290
|
+
Fetch task result using BaseAsyncAioApi
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
api_key: DashScope API key for authentication
|
|
294
|
+
task: Task response containing task_id
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Response containing task status and result
|
|
298
|
+
"""
|
|
299
|
+
# Use BaseAsyncAioApi.fetch directly with await
|
|
300
|
+
result = await BaseAsyncAioApi.fetch(
|
|
301
|
+
api_key=api_key,
|
|
302
|
+
task=task,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
return result
|
|
306
|
+
|
|
307
|
+
@trace(trace_type="AIGC", trace_name="speech_to_video_fetch")
|
|
308
|
+
async def arun(
|
|
309
|
+
self,
|
|
310
|
+
args: SpeechToVideoFetchInput,
|
|
311
|
+
**kwargs: Any,
|
|
312
|
+
) -> SpeechToVideoFetchOutput:
|
|
313
|
+
"""
|
|
314
|
+
Fetch speech to video generation result using DashScope wan2.2-s2v API
|
|
315
|
+
|
|
316
|
+
This method wraps DashScope's wan2.2-s2v fetch service to retrieve
|
|
317
|
+
video generation results based on task ID. It uses async call pattern
|
|
318
|
+
for better performance.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
args: SpeechToVideoFetchInput containing task_id parameter
|
|
322
|
+
**kwargs: Additional keyword arguments including:
|
|
323
|
+
- api_key: DashScope API key for authentication
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
SpeechToVideoFetchOutput containing the video URL, task status,
|
|
327
|
+
request ID and video duration
|
|
328
|
+
|
|
329
|
+
Raises:
|
|
330
|
+
ValueError: If DASHSCOPE_API_KEY is not set or invalid
|
|
331
|
+
RuntimeError: If video fetch fails or response status is not OK
|
|
332
|
+
"""
|
|
333
|
+
trace_event = kwargs.pop("trace_event", None)
|
|
334
|
+
request_id = TracingUtil.get_request_id()
|
|
335
|
+
|
|
336
|
+
try:
|
|
337
|
+
api_key = get_api_key(ApiNames.dashscope_api_key, **kwargs)
|
|
338
|
+
except AssertionError as e:
|
|
339
|
+
raise ValueError("Please set valid DASHSCOPE_API_KEY!") from e
|
|
340
|
+
|
|
341
|
+
response = await self._fetch(
|
|
342
|
+
api_key=api_key,
|
|
343
|
+
task=args.task_id,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Log trace event if provided
|
|
347
|
+
if trace_event:
|
|
348
|
+
trace_event.on_log(
|
|
349
|
+
"",
|
|
350
|
+
**{
|
|
351
|
+
"step_suffix": "results",
|
|
352
|
+
"payload": {
|
|
353
|
+
"request_id": response.request_id,
|
|
354
|
+
"fetch_result": response,
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
if (
|
|
360
|
+
response.status_code != HTTPStatus.OK
|
|
361
|
+
or not response.output
|
|
362
|
+
or response.output.get("task_status", "UNKNOWN")
|
|
363
|
+
in ["FAILED", "CANCELED"]
|
|
364
|
+
):
|
|
365
|
+
raise RuntimeError(f"Failed to fetch result: {response}")
|
|
366
|
+
|
|
367
|
+
# Handle request ID
|
|
368
|
+
if not request_id:
|
|
369
|
+
request_id = (
|
|
370
|
+
response.request_id
|
|
371
|
+
if response.request_id
|
|
372
|
+
else str(uuid.uuid4())
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
# Extract task information from response
|
|
376
|
+
if isinstance(response.output, dict):
|
|
377
|
+
task_id = response.output.get("task_id", args.task_id)
|
|
378
|
+
task_status = response.output.get("task_status", "UNKNOWN")
|
|
379
|
+
|
|
380
|
+
# For completed tasks, extract video URL from results
|
|
381
|
+
video_url = None
|
|
382
|
+
if task_status == "SUCCEEDED" and "results" in response.output:
|
|
383
|
+
results = response.output["results"]
|
|
384
|
+
if isinstance(results, dict):
|
|
385
|
+
video_url = results.get("video_url")
|
|
386
|
+
else:
|
|
387
|
+
video_url = getattr(results, "video_url", None)
|
|
388
|
+
|
|
389
|
+
if not video_url:
|
|
390
|
+
raise RuntimeError(
|
|
391
|
+
f"Failed to extract video URL from response: "
|
|
392
|
+
f"{response}",
|
|
393
|
+
)
|
|
394
|
+
elif task_status == "SUCCEEDED":
|
|
395
|
+
# If task succeeded but no results found
|
|
396
|
+
raise RuntimeError(
|
|
397
|
+
f"Task succeeded but no video URL found in response: "
|
|
398
|
+
f"{response.output}",
|
|
399
|
+
)
|
|
400
|
+
# For PENDING/RUNNING tasks, video_url will remain None
|
|
401
|
+
else:
|
|
402
|
+
raise RuntimeError(
|
|
403
|
+
f"Unexpected response format: {response.output}",
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
# Extract video duration from usage
|
|
407
|
+
video_duration = None
|
|
408
|
+
if hasattr(response, "usage") and response.usage:
|
|
409
|
+
if isinstance(response.usage, dict):
|
|
410
|
+
video_duration = response.usage.get("duration")
|
|
411
|
+
else:
|
|
412
|
+
video_duration = getattr(response.usage, "duration", None)
|
|
413
|
+
|
|
414
|
+
result = SpeechToVideoFetchOutput(
|
|
415
|
+
video_url=video_url,
|
|
416
|
+
task_id=task_id,
|
|
417
|
+
task_status=task_status,
|
|
418
|
+
request_id=request_id,
|
|
419
|
+
video_duration=video_duration,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
return result
|