pliny-the-prompter commited on
Commit
c85bd2d
·
verified ·
1 Parent(s): 362bf2f

Upload 80 files

Browse files
Files changed (3) hide show
  1. app.py +28 -0
  2. obliteratus/abliterate.py +3 -1
  3. obliteratus/cli.py +5 -0
app.py CHANGED
@@ -73,6 +73,29 @@ METHODS = {
73
  "aggressive (maximum removal)": "aggressive",
74
  }
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  # ---------------------------------------------------------------------------
78
  # Obliteration
@@ -118,6 +141,8 @@ def obliterate(model_choice: str, method_choice: str, progress=gr.Progress()):
118
  idx = stage_order.get(stage_key, 0)
119
  progress((idx + 1) / 6, desc=f"{stage_key.upper()}")
120
 
 
 
121
  def run_pipeline():
122
  try:
123
  from obliteratus.abliterate import AbliterationPipeline
@@ -127,6 +152,7 @@ def obliterate(model_choice: str, method_choice: str, progress=gr.Progress()):
127
  device="auto",
128
  dtype="float16",
129
  method=method,
 
130
  on_stage=on_stage,
131
  on_log=on_log,
132
  )
@@ -137,6 +163,8 @@ def obliterate(model_choice: str, method_choice: str, progress=gr.Progress()):
137
 
138
  log_lines.append(f"Target: {model_id}")
139
  log_lines.append(f"Method: {method}")
 
 
140
  log_lines.append("")
141
 
142
  worker = threading.Thread(target=run_pipeline, daemon=True)
 
73
  "aggressive (maximum removal)": "aggressive",
74
  }
75
 
76
+ # Models that need 4bit quantization to fit on a T4 16GB
77
+ _NEEDS_QUANTIZATION = {
78
+ "openai/gpt-oss-20b",
79
+ }
80
+
81
+
82
+ def _should_quantize(model_id: str) -> str | None:
83
+ """Return '4bit' if the model needs quantization for available GPU, else None."""
84
+ if model_id in _NEEDS_QUANTIZATION:
85
+ return "4bit"
86
+ # Auto-detect from config for custom model IDs
87
+ try:
88
+ from obliteratus.models.loader import _estimate_model_memory_gb, _available_gpu_memory_gb
89
+ from transformers import AutoConfig
90
+ config = AutoConfig.from_pretrained(model_id, trust_remote_code=True)
91
+ est_gb = _estimate_model_memory_gb(config, torch.float16)
92
+ gpu_gb = _available_gpu_memory_gb()
93
+ if gpu_gb > 0 and est_gb > gpu_gb * 0.85:
94
+ return "4bit"
95
+ except Exception:
96
+ pass
97
+ return None
98
+
99
 
100
  # ---------------------------------------------------------------------------
101
  # Obliteration
 
141
  idx = stage_order.get(stage_key, 0)
142
  progress((idx + 1) / 6, desc=f"{stage_key.upper()}")
143
 
144
+ quantization = _should_quantize(model_id)
145
+
146
  def run_pipeline():
147
  try:
148
  from obliteratus.abliterate import AbliterationPipeline
 
152
  device="auto",
153
  dtype="float16",
154
  method=method,
155
+ quantization=quantization,
156
  on_stage=on_stage,
157
  on_log=on_log,
158
  )
 
163
 
164
  log_lines.append(f"Target: {model_id}")
165
  log_lines.append(f"Method: {method}")
166
+ if quantization:
167
+ log_lines.append(f"Quantization: {quantization} (auto-detected for GPU fit)")
168
  log_lines.append("")
169
 
170
  worker = threading.Thread(target=run_pipeline, daemon=True)
obliteratus/abliterate.py CHANGED
@@ -252,6 +252,7 @@ class AbliterationPipeline:
252
  use_chat_template: bool | None = None,
253
  use_whitened_svd: bool | None = None,
254
  true_iterative_refinement: bool | None = None,
 
255
  harmful_prompts: list[str] | None = None,
256
  harmless_prompts: list[str] | None = None,
257
  on_stage: Callable[[StageResult], None] | None = None,
@@ -278,6 +279,7 @@ class AbliterationPipeline:
278
  self.use_chat_template = use_chat_template if use_chat_template is not None else method_cfg.get("use_chat_template", False)
279
  self.use_whitened_svd = use_whitened_svd if use_whitened_svd is not None else method_cfg.get("use_whitened_svd", False)
280
  self.true_iterative_refinement = true_iterative_refinement if true_iterative_refinement is not None else method_cfg.get("true_iterative_refinement", False)
 
281
 
282
  self.handle: ModelHandle | None = None
283
  self.refusal_directions: dict[int, torch.Tensor] = {} # per-layer primary direction
@@ -339,7 +341,7 @@ class AbliterationPipeline:
339
  device=self.device,
340
  dtype=self.dtype,
341
  trust_remote_code=self.trust_remote_code,
342
- quantization=getattr(self, "quantization", None),
343
  )
344
 
345
  summary = self.handle.summary()
 
252
  use_chat_template: bool | None = None,
253
  use_whitened_svd: bool | None = None,
254
  true_iterative_refinement: bool | None = None,
255
+ quantization: str | None = None,
256
  harmful_prompts: list[str] | None = None,
257
  harmless_prompts: list[str] | None = None,
258
  on_stage: Callable[[StageResult], None] | None = None,
 
279
  self.use_chat_template = use_chat_template if use_chat_template is not None else method_cfg.get("use_chat_template", False)
280
  self.use_whitened_svd = use_whitened_svd if use_whitened_svd is not None else method_cfg.get("use_whitened_svd", False)
281
  self.true_iterative_refinement = true_iterative_refinement if true_iterative_refinement is not None else method_cfg.get("true_iterative_refinement", False)
282
+ self.quantization = quantization
283
 
284
  self.handle: ModelHandle | None = None
285
  self.refusal_directions: dict[int, torch.Tensor] = {} # per-layer primary direction
 
341
  device=self.device,
342
  dtype=self.dtype,
343
  trust_remote_code=self.trust_remote_code,
344
+ quantization=self.quantization,
345
  )
346
 
347
  summary = self.handle.summary()
obliteratus/cli.py CHANGED
@@ -71,6 +71,10 @@ def main(argv: list[str] | None = None):
71
  p.add_argument("--n-directions", type=int, default=None, help="Override: number of SVD directions to extract")
72
  p.add_argument("--regularization", type=float, default=None, help="Override: fraction to preserve (0.0-1.0)")
73
  p.add_argument("--refinement-passes", type=int, default=None, help="Override: number of iterative passes")
 
 
 
 
74
 
75
  abl_parser = subparsers.add_parser(
76
  "obliterate",
@@ -323,6 +327,7 @@ def _cmd_abliterate(args):
323
  n_directions=args.n_directions,
324
  regularization=args.regularization,
325
  refinement_passes=args.refinement_passes,
 
326
  on_stage=on_stage,
327
  on_log=on_log,
328
  )
 
71
  p.add_argument("--n-directions", type=int, default=None, help="Override: number of SVD directions to extract")
72
  p.add_argument("--regularization", type=float, default=None, help="Override: fraction to preserve (0.0-1.0)")
73
  p.add_argument("--refinement-passes", type=int, default=None, help="Override: number of iterative passes")
74
+ p.add_argument(
75
+ "--quantization", type=str, default=None, choices=["4bit", "8bit"],
76
+ help="Load model with quantization (4bit or 8bit). Requires bitsandbytes.",
77
+ )
78
 
79
  abl_parser = subparsers.add_parser(
80
  "obliterate",
 
327
  n_directions=args.n_directions,
328
  regularization=args.regularization,
329
  refinement_passes=args.refinement_passes,
330
+ quantization=args.quantization,
331
  on_stage=on_stage,
332
  on_log=on_log,
333
  )