NLD-Uni / padding.py
gheinrich's picture
Release NLD-Uni
300c478
Raw History Blame Contribute Delete
5.91 kB
from __future__ import annotations
import numpy as np
import torch
def resolve_source_padding_vq_lock(model_config, override=None, *, has_edit_image):
if not isinstance(has_edit_image, bool):
raise TypeError('has_edit_image must be boolean')
if override is None:
resolved = getattr(model_config, 'lock_source_padding_vq', False)
if resolved is None:
resolved = False
if not isinstance(resolved, bool):
raise TypeError('config.lock_source_padding_vq must be boolean or null')
if resolved and (not has_edit_image):
return False
return resolved
if not isinstance(override, bool):
raise TypeError('lock_source_padding_vq override must be boolean or null')
if override and (not has_edit_image):
raise ValueError('lock_source_padding_vq requires an edit_image')
return override
def _resolve_source_native_size(value, *, fallback):
resolved = fallback if value is None else value
if not isinstance(resolved, (tuple, list)) or len(resolved) != 2 or any((isinstance(item, bool) or not isinstance(item, (int, np.integer)) or int(item) < 1 for item in resolved)):
raise ValueError('edit_source_native_size must contain positive integer width and height')
return (int(resolved[0]), int(resolved[1]))
def _source_padding_vq_mask(source_native_size, raw_grid_shape, *, device):
(width, height) = _resolve_source_native_size(source_native_size, fallback=source_native_size)
if not isinstance(raw_grid_shape, (tuple, list)) or len(raw_grid_shape) != 2 or any((isinstance(item, bool) or not isinstance(item, (int, np.integer)) or int(item) < 1 for item in raw_grid_shape)):
raise ValueError('raw_grid_shape must contain positive integer height and width')
(grid_height, grid_width) = (int(value) for value in raw_grid_shape)
if grid_height != grid_width:
raise ValueError('source-padding VQ locking requires a square raw VQ grid')
side = max(width, height)
left = round((side - width) * 0.5)
top = round((side - height) * 0.5)
right = left + width
bottom = top + height
columns = torch.arange(grid_width, dtype=torch.long, device=device)
rows = torch.arange(grid_height, dtype=torch.long, device=device)
horizontally_outside = ((columns + 1) * side <= left * grid_width) | (columns * side >= right * grid_width)
vertically_outside = ((rows + 1) * side <= top * grid_height) | (rows * side >= bottom * grid_height)
return (vertically_outside[:, None] | horizontally_outside[None, :]).reshape(1, -1)
def _augment_source_padding_vq_mask(state, raw_padding_mask, content_positions):
if not torch.is_tensor(state) or state.ndim != 2:
raise ValueError('generation state must have shape [batch, tokens]')
if not torch.is_tensor(raw_padding_mask) or raw_padding_mask.dtype is not torch.bool or raw_padding_mask.ndim != 2 or (raw_padding_mask.shape[0] != state.shape[0]) or (raw_padding_mask.device != state.device):
raise TypeError('raw_padding_mask must be device-local bool with the state batch size')
if not torch.is_tensor(content_positions) or content_positions.ndim != 1 or content_positions.dtype is not torch.long or (content_positions.device != state.device) or (content_positions.numel() != raw_padding_mask.shape[1]):
raise TypeError('content_positions must be a device-local long vector covering raw cells')
if bool((content_positions < 0).any()) or bool((content_positions >= state.shape[1]).any()):
raise ValueError('content_positions contains an out-of-range state index')
locked_mask = torch.zeros_like(state, dtype=torch.bool)
locked_mask[:, content_positions] = raw_padding_mask
return locked_mask
def _prefill_source_padding_vq(state, source_codes, raw_padding_mask, content_positions):
if not torch.is_tensor(state) or state.ndim != 2:
raise ValueError('generation state must have shape [batch, tokens]')
if not torch.is_tensor(source_codes) or source_codes.ndim != 2 or source_codes.dtype != state.dtype or (source_codes.device != state.device):
raise TypeError('source_codes must match the state integer dtype and device')
if source_codes.shape != raw_padding_mask.shape:
raise TypeError('raw_padding_mask must be bool and match source_codes')
locked_mask = _augment_source_padding_vq_mask(state, raw_padding_mask, content_positions)
locked_codes = torch.zeros_like(state)
locked_codes[:, content_positions] = source_codes
prefilled = state.clone()
prefilled[locked_mask] = locked_codes[locked_mask]
return (prefilled, locked_mask, locked_codes)
def _restore_source_padding_vq(state, locked_mask, locked_codes):
if locked_mask is None:
return state
if not torch.is_tensor(state) or state.ndim != 2 or (not torch.is_tensor(locked_mask)) or (locked_mask.dtype is not torch.bool) or (locked_mask.shape != state.shape) or (locked_mask.device != state.device) or (not torch.is_tensor(locked_codes)) or (locked_codes.shape != state.shape) or (locked_codes.dtype != state.dtype) or (locked_codes.device != state.device):
raise TypeError('locked source-padding tensors must align with sampler state')
restored = state.clone()
restored[locked_mask] = locked_codes[locked_mask]
return restored
def _assert_source_padding_vq_locked(state, locked_mask, locked_codes):
if locked_mask is None:
return
if not torch.is_tensor(locked_mask) or locked_mask.dtype is not torch.bool or locked_mask.shape != state.shape or (not torch.is_tensor(locked_codes)) or (locked_codes.shape != state.shape):
raise TypeError('locked source-padding tensors must align with sampler state')
if not torch.equal(state[locked_mask], locked_codes[locked_mask]):
raise RuntimeError('a locked source-padding VQ code changed during sampling')