[Bagel]Add image edit (#588)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
This commit is contained in:
2 files changed
+477
-18
No files matched your search
@@ -29,6 +29,43 @@ from vllm.vllm_flash_attn import flash_attn_varlen_func
|
||||
|
||||
from vllm_omni.diffusion.layers.rope import RotaryEmbedding
|
||||
|
||||
|
||||
def patchify(imgs, p):
|
||||
"""
|
||||
imgs: (N, 3, H, W) or (3, H, W)
|
||||
x: (N, L, patch_size**2 *3) or (L, patch_size**2 *3)
|
||||
"""
|
||||
is_batch = imgs.ndim == 4
|
||||
if not is_batch:
|
||||
imgs = imgs.unsqueeze(0)
|
||||
|
||||
# n: batch, c: channel, h: grid_h, p: patch_h, w: grid_w, q: patch_w
|
||||
x = imgs.reshape(imgs.shape[0], 3, imgs.shape[2] // p, p, imgs.shape[3] // p, p)
|
||||
# Permute to (n, grid_h, grid_w, c, patch_h, patch_w) to match Conv2d (c, h, w) flattening
|
||||
x = torch.einsum("nchpwq->nhwcpq", x)
|
||||
x = x.reshape(imgs.shape[0], -1, 3 * p**2)
|
||||
|
||||
if not is_batch:
|
||||
x = x.squeeze(0)
|
||||
return x
|
||||
|
||||
|
||||
class MLPconnector(nn.Module):
|
||||
def __init__(self, input_dim, output_dim, activation="gelu_pytorch_tanh"):
|
||||
super().__init__()
|
||||
self.fc1 = nn.Linear(input_dim, output_dim)
|
||||
if activation == "gelu":
|
||||
self.act = nn.GELU()
|
||||
elif activation == "gelu_pytorch_tanh":
|
||||
self.act = nn.GELU(approximate="tanh")
|
||||
else:
|
||||
self.act = nn.ReLU()
|
||||
self.fc2 = nn.Linear(output_dim, output_dim)
|
||||
|
||||
def forward(self, x):
|
||||
return self.fc2(self.act(self.fc1(x)))
|
||||
|
||||
|
||||
torch._dynamo.config.cache_size_limit = 512
|
||||
torch._dynamo.config.accumulated_cache_size_limit = 4096
|
||||
flex_attention = torch.compile(flex_attention)
|
||||
@@ -600,18 +637,30 @@ def get_flattened_position_ids_extrapolate(img_h, img_w, patch_size, max_num_pat
|
||||
class BagelConfig(PretrainedConfig):
|
||||
def __init__(
|
||||
self,
|
||||
visual_gen=True,
|
||||
visual_und=True,
|
||||
llm_config=None,
|
||||
vit_config=None,
|
||||
vae_config=None,
|
||||
latent_patch_size=2,
|
||||
max_latent_size=32,
|
||||
vit_max_num_patch_per_side=70,
|
||||
connector_act="gelu_pytorch_tanh",
|
||||
interpolate_pos=False,
|
||||
timestep_shift=1.0,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self.visual_gen = visual_gen
|
||||
self.visual_und = visual_und
|
||||
self.llm_config = llm_config
|
||||
self.vit_config = vit_config
|
||||
self.vae_config = vae_config
|
||||
self.latent_patch_size = latent_patch_size
|
||||
self.max_latent_size = max_latent_size
|
||||
self.vit_max_num_patch_per_side = vit_max_num_patch_per_side
|
||||
self.connector_act = connector_act
|
||||
self.interpolate_pos = interpolate_pos
|
||||
self.timestep_shift = timestep_shift
|
||||
|
||||
|
||||
@@ -619,23 +668,32 @@ class Bagel(torch.nn.Module):
|
||||
config_class = BagelConfig
|
||||
base_model_prefix = "bagel"
|
||||
|
||||
def __init__(self, language_model, config: BagelConfig):
|
||||
def __init__(self, language_model, vit_model, config: BagelConfig):
|
||||
super().__init__()
|
||||
self.language_model = language_model
|
||||
self.hidden_size = config.llm_config.hidden_size
|
||||
self.use_moe = "Mo" in config.llm_config.layer_module
|
||||
self.num_heads = config.llm_config.num_attention_heads
|
||||
|
||||
self.latent_patch_size = config.latent_patch_size
|
||||
self.timestep_shift = config.timestep_shift
|
||||
self.latent_downsample = config.vae_config.downsample * config.latent_patch_size
|
||||
self.max_latent_size = config.max_latent_size
|
||||
self.latent_channel = config.vae_config.z_channels
|
||||
self.patch_latent_dim = self.latent_patch_size**2 * self.latent_channel
|
||||
self.time_embedder = TimestepEmbedder(self.hidden_size)
|
||||
self.vae2llm = nn.Linear(self.patch_latent_dim, self.hidden_size)
|
||||
self.llm2vae = nn.Linear(self.hidden_size, self.patch_latent_dim)
|
||||
self.latent_pos_embed = PositionEmbedding(self.max_latent_size, self.hidden_size)
|
||||
if config.visual_gen:
|
||||
self.latent_patch_size = config.latent_patch_size
|
||||
self.timestep_shift = config.timestep_shift
|
||||
self.latent_downsample = config.vae_config.downsample * config.latent_patch_size
|
||||
self.max_latent_size = config.max_latent_size
|
||||
self.latent_channel = config.vae_config.z_channels
|
||||
self.patch_latent_dim = self.latent_patch_size**2 * self.latent_channel
|
||||
self.time_embedder = TimestepEmbedder(self.hidden_size)
|
||||
self.vae2llm = nn.Linear(self.patch_latent_dim, self.hidden_size)
|
||||
self.llm2vae = nn.Linear(self.hidden_size, self.patch_latent_dim)
|
||||
self.latent_pos_embed = PositionEmbedding(self.max_latent_size, self.hidden_size)
|
||||
|
||||
if config.visual_und:
|
||||
self.vit_model = vit_model
|
||||
self.vit_patch_size = config.vit_config.patch_size
|
||||
self.vit_max_num_patch_per_side = config.vit_max_num_patch_per_side
|
||||
self.vit_hidden_size = config.vit_config.hidden_size
|
||||
self.connector = MLPconnector(self.vit_hidden_size, self.hidden_size, config.connector_act)
|
||||
self.vit_pos_embed = PositionEmbedding(self.vit_max_num_patch_per_side, self.hidden_size)
|
||||
|
||||
self.get_flattened_position_ids = get_flattened_position_ids_extrapolate
|
||||
|
||||
@@ -643,8 +701,9 @@ class Bagel(torch.nn.Module):
|
||||
self._init_weights()
|
||||
|
||||
def _init_weights(self):
|
||||
nn.init.constant_(self.llm2vae.weight, 0)
|
||||
nn.init.constant_(self.llm2vae.bias, 0)
|
||||
if self.config.visual_gen:
|
||||
nn.init.constant_(self.llm2vae.weight, 0)
|
||||
nn.init.constant_(self.llm2vae.bias, 0)
|
||||
|
||||
def prepare_prompts(self, curr_kvlens, curr_rope, prompts, tokenizer, new_token_ids):
|
||||
packed_text_ids = list()
|
||||
@@ -713,6 +772,261 @@ class Bagel(torch.nn.Module):
|
||||
|
||||
return past_key_values
|
||||
|
||||
def prepare_vae_images(self, curr_kvlens, curr_rope, images, transforms, new_token_ids, timestep=0):
|
||||
patchified_vae_latent_shapes, packed_vae_position_ids = list(), list()
|
||||
packed_vae_token_indexes = list()
|
||||
packed_text_ids, packed_text_indexes = list(), list()
|
||||
packed_seqlens, packed_position_ids, packed_indexes = list(), list(), list()
|
||||
packed_key_value_indexes = list()
|
||||
|
||||
_curr = curr = 0
|
||||
vae_image_tensors = list()
|
||||
newlens, new_rope = list(), list()
|
||||
for image, curr_kvlen, curr_position_id in zip(images, curr_kvlens, curr_rope):
|
||||
packed_key_value_indexes.extend(range(curr, curr + curr_kvlen))
|
||||
curr += curr_kvlen
|
||||
|
||||
packed_text_ids.append(new_token_ids["start_of_image"])
|
||||
packed_text_indexes.append(_curr)
|
||||
packed_indexes.append(curr)
|
||||
curr += 1
|
||||
_curr += 1
|
||||
|
||||
image_tensor = transforms(image)
|
||||
vae_image_tensors.append(image_tensor)
|
||||
vae_position_ids = self.get_flattened_position_ids(
|
||||
image_tensor.size(1),
|
||||
image_tensor.size(2),
|
||||
self.latent_downsample,
|
||||
max_num_patches_per_side=self.max_latent_size,
|
||||
)
|
||||
packed_vae_position_ids.append(vae_position_ids)
|
||||
H, W = image_tensor.shape[1:]
|
||||
h = H // self.latent_downsample
|
||||
w = W // self.latent_downsample
|
||||
patchified_vae_latent_shapes.append((h, w))
|
||||
|
||||
num_img_tokens = w * h
|
||||
packed_vae_token_indexes.extend(range(_curr, _curr + num_img_tokens))
|
||||
packed_indexes.extend(range(curr, curr + num_img_tokens))
|
||||
curr += num_img_tokens
|
||||
_curr += num_img_tokens
|
||||
|
||||
packed_text_ids.append(new_token_ids["end_of_image"])
|
||||
packed_text_indexes.append(_curr)
|
||||
packed_indexes.append(curr)
|
||||
curr += 1
|
||||
_curr += 1
|
||||
|
||||
packed_position_ids.extend([curr_position_id] * (num_img_tokens + 2))
|
||||
packed_seqlens.append(num_img_tokens + 2)
|
||||
newlens.append(curr_kvlen + num_img_tokens + 2)
|
||||
new_rope.append(curr_position_id + 1)
|
||||
|
||||
image_sizes = [item.shape for item in vae_image_tensors]
|
||||
max_image_size = [max(item) for item in list(zip(*image_sizes))]
|
||||
padded_images = torch.zeros(size=(len(vae_image_tensors), *max_image_size))
|
||||
for i, image_tensor in enumerate(vae_image_tensors):
|
||||
padded_images[i, :, : image_tensor.shape[1], : image_tensor.shape[2]] = image_tensor
|
||||
|
||||
generation_input = {
|
||||
"padded_images": padded_images,
|
||||
"patchified_vae_latent_shapes": patchified_vae_latent_shapes,
|
||||
"packed_vae_position_ids": torch.cat(packed_vae_position_ids, dim=0),
|
||||
"packed_timesteps": torch.tensor([timestep]),
|
||||
"packed_vae_token_indexes": torch.tensor(packed_vae_token_indexes, dtype=torch.long),
|
||||
"packed_text_ids": torch.tensor(packed_text_ids, dtype=torch.long),
|
||||
"packed_text_indexes": torch.tensor(packed_text_indexes, dtype=torch.long),
|
||||
"packed_position_ids": torch.tensor(packed_position_ids, dtype=torch.long),
|
||||
"packed_seqlens": torch.tensor(packed_seqlens, dtype=torch.int),
|
||||
"packed_indexes": torch.tensor(packed_indexes, dtype=torch.long),
|
||||
"packed_key_value_indexes": torch.tensor(packed_key_value_indexes, dtype=torch.long),
|
||||
"key_values_lens": torch.tensor(curr_kvlens, dtype=torch.int),
|
||||
}
|
||||
|
||||
return generation_input, newlens, new_rope
|
||||
|
||||
@torch.no_grad
|
||||
def forward_cache_update_vae(
|
||||
self,
|
||||
vae_model,
|
||||
past_key_values: NaiveCache,
|
||||
padded_images: torch.Tensor,
|
||||
patchified_vae_latent_shapes: list,
|
||||
packed_vae_position_ids: torch.LongTensor,
|
||||
packed_timesteps: torch.Tensor,
|
||||
packed_vae_token_indexes: torch.LongTensor,
|
||||
packed_text_ids: torch.LongTensor,
|
||||
packed_text_indexes: torch.LongTensor,
|
||||
packed_position_ids: torch.LongTensor,
|
||||
packed_seqlens: torch.IntTensor,
|
||||
packed_indexes: torch.LongTensor,
|
||||
key_values_lens: torch.IntTensor,
|
||||
packed_key_value_indexes: torch.Tensor,
|
||||
):
|
||||
packed_text_embedding = self.language_model.model.embed_tokens(packed_text_ids)
|
||||
packed_sequence = packed_text_embedding.new_zeros((sum(packed_seqlens), self.hidden_size))
|
||||
packed_sequence[packed_text_indexes] = packed_text_embedding
|
||||
|
||||
padded_latent = vae_model.encode(padded_images)
|
||||
|
||||
p = self.latent_patch_size
|
||||
packed_latent = list()
|
||||
for latent, (h, w) in zip(padded_latent, patchified_vae_latent_shapes):
|
||||
latent = latent[:, : h * p, : w * p].reshape(self.latent_channel, h, p, w, p)
|
||||
latent = torch.einsum("chpwq->hwpqc", latent).reshape(-1, p * p * self.latent_channel)
|
||||
packed_latent.append(latent)
|
||||
packed_latent = torch.cat(packed_latent, dim=0)
|
||||
packed_pos_embed = self.latent_pos_embed(packed_vae_position_ids)
|
||||
packed_timestep_embeds = self.time_embedder(packed_timesteps)
|
||||
packed_latent = self.vae2llm(packed_latent) + packed_timestep_embeds + packed_pos_embed
|
||||
if packed_latent.dtype != packed_sequence.dtype:
|
||||
packed_latent = packed_latent.to(packed_sequence.dtype)
|
||||
packed_sequence[packed_vae_token_indexes] = packed_latent
|
||||
|
||||
extra_inputs = {}
|
||||
if self.use_moe:
|
||||
extra_inputs = {
|
||||
"mode": "gen",
|
||||
"packed_vae_token_indexes": packed_vae_token_indexes,
|
||||
"packed_text_indexes": packed_text_indexes,
|
||||
}
|
||||
|
||||
output = self.language_model.forward(
|
||||
packed_query_sequence=packed_sequence,
|
||||
query_lens=packed_seqlens,
|
||||
packed_query_position_ids=packed_position_ids,
|
||||
packed_query_indexes=packed_indexes,
|
||||
past_key_values=past_key_values,
|
||||
key_values_lens=key_values_lens,
|
||||
packed_key_value_indexes=packed_key_value_indexes,
|
||||
update_past_key_values=True,
|
||||
is_causal=False,
|
||||
**extra_inputs,
|
||||
)
|
||||
past_key_values = output.past_key_values
|
||||
|
||||
return past_key_values
|
||||
|
||||
def prepare_vit_images(self, curr_kvlens, curr_rope, images, transforms, new_token_ids):
|
||||
packed_vit_token_indexes = list()
|
||||
vit_token_seqlens, packed_vit_tokens, packed_vit_position_ids = list(), list(), list()
|
||||
packed_text_ids, packed_text_indexes = list(), list()
|
||||
packed_seqlens, packed_position_ids, packed_indexes = list(), list(), list()
|
||||
packed_key_value_indexes = list()
|
||||
|
||||
_curr = curr = 0
|
||||
newlens, new_rope = list(), list()
|
||||
for image, curr_kvlen, curr_position_id in zip(images, curr_kvlens, curr_rope):
|
||||
packed_key_value_indexes.extend(range(curr, curr + curr_kvlen))
|
||||
curr += curr_kvlen
|
||||
|
||||
packed_text_ids.append(new_token_ids["start_of_image"])
|
||||
packed_text_indexes.append(_curr)
|
||||
packed_indexes.append(curr)
|
||||
curr += 1
|
||||
_curr += 1
|
||||
|
||||
image_tensor = transforms(image)
|
||||
vit_position_ids = self.get_flattened_position_ids(
|
||||
image_tensor.size(1),
|
||||
image_tensor.size(2),
|
||||
self.vit_patch_size,
|
||||
max_num_patches_per_side=self.vit_max_num_patch_per_side,
|
||||
)
|
||||
vit_tokens = patchify(image_tensor, self.vit_patch_size)
|
||||
packed_vit_tokens.append(vit_tokens)
|
||||
num_img_tokens = vit_tokens.shape[0]
|
||||
packed_vit_position_ids.append(vit_position_ids)
|
||||
vit_token_seqlens.append(num_img_tokens)
|
||||
packed_vit_token_indexes.extend(range(_curr, _curr + num_img_tokens))
|
||||
packed_indexes.extend(range(curr, curr + num_img_tokens))
|
||||
curr += num_img_tokens
|
||||
_curr += num_img_tokens
|
||||
|
||||
packed_text_ids.append(new_token_ids["end_of_image"])
|
||||
packed_text_indexes.append(_curr)
|
||||
packed_indexes.append(curr)
|
||||
curr += 1
|
||||
_curr += 1
|
||||
|
||||
packed_position_ids.extend([curr_position_id] * (num_img_tokens + 2))
|
||||
packed_seqlens.append(num_img_tokens + 2)
|
||||
newlens.append(curr_kvlen + num_img_tokens + 2)
|
||||
new_rope.append(curr_position_id + 1)
|
||||
|
||||
generation_input = {
|
||||
"packed_text_ids": torch.tensor(packed_text_ids, dtype=torch.long),
|
||||
"packed_text_indexes": torch.tensor(packed_text_indexes, dtype=torch.long),
|
||||
"vit_token_seqlens": torch.tensor(vit_token_seqlens, dtype=torch.int),
|
||||
"packed_vit_tokens": torch.cat(packed_vit_tokens, dim=0),
|
||||
"packed_vit_position_ids": torch.cat(packed_vit_position_ids, dim=0),
|
||||
"packed_vit_token_indexes": torch.tensor(packed_vit_token_indexes, dtype=torch.long),
|
||||
"packed_position_ids": torch.tensor(packed_position_ids, dtype=torch.long),
|
||||
"packed_seqlens": torch.tensor(packed_seqlens, dtype=torch.int),
|
||||
"packed_indexes": torch.tensor(packed_indexes, dtype=torch.long),
|
||||
"packed_key_value_indexes": torch.tensor(packed_key_value_indexes, dtype=torch.long),
|
||||
"key_values_lens": torch.tensor(curr_kvlens, dtype=torch.int),
|
||||
}
|
||||
|
||||
return generation_input, newlens, new_rope
|
||||
|
||||
@torch.no_grad
|
||||
def forward_cache_update_vit(
|
||||
self,
|
||||
past_key_values: NaiveCache,
|
||||
packed_text_ids: torch.LongTensor,
|
||||
packed_text_indexes: torch.LongTensor,
|
||||
packed_vit_tokens: torch.Tensor,
|
||||
packed_vit_token_indexes: torch.LongTensor,
|
||||
packed_vit_position_ids: torch.LongTensor,
|
||||
vit_token_seqlens: torch.IntTensor,
|
||||
packed_position_ids: torch.LongTensor,
|
||||
packed_seqlens: torch.IntTensor,
|
||||
packed_indexes: torch.LongTensor,
|
||||
packed_key_value_indexes: torch.LongTensor,
|
||||
key_values_lens: torch.IntTensor,
|
||||
):
|
||||
packed_text_embedding = self.language_model.model.embed_tokens(packed_text_ids)
|
||||
packed_sequence = packed_text_embedding.new_zeros((sum(packed_seqlens), self.hidden_size))
|
||||
packed_sequence[packed_text_indexes] = packed_text_embedding
|
||||
|
||||
cu_seqlens = torch.nn.functional.pad(torch.cumsum(vit_token_seqlens, dim=0), (1, 0))
|
||||
cu_seqlens = cu_seqlens.to(torch.int32)
|
||||
max_seqlen = torch.max(vit_token_seqlens).item()
|
||||
packed_vit_token_embed = self.vit_model(
|
||||
packed_pixel_values=packed_vit_tokens,
|
||||
packed_flattened_position_ids=packed_vit_position_ids,
|
||||
cu_seqlens=cu_seqlens,
|
||||
max_seqlen=max_seqlen,
|
||||
)
|
||||
packed_vit_token_embed = self.connector(packed_vit_token_embed)
|
||||
pos_emb = self.vit_pos_embed(packed_vit_position_ids)
|
||||
packed_vit_token_embed = packed_vit_token_embed + pos_emb
|
||||
if packed_vit_token_embed.dtype != packed_sequence.dtype:
|
||||
packed_vit_token_embed = packed_vit_token_embed.to(packed_sequence.dtype)
|
||||
packed_sequence[packed_vit_token_indexes] = packed_vit_token_embed
|
||||
|
||||
extra_inputs = {}
|
||||
if self.use_moe:
|
||||
extra_inputs = {"mode": "und"}
|
||||
|
||||
output = self.language_model.forward(
|
||||
packed_query_sequence=packed_sequence,
|
||||
query_lens=packed_seqlens,
|
||||
packed_query_position_ids=packed_position_ids,
|
||||
packed_query_indexes=packed_indexes,
|
||||
past_key_values=past_key_values,
|
||||
packed_key_value_indexes=packed_key_value_indexes,
|
||||
key_values_lens=key_values_lens,
|
||||
update_past_key_values=True,
|
||||
is_causal=False,
|
||||
**extra_inputs,
|
||||
)
|
||||
past_key_values = output.past_key_values
|
||||
|
||||
return past_key_values
|
||||
|
||||
def prepare_input(self, curr_kvlens, curr_rope, image_sizes, new_token_ids=None):
|
||||
packed_text_ids, packed_text_indexes = list(), list()
|
||||
packed_vae_position_ids, packed_vae_token_indexes, packed_init_noises = list(), list(), list()
|
||||
|
||||
@@ -12,10 +12,12 @@ from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from math import isqrt
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
from PIL import Image
|
||||
from torch import nn
|
||||
from transformers import AutoTokenizer
|
||||
from transformers import AutoTokenizer, SiglipImageProcessor, SiglipVisionConfig, SiglipVisionModel
|
||||
from vllm.logger import init_logger
|
||||
from vllm.model_executor.models.utils import AutoWeightsLoader
|
||||
|
||||
@@ -89,6 +91,12 @@ class _VaeCfg:
|
||||
downsample: int = 8
|
||||
|
||||
|
||||
@dataclass
|
||||
class _VitCfg:
|
||||
patch_size: int = 14
|
||||
hidden_size: int = 1152
|
||||
|
||||
|
||||
def default_ae_params() -> AutoEncoderParams:
|
||||
return AutoEncoderParams(
|
||||
resolution=256,
|
||||
@@ -104,6 +112,37 @@ def default_ae_params() -> AutoEncoderParams:
|
||||
)
|
||||
|
||||
|
||||
class SiglipNaViTWrapper(nn.Module):
|
||||
def __init__(self, vision_model):
|
||||
super().__init__()
|
||||
# If input is SiglipVisionModel, unwrap it to get SiglipVisionTransformer
|
||||
if hasattr(vision_model, "vision_model"):
|
||||
self.vision_model = vision_model.vision_model
|
||||
else:
|
||||
self.vision_model = vision_model
|
||||
|
||||
# Configure weights for linear equivalent of patch embedding
|
||||
self.patch_embed_weight = self.vision_model.embeddings.patch_embedding.weight
|
||||
self.patch_embed_bias = self.vision_model.embeddings.patch_embedding.bias
|
||||
|
||||
def forward(self, packed_pixel_values, packed_flattened_position_ids, cu_seqlens, max_seqlen):
|
||||
w = self.patch_embed_weight.view(self.patch_embed_weight.shape[0], -1)
|
||||
x = F.linear(packed_pixel_values, w, self.patch_embed_bias)
|
||||
pos = self.vision_model.embeddings.position_embedding(packed_flattened_position_ids)
|
||||
x = x + pos
|
||||
hidden_states = x.unsqueeze(0)
|
||||
seq_len = x.shape[0]
|
||||
mask = torch.full((1, 1, seq_len, seq_len), torch.finfo(x.dtype).min, device=x.device, dtype=x.dtype)
|
||||
cu_seqlens_list = cu_seqlens.tolist()
|
||||
for i in range(len(cu_seqlens_list) - 1):
|
||||
start = cu_seqlens_list[i]
|
||||
end = cu_seqlens_list[i + 1]
|
||||
mask[..., start:end, start:end] = 0.0
|
||||
|
||||
outputs = self.vision_model.encoder(inputs_embeds=hidden_states, attention_mask=mask)
|
||||
return outputs.last_hidden_state.squeeze(0)
|
||||
|
||||
|
||||
class BagelPipeline(nn.Module):
|
||||
"""Bagel generation pipeline (MoT) packaged for vllm-omni diffusion engine.
|
||||
|
||||
@@ -150,12 +189,26 @@ class BagelPipeline(nn.Module):
|
||||
local_files_only=True,
|
||||
trust_remote_code=True,
|
||||
)
|
||||
|
||||
# Try finding vision_config or interpolate from top-level config
|
||||
vit_cfg_dict = bagel_cfg.get("vit_config") or {}
|
||||
vit_cfg = _VitCfg(
|
||||
patch_size=int(vit_cfg_dict.get("patch_size", 14)),
|
||||
hidden_size=int(vit_cfg_dict.get("hidden_size", 1152)),
|
||||
)
|
||||
vit_config_path = os.path.join(model_path, "vit_config.json")
|
||||
vit_conf = SiglipVisionConfig.from_json_file(vit_config_path)
|
||||
self.vit_model = SiglipVisionModel(vit_conf)
|
||||
self.image_processor = SiglipImageProcessor.from_pretrained(model_path, local_files_only=True)
|
||||
|
||||
if self.vit_model:
|
||||
self.vit_model = SiglipNaViTWrapper(self.vit_model)
|
||||
vit_cfg.hidden_size = self.vit_model.vision_model.config.hidden_size
|
||||
vit_cfg.patch_size = self.vit_model.vision_model.config.patch_size
|
||||
|
||||
self.tokenizer, self.new_token_ids, _ = add_special_tokens(self.tokenizer)
|
||||
|
||||
try:
|
||||
tok_len = len(self.tokenizer)
|
||||
except Exception: # pragma: no cover - very old tokenizers
|
||||
tok_len = getattr(self.tokenizer, "vocab_size", llm_config.vocab_size)
|
||||
tok_len = len(self.tokenizer)
|
||||
required_max_id = max(int(v) for v in self.new_token_ids.values())
|
||||
llm_config.vocab_size = max(
|
||||
int(getattr(llm_config, "vocab_size", tok_len)),
|
||||
@@ -169,9 +222,14 @@ class BagelPipeline(nn.Module):
|
||||
|
||||
self.bagel = Bagel(
|
||||
language_model=self.language_model,
|
||||
vit_model=self.vit_model,
|
||||
config=BagelConfig(
|
||||
llm_config=llm_config,
|
||||
vae_config=vae_cfg,
|
||||
vit_config=vit_cfg,
|
||||
vit_max_num_patch_per_side=int(bagel_cfg.get("vit_max_num_patch_per_side", 70)),
|
||||
connector_act=str(bagel_cfg.get("connector_act", "gelu_pytorch_tanh")),
|
||||
interpolate_pos=bool(bagel_cfg.get("interpolate_pos", False)),
|
||||
latent_patch_size=int(bagel_cfg.get("latent_patch_size", 2)),
|
||||
max_latent_size=int(bagel_cfg.get("max_latent_size", 32)),
|
||||
timestep_shift=float(bagel_cfg.get("timestep_shift", 1.0)),
|
||||
@@ -248,6 +306,69 @@ class BagelPipeline(nn.Module):
|
||||
injected_kv = getattr(req, "past_key_values", None)
|
||||
injected_metadata = getattr(req, "kv_metadata", None)
|
||||
|
||||
# Image input handling
|
||||
image_input = getattr(req, "pil_image", None)
|
||||
if image_input and not isinstance(image_input, list):
|
||||
image_input = [image_input]
|
||||
|
||||
if image_input:
|
||||
# If we have an image, we prefill with it
|
||||
if self.image_processor and self.vae:
|
||||
|
||||
def vit_transforms(img):
|
||||
# SigLIP processor returns dict with pixel_values; we want the tensor
|
||||
return self.image_processor(images=img, return_tensors="pt").pixel_values[0]
|
||||
|
||||
def vae_transforms(img):
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
# Convert to [-1, 1] tensor (H, W, C) -> (C, H, W)
|
||||
arr = torch.from_numpy(np.array(img)).float() / 127.5 - 1.0
|
||||
return arr.permute(2, 0, 1)
|
||||
|
||||
# 1. Update VAE
|
||||
gen_input_vae, newlens_vae, new_rope_vae = self.bagel.prepare_vae_images(
|
||||
curr_kvlens=gen_context["kv_lens"],
|
||||
curr_rope=gen_context["ropes"],
|
||||
images=image_input,
|
||||
transforms=vae_transforms,
|
||||
new_token_ids=self.new_token_ids,
|
||||
)
|
||||
|
||||
for k, v in gen_input_vae.items():
|
||||
if torch.is_tensor(v):
|
||||
gen_input_vae[k] = v.to(self.device)
|
||||
|
||||
# VAE needs bfloat16 to match model strings usually, specifically encode
|
||||
with torch.autocast(device_type="cuda", enabled=self.device.type == "cuda", dtype=torch.bfloat16):
|
||||
gen_context["past_key_values"] = self.bagel.forward_cache_update_vae(
|
||||
self.vae, gen_context["past_key_values"], **gen_input_vae
|
||||
)
|
||||
gen_context["kv_lens"] = newlens_vae
|
||||
gen_context["ropes"] = new_rope_vae
|
||||
|
||||
# 2. Update ViT
|
||||
gen_input_img, newlens_img, new_rope_img = self.bagel.prepare_vit_images(
|
||||
curr_kvlens=gen_context["kv_lens"],
|
||||
curr_rope=gen_context["ropes"],
|
||||
images=image_input,
|
||||
transforms=vit_transforms,
|
||||
new_token_ids=self.new_token_ids,
|
||||
)
|
||||
|
||||
for k, v in gen_input_img.items():
|
||||
if torch.is_tensor(v):
|
||||
gen_input_img[k] = v.to(self.device)
|
||||
|
||||
with torch.autocast(device_type="cuda", enabled=self.device.type == "cuda", dtype=torch.bfloat16):
|
||||
gen_context["past_key_values"] = self.bagel.forward_cache_update_vit(
|
||||
gen_context["past_key_values"], **gen_input_img
|
||||
)
|
||||
gen_context["kv_lens"] = newlens_img
|
||||
gen_context["ropes"] = new_rope_img
|
||||
else:
|
||||
logger.warning("Image provided but no image processor available.")
|
||||
|
||||
if injected_kv is not None and injected_metadata is not None:
|
||||
logger.info("Using injected KV Cache from remote transfer")
|
||||
|
||||
@@ -409,6 +530,19 @@ class BagelPipeline(nn.Module):
|
||||
yield "bagel." + n
|
||||
break
|
||||
|
||||
# Map connector and vit_pos_embed to `bagel.*`
|
||||
for pfx in ("connector.", "vit_pos_embed."):
|
||||
if n.startswith(pfx):
|
||||
yield "bagel." + n
|
||||
break
|
||||
|
||||
if n.startswith("vit_model."):
|
||||
yield "bagel." + n # matches self.bagel.vit_model
|
||||
elif n.startswith("vision_model."):
|
||||
yield "bagel.vit_model." + n
|
||||
elif n.startswith("model.vision_model."):
|
||||
yield "bagel.vit_model." + n[len("model.") :]
|
||||
|
||||
def _filtered_weights():
|
||||
total = 0
|
||||
kept = 0
|
||||
@@ -439,6 +573,17 @@ class BagelPipeline(nn.Module):
|
||||
shapes[cand] = (npos, hdim)
|
||||
picked = cand
|
||||
break
|
||||
# Handle flattened patch embedding for SigLIP
|
||||
if cand.endswith("embeddings.patch_embedding.weight") and tensor.ndim == 2:
|
||||
# Checkpoint has (Hidden, C*P*P), model expects (Hidden, C, P, P)
|
||||
if shapes.get(cand) is not None:
|
||||
target_shape = shapes[cand]
|
||||
if tensor.numel() == torch.prod(torch.tensor(target_shape)):
|
||||
# Reshape tensor to match target
|
||||
tensor = tensor.view(target_shape)
|
||||
picked = cand
|
||||
break
|
||||
|
||||
shape_mismatch += 1
|
||||
# Keep this quiet; shape mismatches are expected for ignored modules.
|
||||
if picked is not None:
|
||||
|
||||
Reference in new issue
Block a user