Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import torch | |
| import torch.nn as nn | |
| from sentence_transformers import SentenceTransformer | |
| import numpy as np | |
| class VAEProfiler(nn.Module): | |
| def __init__(self, input_dim=384, latent_dim=32): | |
| super(VAEProfiler, self).__init__() | |
| self.encoder = nn.Sequential( | |
| nn.Linear(input_dim, 128), nn.ReLU(), | |
| nn.Linear(128, 64), nn.ReLU() | |
| ) | |
| self.fc_mu = nn.Linear(64, latent_dim) | |
| self.fc_logvar = nn.Linear(64, latent_dim) | |
| self.decoder = nn.Sequential( | |
| nn.Linear(latent_dim, 64), nn.ReLU(), | |
| nn.Linear(64, 128), nn.ReLU(), | |
| nn.Linear(128, input_dim) | |
| ) | |
| def reparameterize(self, mu, logvar): | |
| std = torch.exp(0.5 * logvar) | |
| eps = torch.randn_like(std) | |
| return mu + eps * std | |
| def forward(self, x): | |
| h = self.encoder(x) | |
| mu, logvar = self.fc_mu(h), self.fc_logvar(h) | |
| z = self.reparameterize(mu, logvar) | |
| return self.decoder(z), mu, logvar | |
| def calibrate_threshold(vae_model, benign_embeddings, target_fpr=0.01, n_samples=50, noise_std=0.25): | |
| vae_model.eval() | |
| mses = [] | |
| with torch.no_grad(): | |
| for emb in benign_embeddings: | |
| emb = emb.unsqueeze(0) | |
| noisy_embs = emb.repeat(n_samples, 1) + torch.randn_like(emb.repeat(n_samples, 1)) * noise_std | |
| reconstructions, _, _ = vae_model(noisy_embs) | |
| mse = torch.mean((noisy_embs - reconstructions) ** 2, dim=1).mean().item() | |
| mses.append(mse) | |
| mses = np.array(mses) | |
| threshold = np.quantile(mses, 1.0 - target_fpr) | |
| return float(threshold) | |
| def main(): | |
| print("Initializing...") | |
| device = torch.device("cpu") # Force CPU to avoid CUDA errors in map_location | |
| print(f"Device: {device}") | |
| embed_model = SentenceTransformer('all-MiniLM-L6-v2') | |
| vae_model = VAEProfiler(input_dim=384).to(device) | |
| model_path = "kingsguard_l2_vae.pth" | |
| print(f"Loading weights from {model_path}...") | |
| vae_model.load_state_dict(torch.load(model_path, map_location=device, weights_only=True)) | |
| vae_model.eval() | |
| user_cases_path = os.path.join("injecagent_data", "user_cases.jsonl") | |
| texts = [] | |
| print(f"Reading benign data from {user_cases_path}...") | |
| with open(user_cases_path, "r", encoding="utf-8") as f: | |
| for line in f: | |
| if line.strip(): | |
| data = json.loads(line) | |
| if "User Instruction" in data: | |
| texts.append(data["User Instruction"]) | |
| print(f"Extracted {len(texts)} benign samples. Generating embeddings...") | |
| embeddings = embed_model.encode(texts, convert_to_tensor=True).to(device) | |
| print("Calibrating VAE threshold...") | |
| threshold = calibrate_threshold(vae_model, embeddings, target_fpr=0.01) | |
| print(f"Calibration complete! Calculated Threshold (theta_VAE): {threshold:.4f}") | |
| out_path = "calibrated_threshold.json" | |
| with open(out_path, "w") as f: | |
| json.dump({"theta_VAE": threshold}, f, indent=4) | |
| print(f"Saved threshold to {out_path}") | |
| if __name__ == "__main__": | |
| main() | |