Instructions to use darask0/MOSS-Image_4-step_adapter_lora with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use darask0/MOSS-Image_4-step_adapter_lora with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("OpenMOSS-Team/MOSS-Image-SFT", dtype=torch.bfloat16, device_map="cuda") pipe.load_lora_weights("darask0/MOSS-Image_4-step_adapter_lora") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Draw Things
- DiffusionBee
File size: 5,869 Bytes
1ec327b | 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | """COMFYUI_ROOT=/path/to/ComfyUI python -m pytest code/tests/test_comfy_adapter.py"""
import importlib.util
import os
from pathlib import Path
import sys
import pytest
import torch
from safetensors.torch import save_file
sys.path.insert(0, os.environ['COMFYUI_ROOT'])
from comfy.cli_args import args
args.cpu = True
import comfy.ops
from comfy.ldm.moss_image.model import MOSSImage
from comfy.model_patcher import ModelPatcher
spec = importlib.util.spec_from_file_location('rapid_nodes', Path(__file__).parents[2] / 'comfyui/rapid-moss/nodes.py')
rapid = importlib.util.module_from_spec(spec)
spec.loader.exec_module(rapid)
@pytest.fixture
def adapter(tmp_path, monkeypatch):
torch.manual_seed(123)
dim, ffn, rank = 128, 192, 3
lora = {}
for name in rapid.PROJ:
inp, out = (ffn, dim) if name == 'ffn_down' else (dim, 2 * ffn if name == 'ffn_up_gate' else dim)
prefix = 'diffusion_model.layers.0.proj.' + name
lora[prefix + '.lora_down.weight'] = torch.randn(rank, inp) * 0.03
lora[prefix + '.lora_up.weight'] = torch.randn(out, rank) * 0.03
lora[prefix + '.alpha'] = torch.tensor(float(rank))
time = {
'time_embedding.0.weight': torch.randn(dim, 256) * .01,
'time_embedding.0.bias': torch.randn(dim) * .01,
'time_embedding.2.weight': torch.randn(dim, dim) * .01,
'time_embedding.2.bias': torch.randn(dim) * .01,
'shared_block_modulation.bias': torch.randn(6 * dim) * .01,
'video_head_modulation.bias': torch.randn(2 * dim) * .01,
}
save_file(lora, tmp_path / 'lora.safetensors')
save_file(time, tmp_path / 'time_embedding.safetensors')
save_file({'latent_mix.Q': torch.eye(128), 'step_codes': torch.tensor([1000, 968, 926, 871])},
tmp_path / 'dataspace.safetensors')
monkeypatch.setattr(rapid, '_adapter_dirs', lambda: {'test': str(tmp_path)})
return lora
def make_model(fused):
holder = torch.nn.Module()
holder.diffusion_model = MOSSImage(dim=128, ffn_dim=192, num_heads=1, num_layers=1,
fused_qkv=fused, dtype=torch.float32, operations=comfy.ops.manual_cast)
for p in holder.parameters():
torch.nn.init.normal_(p, std=.02)
return ModelPatcher(holder, torch.device('cpu'), torch.device('cpu'))
@pytest.mark.parametrize('fused', [False, True])
def test_lora_apply_and_restore(adapter, fused):
model = make_model(fused)
layer = model.model.diffusion_model.layers[0]
base_weights = {k: m.weight.detach().clone() for k, m in layer.proj.items()}
patched, _, sigmas = rapid.RapidMOSSAdapter().apply(model, 'test', 4, .7)
assert sigmas.tolist() == pytest.approx([1, .968, .926, .871, 0])
assert not model.object_patches
patched.patch_model(load_weights=False)
for name, module in layer.proj.items():
x = torch.randn(1, 5, module.weight.shape[1])
expected = torch.nn.functional.linear(x, base_weights[name])
names = ('q', 'k', 'v') if name == 'qkv' else (name,)
deltas = []
for proj in names:
prefix = 'diffusion_model.layers.0.proj.' + proj
deltas.append(.7 * (x @ adapter[prefix + '.lora_down.weight'].T) @ adapter[prefix + '.lora_up.weight'].T)
expected += torch.cat(deltas, dim=-1)
torch.testing.assert_close(module(x), expected)
torch.testing.assert_close(module.weight, base_weights[name], rtol=0, atol=0)
patched.unpatch_model()
for name, module in layer.proj.items():
x = torch.randn(1, 2, module.weight.shape[1])
torch.testing.assert_close(module(x), torch.nn.functional.linear(x, base_weights[name]))
def test_sampler_matches_dataspace_recurrence():
torch.manual_seed(4)
z = torch.randn(1, 3, 2, 2)
q = torch.randn(3, 3) * .1
codes = torch.tensor([1000, 968, 926, 871])
sigmas = torch.cat((codes.float() / 1000, torch.zeros(1)))
calls = []
def denoise(x, sigma):
calls.append(sigma.clone())
return x - sigma[:, None, None, None] * (x * .3 + sigma[:, None, None, None])
expected = torch.zeros_like(z)
for code in codes:
x = z + torch.einsum('oc,bchw->bohw', q, expected)
expected = z - (x * .3 + code / 1000)
actual = rapid.sample_dataspace(denoise, z, sigmas, Q=q, codes=codes)
torch.testing.assert_close(actual, expected)
assert len(calls) == 4
def test_reject_too_many_steps(adapter):
with pytest.raises(ValueError, match='4 step codes'):
rapid.RapidMOSSAdapter().apply(make_model(True), 'test', 5, 1.)
@pytest.mark.parametrize('dtype', [torch.float32, torch.bfloat16])
@pytest.mark.parametrize('device', ['cpu', pytest.param('cuda', marks=pytest.mark.skipif(
os.environ.get('RAPID_MOSS_TEST_CUDA') != '1', reason='set RAPID_MOSS_TEST_CUDA=1 for GPU checks'))])
def test_native_forward_fused_matches_split(adapter, dtype, device):
model = make_model(False)
fused = make_model(True)
sd = model.model.state_dict()
prefix = 'diffusion_model.layers.0.proj.'
sd[prefix + 'qkv.weight'] = torch.cat([sd.pop(prefix + n + '.weight') for n in ('q', 'k', 'v')])
fused.model.load_state_dict(sd)
x = torch.randn(1, 128, 2, 3, device=device, dtype=dtype)
ctx = torch.randn(1, 4, 4096, device=device, dtype=dtype)
t = torch.tensor([.968], device=device)
outputs = []
for m in (model, fused):
m.model.to(device=device, dtype=dtype)
patched, _, _ = rapid.RapidMOSSAdapter().apply(m, 'test', 4, 1.)
patched.patch_model(load_weights=False)
with torch.no_grad():
outputs.append(m.model.diffusion_model(x.clone(), t, ctx))
patched.unpatch_model()
assert all(torch.isfinite(out).all() for out in outputs)
assert all(out.abs().max() < 10 for out in outputs)
torch.testing.assert_close(*outputs, rtol=.01, atol=.001)
|