refactor(script): remove sync endpoint, add thread-pool & timeout

- Remove unused POST /script/generate sync endpoint and frontend generate()
- Move JSON parsing/validation to asyncio.to_thread() to avoid event-loop blocking
- Add 60s asyncio.timeout() around entire script generation pipeline
- Migrate volcengine_provider to unified AsyncArk client
This commit is contained in:
小鱼开发
2026-04-30 23:51:30 +08:00
parent 08a430ad9d
commit feddeed950
4 changed files with 94 additions and 135 deletions
+84 -73
View File
@@ -141,89 +141,100 @@ class ScriptService:
model_router = await get_model_router()
try:
# 加载 Prompt
system_prompt = load_system_prompt(category, subcategory)
if not system_prompt:
yield ScriptGenerationEvent(
type="error",
message=f"未找到提示词: category={category}, subcategory={subcategory}",
)
return
user_prompt = load_script_user_prompt(
topic=f"{category}/{subcategory}",
duration=duration,
)
yield ScriptGenerationEvent(
type="start",
message="准备生成...",
)
full_content = ""
has_shown_generating = False
async for chunk in model_router.generate_stream_with_progress(
prompt=user_prompt,
system_prompt=system_prompt,
model_id=model,
task_type="script",
temperature=0.7,
response_format="json_object",
):
if chunk["type"] == "chunk":
chunk_content = chunk.get("content", "")
if not chunk_content:
continue
full_content += chunk_content
if not has_shown_generating:
yield ScriptGenerationEvent(
type="generating",
message="正在创作脚本...",
)
has_shown_generating = True
if not full_content or not full_content.strip():
yield ScriptGenerationEvent(
type="error",
message="AI 返回内容为空,请检查模型配置或重试",
)
return
success, parsed_data, error_msg = safe_parse_ai_json_response(full_content)
if not success:
yield ScriptGenerationEvent(
type="error",
message=f"脚本解析失败: {error_msg or '无法解析 AI 返回的内容'}",
)
return
try:
shots_data = validate_and_normalize_shots(parsed_data)
if not shots_data:
async with asyncio.timeout(60):
# 加载 Prompt
system_prompt = load_system_prompt(category, subcategory)
if not system_prompt:
yield ScriptGenerationEvent(
type="error",
message="AI 返回的分镜数据为空或格式不正确",
message=f"未找到提示词: category={category}, subcategory={subcategory}",
)
return
shots = [ScriptShot(**shot) for shot in shots_data]
yield ScriptGenerationEvent(
type="complete",
message="脚本生成成功",
result=shots,
user_prompt = load_script_user_prompt(
topic=f"{category}/{subcategory}",
duration=duration,
)
except Exception as e:
yield ScriptGenerationEvent(
type="error",
message=f"分镜数据处理失败: {str(e)}",
type="start",
message="准备生成...",
)
full_content = ""
has_shown_generating = False
async for chunk in model_router.generate_stream_with_progress(
prompt=user_prompt,
system_prompt=system_prompt,
model_id=model,
task_type="script",
temperature=0.7,
response_format="json_object",
):
if chunk["type"] == "chunk":
chunk_content = chunk.get("content", "")
if not chunk_content:
continue
full_content += chunk_content
if not has_shown_generating:
yield ScriptGenerationEvent(
type="generating",
message="正在创作脚本...",
)
has_shown_generating = True
if not full_content or not full_content.strip():
yield ScriptGenerationEvent(
type="error",
message="AI 返回内容为空,请检查模型配置或重试",
)
return
success, parsed_data, error_msg = await asyncio.to_thread(
safe_parse_ai_json_response, full_content
)
if not success:
yield ScriptGenerationEvent(
type="error",
message=f"脚本解析失败: {error_msg or '无法解析 AI 返回的内容'}",
)
return
try:
shots_data = await asyncio.to_thread(
validate_and_normalize_shots, parsed_data
)
if not shots_data:
yield ScriptGenerationEvent(
type="error",
message="AI 返回的分镜数据为空或格式不正确",
)
return
shots = [ScriptShot(**shot) for shot in shots_data]
yield ScriptGenerationEvent(
type="complete",
message="脚本生成成功",
result=shots,
)
except Exception as e:
yield ScriptGenerationEvent(
type="error",
message=f"分镜数据处理失败: {str(e)}",
)
except asyncio.TimeoutError:
yield ScriptGenerationEvent(
type="error",
message="脚本生成超时,请重试",
)
except Exception as e:
yield ScriptGenerationEvent(
type="error",