mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-05 15:20:40 +08:00
fix: tighten input_schema per Volcengine Jimeng 3.0 Pro contract
- frames: enum [121, 241] (was minimum 1) - prompt: maxLength 800 (was 2000) - seed: minimum -1 (was unbounded) - Add 9 schema validation rejection tests - Add authoritative API reference link to PROVIDERS.md - Document CVSync2Async* route choice and schema constraints Fixes calesthio's second review feedback on PR #341.
This commit is contained in:
@@ -123,8 +123,17 @@ Authentication uses Volcengine IAM V4 signing (HMAC-SHA256), not a Bearer token.
|
||||
|
||||
API flow: `POST ?Action=CVSync2AsyncSubmitTask` → poll `POST ?Action=CVSync2AsyncGetResult` → download `video_url`.
|
||||
|
||||
The implementation uses the compatible generic `CVSync2Async*` route (API version `2022-08-31`) rather than the model-specific `2024-06-06` actions presented in the public API explorer. This is intentional — the generic route supports the same Jimeng 3.0 Pro model via `req_key` while remaining stable across model updates.
|
||||
|
||||
The `req_key` for video is `jimeng_ti2v_v30_pro`. Success code is `10000`. Task statuses: `in_queue`, `generating`, `done`, `not_found`, `expired`.
|
||||
|
||||
**Authoritative API reference:** [Jimeng TI2V V30 Pro SubmitTask](https://api.volcengine.com/api-docs/view?action=JimengTI2VV30PROSubmitTask&serviceCode=cv&version=2024-06-06)
|
||||
|
||||
**Schema constraints** (enforced by `input_schema` to prevent paid-call failures):
|
||||
- `prompt`: max 800 characters
|
||||
- `frames`: must be exactly `121` (5s) or `241` (10s) at 24fps
|
||||
- `seed`: `-1` for random, or any non-negative integer
|
||||
|
||||
#### Pricing
|
||||
|
||||
| Model | Price |
|
||||
|
||||
@@ -318,3 +318,63 @@ class TestRegistryDiscovery:
|
||||
jimeng = [t for t in registry._tools.values() if t.name == "jimeng_video"]
|
||||
assert len(jimeng) == 1
|
||||
assert jimeng[0].provider == "volcengine"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Schema validation — reject invalid inputs before paid API call
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
class TestSchemaValidation:
|
||||
|
||||
def test_frames_accepts_121(self):
|
||||
schema = JimengVideo().input_schema
|
||||
valid = schema["properties"]["frames"]
|
||||
assert valid["enum"] == [121, 241]
|
||||
|
||||
def test_frames_rejects_non_enum(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
for invalid in [1, 100, 200, 500, 0, -1]:
|
||||
instance = {"prompt": "test", "frames": invalid}
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
jsonschema.validate(instance, schema)
|
||||
|
||||
def test_prompt_max_length_800(self):
|
||||
schema = JimengVideo().input_schema
|
||||
assert schema["properties"]["prompt"]["maxLength"] == 800
|
||||
|
||||
def test_prompt_rejects_over_800_chars(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
instance = {"prompt": "x" * 801}
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
jsonschema.validate(instance, schema)
|
||||
|
||||
def test_prompt_accepts_800_chars(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
instance = {"prompt": "x" * 800}
|
||||
jsonschema.validate(instance, schema)
|
||||
|
||||
def test_seed_minimum_is_negative_one(self):
|
||||
schema = JimengVideo().input_schema
|
||||
assert schema["properties"]["seed"]["minimum"] == -1
|
||||
|
||||
def test_seed_rejects_below_negative_one(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
for invalid in [-2, -10, -100]:
|
||||
instance = {"prompt": "test", "seed": invalid}
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
jsonschema.validate(instance, schema)
|
||||
|
||||
def test_seed_accepts_negative_one(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
jsonschema.validate({"prompt": "test", "seed": -1}, schema)
|
||||
|
||||
def test_seed_accepts_zero_and_positive(self):
|
||||
import jsonschema
|
||||
schema = JimengVideo().input_schema
|
||||
for valid in [0, 1, 42, 999999]:
|
||||
jsonschema.validate({"prompt": "test", "seed": valid}, schema)
|
||||
|
||||
@@ -86,7 +86,8 @@ class JimengVideo(BaseTool):
|
||||
"properties": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"description": "Video description. Max 2000 chars. Supports Chinese.",
|
||||
"maxLength": 800,
|
||||
"description": "Video description. Max 800 chars. Supports Chinese.",
|
||||
},
|
||||
"operation": {
|
||||
"type": "string",
|
||||
@@ -102,7 +103,7 @@ class JimengVideo(BaseTool):
|
||||
},
|
||||
"frames": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"enum": [121, 241],
|
||||
"default": 121,
|
||||
"description": "Total frames. 121=5s, 241=10s at 24fps.",
|
||||
},
|
||||
@@ -113,6 +114,7 @@ class JimengVideo(BaseTool):
|
||||
},
|
||||
"seed": {
|
||||
"type": "integer",
|
||||
"minimum": -1,
|
||||
"default": -1,
|
||||
"description": "Random seed. -1 for random.",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user