Skip to content

BUG Make GCG random_seed deterministic across workers and devices #2490

Description

@romanlutz

Is your feature request related to a problem? Please describe.

GCGAlgorithmConfig.random_seed is documented as the seed for Torch, NumPy, and Python randomness, but the current implementation only uses it when shuffling CSV input rows. Candidate sampling uses Torch randomness, target augmentation uses NumPy randomness, and annealing uses Python randomness without a per-run seeded source. Multiprocessing workers also do not receive deterministic derived seeds.

As a result, two runs with the same GCG configuration can follow different candidate and suffix trajectories. Concurrent runs can also interfere through process-global RNG state.

Describe the solution you'd like

Create a per-run RNG bundle derived from GCGAlgorithmConfig.random_seed and thread it through every stochastic GCG operation:

  • a local random.Random instance for annealing;
  • a local numpy.random.Generator for target preprocessing;
  • explicit torch.Generator instances for candidate sampling, derived deterministically per worker/device;
  • deterministic worker seed derivation that does not depend on process launch order.

Avoid calling global random.seed, numpy.random.seed, or torch.manual_seed as the runtime mechanism because multiple GCG executions may share a process. Record the base seed and any derived worker seeds in the result or run metadata.

Acceptance criteria:

  • Repeating a run with the same configuration, seed, hardware, and process topology produces the same sampled candidates, accepted controls, loss history, and final suffix.
  • Concurrent runs do not change one another's random trajectories.
  • Different seeds can produce different candidate trajectories.
  • Tests cover single-model/single-prompt, multi-model, multi-prompt, and progressive model/goal execution.
  • Existing custom sampling, loss, candidate-filter, and suffix-initializer extension points continue to work.
  • Multi-model, multi-prompt, held-out evaluation, and progressive optimization behavior are preserved.

Describe alternatives you've considered, if relevant

Seeding the global Python, NumPy, and Torch RNGs at the start of execute_async is simpler, but it would make concurrent executions interfere with each other. Tests that manually call random.seed are also insufficient because they do not make the public random_seed setting effective throughout the implementation.

Additional context

This is a focused follow-up to #960 and should preserve the performance/generalization goals in #962. PR #2467 adds seeded state-transition tests but does not wire GCGAlgorithmConfig.random_seed through all stochastic runtime paths.

Metadata

Metadata

Labels

help wantedExtra attention is needed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions