ActAdd
steerability.algorithms.state_control.act_add
args
ActAdd argument validation.
control
ActAdd (Activation Addition) control implementation.
ActAdd
Bases: InterventionControl
Activation Addition (ActAdd).
Steers model behavior by adding a positional steering vector, computed from a single contrast pair of short prompts, to the residual stream at a single layer. The vector is extracted at the layer-input boundary of each layer and injected at the same boundary, so extraction and injection read and write the same residual point.
The control is declarative: _configure maps the validated args onto one Intervention
at the layer-input boundary with an "all" token scope, since spatial control comes from
the transform's positional injection rather than the mask. Row t of the [T, H] vector
is added at absolute token position alignment + t. When the window
[alignment, alignment + T) lies within the prompt, injection happens entirely on the
prefill pass; when it extends past a shorter prompt, the covered generated positions
receive their rows once each.
Reference:
- "Steering Language Models With Activation Engineering" Alexander Matt Turner, Lisa Thiergart, Gavin Leech, David Udell, Juan J. Vazquez, Ulisse Mini, Monte MacDiarmid https://arxiv.org/abs/2308.10248
Source code in steerability/algorithms/state_control/act_add/control.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
RUNTIME_KWARGS_SCHEMA = []
class-attribute
instance-attribute
_gate
property
The first intervention's gate (None before steer() or when unconditional).
_layer_id
property
The resolved behavior layer (None before steer()).
_steering_vector
property
The bound steering artifact as a SteeringVector view (None before steer()).
_template = ()
class-attribute
instance-attribute
_transform
property
writable
The first intervention's transform (None before steer()).
Assignment replaces the transform on the first intervention, so a wrapped or instrumented transform takes effect in subsequently built hooks.
args = self.Args.validate(*args, **kwargs)
instance-attribute
enabled = True
class-attribute
instance-attribute
hook_only_hint
property
interventions = ()
class-attribute
instance-attribute
supports_batching = False
class-attribute
instance-attribute
tokenizer = None
class-attribute
instance-attribute
__init__(*args, **kwargs)
Source code in steerability/algorithms/core/base_control.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
_configure()
Post-construction hook, called after Args fields are mirrored onto the instance.
Driver presets override this to map their mirrored args onto the fields their generic base
reads, so subclasses never bypass a parent __init__. Default no-op.
Source code in steerability/algorithms/state_control/act_add/control.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
_fit_sources()
Yield the template's fit sources: unbound sources carrying an artifact_class
whose resolution does model-side work (access above ModelAccess.FACTS).
Source code in steerability/algorithms/state_control/base.py
377 378 379 380 381 382 383 384 385 | |
_resolve_module_layout(model=None)
The module-path layout, resolved from the module tree on first use.
Source code in steerability/algorithms/state_control/base.py
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | |
_unbound_sources()
Yield each unbound template element's source (or undeclared factory slot).
Yields the transform sources of unbound transform elements, factory transform slots
themselves (which declare their own access or default to the live model), and
unresolved gate sources, in template order.
Source code in steerability/algorithms/state_control/base.py
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | |
cleanup()
Release resources allocated during steer().
Override in subclasses that allocate GPU memory or other resources during steering. Default no-op.
Source code in steerability/algorithms/core/base_control.py
195 196 197 198 199 200 201 | |
clone_for_call(seed=None)
A per-call clone whose interventions carry independent gate state.
Gates are deep-copied with one shared memo across the control's interventions, so a gate instance shared by several interventions stays shared inside the clone while being isolated from the original and from sibling clones. Transforms, scorers, and steer-time artifacts stay shared.
Source code in steerability/algorithms/state_control/base.py
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | |
export_intervention_spec(runtime_kwargs=None)
The control's InterventionSpec, lowered from the bound interventions, or None.
Must be called after steer(). Returns None when the configuration has no wire form.
Source code in steerability/algorithms/state_control/base.py
320 321 322 323 324 325 326 327 328 329 330 331 332 | |
export_state()
The bound positional steering vector under the "steering_vector" key (after steer()).
Source code in steerability/algorithms/state_control/act_add/control.py
96 97 98 99 | |
fit_identity()
The template's fit sources in template order, each in its encodable form, or None when the template declares no fits.
Source code in steerability/algorithms/state_control/base.py
394 395 396 397 398 399 400 | |
frozen_form(state)
A same-class frozen form: the bound positional vector plus the resolved layer.
normalize_vector is cleared since the exported vector is already in its applied
form.
Source code in steerability/algorithms/state_control/act_add/control.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
get_hooks(input_ids, runtime_kwargs=None, attention_mask=None, **kwargs)
Compile the bound interventions to hooks for the current generation.
Delegates to build_hooks: a fresh hook runtime is created, gates reset to the
logical batch, and one behavior hook is emitted per (intervention, layer).
Generation-time context arrives through **kwargs; model is consulted to resolve
hook module names when steering ran without a live model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
Tensor | dict
|
Prompt token ids of shape |
required |
runtime_kwargs
|
dict | None
|
Unused. |
None
|
attention_mask
|
Tensor | None
|
The prompt attention mask matching |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, list[HookSpec]]
|
Hook specifications with |
Source code in steerability/algorithms/state_control/base.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
requirements()
Backend requirements derived from the declared interventions, per phase.
Generate offers the intervention-spec alternative whenever every component of every intervention has a wire form; hook-only configurations require the in-process backend. Score is in-process: remote prompt-logprob scoring anchors token scopes at the request's prompt end (the end of the prompt-plus-reference concatenation), which would silently unanchor prompt-relative interventions.
Source code in steerability/algorithms/state_control/base.py
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | |
steer(model=None, tokenizer=None, session=None, **kwargs)
Bind the intervention template against the model (or the session's layout).
Structural facts come from the steering session's layout when a session is given, so a
fully concrete template (precomputed vectors, manual thresholds) binds with
model=None. Templates carrying sources (fits, searches) resolve them here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
The base language model, or None for concrete templates bound against a session layout. |
None
|
tokenizer
|
PreTrainedTokenizerBase | None
|
Tokenizer used when fitting sources. |
None
|
session
|
SteeringSession | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
PreTrainedModel | None
|
The input model, unchanged. |
Source code in steerability/algorithms/state_control/base.py
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
steer_access()
The model access the template's steer step requires, folded over its sources.
A fully bound template requires ModelAccess.FACTS, since pure layer selectors
resolve from structural facts available on any session. Otherwise the strongest
declared source access wins; a source or factory slot without an access declaration
builds against the live model, so it counts as ModelAccess.MODULE.
Source code in steerability/algorithms/state_control/base.py
364 365 366 367 368 369 370 371 372 373 374 375 | |
steer_fits()
The template's fit artifacts, i.e. every unbound source carrying an
artifact_class, as (artifact, artifact_class) pairs in template order.
Source code in steerability/algorithms/state_control/base.py
387 388 389 390 391 392 | |
wire_kinds()
The combined wire kinds of the bound interventions (or the template before
steer()), or None when any intervention is hook-only.
Source code in steerability/algorithms/state_control/base.py
334 335 336 337 338 339 340 | |