Spaces:
Sleeping
Sleeping
| """Compute a trust/suspicion activation vector for Gemma 4. | |
| Requires a machine with an NVIDIA GPU and at least 24GB VRAM: | |
| uv run --extra gpu python training/compute_vector.py | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| from pathlib import Path | |
| import torch | |
| from safetensors.torch import save_file | |
| from steering_vectors import train_steering_vector | |
| from transformers import AutoProcessor, Gemma4ForConditionalGeneration | |
| ROOT = Path(__file__).parents[1] | |
| MODEL_ID = os.getenv("GEMMA_MODEL_ID", "google/gemma-4-E4B-it") | |
| LAYERS = [ | |
| int(value) | |
| for value in os.getenv("STEERING_LAYERS", "20,21,22,23,24,25").split(",") | |
| ] | |
| DATA_PATH = ROOT / "training" / "trust_pairs.json" | |
| OUTPUT_DIR = ROOT / "artifacts" | |
| def compute_vector() -> tuple[Path, Path]: | |
| rows = json.loads(DATA_PATH.read_text(encoding="utf-8")) | |
| # The earlier vector changed tone but rarely changed the gate decision. Make | |
| # the behavioral target explicit at the token where the guard commits. | |
| samples = [ | |
| ( | |
| f'{row["trusting"]}\nDECISION: OPEN', | |
| f'{row["suspicious"]}\nDECISION: CLOSED', | |
| ) | |
| for row in rows | |
| ] | |
| token = os.getenv("HF_TOKEN") or None | |
| processor = AutoProcessor.from_pretrained(MODEL_ID, token=token) | |
| model = Gemma4ForConditionalGeneration.from_pretrained( | |
| MODEL_ID, | |
| dtype=torch.bfloat16, | |
| device_map="cuda", | |
| token=token, | |
| ) | |
| model.eval() | |
| tokenizer = processor.tokenizer | |
| tokenizer.padding_side = "left" | |
| if tokenizer.pad_token is None: | |
| tokenizer.pad_token = tokenizer.eos_token | |
| vector = train_steering_vector( | |
| model, | |
| tokenizer, | |
| training_samples=samples, | |
| layers=LAYERS, | |
| layer_type="decoder_block", | |
| read_token_index=-1, | |
| move_to_cpu=True, | |
| batch_size=int(os.getenv("STEERING_BATCH_SIZE", "4")), | |
| show_progress=True, | |
| ) | |
| OUTPUT_DIR.mkdir(exist_ok=True) | |
| tensors = {f"layer_{layer}": value.cpu() for layer, value in vector.layer_activations.items()} | |
| save_file(tensors, OUTPUT_DIR / "trust_vector.safetensors") | |
| metadata = { | |
| "model_id": MODEL_ID, | |
| "layers": LAYERS, | |
| "pairs": len(samples), | |
| "positive_direction": "trusting OPEN minus suspicious CLOSED", | |
| "behavioral_target": "increase the OPEN-vs-CLOSED decision margin", | |
| "read_token_index": -1, | |
| } | |
| (OUTPUT_DIR / "trust_vector.json").write_text( | |
| json.dumps(metadata, indent=2) + "\n", encoding="utf-8" | |
| ) | |
| vector_path = OUTPUT_DIR / "trust_vector.safetensors" | |
| metadata_path = OUTPUT_DIR / "trust_vector.json" | |
| print(f"Saved {vector_path}") | |
| return vector_path, metadata_path | |
| def main() -> None: | |
| compute_vector() | |
| if __name__ == "__main__": | |
| main() | |