Directly-constructed GenerationRequests marked every schema default as explicit (normalize_generation_request bound the full serialization when _fastvideo_explicit_paths was absent), so request_to_sampling_param overwrote model preset values with schema defaults: FastWan DMD ran 3->50 steps, TurboDiffusion 4->50, stable-audio 100 steps/CFG7 -> 50/CFG1, and 1.3B Wan examples rendered 720x1280x125f with CFG off. Fix at the root: SamplingConfig fields now default to None = "inherit the model preset". None leaves are never bound as explicit paths — for directly-constructed requests (normalize_generation_request) and for parsed YAML/JSON (parse_config treats explicit null as unset, so widening the types cannot let nulls stomp presets either). Dicts emptied by the pruning are dropped too, so None-valued extensions cannot resurface via the live-attribute read in explicit_request_updates. The _SCHEMA_DEFAULT_UPDATES tolerance hack is deleted (an explicitly-set field unsupported by a model's SamplingParam now always fails loudly), and return_state is skipped in the update loop since it is already translated to return_continuation_state. Consumers of raw (pre-resolution) sampling fields are guarded: the streaming server validates operator-pinned default_request.sampling before the multi-minute model boot (run_server) and in build_app; its segment negative_prompt merge preserves an explicit "" clear; the mock server supplies concrete fallbacks; generate_async resolves the preset so its advertised total_steps matches the actual run; the ray-serve gradio demo passes "" to keep its no-negative-prompt default. Stale schema-default claims in video_api/ServeConfig/openai.md docs updated. Tests: test_preset_inheritance.py locks the contract (bare request inherits preset; partial override; explicit value equal to an old schema default wins; negative_prompt None-inherits/""-clears; parsed nulls inherit; None-valued extensions are dropped; unsupported explicit field raises) plus a build_app pin-validation test.
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
from fastvideo.api import (
|
|
GenerationRequest,
|
|
GeneratorConfig,
|
|
RunConfig,
|
|
SamplingConfig,
|
|
ServeConfig,
|
|
config_to_dict,
|
|
)
|
|
|
|
|
|
def test_run_config_roundtrip_preserves_nested_defaults() -> None:
|
|
config = RunConfig(
|
|
generator=GeneratorConfig(model_path="hf://model"),
|
|
request=GenerationRequest(
|
|
prompt="hello",
|
|
sampling=SamplingConfig(num_frames=48, width=832, height=480),
|
|
),
|
|
)
|
|
|
|
dumped = config_to_dict(config)
|
|
|
|
assert dumped["generator"]["model_path"] == "hf://model"
|
|
assert dumped["generator"]["engine"]["execution_backend"] == "mp"
|
|
assert dumped["request"]["sampling"]["num_frames"] == 48
|
|
assert dumped["request"]["sampling"]["guidance_scale_2"] is None
|
|
assert dumped["request"]["output"]["save_video"] is True
|
|
|
|
|
|
def test_serve_config_includes_server_and_default_request_defaults() -> None:
|
|
config = ServeConfig(generator=GeneratorConfig(model_path="/models/ltx2"))
|
|
|
|
dumped = config_to_dict(config)
|
|
|
|
assert dumped["server"] == {
|
|
"host": "0.0.0.0",
|
|
"port": 8000,
|
|
"output_dir": "outputs/",
|
|
}
|
|
# Sampling fields default to None = "inherit the model preset".
|
|
assert dumped["default_request"]["sampling"]["fps"] is None
|
|
assert dumped["default_request"]["runtime"]["enable_teacache"] is False
|