ffgs 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ffgs/__init__.py +39 -0
- ffgs/dynamic.py +239 -0
- ffgs/geometry.py +418 -0
- ffgs/image.py +204 -0
- ffgs/models/__init__.py +2 -0
- ffgs/models/anysplat/LICENSE +1120 -0
- ffgs/models/anysplat/__init__.py +49 -0
- ffgs/models/anysplat/encoder.py +372 -0
- ffgs/models/anysplat/evaluation.py +98 -0
- ffgs/models/anysplat/gaussian_adapter.py +96 -0
- ffgs/models/anysplat/gs_head.py +166 -0
- ffgs/models/anysplat/modeling.py +95 -0
- ffgs/models/anysplat/processing.py +249 -0
- ffgs/models/anysplat/vggt/__init__.py +0 -0
- ffgs/models/anysplat/vggt/heads/__init__.py +0 -0
- ffgs/models/anysplat/vggt/heads/camera_head.py +181 -0
- ffgs/models/anysplat/vggt/heads/dpt_head.py +612 -0
- ffgs/models/anysplat/vggt/heads/head_act.py +134 -0
- ffgs/models/anysplat/vggt/heads/utils.py +126 -0
- ffgs/models/anysplat/vggt/layers/__init__.py +28 -0
- ffgs/models/anysplat/vggt/layers/attention.py +92 -0
- ffgs/models/anysplat/vggt/layers/block.py +157 -0
- ffgs/models/anysplat/vggt/layers/drop_path.py +42 -0
- ffgs/models/anysplat/vggt/layers/layer_scale.py +32 -0
- ffgs/models/anysplat/vggt/layers/mlp.py +45 -0
- ffgs/models/anysplat/vggt/layers/patch_embed.py +106 -0
- ffgs/models/anysplat/vggt/layers/rope.py +211 -0
- ffgs/models/anysplat/vggt/layers/swiglu_ffn.py +77 -0
- ffgs/models/anysplat/vggt/layers/vision_transformer.py +463 -0
- ffgs/models/anysplat/vggt/models/__init__.py +0 -0
- ffgs/models/anysplat/vggt/models/aggregator.py +398 -0
- ffgs/models/anysplat/vggt/utils/__init__.py +0 -0
- ffgs/models/anysplat/vggt/utils/geometry.py +230 -0
- ffgs/models/anysplat/vggt/utils/pose_enc.py +144 -0
- ffgs/models/anysplat/vggt/utils/rotation.py +148 -0
- ffgs/models/tokengs/__init__.py +43 -0
- ffgs/models/tokengs/activations.py +135 -0
- ffgs/models/tokengs/attention.py +189 -0
- ffgs/models/tokengs/enc_dec.py +323 -0
- ffgs/models/tokengs/modeling.py +173 -0
- ffgs/models/tokengs/processing.py +339 -0
- ffgs/pipeline.py +341 -0
- ffgs/processor.py +236 -0
- ffgs/registry.py +132 -0
- ffgs/render.py +111 -0
- ffgs/types.py +291 -0
- ffgs/zoo/__init__.py +234 -0
- ffgs/zoo/anysplat/default.json +34 -0
- ffgs/zoo/tokengs/dl3dv-2v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-4v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-6v.json +29 -0
- ffgs/zoo/tokengs/dl3dv-base.json +29 -0
- ffgs/zoo/tokengs/dl3dv-latent-2v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-2v-ssim.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-4v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-4v-ssim.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-6v-lpips.json +48 -0
- ffgs/zoo/tokengs/dl3dv-latent-6v-ssim.json +48 -0
- ffgs-0.1.0.dev0.dist-info/METADATA +320 -0
- ffgs-0.1.0.dev0.dist-info/RECORD +63 -0
- ffgs-0.1.0.dev0.dist-info/WHEEL +4 -0
- ffgs-0.1.0.dev0.dist-info/licenses/LICENSE +237 -0
- ffgs-0.1.0.dev0.dist-info/licenses/src/ffgs/models/anysplat/LICENSE +1120 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the Apache License, Version 2.0
|
|
4
|
+
# found in the LICENSE file in the root directory of this source tree.
|
|
5
|
+
#
|
|
6
|
+
# Modified by the libgs contributors, 2026, from
|
|
7
|
+
# src/model/encoder/vggt/layers/patch_embed.py of
|
|
8
|
+
# https://github.com/InternRobotics/AnySplat (5f5e208): formatted with black, unused
|
|
9
|
+
# imports removed.
|
|
10
|
+
# Apache License 2.0: see the Apache-2.0 text in LICENSE (this directory).
|
|
11
|
+
|
|
12
|
+
# References:
|
|
13
|
+
# https://github.com/facebookresearch/dino/blob/master/vision_transformer.py
|
|
14
|
+
# https://github.com/rwightman/pytorch-image-models/tree/master/timm/layers/patch_embed.py
|
|
15
|
+
|
|
16
|
+
from typing import Callable, Optional, Tuple, Union
|
|
17
|
+
|
|
18
|
+
import torch.nn as nn
|
|
19
|
+
from torch import Tensor
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def make_2tuple(x):
|
|
23
|
+
if isinstance(x, tuple):
|
|
24
|
+
assert len(x) == 2
|
|
25
|
+
return x
|
|
26
|
+
|
|
27
|
+
assert isinstance(x, int)
|
|
28
|
+
return (x, x)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PatchEmbed(nn.Module):
|
|
32
|
+
"""
|
|
33
|
+
2D image to patch embedding: (B,C,H,W) -> (B,N,D)
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
img_size: Image size.
|
|
37
|
+
patch_size: Patch token size.
|
|
38
|
+
in_chans: Number of input image channels.
|
|
39
|
+
embed_dim: Number of linear projection output channels.
|
|
40
|
+
norm_layer: Normalization layer.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
img_size: Union[int, Tuple[int, int]] = 224,
|
|
46
|
+
patch_size: Union[int, Tuple[int, int]] = 16,
|
|
47
|
+
in_chans: int = 3,
|
|
48
|
+
embed_dim: int = 768,
|
|
49
|
+
norm_layer: Optional[Callable] = None,
|
|
50
|
+
flatten_embedding: bool = True,
|
|
51
|
+
) -> None:
|
|
52
|
+
super().__init__()
|
|
53
|
+
|
|
54
|
+
image_HW = make_2tuple(img_size)
|
|
55
|
+
patch_HW = make_2tuple(patch_size)
|
|
56
|
+
patch_grid_size = (
|
|
57
|
+
image_HW[0] // patch_HW[0],
|
|
58
|
+
image_HW[1] // patch_HW[1],
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
self.img_size = image_HW
|
|
62
|
+
self.patch_size = patch_HW
|
|
63
|
+
self.patches_resolution = patch_grid_size
|
|
64
|
+
self.num_patches = patch_grid_size[0] * patch_grid_size[1]
|
|
65
|
+
|
|
66
|
+
self.in_chans = in_chans
|
|
67
|
+
self.embed_dim = embed_dim
|
|
68
|
+
|
|
69
|
+
self.flatten_embedding = flatten_embedding
|
|
70
|
+
|
|
71
|
+
self.proj = nn.Conv2d(
|
|
72
|
+
in_chans, embed_dim, kernel_size=patch_HW, stride=patch_HW
|
|
73
|
+
)
|
|
74
|
+
self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
|
|
75
|
+
|
|
76
|
+
def forward(self, x: Tensor) -> Tensor:
|
|
77
|
+
_, _, H, W = x.shape
|
|
78
|
+
patch_H, patch_W = self.patch_size
|
|
79
|
+
|
|
80
|
+
assert (
|
|
81
|
+
H % patch_H == 0
|
|
82
|
+
), f"Input image height {H} is not a multiple of patch height {patch_H}"
|
|
83
|
+
assert (
|
|
84
|
+
W % patch_W == 0
|
|
85
|
+
), f"Input image width {W} is not a multiple of patch width: {patch_W}"
|
|
86
|
+
|
|
87
|
+
x = self.proj(x) # B C H W
|
|
88
|
+
H, W = x.size(2), x.size(3)
|
|
89
|
+
x = x.flatten(2).transpose(1, 2) # B HW C
|
|
90
|
+
x = self.norm(x)
|
|
91
|
+
if not self.flatten_embedding:
|
|
92
|
+
x = x.reshape(-1, H, W, self.embed_dim) # B H W C
|
|
93
|
+
return x
|
|
94
|
+
|
|
95
|
+
def flops(self) -> float:
|
|
96
|
+
Ho, Wo = self.patches_resolution
|
|
97
|
+
flops = (
|
|
98
|
+
Ho
|
|
99
|
+
* Wo
|
|
100
|
+
* self.embed_dim
|
|
101
|
+
* self.in_chans
|
|
102
|
+
* (self.patch_size[0] * self.patch_size[1])
|
|
103
|
+
)
|
|
104
|
+
if self.norm is not None:
|
|
105
|
+
flops += Ho * Wo * self.embed_dim
|
|
106
|
+
return flops
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the Apache License, Version 2.0
|
|
4
|
+
# found in the LICENSE file in the root directory of this source tree.
|
|
5
|
+
#
|
|
6
|
+
# Modified by the libgs contributors, 2026, from src/model/encoder/vggt/layers/rope.py
|
|
7
|
+
# of https://github.com/InternRobotics/AnySplat (5f5e208): formatted with black, unused
|
|
8
|
+
# imports removed.
|
|
9
|
+
# Apache License 2.0: see the Apache-2.0 text in LICENSE (this directory).
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Implementation of 2D Rotary Position Embeddings (RoPE).
|
|
13
|
+
|
|
14
|
+
# This module provides a clean implementation of 2D Rotary Position Embeddings,
|
|
15
|
+
# which extends the original RoPE concept to handle 2D spatial positions.
|
|
16
|
+
|
|
17
|
+
# Inspired by:
|
|
18
|
+
# https://github.com/meta-llama/codellama/blob/main/llama/model.py
|
|
19
|
+
# https://github.com/naver-ai/rope-vit
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from typing import Dict, Tuple
|
|
23
|
+
|
|
24
|
+
import torch
|
|
25
|
+
import torch.nn as nn
|
|
26
|
+
import torch.nn.functional as F
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PositionGetter:
|
|
30
|
+
"""Generates and caches 2D spatial positions for patches in a grid.
|
|
31
|
+
|
|
32
|
+
This class efficiently manages the generation of spatial coordinates for patches
|
|
33
|
+
in a 2D grid, caching results to avoid redundant computations.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
position_cache: Dictionary storing precomputed position tensors for different
|
|
37
|
+
grid dimensions.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
"""Initializes the position generator with an empty cache."""
|
|
42
|
+
self.position_cache: Dict[Tuple[int, int], torch.Tensor] = {}
|
|
43
|
+
|
|
44
|
+
def __call__(
|
|
45
|
+
self, batch_size: int, height: int, width: int, device: torch.device
|
|
46
|
+
) -> torch.Tensor:
|
|
47
|
+
"""Generates spatial positions for a batch of patches.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
batch_size: Number of samples in the batch.
|
|
51
|
+
height: Height of the grid in patches.
|
|
52
|
+
width: Width of the grid in patches.
|
|
53
|
+
device: Target device for the position tensor.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Tensor of shape (batch_size, height*width, 2) containing y,x coordinates
|
|
57
|
+
for each position in the grid, repeated for each batch item.
|
|
58
|
+
"""
|
|
59
|
+
if (height, width) not in self.position_cache:
|
|
60
|
+
y_coords = torch.arange(height, device=device)
|
|
61
|
+
x_coords = torch.arange(width, device=device)
|
|
62
|
+
positions = torch.cartesian_prod(y_coords, x_coords)
|
|
63
|
+
self.position_cache[height, width] = positions
|
|
64
|
+
|
|
65
|
+
cached_positions = self.position_cache[height, width]
|
|
66
|
+
return (
|
|
67
|
+
cached_positions.view(1, height * width, 2)
|
|
68
|
+
.expand(batch_size, -1, -1)
|
|
69
|
+
.clone()
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class RotaryPositionEmbedding2D(nn.Module):
|
|
74
|
+
"""2D Rotary Position Embedding implementation.
|
|
75
|
+
|
|
76
|
+
This module applies rotary position embeddings to input tokens based on their
|
|
77
|
+
2D spatial positions. It handles the position-dependent rotation of features
|
|
78
|
+
separately for vertical and horizontal dimensions.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
frequency: Base frequency for the position embeddings. Default: 100.0
|
|
82
|
+
scaling_factor: Scaling factor for frequency computation. Default: 1.0
|
|
83
|
+
|
|
84
|
+
Attributes:
|
|
85
|
+
base_frequency: Base frequency for computing position embeddings.
|
|
86
|
+
scaling_factor: Factor to scale the computed frequencies.
|
|
87
|
+
frequency_cache: Cache for storing precomputed frequency components.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __init__(self, frequency: float = 100.0, scaling_factor: float = 1.0):
|
|
91
|
+
"""Initializes the 2D RoPE module."""
|
|
92
|
+
super().__init__()
|
|
93
|
+
self.base_frequency = frequency
|
|
94
|
+
self.scaling_factor = scaling_factor
|
|
95
|
+
self.frequency_cache: Dict[Tuple, Tuple[torch.Tensor, torch.Tensor]] = {}
|
|
96
|
+
|
|
97
|
+
def _compute_frequency_components(
|
|
98
|
+
self, dim: int, seq_len: int, device: torch.device, dtype: torch.dtype
|
|
99
|
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
|
100
|
+
"""Computes frequency components for rotary embeddings.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
dim: Feature dimension (must be even).
|
|
104
|
+
seq_len: Maximum sequence length.
|
|
105
|
+
device: Target device for computations.
|
|
106
|
+
dtype: Data type for the computed tensors.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Tuple of (cosine, sine) tensors for frequency components.
|
|
110
|
+
"""
|
|
111
|
+
cache_key = (dim, seq_len, device, dtype)
|
|
112
|
+
if cache_key not in self.frequency_cache:
|
|
113
|
+
# Compute frequency bands
|
|
114
|
+
exponents = torch.arange(0, dim, 2, device=device).float() / dim
|
|
115
|
+
inv_freq = 1.0 / (self.base_frequency**exponents)
|
|
116
|
+
|
|
117
|
+
# Generate position-dependent frequencies
|
|
118
|
+
positions = torch.arange(seq_len, device=device, dtype=inv_freq.dtype)
|
|
119
|
+
angles = torch.einsum("i,j->ij", positions, inv_freq)
|
|
120
|
+
|
|
121
|
+
# Compute and cache frequency components
|
|
122
|
+
angles = angles.to(dtype)
|
|
123
|
+
angles = torch.cat((angles, angles), dim=-1)
|
|
124
|
+
cos_components = angles.cos().to(dtype)
|
|
125
|
+
sin_components = angles.sin().to(dtype)
|
|
126
|
+
self.frequency_cache[cache_key] = (cos_components, sin_components)
|
|
127
|
+
|
|
128
|
+
return self.frequency_cache[cache_key]
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def _rotate_features(x: torch.Tensor) -> torch.Tensor:
|
|
132
|
+
"""Performs feature rotation by splitting and recombining feature dimensions.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
x: Input tensor to rotate.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Rotated feature tensor.
|
|
139
|
+
"""
|
|
140
|
+
feature_dim = x.shape[-1]
|
|
141
|
+
x1, x2 = x[..., : feature_dim // 2], x[..., feature_dim // 2 :]
|
|
142
|
+
return torch.cat((-x2, x1), dim=-1)
|
|
143
|
+
|
|
144
|
+
def _apply_1d_rope(
|
|
145
|
+
self,
|
|
146
|
+
tokens: torch.Tensor,
|
|
147
|
+
positions: torch.Tensor,
|
|
148
|
+
cos_comp: torch.Tensor,
|
|
149
|
+
sin_comp: torch.Tensor,
|
|
150
|
+
) -> torch.Tensor:
|
|
151
|
+
"""Applies 1D rotary position embeddings along one dimension.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
tokens: Input token features.
|
|
155
|
+
positions: Position indices.
|
|
156
|
+
cos_comp: Cosine components for rotation.
|
|
157
|
+
sin_comp: Sine components for rotation.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Tokens with applied rotary position embeddings.
|
|
161
|
+
"""
|
|
162
|
+
# Embed positions with frequency components
|
|
163
|
+
cos = F.embedding(positions, cos_comp)[:, None, :, :]
|
|
164
|
+
sin = F.embedding(positions, sin_comp)[:, None, :, :]
|
|
165
|
+
|
|
166
|
+
# Apply rotation
|
|
167
|
+
return (tokens * cos) + (self._rotate_features(tokens) * sin)
|
|
168
|
+
|
|
169
|
+
def forward(self, tokens: torch.Tensor, positions: torch.Tensor) -> torch.Tensor:
|
|
170
|
+
"""Applies 2D rotary position embeddings to input tokens.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
tokens: Input tensor of shape (batch_size, n_heads, n_tokens, dim).
|
|
174
|
+
The feature dimension (dim) must be divisible by 4.
|
|
175
|
+
positions: Position tensor of shape (batch_size, n_tokens, 2) containing
|
|
176
|
+
the y and x coordinates for each token.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
Tensor of same shape as input with applied 2D rotary position embeddings.
|
|
180
|
+
|
|
181
|
+
Raises:
|
|
182
|
+
AssertionError: If input dimensions are invalid or positions are malformed.
|
|
183
|
+
"""
|
|
184
|
+
# Validate inputs
|
|
185
|
+
assert tokens.size(-1) % 2 == 0, "Feature dimension must be even"
|
|
186
|
+
assert (
|
|
187
|
+
positions.ndim == 3 and positions.shape[-1] == 2
|
|
188
|
+
), "Positions must have shape (batch_size, n_tokens, 2)"
|
|
189
|
+
|
|
190
|
+
# Compute feature dimension for each spatial direction
|
|
191
|
+
feature_dim = tokens.size(-1) // 2
|
|
192
|
+
|
|
193
|
+
# Get frequency components
|
|
194
|
+
max_position = int(positions.max()) + 1
|
|
195
|
+
cos_comp, sin_comp = self._compute_frequency_components(
|
|
196
|
+
feature_dim, max_position, tokens.device, tokens.dtype
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Split features for vertical and horizontal processing
|
|
200
|
+
vertical_features, horizontal_features = tokens.chunk(2, dim=-1)
|
|
201
|
+
|
|
202
|
+
# Apply RoPE separately for each dimension
|
|
203
|
+
vertical_features = self._apply_1d_rope(
|
|
204
|
+
vertical_features, positions[..., 0], cos_comp, sin_comp
|
|
205
|
+
)
|
|
206
|
+
horizontal_features = self._apply_1d_rope(
|
|
207
|
+
horizontal_features, positions[..., 1], cos_comp, sin_comp
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Combine processed features
|
|
211
|
+
return torch.cat((vertical_features, horizontal_features), dim=-1)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the Apache License, Version 2.0
|
|
4
|
+
# found in the LICENSE file in the root directory of this source tree.
|
|
5
|
+
#
|
|
6
|
+
# Modified by the libgs contributors, 2026, from
|
|
7
|
+
# src/model/encoder/vggt/layers/swiglu_ffn.py of
|
|
8
|
+
# https://github.com/InternRobotics/AnySplat (5f5e208): formatted with black, unused
|
|
9
|
+
# imports removed.
|
|
10
|
+
# Apache License 2.0: see the Apache-2.0 text in LICENSE (this directory).
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from typing import Callable, Optional
|
|
14
|
+
|
|
15
|
+
import torch.nn.functional as F
|
|
16
|
+
from torch import Tensor, nn
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SwiGLUFFN(nn.Module):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
in_features: int,
|
|
23
|
+
hidden_features: Optional[int] = None,
|
|
24
|
+
out_features: Optional[int] = None,
|
|
25
|
+
act_layer: Callable[..., nn.Module] = None,
|
|
26
|
+
drop: float = 0.0,
|
|
27
|
+
bias: bool = True,
|
|
28
|
+
) -> None:
|
|
29
|
+
super().__init__()
|
|
30
|
+
out_features = out_features or in_features
|
|
31
|
+
hidden_features = hidden_features or in_features
|
|
32
|
+
self.w12 = nn.Linear(in_features, 2 * hidden_features, bias=bias)
|
|
33
|
+
self.w3 = nn.Linear(hidden_features, out_features, bias=bias)
|
|
34
|
+
|
|
35
|
+
def forward(self, x: Tensor) -> Tensor:
|
|
36
|
+
x12 = self.w12(x)
|
|
37
|
+
x1, x2 = x12.chunk(2, dim=-1)
|
|
38
|
+
hidden = F.silu(x1) * x2
|
|
39
|
+
return self.w3(hidden)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
XFORMERS_ENABLED = os.environ.get("XFORMERS_DISABLED") is None
|
|
43
|
+
# try:
|
|
44
|
+
# if XFORMERS_ENABLED:
|
|
45
|
+
# from xformers.ops import SwiGLU
|
|
46
|
+
|
|
47
|
+
# XFORMERS_AVAILABLE = True
|
|
48
|
+
# warnings.warn("xFormers is available (SwiGLU)")
|
|
49
|
+
# else:
|
|
50
|
+
# warnings.warn("xFormers is disabled (SwiGLU)")
|
|
51
|
+
# raise ImportError
|
|
52
|
+
# except ImportError:
|
|
53
|
+
SwiGLU = SwiGLUFFN
|
|
54
|
+
XFORMERS_AVAILABLE = False
|
|
55
|
+
|
|
56
|
+
# warnings.warn("xFormers is not available (SwiGLU)")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class SwiGLUFFNFused(SwiGLU):
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
in_features: int,
|
|
63
|
+
hidden_features: Optional[int] = None,
|
|
64
|
+
out_features: Optional[int] = None,
|
|
65
|
+
act_layer: Callable[..., nn.Module] = None,
|
|
66
|
+
drop: float = 0.0,
|
|
67
|
+
bias: bool = True,
|
|
68
|
+
) -> None:
|
|
69
|
+
out_features = out_features or in_features
|
|
70
|
+
hidden_features = hidden_features or in_features
|
|
71
|
+
hidden_features = (int(hidden_features * 2 / 3) + 7) // 8 * 8
|
|
72
|
+
super().__init__(
|
|
73
|
+
in_features=in_features,
|
|
74
|
+
hidden_features=hidden_features,
|
|
75
|
+
out_features=out_features,
|
|
76
|
+
bias=bias,
|
|
77
|
+
)
|