feat(seedance): 两个已开通模型的限制表与提交前本地预校验(23 测试)

账号实际接入 doubao-seedance-2-5-260628 与 doubao-seedance-2-0-260128,两者限制
差异不小,且同一组参数在一个上合法、在另一个上不合法:

|            | 2.5              | 2.0                |
| 时长        | [4, 30]          | [4, 15]            |
| 分辨率      | 480p/720p/1080p  | 480p/720p/1080p/4k |
| 图生视频 ratio | **只能 adaptive** | 可指定             |
| output_format | mp4/mov        | 仅 mp4             |

超范围的请求会被厂商 400 拒绝——那要花一次往返、计入 RPM,并表现为一个失败的
任务。故在 capabilities.py 落一张限制表并在提交前本地预校验,错误信息直接指出
是哪个模型的哪条限制。

两处刻意的设计:
- **按模型族前缀匹配**而非完整 ID:尾部是日期版本(260628/260128),会随厂商
  小版本更新而变,按前缀匹配使一次升级不必改表。
- **未知模型一律放行**(只记日志):账号新开通一个模型时不该因为这张表没更新
  就用不了,否则「开通即可用」会退化成「开通还得改代码发版」。代价只是失去
  本地预校验,厂商仍会兜底。

测试 100 → 123:限制表 23 项逐条对应官方文档的一条限制,另在适配器层加 4 项
端到端断言(超范围请求的 handler 直接 assert 不该被调用,确认请求根本没发出)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-20 15:12:06 +08:00
parent db87d66403
commit 8f1d1bc5f3
4 changed files with 324 additions and 0 deletions
+60
View File
@@ -396,3 +396,63 @@ class TestPixelDimensionsAreLeftBlankOnPurpose:
assert result.height_px is None
# 但原始信息要透出,供上层或后续实现换算。
assert (result.ratio, result.resolution) == ("16:9", "720p")
class TestPerModelLimitsAreEnforcedBeforeCallingTheVendor:
"""超范围的请求本地就拦下,不花一次往返去换一个厂商 400。
两个已接入模型的限制不同,同一组参数在一个上合法、在另一个上不合法——
这正是需要本地预校验的理由。
"""
def test_duration_beyond_the_2_0_cap_is_rejected_locally(self):
def handler(request):
raise AssertionError("不应发出请求:本地预校验就该拦下")
with pytest.raises(ValueError, match=r"\[4, 15\]"):
provider_with(handler).submit(
video_request(model="doubao-seedance-2-0-260128", duration_sec=20)
)
def test_the_same_duration_passes_on_2_5(self):
def handler(request):
return httpx.Response(200, json={"id": "cgt-1"})
assert (
provider_with(handler).submit(
video_request(model="doubao-seedance-2-5-260628", duration_sec=20)
)
== "cgt-1"
)
def test_4k_is_rejected_on_2_5_but_allowed_on_2_0(self):
def rejecting(request):
raise AssertionError("不应发出请求")
with pytest.raises(ValueError, match="不支持分辨率 4k"):
provider_with(rejecting).submit(
video_request(model="doubao-seedance-2-5-260628", resolution="4k")
)
def accepting(request):
return httpx.Response(200, json={"id": "cgt-2"})
assert (
provider_with(accepting).submit(
video_request(model="doubao-seedance-2-0-260128", resolution="4k")
)
== "cgt-2"
)
def test_2_5_image_to_video_rejects_a_specific_ratio(self):
def handler(request):
raise AssertionError("不应发出请求")
with pytest.raises(ValueError, match="只支持 ratio=adaptive"):
provider_with(handler).submit(
video_request(
model="doubao-seedance-2-5-260628",
input_url="https://x/a.png",
ratio="16:9",
)
)