feat: 接入模型动态 Fallback 与调用审计
This commit is contained in:
@@ -24,6 +24,41 @@ def env_list(name: str, default: str = "") -> list[str]:
|
||||
return [item.strip() for item in value.split(",") if item.strip()]
|
||||
|
||||
|
||||
def env_int(name: str, default: int) -> int:
|
||||
"""读取整数环境变量;格式错误时给出可直接定位配置项的中文错误。"""
|
||||
value = os.getenv(name)
|
||||
if value is None or not value.strip():
|
||||
return default
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"环境变量 {name} 必须是整数,当前值:{value!r}") from exc
|
||||
|
||||
|
||||
def env_float(name: str, default: float) -> float:
|
||||
"""读取小数环境变量;格式错误时给出可直接定位配置项的中文错误。"""
|
||||
value = os.getenv(name)
|
||||
if value is None or not value.strip():
|
||||
return default
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"环境变量 {name} 必须是数字,当前值:{value!r}") from exc
|
||||
|
||||
|
||||
def env_int_list(name: str, default: tuple[int, ...]) -> list[int]:
|
||||
"""读取逗号分隔的整数列表;空字符串表示不重试。"""
|
||||
value = os.getenv(name)
|
||||
if value is None:
|
||||
return list(default)
|
||||
if not value.strip():
|
||||
return []
|
||||
try:
|
||||
return [int(item.strip()) for item in value.split(",") if item.strip()]
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"环境变量 {name} 必须是逗号分隔的整数列表,当前值:{value!r}") from exc
|
||||
|
||||
|
||||
SECRET_KEY = env("DJANGO_SECRET_KEY", "airshelf-dev-insecure-key")
|
||||
DEBUG = env_bool("DJANGO_DEBUG", False)
|
||||
ALLOWED_HOSTS = env_list("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1")
|
||||
@@ -235,6 +270,73 @@ PROVIDER_API_VERSIONS = {
|
||||
# 自由创作视频:团队在途任务并发上限(视频长时高价,限并发同时压 web 慢调用敞口)
|
||||
FREE_VIDEO_MAX_CONCURRENT = int(env("FREE_VIDEO_MAX_CONCURRENT", "3"))
|
||||
|
||||
# 模型失败重试与动态 Fallback 的统一策略配置,已由全部 AI 业务入口与调用审计共用。
|
||||
#
|
||||
# 生效方式:修改环境变量后,需要同步重启 Django API 与 Celery Worker,确保两端读取同一策略。
|
||||
# 时间单位:除 jitter_ratio 外,所有 timeout、cap 和 retry_delays 均为“秒”。
|
||||
# 次数口径:max_calls 包含首次调用、原模型重试和所有候选模型调用;max_models 包含主模型。
|
||||
MODEL_ROUTING_POLICY = {
|
||||
# 单个用户逻辑任务最多尝试的不同模型数量;包含用户选择或系统默认的主模型。
|
||||
# 合法范围 1~10。调大可提高成功率,但会增加等待时间和平台真实成本。
|
||||
"max_models": env_int("MODEL_ROUTING_MAX_MODELS", 3),
|
||||
# 单个用户逻辑任务最多发出的真实模型请求总数;包含首次调用、重试和 Fallback。
|
||||
# 合法范围 1~20,且不得小于 max_models。用户侧仍只允许一次预留和一次最终结算。
|
||||
"max_calls": env_int("MODEL_ROUTING_MAX_CALLS", 5),
|
||||
# 退避时间随机抖动比例;0.20 表示在基础等待时间上随机浮动 ±20%。
|
||||
# 合法范围 0~1。调大可减轻并发任务同时重试,但会让实际等待时间波动更明显。
|
||||
"jitter_ratio": env_float("MODEL_ROUTING_JITTER_RATIO", 0.20),
|
||||
"text": {
|
||||
# 文本主模型失败后的重试等待时间;列表长度就是重试次数,默认 1 秒、3 秒(最多重试 2 次)。
|
||||
"retry_delays": env_int_list("MODEL_ROUTING_TEXT_RETRY_DELAYS", (1, 3)),
|
||||
# 普通非流式文本请求的单次最长等待时间。
|
||||
"request_timeout": env_int("MODEL_ROUTING_TEXT_REQUEST_TIMEOUT", 120),
|
||||
# 流式文本请求的单次最长等待时间;脚本 SSE 正常生成可能明显慢于普通文本。
|
||||
"stream_timeout": env_int("MODEL_ROUTING_TEXT_STREAM_TIMEOUT", 300),
|
||||
# 单个文本逻辑任务从首次调用 Provider 起允许的总执行时间,默认 8 分钟。
|
||||
"total_timeout": env_int("MODEL_ROUTING_TEXT_TOTAL_TIMEOUT", 480),
|
||||
# 429 响应 Retry-After 的最长接受时间;超过该值时不继续长时间等待,转入 Fallback 或最终失败。
|
||||
"retry_after_cap": env_int("MODEL_ROUTING_TEXT_RETRY_AFTER_CAP", 15),
|
||||
},
|
||||
"image": {
|
||||
# 图片主模型失败后的重试等待时间;默认等待 3 秒后重试 1 次。
|
||||
"retry_delays": env_int_list("MODEL_ROUTING_IMAGE_RETRY_DELAYS", (3,)),
|
||||
# 单次图片生成或编辑请求的最长等待时间;中转站真实出图可能超过 75 秒。
|
||||
"request_timeout": env_int("MODEL_ROUTING_IMAGE_REQUEST_TIMEOUT", 300),
|
||||
# 单张图片逻辑任务的总执行时间,默认 15 分钟。
|
||||
"total_timeout": env_int("MODEL_ROUTING_IMAGE_TOTAL_TIMEOUT", 900),
|
||||
# 图片 429 Retry-After 的最长接受时间。
|
||||
"retry_after_cap": env_int("MODEL_ROUTING_IMAGE_RETRY_AFTER_CAP", 15),
|
||||
},
|
||||
"audio": {
|
||||
# 配音主模型失败后的重试等待时间;默认等待 2 秒后重试 1 次。
|
||||
"retry_delays": env_int_list("MODEL_ROUTING_AUDIO_RETRY_DELAYS", (2,)),
|
||||
# 单次配音请求的最长等待时间。
|
||||
"request_timeout": env_int("MODEL_ROUTING_AUDIO_REQUEST_TIMEOUT", 60),
|
||||
# 单个配音逻辑任务的总执行时间,默认 3 分钟。
|
||||
"total_timeout": env_int("MODEL_ROUTING_AUDIO_TOTAL_TIMEOUT", 180),
|
||||
# 配音 429 Retry-After 的最长接受时间。
|
||||
"retry_after_cap": env_int("MODEL_ROUTING_AUDIO_RETRY_AFTER_CAP", 15),
|
||||
},
|
||||
"video": {
|
||||
# 视频尚未拿到 Provider 任务 ID 时的提交重试等待时间;默认等待 3 秒后重试 1 次。
|
||||
"submit_retry_delays": env_int_list("MODEL_ROUTING_VIDEO_SUBMIT_RETRY_DELAYS", (3,)),
|
||||
# 单次创建视频 Provider 任务的最长等待时间。
|
||||
"submit_timeout": env_int("MODEL_ROUTING_VIDEO_SUBMIT_TIMEOUT", 120),
|
||||
# 视频“提交与 Fallback”阶段总时限,默认 5 分钟;成功拿到 Provider 任务 ID 后结束该阶段。
|
||||
"submit_total_timeout": env_int("MODEL_ROUTING_VIDEO_SUBMIT_TOTAL_TIMEOUT", 300),
|
||||
# 单次查询视频任务状态的最长等待时间。
|
||||
"poll_request_timeout": env_int("MODEL_ROUTING_VIDEO_POLL_REQUEST_TIMEOUT", 60),
|
||||
# 视频成功提交后的最长成片等待时间,默认 30 分钟;状态未知或普通轮询超时不得重复提交视频。
|
||||
"generation_timeout": env_int("MODEL_ROUTING_VIDEO_GENERATION_TIMEOUT", 1800),
|
||||
# 视频提交遇到 429 时,Retry-After 的最长接受时间。
|
||||
"retry_after_cap": env_int("MODEL_ROUTING_VIDEO_RETRY_AFTER_CAP", 30),
|
||||
},
|
||||
"postprocess": {
|
||||
# 模型成功后的下载、上传和资产保存重试等待时间;不增加模型调用次数,也不触发模型 Fallback。
|
||||
"retry_delays": env_int_list("MODEL_ROUTING_POSTPROCESS_RETRY_DELAYS", (2, 5, 10)),
|
||||
},
|
||||
}
|
||||
|
||||
# 模特库三视图真实生成与计费开关:必须在 API 与 Celery worker 同步部署后才显式开启。
|
||||
# 关闭时提交接口直接拒绝;开启后允许预留积分并把生成任务投递给 worker。
|
||||
MODEL_TRIVIEW_GENERATION_ENABLED = env_bool("MODEL_TRIVIEW_GENERATION_ENABLED", False)
|
||||
|
||||
Reference in New Issue
Block a user