Spaces:
Running on Zero
Running on Zero
| import torch | |
| import torch.nn as nn | |
| def _make_scalar_embedder(hidden_size): | |
| embedder = nn.Sequential( | |
| nn.Linear(1, hidden_size, bias=True), | |
| nn.SiLU(), | |
| nn.Linear(hidden_size, hidden_size, bias=True), | |
| ) | |
| nn.init.normal_(embedder[0].weight, std=0.02) | |
| nn.init.normal_(embedder[0].bias, std=0.02) | |
| nn.init.normal_(embedder[2].weight, std=0.02) | |
| nn.init.normal_(embedder[2].bias, std=0.02) | |
| return embedder | |
| class LinearSteeringEmbedder(torch.nn.Module): | |
| """ | |
| Generic linear embedding layer for steering signals. When steering is missing, outputs a fixed zero embedding. | |
| """ | |
| def __init__(self, num_input_features, hidden_size, learnable_no_value_embedding=False): | |
| super().__init__() | |
| self.embedders = nn.ModuleList() | |
| self.register_buffer("no_value_embeddings", torch.zeros(num_input_features, hidden_size)) | |
| if learnable_no_value_embedding: | |
| self.no_value_embeddings = nn.Parameter(torch.zeros(num_input_features, hidden_size)) | |
| for _i in range(num_input_features): | |
| self.embedders.append(_make_scalar_embedder(hidden_size)) | |
| def forward(self, steering): | |
| squeeze_k = False | |
| if steering.ndim == 2: | |
| steering = steering.unsqueeze(1) | |
| squeeze_k = True | |
| elif steering.ndim != 3: | |
| raise ValueError(f"Expected steering to have shape [B, D] or [B, K, D], got {tuple(steering.shape)}") | |
| _b, _k, num_features = steering.shape | |
| assert num_features == len(self.embedders), f"Expected {len(self.embedders)} features, but got {num_features}" | |
| embeddings = [] | |
| for i in range(num_features): | |
| feature = steering[:, :, [i]] | |
| missing = torch.isnan(feature).squeeze(-1).unsqueeze(-1) | |
| embedding = self.embedders[i](torch.nan_to_num(feature, nan=0.0)) | |
| if missing.any(): | |
| embedding = torch.where(missing, self.no_value_embeddings[i].to(embedding.dtype).view(1, 1, -1), embedding) | |
| embeddings.append(embedding) | |
| steering_embedding = torch.stack(embeddings, dim=1).sum(dim=1) | |
| if squeeze_k: | |
| return steering_embedding[:, 0] | |
| return steering_embedding | |