ControlAR / model.py
wondervictor's picture
Update model.py
be788b7 verified
import gc
import spaces
from safetensors.torch import load_file
from autoregressive.models.gpt_t2i import GPT_models
from tokenizer.tokenizer_image.vq_model import VQ_models
from language.t5 import T5Embedder
import torch
import numpy as np
import PIL
from PIL import Image
from condition.canny import CannyDetector
import time
from autoregressive.models.generate import generate
from condition.midas.depth import MidasDetector
from preprocessor import Preprocessor
models = {
"edge": "checkpoints/edge_base.safetensors",
"depth": "checkpoints/depth_base.safetensors",
}
class Model:
def __init__(self):
self.device = torch.device(
"cuda")
self.base_model_id = ""
self.task_name = ""
self.vq_model = self.load_vq()
self.t5_model = self.load_t5()
# self.gpt_model_edge = self.load_gpt(condition_type='edge')
# self.gpt_model_depth = self.load_gpt(condition_type='depth')
self.gpt_model = self.load_gpt()
self.preprocessor = Preprocessor()
def to(self, device):
self.gpt_model_canny.to('cuda')
def load_vq(self):
vq_model = VQ_models["VQ-16"](codebook_size=16384,
codebook_embed_dim=8)
vq_model.eval()
checkpoint = torch.load(f"checkpoints/vq_ds16_t2i.pt",
map_location="cpu")
vq_model.load_state_dict(checkpoint["model"])
del checkpoint
print("image tokenizer is loaded")
return vq_model
def load_gpt(self, condition_type='edge'):
# gpt_ckpt = models[condition_type]
# precision = torch.bfloat16
precision = torch.float32
latent_size = 512 // 16
gpt_model = GPT_models["GPT-XL"](
block_size=latent_size**2,
cls_token_num=120,
model_type='t2i',
condition_type=condition_type,
adapter_size='base',
).to(device='cpu', dtype=precision)
# model_weight = load_file(gpt_ckpt)
# gpt_model.load_state_dict(model_weight, strict=False)
# gpt_model.eval()
# print("gpt model is loaded")
return gpt_model
def load_gpt_weight(self, condition_type='edge'):
torch.cuda.empty_cache()
gc.collect()
gpt_ckpt = models[condition_type]
model_weight = load_file(gpt_ckpt)
self.gpt_model.load_state_dict(model_weight, strict=False)
self.gpt_model.eval()
torch.cuda.empty_cache()
gc.collect()
# print("gpt model is loaded")
def load_t5(self):
# precision = torch.bfloat16
precision = torch.float32
t5_model = T5Embedder(
device=self.device,
local_cache=True,
cache_dir='checkpoints/flan-t5-xl',
dir_or_name='flan-t5-xl',
torch_dtype=precision,
model_max_length=120,
)
return t5_model
@torch.no_grad()
@spaces.GPU(enable_queue=True, duration=120)
def process_edge(
self,
image: np.ndarray,
prompt: str,
cfg_scale: float,
temperature: float,
top_k: int,
top_p: int,
seed: int,
low_threshold: int,
high_threshold: int,
control_strength: float,
preprocessor_name: str,
) -> list[PIL.Image.Image]:
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
origin_W, origin_H = image.size
if preprocessor_name == 'Canny':
self.preprocessor.load("Canny")
condition_img = self.preprocessor(
image=image, low_threshold=low_threshold, high_threshold=high_threshold, detect_resolution=512)
elif preprocessor_name == 'Hed':
self.preprocessor.load("HED")
condition_img = self.preprocessor(
image=image,image_resolution=512, detect_resolution=512)
elif preprocessor_name == 'Lineart':
self.preprocessor.load("Lineart")
condition_img = self.preprocessor(
image=image,image_resolution=512, detect_resolution=512)
elif preprocessor_name == 'No preprocess':
condition_img = image
print('get edge')
# del self.preprocessor.model
# torch.cuda.empty_cache()
condition_img = condition_img.resize((512,512))
W, H = condition_img.size
self.t5_model.model.to('cuda').to(torch.bfloat16)
self.load_gpt_weight('edge')
self.gpt_model.to('cuda').to(torch.bfloat16)
self.vq_model.to('cuda')
condition_img = torch.from_numpy(np.array(condition_img)).unsqueeze(0).permute(0,3,1,2).repeat(3,1,1,1)
condition_img = condition_img.to(self.device)
condition_img = 2*(condition_img/255 - 0.5)
prompts = [prompt] * 3
caption_embs, emb_masks = self.t5_model.get_text_embeddings(prompts)
print(f"processing left-padding...")
new_emb_masks = torch.flip(emb_masks, dims=[-1])
new_caption_embs = []
for idx, (caption_emb,
emb_mask) in enumerate(zip(caption_embs, emb_masks)):
valid_num = int(emb_mask.sum().item())
print(f' prompt {idx} token len: {valid_num}')
new_caption_emb = torch.cat(
[caption_emb[valid_num:], caption_emb[:valid_num]])
new_caption_embs.append(new_caption_emb)
new_caption_embs = torch.stack(new_caption_embs)
c_indices = new_caption_embs * new_emb_masks[:, :, None]
c_emb_masks = new_emb_masks
qzshape = [len(c_indices), 8, H // 16, W // 16]
t1 = time.time()
print(caption_embs.device)
index_sample = generate(
self.gpt_model,
c_indices,
(H // 16) * (W // 16),
c_emb_masks,
condition=condition_img,
cfg_scale=cfg_scale,
temperature=temperature,
top_k=top_k,
top_p=top_p,
sample_logits=True,
control_strength=control_strength,
)
sampling_time = time.time() - t1
print(f"Full sampling takes about {sampling_time:.2f} seconds.")
t2 = time.time()
print(index_sample.shape)
samples = self.vq_model.decode_code(
index_sample, qzshape) # output value is between [-1, 1]
decoder_time = time.time() - t2
print(f"decoder takes about {decoder_time:.2f} seconds.")
# samples = condition_img[0:1]
samples = torch.cat((condition_img[0:1], samples), dim=0)
samples = 255 * (samples * 0.5 + 0.5)
samples = [
Image.fromarray(
sample.permute(1, 2, 0).cpu().detach().numpy().clip(
0, 255).astype(np.uint8)).resize((origin_W, origin_H)) for sample in samples
]
del condition_img
torch.cuda.empty_cache()
return samples
@torch.no_grad()
@spaces.GPU(enable_queue=True, duration=120)
def process_depth(
self,
image: np.ndarray,
prompt: str,
cfg_scale: float,
temperature: float,
top_k: int,
top_p: int,
seed: int,
control_strength: float,
preprocessor_name: str
) -> list[PIL.Image.Image]:
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
origin_W, origin_H = image.size
# print(image)
if preprocessor_name == 'depth':
self.preprocessor.load("Depth")
condition_img = self.preprocessor(
image=image,
image_resolution=512,
detect_resolution=512,
)
elif preprocessor_name == 'No preprocess':
condition_img = image
print('get depth')
# del self.preprocessor.model
# torch.cuda.empty_cache()
condition_img = condition_img.resize((512,512))
W, H = condition_img.size
self.t5_model.model.to(self.device).to(torch.bfloat16)
self.load_gpt_weight('depth')
self.gpt_model.to('cuda').to(torch.bfloat16)
self.vq_model.to(self.device)
condition_img = torch.from_numpy(np.array(condition_img)).unsqueeze(0).permute(0,3,1,2).repeat(3,1,1,1)
condition_img = condition_img.to(self.device)
condition_img = 2*(condition_img/255 - 0.5)
prompts = [prompt] * 3
caption_embs, emb_masks = self.t5_model.get_text_embeddings(prompts)
print(f"processing left-padding...")
new_emb_masks = torch.flip(emb_masks, dims=[-1])
new_caption_embs = []
for idx, (caption_emb,
emb_mask) in enumerate(zip(caption_embs, emb_masks)):
valid_num = int(emb_mask.sum().item())
print(f'prompt {idx} token len: {valid_num}')
new_caption_emb = torch.cat(
[caption_emb[valid_num:], caption_emb[:valid_num]])
new_caption_embs.append(new_caption_emb)
new_caption_embs = torch.stack(new_caption_embs)
c_indices = new_caption_embs * new_emb_masks[:, :, None]
c_emb_masks = new_emb_masks
qzshape = [len(c_indices), 8, H // 16, W // 16]
t1 = time.time()
index_sample = generate(
self.gpt_model,
c_indices,
(H // 16) * (W // 16),
c_emb_masks,
condition=condition_img,
cfg_scale=cfg_scale,
temperature=temperature,
top_k=top_k,
top_p=top_p,
sample_logits=True,
control_strength=control_strength,
)
sampling_time = time.time() - t1
print(f"Full sampling takes about {sampling_time:.2f} seconds.")
t2 = time.time()
print(index_sample.shape)
samples = self.vq_model.decode_code(index_sample, qzshape)
decoder_time = time.time() - t2
print(f"decoder takes about {decoder_time:.2f} seconds.")
condition_img = condition_img.cpu()
samples = samples.cpu()
# samples = condition_img[0:1]
samples = torch.cat((condition_img[0:1], samples), dim=0)
samples = 255 * (samples * 0.5 + 0.5)
samples = [
Image.fromarray(
sample.permute(1, 2, 0).cpu().detach().numpy().clip(0, 255).astype(np.uint8)).resize((origin_W, origin_H))
for sample in samples
]
del condition_img
torch.cuda.empty_cache()
return samples