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.
Files changed (184) hide show
  1. agentscope_runtime/adapters/__init__.py +0 -0
  2. agentscope_runtime/adapters/agentscope/__init__.py +0 -0
  3. agentscope_runtime/adapters/agentscope/long_term_memory/__init__.py +6 -0
  4. agentscope_runtime/adapters/agentscope/long_term_memory/_long_term_memory_adapter.py +258 -0
  5. agentscope_runtime/adapters/agentscope/memory/__init__.py +6 -0
  6. agentscope_runtime/adapters/agentscope/memory/_memory_adapter.py +152 -0
  7. agentscope_runtime/adapters/agentscope/message.py +535 -0
  8. agentscope_runtime/adapters/agentscope/stream.py +506 -0
  9. agentscope_runtime/adapters/agentscope/tool/__init__.py +9 -0
  10. agentscope_runtime/adapters/agentscope/tool/sandbox_tool.py +69 -0
  11. agentscope_runtime/adapters/agentscope/tool/tool.py +233 -0
  12. agentscope_runtime/adapters/autogen/__init__.py +0 -0
  13. agentscope_runtime/adapters/autogen/tool/__init__.py +7 -0
  14. agentscope_runtime/adapters/autogen/tool/tool.py +211 -0
  15. agentscope_runtime/adapters/text/__init__.py +0 -0
  16. agentscope_runtime/adapters/text/stream.py +29 -0
  17. agentscope_runtime/common/collections/redis_mapping.py +4 -1
  18. agentscope_runtime/common/container_clients/fc_client.py +855 -0
  19. agentscope_runtime/common/utils/__init__.py +0 -0
  20. agentscope_runtime/common/utils/lazy_loader.py +57 -0
  21. agentscope_runtime/engine/__init__.py +25 -18
  22. agentscope_runtime/engine/app/agent_app.py +161 -91
  23. agentscope_runtime/engine/app/base_app.py +4 -118
  24. agentscope_runtime/engine/constant.py +8 -0
  25. agentscope_runtime/engine/deployers/__init__.py +8 -0
  26. agentscope_runtime/engine/deployers/adapter/__init__.py +2 -0
  27. agentscope_runtime/engine/deployers/adapter/a2a/a2a_adapter_utils.py +0 -21
  28. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +28 -9
  29. agentscope_runtime/engine/deployers/adapter/responses/__init__.py +2 -0
  30. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +5 -2
  31. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +1 -1
  32. agentscope_runtime/engine/deployers/agentrun_deployer.py +2541 -0
  33. agentscope_runtime/engine/deployers/cli_fc_deploy.py +1 -1
  34. agentscope_runtime/engine/deployers/kubernetes_deployer.py +9 -21
  35. agentscope_runtime/engine/deployers/local_deployer.py +47 -74
  36. agentscope_runtime/engine/deployers/modelstudio_deployer.py +216 -50
  37. agentscope_runtime/engine/deployers/utils/app_runner_utils.py +29 -0
  38. agentscope_runtime/engine/deployers/utils/detached_app.py +510 -0
  39. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +1 -1
  40. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +1 -1
  41. agentscope_runtime/engine/deployers/utils/docker_image_utils/{runner_image_factory.py → image_factory.py} +121 -61
  42. agentscope_runtime/engine/deployers/utils/package.py +693 -0
  43. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -5
  44. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +301 -282
  45. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +2 -4
  46. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +23 -1
  47. agentscope_runtime/engine/deployers/utils/templates/app_main.py.j2 +84 -0
  48. agentscope_runtime/engine/deployers/utils/templates/runner_main.py.j2 +95 -0
  49. agentscope_runtime/engine/deployers/utils/{service_utils → templates}/standalone_main.py.j2 +0 -45
  50. agentscope_runtime/engine/deployers/utils/wheel_packager.py +119 -18
  51. agentscope_runtime/engine/helpers/runner.py +40 -0
  52. agentscope_runtime/engine/runner.py +171 -130
  53. agentscope_runtime/engine/schemas/agent_schemas.py +114 -3
  54. agentscope_runtime/engine/schemas/modelstudio_llm.py +4 -2
  55. agentscope_runtime/engine/schemas/oai_llm.py +23 -23
  56. agentscope_runtime/engine/schemas/response_api.py +65 -0
  57. agentscope_runtime/engine/schemas/session.py +24 -0
  58. agentscope_runtime/engine/services/__init__.py +0 -9
  59. agentscope_runtime/engine/services/agent_state/__init__.py +16 -0
  60. agentscope_runtime/engine/services/agent_state/redis_state_service.py +113 -0
  61. agentscope_runtime/engine/services/agent_state/state_service.py +179 -0
  62. agentscope_runtime/engine/services/memory/__init__.py +24 -0
  63. agentscope_runtime/engine/services/{mem0_memory_service.py → memory/mem0_memory_service.py} +17 -13
  64. agentscope_runtime/engine/services/{memory_service.py → memory/memory_service.py} +28 -7
  65. agentscope_runtime/engine/services/{redis_memory_service.py → memory/redis_memory_service.py} +1 -1
  66. agentscope_runtime/engine/services/{reme_personal_memory_service.py → memory/reme_personal_memory_service.py} +9 -6
  67. agentscope_runtime/engine/services/{reme_task_memory_service.py → memory/reme_task_memory_service.py} +2 -2
  68. agentscope_runtime/engine/services/{tablestore_memory_service.py → memory/tablestore_memory_service.py} +12 -18
  69. agentscope_runtime/engine/services/sandbox/__init__.py +13 -0
  70. agentscope_runtime/engine/services/{sandbox_service.py → sandbox/sandbox_service.py} +86 -71
  71. agentscope_runtime/engine/services/session_history/__init__.py +23 -0
  72. agentscope_runtime/engine/services/{redis_session_history_service.py → session_history/redis_session_history_service.py} +3 -2
  73. agentscope_runtime/engine/services/{session_history_service.py → session_history/session_history_service.py} +44 -34
  74. agentscope_runtime/engine/services/{tablestore_session_history_service.py → session_history/tablestore_session_history_service.py} +14 -19
  75. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +2 -2
  76. agentscope_runtime/engine/tracing/base.py +10 -9
  77. agentscope_runtime/engine/tracing/message_util.py +1 -1
  78. agentscope_runtime/engine/tracing/tracing_util.py +7 -2
  79. agentscope_runtime/engine/tracing/wrapper.py +49 -31
  80. agentscope_runtime/sandbox/__init__.py +10 -2
  81. agentscope_runtime/sandbox/box/agentbay/__init__.py +4 -0
  82. agentscope_runtime/sandbox/box/agentbay/agentbay_sandbox.py +559 -0
  83. agentscope_runtime/sandbox/box/base/base_sandbox.py +12 -0
  84. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +115 -11
  85. agentscope_runtime/sandbox/box/cloud/__init__.py +4 -0
  86. agentscope_runtime/sandbox/box/cloud/cloud_sandbox.py +254 -0
  87. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +66 -0
  88. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +42 -0
  89. agentscope_runtime/sandbox/box/mobile/__init__.py +4 -0
  90. agentscope_runtime/sandbox/box/mobile/box/__init__.py +0 -0
  91. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +216 -0
  92. agentscope_runtime/sandbox/box/training_box/training_box.py +2 -2
  93. agentscope_runtime/sandbox/client/http_client.py +1 -0
  94. agentscope_runtime/sandbox/enums.py +2 -0
  95. agentscope_runtime/sandbox/manager/sandbox_manager.py +15 -2
  96. agentscope_runtime/sandbox/manager/server/app.py +12 -0
  97. agentscope_runtime/sandbox/manager/server/config.py +19 -0
  98. agentscope_runtime/sandbox/model/manager_config.py +79 -2
  99. agentscope_runtime/sandbox/utils.py +0 -18
  100. agentscope_runtime/tools/RAGs/__init__.py +0 -0
  101. agentscope_runtime/tools/RAGs/modelstudio_rag.py +377 -0
  102. agentscope_runtime/tools/RAGs/modelstudio_rag_lite.py +219 -0
  103. agentscope_runtime/tools/__init__.py +119 -0
  104. agentscope_runtime/tools/_constants.py +18 -0
  105. agentscope_runtime/tools/alipay/__init__.py +4 -0
  106. agentscope_runtime/tools/alipay/base.py +334 -0
  107. agentscope_runtime/tools/alipay/payment.py +835 -0
  108. agentscope_runtime/tools/alipay/subscribe.py +551 -0
  109. agentscope_runtime/tools/base.py +264 -0
  110. agentscope_runtime/tools/cli/__init__.py +0 -0
  111. agentscope_runtime/tools/cli/modelstudio_mcp_server.py +78 -0
  112. agentscope_runtime/tools/generations/__init__.py +75 -0
  113. agentscope_runtime/tools/generations/async_image_to_video.py +350 -0
  114. agentscope_runtime/tools/generations/async_image_to_video_wan25.py +366 -0
  115. agentscope_runtime/tools/generations/async_speech_to_video.py +422 -0
  116. agentscope_runtime/tools/generations/async_text_to_video.py +320 -0
  117. agentscope_runtime/tools/generations/async_text_to_video_wan25.py +334 -0
  118. agentscope_runtime/tools/generations/image_edit.py +208 -0
  119. agentscope_runtime/tools/generations/image_edit_wan25.py +193 -0
  120. agentscope_runtime/tools/generations/image_generation.py +202 -0
  121. agentscope_runtime/tools/generations/image_generation_wan25.py +201 -0
  122. agentscope_runtime/tools/generations/image_style_repaint.py +208 -0
  123. agentscope_runtime/tools/generations/image_to_video.py +233 -0
  124. agentscope_runtime/tools/generations/qwen_image_edit.py +205 -0
  125. agentscope_runtime/tools/generations/qwen_image_generation.py +214 -0
  126. agentscope_runtime/tools/generations/qwen_text_to_speech.py +154 -0
  127. agentscope_runtime/tools/generations/speech_to_text.py +260 -0
  128. agentscope_runtime/tools/generations/speech_to_video.py +314 -0
  129. agentscope_runtime/tools/generations/text_to_video.py +221 -0
  130. agentscope_runtime/tools/mcp_wrapper.py +215 -0
  131. agentscope_runtime/tools/realtime_clients/__init__.py +13 -0
  132. agentscope_runtime/tools/realtime_clients/asr_client.py +27 -0
  133. agentscope_runtime/tools/realtime_clients/azure_asr_client.py +195 -0
  134. agentscope_runtime/tools/realtime_clients/azure_tts_client.py +383 -0
  135. agentscope_runtime/tools/realtime_clients/modelstudio_asr_client.py +151 -0
  136. agentscope_runtime/tools/realtime_clients/modelstudio_tts_client.py +199 -0
  137. agentscope_runtime/tools/realtime_clients/realtime_tool.py +55 -0
  138. agentscope_runtime/tools/realtime_clients/tts_client.py +33 -0
  139. agentscope_runtime/tools/searches/__init__.py +3 -0
  140. agentscope_runtime/tools/searches/modelstudio_search.py +877 -0
  141. agentscope_runtime/tools/searches/modelstudio_search_lite.py +310 -0
  142. agentscope_runtime/tools/utils/__init__.py +0 -0
  143. agentscope_runtime/tools/utils/api_key_util.py +45 -0
  144. agentscope_runtime/tools/utils/crypto_utils.py +99 -0
  145. agentscope_runtime/tools/utils/mcp_util.py +35 -0
  146. agentscope_runtime/version.py +1 -1
  147. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/METADATA +240 -168
  148. agentscope_runtime-1.0.0.dist-info/RECORD +240 -0
  149. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/entry_points.txt +1 -0
  150. agentscope_runtime/engine/agents/__init__.py +0 -2
  151. agentscope_runtime/engine/agents/agentscope_agent.py +0 -488
  152. agentscope_runtime/engine/agents/agno_agent.py +0 -220
  153. agentscope_runtime/engine/agents/autogen_agent.py +0 -250
  154. agentscope_runtime/engine/agents/base_agent.py +0 -29
  155. agentscope_runtime/engine/agents/langgraph_agent.py +0 -59
  156. agentscope_runtime/engine/agents/utils.py +0 -53
  157. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -1163
  158. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  159. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  160. agentscope_runtime/engine/helpers/helper.py +0 -179
  161. agentscope_runtime/engine/schemas/context.py +0 -54
  162. agentscope_runtime/engine/services/context_manager.py +0 -164
  163. agentscope_runtime/engine/services/environment_manager.py +0 -50
  164. agentscope_runtime/engine/services/manager.py +0 -174
  165. agentscope_runtime/engine/services/rag_service.py +0 -195
  166. agentscope_runtime/engine/services/tablestore_rag_service.py +0 -143
  167. agentscope_runtime/sandbox/tools/__init__.py +0 -12
  168. agentscope_runtime/sandbox/tools/base/__init__.py +0 -8
  169. agentscope_runtime/sandbox/tools/base/tool.py +0 -52
  170. agentscope_runtime/sandbox/tools/browser/__init__.py +0 -57
  171. agentscope_runtime/sandbox/tools/browser/tool.py +0 -597
  172. agentscope_runtime/sandbox/tools/filesystem/__init__.py +0 -32
  173. agentscope_runtime/sandbox/tools/filesystem/tool.py +0 -319
  174. agentscope_runtime/sandbox/tools/function_tool.py +0 -321
  175. agentscope_runtime/sandbox/tools/gui/__init__.py +0 -7
  176. agentscope_runtime/sandbox/tools/gui/tool.py +0 -77
  177. agentscope_runtime/sandbox/tools/mcp_tool.py +0 -195
  178. agentscope_runtime/sandbox/tools/sandbox_tool.py +0 -104
  179. agentscope_runtime/sandbox/tools/tool.py +0 -238
  180. agentscope_runtime/sandbox/tools/utils.py +0 -68
  181. agentscope_runtime-0.2.0b2.dist-info/RECORD +0 -183
  182. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/WHEEL +0 -0
  183. {agentscope_runtime-0.2.0b2.dist-info → agentscope_runtime-1.0.0.dist-info}/licenses/LICENSE +0 -0
  184. {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