Skip to content

RQ3: re-run safety eval on llava-1.5-7b with multimodal (Gemini) judge - #1

Open
Arth-Singh wants to merge 21 commits into
mainfrom
rq3/llava-1.5-7b-mm-judge
Open

RQ3: re-run safety eval on llava-1.5-7b with multimodal (Gemini) judge#1
Arth-Singh wants to merge 21 commits into
mainfrom
rq3/llava-1.5-7b-mm-judge

Conversation

@Arth-Singh

@Arth-Singh Arth-Singh commented May 8, 2026

Copy link
Copy Markdown
Owner

Summary

Switches the RQ3 safety evaluation pipeline to llava-hf/llava-1.5-7b-hf and replaces the text-only Claude judge with an image-aware Gemini-3.1-flash-lite judge via OpenRouter. The dataset's harm is image-encoded (innocuous-looking text + harmful imagery: weapons, drugs, chemicals, lock picks, etc.), so a text-only judge cannot tell whether a fluent description constitutes a safety failure. The multimodal judge fixes this.

The full writeup is at experiments/rq3/RESULTS_llava-1.5-7b.md.

Experiments delivered (all four safety experiments rerun on llava-1.5-7b)

1. Activation patching (logit-difference metric)

Full sweep: 420 entries × 65 patchable components (1 projector + 32 attn + 32 MLP). Logit-difference metric (mean refusal-token logits − mean compliance-token logits) following NOTICE / Zhang & Nanda.

Top-5 safety-critical components by recovery score:

  • projector1.0000
  • layer_9_attn — 0.4972
  • layer_1_mlp — 0.4245
  • layer_12_attn — 0.4038
  • layer_6_attn — 0.3960

Outputs: experiments/rq3/results/patching_llava-1.5-7b-hf.json (~6.9 MB), safety_heatmap_llava-1.5-7b-hf.png, top_safety_components_llava-1.5-7b-hf.png, plus per-counterfactual-type top-component plots.

2. Logit lens (safety-trajectory analysis)

Per-layer projection of the residual stream through final_norm + lm_head (per Belrose et al. 2023 — final RMSNorm is required, residual stream norms grow exponentially). 32 layers, refusal vs compliance token probability mass at each layer for harmful inputs. Both refusal and compliance probabilities sit around 10⁻⁴ throughout, consistent with the behavioural finding that the model has no internalized refusal direction for visual harm.

Output: experiments/rq3/results/logit_lens_llava-1.5-7b-hf.json.

3. Compression eval (multimodal LLM-judge, n=149)

Configuration Multimodal-judge refusal Text-judge refusal
baseline (uncompressed) 0.0% (0/149) 0.7% (1/149)
AWQ int4 0.0% 0.0%
Wanda 10% 0.7% 0.0%
Wanda 20% 0.0% 0.7%
Wanda 30% 0.0% 1.3%
Wanda 50% 1.3% 6.7%

llava-1.5-7b refuses 0/149 harmful image prompts at baseline. Compression cannot destroy what isn't there. The apparent monotonic "more pruning → more refusals" trend under the text-only judge (0/0.7/1.3/6.7% at Wanda 10/20/30/50%) collapses to noise under the multimodal judge — the text-judge over-counted because it labelled "I cannot tell what this is" outputs from heavily-pruned models as refusals; the multimodal judge sees the image and correctly classifies them as compliance. The Wanda 50% number drops 5.4 pp once the judge can see the image.

Outputs: experiments/rq3/results/llm_judge_llava-1.5-7b-hf.json (uncompressed baseline) + experiments/rq3/results/llm_judge_v3_{awq_int4,wanda_10%,wanda_20%,wanda_30%,wanda_50%}_llava-1.5-7b-hf.json.

4. Targeted ablation (necessity / sufficiency / projector isolation, n=149)

At sparsity 0.5 with n_random=10:

Ablation Genuine refusal
prune_safety_only (necessity) 0.0%
prune_nonsafety_only (sufficiency) 0.7% (1/149)
prune_projector_only 0.0%
Random baselines (mean ± std, n=10) 0.3% ± 0.5%
Cohen's d (safety vs random) −0.707
p-value (one-sided t-test) 0.026

Cohen's d is negative — pruning safety-critical components produces fewer refusals than random pruning. The "significance" is an artifact of zero variance in the safety arm hitting the 0% floor. With baseline at 0%, all conditions are pinned at the floor and the ablation cannot meaningfully distinguish "safety-critical" from random subsets. This is not a failure of the ablation methodology — it's the dataset+model combination giving zero signal.

Output: experiments/rq3/results/targeted_ablation_v2_llava-1.5-7b-hf.json.

Code changes

  • llm_judge.py: anthropic.AsyncAnthropicopenai.AsyncOpenAI against OpenRouter. Image base64 data URLs (PIL → JPEG q=85, downscaled to 768 px max side). Async batch judging via asyncio.Semaphore(concurrency) + tqdm_asyncio.gather. System prompt rewritten to brief the judge that harm is image-encoded; coherence vs refusal split kept.
  • llm_judge_compression.py: Wanda sweep loads the model once, computes activation norms once, snapshots/restores prunable weights between sparsity levels (4× faster than per-level fresh loads). AWQ int4 path replaces the broken bnb-NF4 path; quantized checkpoint cached to disk for reuse. Multimodal eval pass plumbs the image data URL through the generate→judge pipeline.
  • targeted_ablation.py: same snapshot/restore optimization — 1 model load instead of 13 (3 fixed ablations + 10 random baselines). Async batch judging.
  • compression_experiment.py: split apply_wanda_pruning into compute_wanda_activation_norms + apply_wanda_with_norms so callers can amortize calibration over multiple sparsity levels.
  • run_all_v2.sh: 3-GPU parallel layout (was 4); parameterizable WORK_DIR / PYENV_ACTIVATE so it doesn't hard-code conda or /data/arth/....
  • logit_lens.py (new): per-layer refusal/compliance probability projection through final RMSNorm + lm_head, per Belrose et al. 2023.

Engineering notes

  • AutoAWQ + transformers 4.57 needed two patches (recorded in RESULTS_llava-1.5-7b.md):
    1. awq/quantize/scale.py: PytorchGELUTanh was renamed to GELUTanh in tx 4.57. Two-line shim.
    2. awq/models/llava.py: tx 4.36+ unwraps model.language_model from LlamaForCausalLM to LlamaModel directly. Patched get_model_layers and move_embed to handle both shapes.
  • AWQ multimodal device placement: from_pretrained(device_map="cuda") only places the LM on GPU; vision_tower and multi_modal_projector stay on CPU and crash generation. Fix: explicit .to("cuda") for those two submodules after AWQ load. Also from_quantized rejects device_map="cuda" — must use "auto".
  • Async judge batching took the full suite from ~120 min wall time (sync) to ~30 min (async, c=100).

What's in this branch (results files)

  • experiments/rq3/results/patching_llava-1.5-7b-hf.json (full activation patching, 420 entries × 65 components)
  • experiments/rq3/results/logit_lens_llava-1.5-7b-hf.json
  • experiments/rq3/results/llm_judge_llava-1.5-7b-hf.json (uncompressed baseline, mm-judge)
  • experiments/rq3/results/llm_judge_v3_{awq_int4,wanda_10%,wanda_20%,wanda_30%,wanda_50%}_llava-1.5-7b-hf.json
  • experiments/rq3/results/targeted_ablation_v2_llava-1.5-7b-hf.json
  • experiments/rq3/results/{safety_heatmap,top_safety_components}_llava-1.5-7b-hf.png

Test plan

  • Reviewer reads experiments/rq3/RESULTS_llava-1.5-7b.md end-to-end and sanity-checks the headline numbers vs the JSON files.
  • Reviewer spot-checks 5–10 entries in any compressed JSON to confirm judge reason strings reference image content (verified during smoke; sample reasons cited "kitchen knife", "chemicals", "lock picks", "pills/medication").
  • Reproduce on a different GPU box: set OPENROUTER_API_KEY, run experiments/rq3/run_all_v2.sh with WORK_DIR=$(pwd)/experiments/rq3 PYENV_ACTIVATE=path/to/venv/bin/activate. Wall time should be ~30 min on 3× B200-class GPUs.
  • If we want a real safety curve to write the paper around: re-run the same suite against llava-hf/llava-v1.6-vicuna-13b-hf or Qwen/Qwen2-VL-7B-Instruct (both have non-trivial baseline visual safety alignment), and/or against AdvBench/HarmfulQA so the safety circuit being localized actually fires.

What this PR does not claim

This is not evidence that compression preserves safety. It is evidence that on this dataset+model combination, there is no safety to preserve in the first place. Drawing conclusions about Wanda vs AWQ for safety preservation requires a model that actually refuses harmful prompts at baseline. Recommendations for a follow-up run are at the bottom of RESULTS_llava-1.5-7b.md.

Veeraraju-E and others added 21 commits March 8, 2026 00:35
adding all results for vqa eval
adding stand-alone script to directly download data and models
Switch RQ3 safety pipeline to llava-hf/llava-1.5-7b-hf and replace the
text-only Claude judge with an image-aware Gemini-3.1-flash-lite judge
(OpenRouter, OpenAI-compat). The dataset's "harm" is image-encoded, so a
text-only judge cannot tell whether a fluent description is a safety
failure; the multimodal judge fixes this.

Code:
- llm_judge.py: AsyncOpenAI → OpenRouter; image base64 data URLs; async
  batch judging with concurrency cap; system prompt rewritten to brief
  the judge that harm is image-encoded; coherence vs refusal split.
- llm_judge_compression.py: Wanda sweep loads model once, computes
  activation norms once, snapshots/restores prunable weights between
  sparsity levels; AWQ int4 path replaces the broken bnb-NF4 path,
  caches quantized checkpoint to disk; multimodal eval pass.
- targeted_ablation.py: same snapshot/restore optimization (1 model load
  vs 13); multimodal eval pass.
- compression_experiment.py: split apply_wanda_pruning into
  compute_wanda_activation_norms + apply_wanda_with_norms.
- run_all_v2.sh: 3-GPU parallel layout (was 4); parameterizable
  WORK_DIR / PYENV_ACTIVATE.

Results (llava-1.5-7b-hf, n=149 harmful image+prompt entries, mm-judge):
- baseline:    0.0% refusal
- AWQ int4:    0.0%
- Wanda 10%:   0.7%   (1/149)
- Wanda 20%:   0.0%
- Wanda 30%:   0.0%
- Wanda 50%:   1.3%   (2/149)

Targeted ablation @ sparsity 0.5, n_random=10:
- prune_safety_only:    0.0% genuine refusal
- prune_nonsafety_only: 0.7%
- prune_projector_only: 0.0%
- random baselines:     0.3% ± 0.5%
- Cohen's d: -0.707, p=0.026 one-sided (negative direction;
  noise around the floor — see RESULTS_llava-1.5-7b.md).

Headline: llava-1.5-7b refuses 0/149 harmful image prompts at baseline.
Compression cannot destroy what isn't there. Wanda's apparent monotonic
"more pruning -> more refusals" trend under the text-only judge
(0%/0.7%/1.3%/6.7% at 10/20/30/50%) collapses to noise (0.7/0/0/1.3%)
under the multimodal judge — the text-judge over-counted because it
labelled "I cannot tell what this is" outputs from heavily-pruned
models as refusals; the multimodal judge sees the image and labels them
correctly. RESULTS_llava-1.5-7b.md has the full writeup, engineering
notes (autoawq+transformers 4.57 patches, async batch design) and
suggested next steps (stronger model, text-harmful dataset).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants