-
Notifications
You must be signed in to change notification settings - Fork 262
Expand file tree
/
Copy pathconvert_swiftvr.py
More file actions
112 lines (96 loc) · 3.84 KB
/
Copy pathconvert_swiftvr.py
File metadata and controls
112 lines (96 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python3
"""Convert a SwiftVR Diffusers checkpoint to LightX2V's Wan key layout.
Example:
python tools/convert/examples/convert_swiftvr.py \
--source /path/to/SwiftVR \
--output /path/to/SwiftVR_lightx2v
"""
import argparse
import shutil
import subprocess
import sys
from collections import Counter
from pathlib import Path
from tempfile import TemporaryDirectory
from safetensors import safe_open
CONVERTER = Path(__file__).resolve().parents[1] / "converter.py"
TRANSFORMER_PATH = Path("transformer/diffusion_pytorch_model.safetensors")
RUNTIME_FILES = (
Path("reae.safetensors"),
Path("prompt_embedding.safetensors"),
Path("transformer/config.json"),
)
REQUIRED_KEYS = {
"blocks.0.self_attn.q.weight",
"blocks.0.cross_attn.q.weight",
"blocks.0.ffn.0.weight",
"blocks.0.norm3.weight",
"blocks.0.modulation",
"head.head.weight",
"head.modulation",
}
def checkpoint_signature(path: Path):
with safe_open(path, framework="pt", device="cpu") as checkpoint:
keys = set(checkpoint.keys())
tensors = Counter()
for key in keys:
tensor = checkpoint.get_slice(key)
tensors[(tensor.get_dtype(), tuple(tensor.get_shape()))] += 1
return keys, tensors
def validate_conversion(source: Path, converted: Path):
source_keys, source_tensors = checkpoint_signature(source)
converted_keys, converted_tensors = checkpoint_signature(converted)
if len(converted_keys) != len(source_keys):
raise RuntimeError(f"Converted checkpoint has {len(converted_keys)} tensors; expected {len(source_keys)}")
if converted_tensors != source_tensors:
raise RuntimeError("Converted checkpoint changed tensor shapes or dtypes")
missing = REQUIRED_KEYS - converted_keys
if missing:
raise RuntimeError(f"Converted checkpoint is missing LightX2V keys: {sorted(missing)}")
def convert_swiftvr(source: Path, output: Path):
source = source.resolve()
output = output.resolve()
source_transformer = source / TRANSFORMER_PATH
if not source_transformer.is_file():
raise FileNotFoundError(f"SwiftVR transformer checkpoint not found: {source_transformer}")
if output.exists():
raise FileExistsError(f"Output already exists: {output}")
output.parent.mkdir(parents=True, exist_ok=True)
with TemporaryDirectory(prefix=f".{output.name}.", dir=output.parent) as workspace:
converted_model = Path(workspace) / output.name
for model_file in RUNTIME_FILES:
destination = converted_model / model_file
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source / model_file, destination)
converted_transformer = converted_model / TRANSFORMER_PATH
subprocess.run(
[
sys.executable,
str(CONVERTER),
"--source",
str(source_transformer),
"--output",
str(converted_transformer.parent),
"--output_name",
converted_transformer.stem,
"--direction",
"backward",
"--model_type",
"wan_dit",
"--device",
"cpu",
"--single_file",
],
check=True,
)
validate_conversion(source_transformer, converted_transformer)
converted_model.rename(output)
print(f"Converted SwiftVR checkpoint: {output}")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--source", type=Path, required=True, help="Official SwiftVR model directory")
parser.add_argument("--output", type=Path, required=True, help="Destination LightX2V model directory")
args = parser.parse_args()
convert_swiftvr(args.source, args.output)
if __name__ == "__main__":
main()