添加seedance2.5

This commit is contained in:
Azmat@qq.com
2026-08-28 16:03:23 +08:00
parent c0a0b9603b
commit a618f02315
16 changed files with 416 additions and 80 deletions
@@ -0,0 +1,100 @@
"""给 Seedance-2.5 补齐能力与定价元数据。
这条模型已经在生产库里(后台加的),但 metadata 装的是 Seedance-2.0 的能力
(durations 只到 15),而且缺 pricing —— 缺 pricing 会让 get_token_price 直接抛
ValueError,每次提交都失败;durations 停在 15 则拿不到「支持 30 秒」这个信息。
视频复刻(商品 / 角色)固定走这一档,两样都必须是对的。
覆盖策略分两类:
- 能力事实(modes / durations / resolutions / capabilities / routing / audio)**强制覆盖** ——
它们描述模型本身能做什么,不是运营偏好。留着 2.0 抄过来的 15 秒会让 30 秒静默失效。
- 运营可调项(pricing / watermark / source)只在缺失时填 —— 后台改过的价目不能被迁移冲掉。
⚠️ pricing 暂用 Seedance-2.0 标准档数字占位,火山 2.5 官方价目待核对(见 catalog.py 注释)。
幂等:可重复 apply。
"""
from django.db import migrations
NAME = "doubao-seedance-2-5-260628"
DURATIONS = list(range(4, 31))
RESOLUTIONS = ["480p", "720p", "1080p", "4k"]
MODES = ["text", "startFrameOptional", "imageReference:9", "videoReference:3", "audioReference:3"]
# 与 apps/ai/catalog.py 的 Seedance-2.5 条目逐键对齐(那边由 _enrich_catalog_routing 自动生成)
CAPABILITY_FACTS = {
"audio": "optional",
"modes": MODES,
"durations": DURATIONS,
"resolutions": RESOLUTIONS,
"routing": {"fallback_on_failure": False, "fallback_candidate": True},
"capabilities": {
"operations": ["video_generate"],
"features": [
"text_to_video", "start_frame", "image_reference",
"video_reference", "audio_reference", "generate_audio",
],
"max_reference_images": 9,
"max_reference_videos": 3,
"max_reference_audios": 3,
"aspect_ratios": ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"],
"resolutions": RESOLUTIONS,
"durations": DURATIONS,
},
}
OPERATOR_TUNABLE = {
"watermark": False,
"source": "volcengine ark · Seedance 2.5",
"pricing": {
"unit": "cny_per_million_tokens",
"default": {"no_ref_video": 46, "with_ref_video": 28},
"1080p": {"no_ref_video": 51, "with_ref_video": 31},
"4k": {"no_ref_video": 26, "with_ref_video": 16},
},
}
def seed(apps, schema_editor):
ModelProvider = apps.get_model("ai", "ModelProvider")
ModelConfig = apps.get_model("ai", "ModelConfig")
provider, _ = ModelProvider.objects.get_or_create(
name="volcengine",
defaults={
"display_name": "火山引擎(豆包)",
"status": "active",
"base_url": "https://ark.cn-beijing.volces.com/api/v3",
},
)
# 生产库里这行已存在,只修元数据;其它环境(测试 / 全新部署)则建出来。
# created_at 晚于现有视频模型 → get_default_model(VIDEO) 仍取原默认,主流程零影响。
ModelConfig.objects.get_or_create(
provider=provider,
name=NAME,
capability="video",
defaults={
"display_name": "Seedance-2.5",
"endpoint": "contents/generations/tasks",
"status": "active",
"is_default": False,
"metadata": {**OPERATOR_TUNABLE, **CAPABILITY_FACTS},
},
)
for config in ModelConfig.objects.filter(name=NAME, capability="video"):
metadata = dict(config.metadata or {})
for key, value in OPERATOR_TUNABLE.items():
metadata.setdefault(key, value)
metadata.update(CAPABILITY_FACTS) # 能力事实强制纠正
config.metadata = metadata
if not config.endpoint:
config.endpoint = "contents/generations/tasks"
config.save(update_fields=["metadata", "endpoint", "updated_at"])
def noop(apps, schema_editor):
"""只补元数据,回滚不删 —— 删了会让在途任务计价失败。"""
class Migration(migrations.Migration):
dependencies = [("ai", "0032_drop_storyboard_prompt_template")]
operations = [migrations.RunPython(seed, noop)]