fix: 修正模型超时与结果未知重放

This commit is contained in:
hh
2026-07-21 15:34:29 +08:00
parent a99aae8231
commit f2114bc36e
22 changed files with 1221 additions and 107 deletions
+8 -22
View File
@@ -18,7 +18,12 @@ from django.db import transaction
from django.utils import timezone
from apps.ai.models import AITask, ModelConfig
from apps.ai.generation_errors import TASK_OPERATIONS, classify_generation_error, public_error_for_task
from apps.ai.generation_errors import (
TASK_OPERATIONS,
ProviderOutcomeUnknownError,
classify_generation_error,
public_error_for_task,
)
from apps.ai.model_routing import ModelRequirements, capability_metadata, model_allows_fallback
from apps.ai.providers import (
OpenAICompatibleProvider,
@@ -200,6 +205,7 @@ def execute_routed_image_request(
except Exception as exc:
# Provider 已返回并可能产生上游费用;响应解析失败仍需审计本次真实尝试成本。
candidate_quote = quote_flat(actual_model, team=task.team)
exc.outcome_unknown = True
exc.attempt_metadata = AttemptMetadata(
usage=actual_response.get("usage") if isinstance(actual_response, dict) else {},
platform_cost=candidate_quote.base_cost_yuan,
@@ -853,7 +859,7 @@ def execute_routed_audio_request(
)
class VideoSubmissionStateUnknown(RuntimeError):
class VideoSubmissionStateUnknown(ProviderOutcomeUnknownError):
"""视频提交可能已到达供应商但未拿到可靠任务 ID;禁止自动重提。"""
@@ -3326,26 +3332,6 @@ def poll_video_segment(*, video_segment: VideoSegment, user) -> VideoSegmentVers
from apps.ai.routing_policy import load_model_routing_policy
video_policy = load_model_routing_policy().video
if ai_task.submitted_at and (timezone.now() - ai_task.submitted_at).total_seconds() >= video_policy.generation_timeout:
timeout_message = "视频生成超过配置的等待总时限"
with transaction.atomic():
locked_task = AITask.objects.select_for_update().get(id=ai_task.id)
if locked_task.status in (AITask.Status.SUCCEEDED, AITask.Status.FAILED, AITask.Status.CANCELLED):
return video_segment.versions.filter(task=locked_task).order_by("-created_at").first()
locked_task.status = AITask.Status.FAILED
locked_task.error_message = timeout_message
locked_task.completed_at = timezone.now()
locked_task.save(update_fields=["status", "error_message", "completed_at", "updated_at"])
release_credit(reservation=locked_task.credit_reservation, reason=timeout_message)
video_segment.status = VideoSegment.Status.FAILED
video_segment.error_message = classify_generation_error(
TimeoutError(timeout_message),
operation="video_generate",
reference_id=str(locked_task.id),
).fallback_message
video_segment.save(update_fields=["status", "error_message", "updated_at"])
return None
provider = get_video_provider(actual_model)
response = provider.poll_video_task(
endpoint=actual_model.endpoint,