import json ARK_ERRORS = { "MissingParameter": "请求缺少必要参数,请查阅API文档。", "InvalidParameter": "请求包含非法参数,请查阅API文档。", "InvalidEndpoint.ClosedEndpoint": "推理接入点处于已关闭或暂时不可用,请稍后重试,或联系管理员。", "SensitiveContentDetected": "输入文本可能包含敏感信息,请使用其他prompt。", "SensitiveContentDetected.SevereViolation": "输入文本可能包含严重违规相关信息,请使用其他prompt。", "SensitiveContentDetected.Violence": "输入文本可能包含激进行为相关信息,请使用其他prompt。", "InputTextSensitiveContentDetected": "输入文本可能包含敏感信息,请更换后重试。", "InputImageSensitiveContentDetected": "输入图像可能包含敏感信息,请更换后重试。", "InputVideoSensitiveContentDetected": "输入视频可能包含敏感信息,请更换后重试。", "InputAudioSensitiveContentDetected": "输入音频可能包含敏感信息,请更换后重试。", "OutputTextSensitiveContentDetected": "生成的文字可能包含敏感信息,请更换输入内容后重试。", "OutputImageSensitiveContentDetected": "生成的图像可能包含敏感信息,请更换输入内容后重试。", "OutputVideoSensitiveContentDetected": "生成的视频可能包含敏感信息,请更换输入内容后重试。", "OutputVideoSensitiveContentDetected.PolicyViolation": "生成的视频可能涉及版权限制,请修改提示词。", "OutputAudioSensitiveContentDetected": "生成的音频可能包含敏感信息,请更换输入内容后重试。", "InputTextSensitiveContentDetected.PolicyViolation": "输入文本可能违反平台规定,请更换后重试。", "InputImageSensitiveContentDetected.PolicyViolation": "输入图片可能违反平台规定,请更换后重试。", "InputVideoSensitiveContentDetected.PolicyViolation": "输入视频可能违反平台规定,请更换后重试。", "InputAudioSensitiveContentDetected.PolicyViolation": "输入音频可能违反平台规定,请更换后重试。", "InputImageSensitiveContentDetected.PrivacyInformation": "输入图片可能包含真人,请更换后重试。", "InputVideoSensitiveContentDetected.PrivacyInformation": "输入视频可能包含真人,请更换后重试。", "InputTextRiskDetection": "风险识别产品检测到输入文本可能包含敏感信息,请更换后重试。", "InputImageRiskDetection": "风险识别产品检测到输入图片可能包含敏感信息,请更换后重试。", "OutputTextRiskDetection": "风险识别产品检测到输出文本可能包含敏感信息,请更换后重试。", "OutputImageRiskDetection": "风险识别产品检测到输出图片可能包含敏感信息,请更换后重试。", "ContentSecurityDetectionError": "风险识别产品请求失败。", "InvalidParameter.InvalidParameter": "请求参数值不合法,请检查参数值的正确性后重试。", "MissingParameter.MissingParameter": "缺少必要的请求参数,请确认请求参数后重试。", "Duplicate.Tags.Key": "对象的标签存在重复Key。", "InvalidArgumentError": "请求中的messages列表里,有消息体缺少role字段。", "InvalidArgumentError.UnknownRole": "消息体中的role值不被支持,如user_。", "InvalidArgumentError.InvalidImageDetail": "image_url中的detail参数值无效,只接受\"auto\", \"high\", \"low\"。", "InvalidArgumentError.InvalidPixelLimit": "用户自定义的图片像素限制无效(例如min_pixels > max_pixels,或超出了服务配置的范围)。", "InvalidImageURL.EmptyURL": "传入的图片URL为空。", "InvalidImageURL.InvalidFormat": "无法解析或处理图片,可能是Base64格式不正确、图片数据损坏或格式不支持。", "OutofContextError": "当请求中包含图片时,文本和图片编码后的总token数超过了模型上下文长度限制。", "InvalidParameter.UnsupportedParameter": "传入的参数在此推理接入点不可用。", "InvalidSubscription": "Coding Plan套餐未订阅或已过期。", "AuthenticationError": "请求携带的API Key或AK/SK校验未通过,请重新检查设置的鉴权凭证。", "InvalidAccountStatus": "当前使用的账号异常。", "OperationDenied.InvalidState": "请求所关联的Context ID处于非空闲状态,不可调用。", "OperationDenied.ConflictedValidationSet": "无法同时上传验证集和设置训练集取样为验证集百分比,不支持该操作。", "OperationDenied.PermissionDenied": "您没有权限访问基础模型的配置,不支持该操作。", "OperationDenied.UnsupportedCustomizationType": "模型不支持该训练方法,不支持该操作。", "OperationDenied.CustomizationNotSupported": "基础模型的版本不支持该训练方法,不支持该操作。", "OperationDenied.ServiceNotOpen": "模型服务不可用,请前往激活模型服务,或提交工单联系我们。", # "OperationDenied.ServiceOverdue": "您的账单已逾期,请前往费用中心充值。", "OperationDenied.ServiceOverdue": "系统使用高峰,请稍后重试", #"AccountOverdueError": "当前账号欠费(余额<0),如需继续调用,请前往费用中心进行充值。", "AccountOverdueError": "系统使用高峰,请稍后重试", "AccessDenied": "没有访问该资源的权限,请检查权限设置,或联系管理员添加白名单。", "OperationDenied.UnsupportedPhase": "操作失败,操作目标在特殊状态,请检查目标是否存在或者被锁定等特殊状态中。", "OperationDenied.FileQuotaExceeded": "当前账号已耗尽文件存储额度,如需继续使用,请删除历史文件。", "InvalidEndpointOrModel.NotFound": "模型或者推理接入点不存在或者您无权访问它。", "ModelNotOpen": "当前账号暂未开通模型服务,请前往开通管理页开通对应模型服务。", "NotFound.NotFound": "指定资源找不到,请确认参数后重试。", "InvalidEndpointOrModel.ModelIDAccessDisabled": "未能找到指定的模型ID,您的账号不允许使用模型ID来调用模型,请使用有权限的推理接入点ID来调用模型服务。", "UnsupportedModel": "当前模型不支持Coding Plan。", "RateLimitExceeded.EndpointRPMExceeded": "请求所关联的推理接入点已超过RPM(Requests Per Minute)限制,请稍后重试。", "RateLimitExceeded.EndpointTPMExceeded": "请求所关联的推理接入点已超过TPM(Tokens Per Minute)限制,请稍后重试。", "ModelAccountRpmRateLimitExceeded": "请求已超过帐户模型RPM(Requests Per Minute)限制,请稍后重试,或联系平台技术同学进行解决。", "ModelAccountTpmRateLimitExceeded": "请求已超过帐户模型TPM(Tokens Per Minute)限制,请稍后重试,或联系平台技术同学进行解决。", "APIAccountRpmRateLimitExceeded": "当前账号该接口的RPM(Requests Per Minute)限制已超出,请稍后重试。", "ModelAccountIpmRateLimitExceeded": "请求已超过账户模型IPM(Images Per Minute)限制,请稍后重试,或联系平台技术同学进行解决。", "QuotaExceeded": "当前账号对模型的免费试用额度已消耗完毕,如需继续调用,请前往开通管理页开通对应模型服务。", "ServerOverloaded": "服务资源紧张,请稍后重试。常出现在调用流量突增或刚开始调用长时间未使用的推理接入点。", "RequestBurstTooFast": "请求量激增触发系统保护,请放缓流量提升速度,逐步增加请求量后再尝试。", "SetLimitExceeded": "当前账号已达到模型推理限制,模型服务已暂停。如需继续使用该模型,请联系平台。", "InternalError": "服务内部错误,请稍后重试。", "ServiceUnavailable": "服务暂时不可用,请稍后重试。", "Timeout": "请求超时,请重试。", "TaskCancelled": "任务已被取消。", "UnsupportedOperation": "当前操作不支持,请联系管理员。", "PermissionDenied": "没有权限执行此操作。", "ResourceNotFound": "请求的资源不存在。", "InvalidApiKey": "API密钥无效,请联系管理员。", "InvalidSignature": "签名验证失败。", "InvalidToken": "Token无效或已过期。", "RequestTimeout": "请求超时,请重试。", "TooManyRequests": "请求过于频繁,请稍后重试。", "MethodNotAllowed": "不支持的HTTP方法。", "MediaTypeNotSupported": "不支持的媒体类型。", "RequestEntityTooLarge": "请求体过大。", "InvalidRequest": "请求格式无效。", "ResourceExists": "资源已存在。", "ResourceNotReady": "资源尚未就绪。", "GenerationFailed": "生成失败,请重试。", "AudioGenerationFailed": "音频生成失败。", "VideoGenerationFailed": "视频生成失败。", "ImageGenerationFailed": "图片生成失败。", "ModelNotFound": "模型不存在。", "ModelNotAvailable": "模型暂不可用。", "RegionNotSupported": "当前区域不支持。", "AccountNotActivated": "账户尚未激活。", "AccountSuspended": "账户已被暂停。", "InsufficientBalance": "余额不足,请充值。", "FeatureNotEnabled": "功能未启用。", "VersionNotSupported": "版本不支持。", "InvalidDuration": "无效的时长参数。", "InvalidSize": "无效的尺寸参数。", "InvalidFormat": "无效的格式参数。", "InvalidAspectRatio": "无效的画面比例。", "InvalidResolution": "无效的分辨率。", "FrameRateNotSupported": "不支持的帧率。", "BitrateNotSupported": "不支持的码率。", "AudioNotSupported": "音频格式不支持。", "VideoCodecNotSupported": "视频编码不支持。", "WatermarkFailed": "水印添加失败。", "TranscodeFailed": "转码失败。", "StorageFailed": "存储失败。", "DownloadFailed": "下载失败。", "UploadFailed": "上传失败。", "ProcessingFailed": "处理失败。", "ValidationFailed": "验证失败。", "AuthorizationFailed": "授权失败。", "AuthenticationFailed": "认证失败。", "SessionExpired": "会话已过期。", "SessionNotFound": "会话不存在。", "RateLimitReached": "达到速率限制。", "ConcurrentLimitReached": "达到并发限制。", "QueueFull": "队列已满。", "ServiceMaintenance": "服务维护中。", "ServiceUpgrade": "服务升级中。", "DataCorrupted": "数据损坏。", "DatabaseError": "数据库错误。", "CacheError": "缓存错误。", "NetworkError": "网络错误。", "DNSFailure": "DNS解析失败。", "ConnectionRefused": "连接被拒绝。", "SSLHandshakeFailed": "SSL握手失败。", "CertificateError": "证书错误。", } def extract_error_message(exc: Exception, service_type: str = "video") -> str: """Extract a clean, user-friendly error message from Ark SDK exceptions.""" raw = str(exc) try: idx = raw.find("{") if idx >= 0: data = json.loads(raw[idx:].replace("'", '"')) err = data.get("error", {}) code = err.get("code", "") msg = err.get("message", "") if code in ARK_ERRORS: return ARK_ERRORS[code] if msg: if "Request id:" in msg or "Request ID:" in msg: idx_request = msg.find("Request id:") if idx_request == -1: idx_request = msg.find("Request ID:") if idx_request >= 0: msg = msg[:idx_request].strip().rstrip(".") return msg if code: return f"{service_type}生成失败: {code}" except (json.JSONDecodeError, TypeError, ValueError): pass return raw[:5000] if len(raw) > 5000 else raw