CI calculation reseeds the global numpy RNG, so --seed makes later numpy draws repeat
_bootstrap_calculation in garak/analyze/bootstrap_ci.py seeds the global numpy generator when a run seed is set:
if (
hasattr(_config, "run")
and hasattr(_config.run, "seed")
and _config.run.seed is not None
):
np.random.seed(_config.run.seed)garak/evaluators/base.py:149 calls this once per probe per detector, and confidence_interval_method defaults to bootstrap. So on any seeded run the global numpy RNG is reset back to the same value repeatedly during evaluation, and every numpy draw after that point restarts from the same state.
Reproduction:
from garak import _config
import garak.analyze.bootstrap_ci as b
import numpy as np
_config.load_base_config()
_config.run.seed = 42
def draw():
return np.random.choice(10, 3).tolist()
np.random.seed(1234)
for _ in range(3):
b.calculate_bootstrap_ci(results=[0]*60+[1]*40, sensitivity=0.95, specificity=0.90)
print(draw())[9, 1, 7]
[9, 1, 7]
[9, 1, 7]Without the CI call in between, the same three draws are [4, 8, 9], [1, 7, 9], [6, 8, 0].
Two places in a run consume that generator:
garak/resources/red_team/conversation.py:185shuffles branches before pruning, to permute equal-scoring elements. With the state pinned, ties break the same way every round.garak/resources/autodan/genetic.py:193picks parents for the genetic algorithm. Pinned state means the same parents are selected each generation.
So passing --seed, which is there to make a run reproducible, currently also removes the randomness TAP and AutoDAN rely on to explore. The bootstrap intervals themselves are affected too, since every probe and detector pair resamples with the same draws rather than independently.
Fix is to draw from a local generator rather than seeding the global one. np.random.default_rng(seed) keeps the interval reproducible for a given seed and drops the side effect. I have this working locally with a regression test, and the existing 14 tests in tests/analyze/test_bootstrap_ci.py still pass, including test_calculate_bootstrap_ci_reproducibility.
I would like to work on this, PR to follow.
Source: NVIDIA/garak