[diffusion] feat: add composable component weight path cli (#36078)
This commit is contained in:
@@ -2760,38 +2760,38 @@ class ServerArgs(DisaggServerArgsMixin):
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _extract_component_paths(
|
||||
def _extract_dynamic_component_map(
|
||||
unknown_args: list[str],
|
||||
*,
|
||||
option_prefixes: tuple[str, ...],
|
||||
alias_suffix: str,
|
||||
) -> tuple[dict[str, str], list[str]]:
|
||||
"""
|
||||
Extract dynamic component path args from unrecognised CLI args.
|
||||
|
||||
Supported forms:
|
||||
- ``--<component>-path /path/to/component``
|
||||
- ``--component-paths.<component> /path/to/component`` (expanded from config)
|
||||
"""
|
||||
component_paths: dict[str, str] = {}
|
||||
component_values: dict[str, str] = {}
|
||||
remaining: list[str] = []
|
||||
i = 0
|
||||
while i < len(unknown_args):
|
||||
arg = unknown_args[i]
|
||||
key_part = arg.split("=", 1)[0] if "=" in arg else arg
|
||||
component = None
|
||||
if key_part.startswith("--component-paths."):
|
||||
component = key_part[len("--component-paths.") :].replace("-", "_")
|
||||
elif key_part.startswith("--component_paths."):
|
||||
component = key_part[len("--component_paths.") :].replace("-", "_")
|
||||
elif key_part.startswith("--") and key_part.endswith("-path"):
|
||||
component = key_part[2:-5].replace("-", "_")
|
||||
for option_prefix in option_prefixes:
|
||||
if key_part.startswith(option_prefix):
|
||||
component = key_part[len(option_prefix) :].replace("-", "_")
|
||||
break
|
||||
if (
|
||||
component is None
|
||||
and key_part.startswith("--")
|
||||
and key_part.endswith(alias_suffix)
|
||||
):
|
||||
component = key_part[2 : -len(alias_suffix)].replace("-", "_")
|
||||
|
||||
if component is not None:
|
||||
if "=" in arg:
|
||||
component_paths[component] = arg.split("=", 1)[1]
|
||||
component_values[component] = arg.split("=", 1)[1]
|
||||
elif i + 1 < len(unknown_args) and not unknown_args[i + 1].startswith(
|
||||
"-"
|
||||
):
|
||||
i += 1
|
||||
component_paths[component] = unknown_args[i]
|
||||
component_values[component] = unknown_args[i]
|
||||
else:
|
||||
remaining.append(arg)
|
||||
i += 1
|
||||
@@ -2800,11 +2800,37 @@ class ServerArgs(DisaggServerArgsMixin):
|
||||
remaining.append(arg)
|
||||
i += 1
|
||||
|
||||
# canonicalize and validate
|
||||
for component, path in component_paths.items():
|
||||
path = os.path.expanduser(path)
|
||||
component_paths[component] = path
|
||||
return component_paths, remaining
|
||||
return {
|
||||
component: os.path.expanduser(value)
|
||||
for component, value in component_values.items()
|
||||
}, remaining
|
||||
|
||||
@classmethod
|
||||
def _extract_component_paths(
|
||||
cls,
|
||||
unknown_args: list[str],
|
||||
) -> tuple[dict[str, str], list[str]]:
|
||||
"""Extract dynamic component configuration paths and aliases."""
|
||||
return cls._extract_dynamic_component_map(
|
||||
unknown_args,
|
||||
option_prefixes=("--component-paths.", "--component_paths."),
|
||||
alias_suffix="-path",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _extract_component_weights_paths(
|
||||
cls,
|
||||
unknown_args: list[str],
|
||||
) -> tuple[dict[str, str], list[str]]:
|
||||
"""Extract dynamic component weight-file paths and aliases."""
|
||||
return cls._extract_dynamic_component_map(
|
||||
unknown_args,
|
||||
option_prefixes=(
|
||||
"--component-weights-paths.",
|
||||
"--component_weights_paths.",
|
||||
),
|
||||
alias_suffix="-weights-path",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _extract_component_attention_backends(
|
||||
@@ -2853,8 +2879,11 @@ class ServerArgs(DisaggServerArgsMixin):
|
||||
if unknown_args is None:
|
||||
unknown_args = []
|
||||
|
||||
# extract dynamic --<component>-path from unknown args
|
||||
dynamic_paths, remaining = cls._extract_component_paths(unknown_args)
|
||||
# Extract the more specific weights suffix before the generic path alias.
|
||||
dynamic_weights_paths, remaining = cls._extract_component_weights_paths(
|
||||
unknown_args
|
||||
)
|
||||
dynamic_paths, remaining = cls._extract_component_paths(remaining)
|
||||
dynamic_attention_backends, remaining = (
|
||||
cls._extract_component_attention_backends(remaining)
|
||||
)
|
||||
@@ -2880,6 +2909,11 @@ class ServerArgs(DisaggServerArgsMixin):
|
||||
existing.update(dynamic_paths)
|
||||
provided_args["component_paths"] = existing
|
||||
explicit_arg_names.add("component_paths")
|
||||
if dynamic_weights_paths:
|
||||
existing = dict(provided_args.get("component_weights_paths") or {})
|
||||
existing.update(dynamic_weights_paths)
|
||||
provided_args["component_weights_paths"] = existing
|
||||
explicit_arg_names.add("component_weights_paths")
|
||||
if dynamic_attention_backends:
|
||||
existing = cls._parse_component_attention_backend_map(
|
||||
provided_args.get("component_attention_backends")
|
||||
|
||||
@@ -464,7 +464,16 @@ class TestServerArgsPathExpansion(unittest.TestCase):
|
||||
)
|
||||
|
||||
with tempfile.NamedTemporaryFile("w", suffix=".json") as config_file:
|
||||
json.dump({"model_path": "/from/config", "num_gpus": 2}, config_file)
|
||||
json.dump(
|
||||
{
|
||||
"model_path": "/from/config",
|
||||
"num_gpus": 2,
|
||||
"component_weights_paths": {
|
||||
"transformer": "owner/repo/transformer.safetensors"
|
||||
},
|
||||
},
|
||||
config_file,
|
||||
)
|
||||
config_file.flush()
|
||||
parser = FlexibleArgumentParser()
|
||||
add_multimodal_gen_serve_args(parser)
|
||||
@@ -475,6 +484,9 @@ class TestServerArgsPathExpansion(unittest.TestCase):
|
||||
"/from/cli",
|
||||
"--vae-path",
|
||||
"/custom/vae",
|
||||
"--component-weights-paths.text_encoder",
|
||||
"owner/repo/text_encoder.safetensors",
|
||||
"--image-encoder-weights-path=/custom/image_encoder.safetensors",
|
||||
"--component-attention-backends.transformer",
|
||||
"fa3",
|
||||
]
|
||||
@@ -505,6 +517,14 @@ class TestServerArgsPathExpansion(unittest.TestCase):
|
||||
self.assertEqual("/from/cli", server_args.model_path)
|
||||
self.assertEqual(2, server_args.num_gpus)
|
||||
self.assertEqual("/custom/vae", server_args.component_paths["vae"])
|
||||
self.assertEqual(
|
||||
{
|
||||
"transformer": "owner/repo/transformer.safetensors",
|
||||
"text_encoder": "owner/repo/text_encoder.safetensors",
|
||||
"image_encoder": "/custom/image_encoder.safetensors",
|
||||
},
|
||||
server_args.component_weights_paths,
|
||||
)
|
||||
self.assertEqual(
|
||||
{"transformer": "fa"},
|
||||
server_args.component_attention_backends,
|
||||
|
||||
Reference in New Issue
Block a user