lip-forcing / lipforcing /utils /__init__.py
multimodalart's picture
multimodalart HF Staff
Initial Lip Forcing 14B streaming demo
9368ee7 verified
Raw
History Blame Contribute Delete
5.54 kB
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# -----------------------------------------------------------------------------
# Copyright (c) Facebook, Inc. and its affiliates.
#
# See licenses/detectron2/LICENSE for more details.
# -----------------------------------------------------------------------------
from collections import abc
from omegaconf import DictConfig, ListConfig
from dataclasses import is_dataclass
import torch
import contextlib
from lipforcing.utils.registry import locate, _convert_target_to_string
import lipforcing.utils.logging_utils as logger
from lipforcing.utils import global_vars
def expand_like(x: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
"""Expands the input tensor `x` to have the same
number of dimensions as the `target` tensor.
Pads `x` with singleton dimensions on the end.
# Example
```
x = torch.ones(5)
target = torch.ones(5, 10, 30, 1, 10)
x = expand_like(x, target)
print(x.shape) # <- [5, 1, 1, 1, 1]
```
Args:
x (torch.Tensor): The input tensor to expand.
target (torch.Tensor): The target tensor whose shape length
will be matched.
Returns:
torch.Tensor: The expanded tensor `x` with trailing singleton
dimensions.
"""
x = torch.atleast_1d(x)
while len(x.shape) < len(target.shape):
x = x[..., None]
return x
def instantiate(cfg, *args, **kwargs):
"""
Recursively instantiate objects defined in dictionaries by
"_target_" and arguments.
Args:
cfg: a dict-like object with "_target_" that defines the caller, and
other keys that define the arguments
Returns:
object instantiated by cfg
"""
if isinstance(cfg, ListConfig):
lst = [instantiate(x) for x in cfg]
return ListConfig(lst, flags={"allow_objects": True})
if isinstance(cfg, list):
# Specialize for list, because many classes take
# list[objects] as arguments, such as ResNet, DatasetMapper
return [instantiate(x) for x in cfg]
if isinstance(cfg, abc.Mapping) and "_target_" in cfg:
# conceptually equivalent to hydra.utils.instantiate(cfg) with _convert_=all,
# but faster: https://github.com/facebookresearch/hydra/issues/1200
cfg = {k: instantiate(v) for k, v in cfg.items()}
cls = cfg.pop("_target_")
cls = instantiate(cls)
if isinstance(cls, str):
cls_name = cls
cls = locate(cls_name)
assert cls is not None, cls_name
else:
try:
cls_name = cls.__module__ + "." + cls.__qualname__
except Exception:
# target could be anything, so the above could fail
cls_name = str(cls)
assert callable(cls), f"_target_ {cls} does not define a callable object"
try:
additional_kwargs = {}
additional_kwargs.update(cfg)
additional_kwargs.update(kwargs)
return cls(*args, **additional_kwargs)
except TypeError:
logger.error(f"Error when instantiating {cls_name}!")
raise
return cfg # return as-is if don't know what to do
class LazyCall:
"""
Wrap a callable so that when it's called, the call will not be executed,
but returns a dict that describes the call.
LazyCall object has to be called with only keyword arguments. Positional
arguments are not yet supported.
Examples:
::
from lipforcing.utils import instantiate, LazyCall
layer_cfg = LazyCall(nn.Conv2d)(in_channels=32, out_channels=32)
layer_cfg.out_channels = 64 # can edit it afterwards
layer = instantiate(layer_cfg)
"""
def __init__(self, target):
if not (callable(target) or isinstance(target, (str, abc.Mapping))):
raise TypeError(f"target of LazyCall must be a callable or defines a callable! Got {target}")
self._target = target
def __call__(self, **kwargs):
if is_dataclass(self._target):
# omegaconf object cannot hold dataclass type
# https://github.com/omry/omegaconf/issues/784
target = _convert_target_to_string(self._target)
else:
target = self._target
kwargs["_target_"] = target
return DictConfig(content=kwargs, flags={"allow_objects": True})
def set_global_vars(config: dict | DictConfig | None = None):
config = config or {}
# update all keys that exist in global_vars
update_config = {k: v for k, v in config.items() if k in global_vars.__all__}
logger.debug(f"Setting global variables {update_config}")
global_vars.__dict__.update(update_config)
# log keys that do not exist in global_vars
ignore_keys = [k for k in config.keys() if k not in global_vars.__all__]
if len(ignore_keys) > 0:
logger.warning(f"Ignoring keys {ignore_keys} since they are not found in global_vars.")
@contextlib.contextmanager
def set_temp_global_vars(config):
# Handle string "None" from command line parsing
if config == "None":
config = None
original_global_vars = {k: global_vars.__dict__[k] for k in global_vars.__all__}
try:
set_global_vars(config)
yield
finally:
logger.debug(f"Resetting global variables to {original_global_vars}")
global_vars.__dict__.update(original_global_vars)