Common library
steerability.algorithms.state_control.common
State control component library.
estimators
Estimator components for state control.
base
Base class for estimators that learn artifacts during steer().
T = TypeVar('T')
module-attribute
BaseEstimator
Bases: ABC, Generic[T]
Learns an artifact from a model and data during the steer() phase.
The type parameter T is the artifact type (e.g., SteeringVector).
Source code in steerability/algorithms/state_control/common/estimators/base.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
fit(model, tokenizer, **kwargs)
abstractmethod
Fit the estimator and return the learned artifact.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model being steered. Used to extract hidden states. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding training data. |
required |
Returns:
| Type | Description |
|---|---|
T
|
The learned artifact of type T. |
Source code in steerability/algorithms/state_control/common/estimators/base.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
contrastive_direction
Contrastive direction estimator using paired PCA.
PcaMethod = Literal['pca_pairwise', 'pca_center']
module-attribute
logger = logging.getLogger(__name__)
module-attribute
ContrastiveDirectionEstimator
Bases: BaseEstimator[SteeringVector]
Learns per-layer direction vectors from contrastive text pairs via PCA.
Two PCA variants are supported, selected by spec.method:
pca_pairwise: centers each pair(H_l^+, H_l^-)at its midpoint, giving the samples±(H_l^+ - H_l^-)/2, and takes the first principal component of that symmetric set.pca_center: fits PCA on the union of positive and negative pooled activations centered by their grand mean:vector_l = PCA(H_l^+ - mu_l, H_l^- - mu_l)withmu_lthe mean over all examples of both classes.
For both methods the first principal component is oriented so positive examples project above
negative examples (see _orient_direction).
Examples are rendered via render_for_model according to spec.prompt_format and tokenized with
add_special_tokens=False for chat-templated text.
Source code in steerability/algorithms/state_control/common/estimators/contrastive_direction.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 | |
fit(model, tokenizer, *, data, spec, on_progress=None, session=None)
Extract contrastive direction vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
Model to extract hidden states from, or None to extract through |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding the contrastive pairs. |
required |
data
|
ContrastivePairs
|
The positive/negative text pairs. |
required |
spec
|
VectorTrainSpec
|
Training configuration (method, accumulate, batch_size). |
required |
on_progress
|
Callable[[int, int], None] | None
|
Optional |
None
|
session
|
SteeringSession | None
|
A |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
SteeringVector with one direction per layer. |
Source code in steerability/algorithms/state_control/common/estimators/contrastive_direction.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 | |
_orient_direction(direction, positive, negative)
Orient direction so the positive class projects above the negative class.
Uses a majority vote over pairs, breaking ties by the sign of the mean projection margin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
direction
|
Tensor
|
Direction to orient, shape |
required |
positive
|
Tensor
|
Pooled positive activations, shape |
required |
negative
|
Tensor
|
Pooled negative activations, shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
The direction, flipped if positives projected below negatives. |
Source code in steerability/algorithms/state_control/common/estimators/contrastive_direction.py
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 | |
_prepare_pca_samples(positive, negative, method)
Build the PCA sample matrix from pooled positive/negative activations.
pca_pairwise: centers each pair(H^+_i, H^-_i)at its midpoint, yielding the two samples±(H^+_i - H^-_i)/2.pca_center: stacks positive and negative activations and centers by their grand mean.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positive
|
Tensor
|
Pooled positive activations, shape |
required |
negative
|
Tensor
|
Pooled negative activations, shape |
required |
method
|
PcaMethod
|
Which sample construction to use. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
A float32 sample matrix of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the shapes disagree, the method is unsupported, or the samples are non-finite. |
Source code in steerability/algorithms/state_control/common/estimators/contrastive_direction.py
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 | |
mean_difference
Mean difference estimator for CAA steering vectors.
logger = logging.getLogger(__name__)
module-attribute
MeanDifferenceEstimator
Bases: BaseEstimator[SteeringVector]
Learns per-layer steering vectors using the mean difference method.
For each layer, computes: v_L = mean(a_L(positive) - a_L(negative))
where activations are extracted at the last non-pad token position of each example (the answer letter in the CAA prompt format).
This differs from ContrastiveDirectionEstimator which uses PCA on the pairwise differences. Mean difference takes the centroid directly, while PCA finds the direction of maximum variance. They converge when difference vectors are nearly collinear.
Examples are rendered via render_for_model according to spec.prompt_format
and tokenized with add_special_tokens=False for chat-templated text.
Source code in steerability/algorithms/state_control/common/estimators/mean_difference.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
fit(model, tokenizer, *, data, spec, on_progress=None, session=None)
Extract steering vectors using mean difference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
Model to extract hidden states from, or None to extract through |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding the contrastive pairs. |
required |
data
|
ContrastivePairs
|
The positive/negative text pairs. |
required |
spec
|
VectorTrainSpec
|
Training configuration (method, accumulate, batch_size). |
required |
on_progress
|
Callable[[int, int], None] | None
|
Optional |
None
|
session
|
SteeringSession | None
|
A |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
SteeringVector with one direction per layer. |
Source code in steerability/algorithms/state_control/common/estimators/mean_difference.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
single_pair
Single-pair estimator for ActAdd steering vectors.
logger = logging.getLogger(__name__)
module-attribute
SinglePairEstimator
Bases: BaseEstimator[SteeringVector]
Extracts per-token positional steering vectors from a single prompt pair.
Given one positive prompt and one negative prompt, it computes the per-token activation difference at every layer (or a specified subset of layers) at the layer-input boundary, i.e. the residual stream a layer pre-hook observes, preserving the full positional structure of the contrast.
The prompts are tokenized without special tokens, so row t of the result
corresponds to content token t of the (co-padded) pair. The result is a
[T, H] direction matrix per layer, where T is the token length of the
longer prompt, and the artifact records meta["location"] = "layer_input".
Source code in steerability/algorithms/state_control/common/estimators/single_pair.py
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 115 116 117 | |
fit(model, tokenizer, *, positive_prompt, negative_prompt, layer_ids=None, session=None)
Extract positional steering vector from a single prompt pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
Model to extract hidden states from, or None to extract through |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding the prompts. |
required |
positive_prompt
|
str
|
Prompt representing the desired direction (e.g., "Love", "I talk about weddings constantly"). |
required |
negative_prompt
|
str
|
Prompt representing the opposite direction (e.g., "Hate", "I do not talk about weddings constantly"). |
required |
layer_ids
|
list[int] | None
|
If provided, only compute directions for these layers. If None, compute for all layers. |
None
|
session
|
SteeringSession | None
|
A |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
SteeringVector with [T, H] directions per layer. |
Source code in steerability/algorithms/state_control/common/estimators/single_pair.py
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 115 116 117 | |
steering_plane
Steering-plane estimator: per-layer 2D bases for angular steering.
logger = logging.getLogger(__name__)
module-attribute
SteeringPlaneEstimator
Bases: BaseEstimator[SteeringVector]
Learns a 2D steering plane per layer (paper sections 4.4-4.5).
The plane is built offline in three steps:
- Per-layer feature axis computed as the difference in means between positive and negative activations.
- One global companion axis: the first PCA component across the stacked per-layer feature directions.
- Per-layer Gram-Schmidt into an orthonormal
(b1, b2), withb1 = normalize(d_feat)andb2 = normalize(d_PC0 - (d_PC0·b1) b1).
Returns a SteeringVector with directions[layer] of shape [2, H] (row 0 = feature axis,
row 1 = companion axis). The cross-layer PCA explained-variance fraction is stored in
explained_variances under the sentinel key -1.
Reference:
- "Angular Steering: Behavior Control via Rotation in Activation Space" Hieu M. Vu, Tan M. Nguyen https://arxiv.org/abs/2510.26243
Source code in steerability/algorithms/state_control/common/estimators/steering_plane.py
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 | |
fit(model, tokenizer, *, data, spec, on_progress=None, session=None)
Fit the per-layer steering planes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
Model to extract hidden states from. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding the contrastive pairs. |
required |
data
|
ContrastivePairs
|
The positive/negative text pairs. |
required |
spec
|
VectorTrainSpec
|
Training configuration (method, accumulate, batch_size, prompt_format). |
required |
on_progress
|
Callable[[int, int], None] | None
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
SteeringVector with a |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than two layers have usable feature directions, or if no plane survives orthogonalization. |
Source code in steerability/algorithms/state_control/common/estimators/steering_plane.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 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 | |
fit_specs
Configuration for fitting and searching steering artifacts.
Holds the fit-time vocabulary shared by state control components: VectorTrainSpec describes
how direction vectors are extracted, ConditionSearchSpec describes how condition points are
searched, and the comparator vocabulary (Comparator, CompMode) carries the gate-comparison
semantics ("ge" opens when score >= threshold, "le" when score <= threshold). These specs
describe how artifacts are produced; the intervention IR in specs.py describes how bound
artifacts are applied.
CompMode = Literal['mean', 'last']
module-attribute
Comparator = Literal['ge', 'le']
module-attribute
ConditionSearchSpec
dataclass
Configuration for automatic condition point search.
Attributes:
| Name | Type | Description |
|---|---|---|
auto_find |
bool
|
If True, run the search during steer(). If False, the user must provide condition_layer_ids and threshold manually. |
candidate_layers |
Sequence[int] | None
|
Explicit layer ids to search over. If None, use layer_range. |
layer_range |
tuple[int, int] | None
|
0-based (start, end) half-open range of layers to consider. Ignored if candidate_layers is set. Defaults to all layers. |
threshold_range |
tuple[float, float]
|
(min, max) for the threshold grid search (half-open, step-exact). |
threshold_step |
float
|
Step size for the threshold grid. |
Source code in steerability/algorithms/state_control/common/fit_specs.py
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 | |
auto_find = True
class-attribute
instance-attribute
candidate_layers = None
class-attribute
instance-attribute
layer_range = None
class-attribute
instance-attribute
threshold_range = (0.0, 1.0)
class-attribute
instance-attribute
threshold_step = 0.01
class-attribute
instance-attribute
__init__(auto_find=True, candidate_layers=None, layer_range=None, threshold_range=(0.0, 1.0), threshold_step=0.01)
__post_init__()
Source code in steerability/algorithms/state_control/common/fit_specs.py
100 101 102 103 104 105 | |
VectorTrainSpec
dataclass
Configuration for how to train/extract direction vectors.
Attributes:
| Name | Type | Description |
|---|---|---|
method |
Literal['pca_pairwise', 'pca_center', 'mean_diff']
|
Extraction algorithm. "pca_pairwise" uses PCA on paired differences of hidden states. "pca_center" uses PCA on all positive/negative hidden states centered by their grand mean (the CAST extraction from the paper). "mean_diff" uses the mean difference of hidden states (CAA method). |
accumulate |
Literal['all', 'suffix-only', 'last_token']
|
How to select hidden state spans for aggregation. "all" uses the full sequence. "suffix-only" uses only the portion after the shared prompt. "last_token" uses only the final non-pad token position. |
batch_size |
int
|
Batch size for hidden state extraction forward passes. |
prompt_format |
PromptFormat
|
How to render contrastive examples into model-ready text
(via |
location |
HiddenStateLocation
|
Residual-stream boundary each layer key maps to. |
Source code in steerability/algorithms/state_control/common/fit_specs.py
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 | |
accumulate = 'all'
class-attribute
instance-attribute
batch_size = 8
class-attribute
instance-attribute
location = 'layer_output'
class-attribute
instance-attribute
method = 'pca_pairwise'
class-attribute
instance-attribute
prompt_format = 'chat_completion'
class-attribute
instance-attribute
__init__(method='pca_pairwise', accumulate='all', batch_size=8, prompt_format='chat_completion', location='layer_output')
__post_init__()
Source code in steerability/algorithms/state_control/common/fit_specs.py
66 67 68 69 70 71 72 73 74 75 76 | |
gating
Gating for state control interventions.
A gate is an operation on evidence decided by a rule. Evidence names where hidden states are
read (condition layers and pooling) and the Readout that turns pooled hidden states into one
value per row; a Rule is a pure decision over the per-layer values; Gate is the single
stateful shell that collects evidence during a generation, freezes the decision when the rule
reports complete, and answers per-row open/closed queries from behavior hooks. Provenance
(probes, contrastive fits, manual weights) produces readouts; it never appears in gate types.
Wire expressibility is a per-component property: a readout or rule with a wire_kind exports
its wire form, and Gate.export composes them into the wire gate object. A CallableReadout
has no wire form and keeps the intervention in process.
This module also holds the score math shared with selectors/condition_point.py
(rank_one_projector, projected_cosine_similarity_tensor), so selector calibration and
runtime scoring provably agree.
AffineReadout
Signed linear readout: value = weights[layer] . pooled.
Constructed from a per-layer weight mapping or a SteeringVector; probe-backed gates build
one from the probe's weights via gate_from_probe. Returns zeros for layers absent from
the weights. The wire form stacks the weight rows aligned with the evidence layer order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weights
|
SteeringVector | Mapping[int, Tensor]
|
Per-layer weight vectors ( |
required |
location
|
str | None
|
The boundary the weights were fitted at, or None to skip the boundary check. |
None
|
model_fingerprint
|
str | None
|
The fitted model's identity, or None to skip the identity check. |
None
|
Source code in steerability/algorithms/state_control/common/gating.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
location = location
instance-attribute
model_fingerprint = model_fingerprint
instance-attribute
weights = {lid: _feature_row(direction).detach().reshape(-1).to(torch.float32) for lid, direction in _extract_directions(weights, type(self).__name__).items()}
instance-attribute
wire_kind = 'affine'
class-attribute
__call__(pooled, layer_id)
Return [B] values weights[layer_id] . pooled (zeros if the layer is absent).
Source code in steerability/algorithms/state_control/common/gating.py
166 167 168 169 170 171 172 | |
__init__(weights, location=None, model_fingerprint=None)
Source code in steerability/algorithms/state_control/common/gating.py
153 154 155 156 157 158 159 160 161 162 163 164 | |
export(layer_ids)
The affine wire form: weights [L, H] row-aligned with layer_ids.
Source code in steerability/algorithms/state_control/common/gating.py
174 175 176 177 178 179 180 181 | |
CallableReadout
Escape hatch wrapping any (pooled [B, H], layer_id) -> Tensor [B] callable.
Has no wire form, so a gate built on it never lowers; support verdicts attribute the in-process-only status to the readout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[Tensor, int], Tensor]
|
The readout callable. |
required |
location
|
str | None
|
The boundary the callable expects features at, or None to skip the check. |
None
|
model_fingerprint
|
str | None
|
The fitted model's identity, or None to skip the check. |
None
|
Source code in steerability/algorithms/state_control/common/gating.py
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | |
fn = fn
instance-attribute
location = location
instance-attribute
model_fingerprint = model_fingerprint
instance-attribute
wire_kind = None
class-attribute
__call__(pooled, layer_id)
Source code in steerability/algorithms/state_control/common/gating.py
331 332 | |
__init__(fn, location=None, model_fingerprint=None)
Source code in steerability/algorithms/state_control/common/gating.py
321 322 323 324 325 326 327 328 329 | |
export(layer_ids)
None; an arbitrary callable has no wire form.
Source code in steerability/algorithms/state_control/common/gating.py
334 335 336 | |
CosineReadout
Signed cosine similarity between the pooled state and a per-layer direction.
[K, H] artifacts use row 0. Returns zeros for layers absent from the directions. The
score is signed: for a mean-difference direction, positives score high, negatives score
low, and unrelated content scores near zero, so a "ge" threshold fails closed on
out-of-distribution inputs. Prefer this readout for topic or domain gates whose calibration
negatives cannot cover the deployment input space; signed scores can be negative, so pair
it with a threshold range that admits negative values, e.g. (-1.0, 1.0).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directions
|
SteeringVector | Mapping[int, Tensor]
|
Per-layer directions, a |
required |
location
|
str | None
|
The boundary the directions were fitted at, or None to skip the check. |
None
|
model_fingerprint
|
str | None
|
The fitted model's identity, or None to skip the check. |
None
|
Reference:
- "Steering Llama 2 via Contrastive Activation Addition" Nina Panickssery, Nick Gabrieli, Julian Schulz, Meg Tong, Evan Hubinger, Alexander Matt Turner https://arxiv.org/abs/2312.06681
Source code in steerability/algorithms/state_control/common/gating.py
184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 | |
directions = _extract_directions(directions, type(self).__name__)
instance-attribute
location = location
instance-attribute
model_fingerprint = model_fingerprint
instance-attribute
wire_kind = 'cosine'
class-attribute
__call__(pooled, layer_id)
Return [B] signed cosine values for layer_id (zeros if the layer is absent).
Source code in steerability/algorithms/state_control/common/gating.py
218 219 220 221 222 223 224 225 | |
__init__(directions, location=None, model_fingerprint=None)
Source code in steerability/algorithms/state_control/common/gating.py
208 209 210 211 212 213 214 215 216 | |
export(layer_ids)
The cosine wire form: directions [L, H] row-aligned with layer_ids.
Source code in steerability/algorithms/state_control/common/gating.py
227 228 229 230 231 232 233 234 235 236 | |
Evidence
dataclass
Where gate evidence is read and how hidden states become values.
Attributes:
| Name | Type | Description |
|---|---|---|
layer_ids |
tuple[int, ...]
|
Condition layers (0-based decoder-layer indices at the intervention's boundary). |
readout |
Readout
|
Per-layer map from pooled hidden states to per-row values. |
pooling |
Literal['mean', 'last']
|
Token aggregation over real (non-pad) prompt positions: |
Source code in steerability/algorithms/state_control/common/gating.py
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | |
layer_ids
instance-attribute
pooling = 'mean'
class-attribute
instance-attribute
readout
instance-attribute
__init__(layer_ids, readout, pooling='mean')
__post_init__()
Source code in steerability/algorithms/state_control/common/gating.py
355 356 357 358 359 360 | |
Gate
The stateful shell around evidence and a rule; holds one decision per logical batch row.
Lifecycle per generation call:
1. `reset(num_rows)` clears state from the previous generation and sizes the gate to
the logical batch (number of prompts, not the beam-expanded batch). Reset is
idempotent: re-resetting an already-reset gate to the same size leaves it in the
same cleared state, which shared-instance composition (one gate read by several
interventions) relies on.
2. `update(values, key=layer_id)` records one condition layer's per-row values as
evidence arrives from condition hooks. When the rule first reports complete
(typically once every evidence layer has reported on the prefill pass), the
decision is computed once, frozen for the generation, and the stored values are
dropped after copying into the diagnostics snapshot.
3. `open_rows()` is queried by behavior hooks; all rows are closed before evidence.
is_ready() reports True once the decision is frozen; the runtime stops condition scoring
then, so the prompt is scored once and the decision holds. A rule whose is_complete
never returns True re-scores every pass (in-process only; wire gates are prompt-decided by
construction).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
evidence
|
Evidence
|
Where evidence is read and how hidden states become values. |
required |
rule
|
Rule
|
The decision over the collected values. |
required |
Source code in steerability/algorithms/state_control/common/gating.py
473 474 475 476 477 478 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 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | |
_decision = None
instance-attribute
_snapshot = {}
instance-attribute
_values = {}
instance-attribute
evidence = evidence
instance-attribute
num_rows = 1
instance-attribute
rule = rule
instance-attribute
__init__(evidence, rule)
Source code in steerability/algorithms/state_control/common/gating.py
500 501 502 503 504 505 506 | |
_coerce_values(values)
Normalize values to a float32 [num_rows] CPU tensor, enforcing the row contract.
Source code in steerability/algorithms/state_control/common/gating.py
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | |
evidence_values()
Per-layer value tensors ([num_rows] each) behind the frozen decision.
Empty before the freeze; retained for diagnostics after the stored values are dropped.
Source code in steerability/algorithms/state_control/common/gating.py
573 574 575 576 577 578 | |
export(register)
The wire gate object, or None when the configuration has no wire form.
The readout's tensors are content-addressed through register; rule params inline.
The caller maps layers to wire indices before export, so the layer values here are
the caller's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
register
|
Callable[[Mapping[str, Tensor]], str]
|
Callable mapping a tensor payload to its content-addressed artifact id. |
required |
Returns:
| Type | Description |
|---|---|
dict | None
|
The wire gate dict ( |
dict | None
|
the evidence layers for the caller to remap, or None. |
Source code in steerability/algorithms/state_control/common/gating.py
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | |
from_config(params, *, readout_tensors=None)
classmethod
Rebuild a gate from its serialized form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
dict
|
The serialized params ( |
required |
readout_tensors
|
Mapping[str, Tensor] | None
|
The readout's stacked tensors, row-aligned with |
None
|
Returns:
| Type | Description |
|---|---|
'Gate'
|
The assembled |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the readout or rule kind is unknown, or the stacked tensor rows do not match the layer count. |
Source code in steerability/algorithms/state_control/common/gating.py
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 | |
is_open()
Scalar convenience: True if any row is open (exact for num_rows == 1).
Source code in steerability/algorithms/state_control/common/gating.py
565 566 567 | |
is_ready()
True once the decision is frozen.
Source code in steerability/algorithms/state_control/common/gating.py
569 570 571 | |
open_rows()
Per-row decision of shape [num_rows].
Returns the frozen decision once the rule has reported complete; before that, the rule is evaluated live over the values collected so far (all-closed before any evidence, since both shipped rules decide all-closed on empty values).
Source code in steerability/algorithms/state_control/common/gating.py
553 554 555 556 557 558 559 560 561 562 563 | |
reset(num_rows=1)
Clear all per-generation state and size the gate to num_rows logical rows.
Source code in steerability/algorithms/state_control/common/gating.py
508 509 510 511 512 513 514 515 | |
to_config()
The gate's serialized form: (params, readout tensors).
Params carry the evidence layers, pooling, the readout's kind, boundary, and recorded model fingerprint, and the rule's kind and parameters; the readout's per-layer tensors are returned stacked row-aligned with the evidence layers, using the readout's wire names.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the readout or rule has no wire form (e.g. |
Source code in steerability/algorithms/state_control/common/gating.py
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | |
update(values, *, key)
Record one condition layer's per-row values; freeze the decision on completion.
Updates after the freeze are ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Tensor | float
|
Per-row values of shape |
required |
key
|
int
|
The condition layer id the values belong to. |
required |
Source code in steerability/algorithms/state_control/common/gating.py
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | |
wire_kinds()
The ({readout kind}, {rule kind}) pair, or None when either has no wire form.
Source code in steerability/algorithms/state_control/common/gating.py
580 581 582 583 584 585 586 | |
GateSource
Bases: Protocol
A recipe resolving to a Gate (or None for unconditional) for a model.
Occupies an Intervention's gate slot; Intervention.bind resolves it once. The declared
wire kinds are class-level facts so Intervention.wire_kinds() can run before binding;
None marks the resolved gating hook-only.
Source code in steerability/algorithms/state_control/common/gating.py
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 | |
wire_readouts
class-attribute
wire_rules
class-attribute
resolve_gate(model, tokenizer, *, layout=None, session=None)
Return the resolved gate, or None for unconditional configurations.
Source code in steerability/algorithms/state_control/common/gating.py
711 712 713 | |
PerKeyThreshold
Per-layer threshold comparison, combined across layers with any/all.
"ge" opens a layer's vote when its value is at or above the threshold; "le" when at or
below. aggregate="any" opens a row when any layer passes for that row; "all" requires
every layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float
|
Score threshold for the per-layer comparison. |
required |
comparator
|
Literal['ge', 'le']
|
|
'ge'
|
aggregate
|
Literal['any', 'all']
|
|
'any'
|
Source code in steerability/algorithms/state_control/common/gating.py
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | |
aggregate = aggregate
instance-attribute
comparator = comparator
instance-attribute
threshold = float(threshold)
instance-attribute
wire_kind = 'per_key_threshold'
class-attribute
__init__(threshold, comparator='ge', aggregate='any')
Source code in steerability/algorithms/state_control/common/gating.py
427 428 429 430 431 432 433 434 435 436 437 438 439 | |
decide(values, num_rows)
Per-row decision across layers; all-closed when no values have arrived.
Source code in steerability/algorithms/state_control/common/gating.py
441 442 443 444 445 446 447 448 449 450 451 452 | |
export()
The per_key_threshold wire form with inline threshold, comparator, and
aggregate params.
Source code in steerability/algorithms/state_control/common/gating.py
458 459 460 461 462 463 464 465 466 467 468 469 470 | |
is_complete(seen, expected)
True once every expected layer has reported.
Source code in steerability/algorithms/state_control/common/gating.py
454 455 456 | |
ProjectedCosineReadout
Projected-cosine score: cosine(pooled, tanh(pooled @ P_layer)) with
P = dd^T / (d . d).
[K, H] artifacts use row 0. Rank-one projectors are built lazily and cached per
(layer_id, device). Returns zeros for layers absent from the directions. The score is
approximately |cos(pooled, d)| (alignment with the line spanned by the direction,
erasing which side of the direction a state lies on).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directions
|
SteeringVector | Mapping[int, Tensor]
|
Per-layer condition directions, a |
required |
location
|
str | None
|
The boundary the directions were fitted at, or None to skip the check. |
None
|
model_fingerprint
|
str | None
|
The fitted model's identity, or None to skip the check. |
None
|
Reference:
- "Programming Refusal with Conditional Activation Steering" Bruce W. Lee, Inkit Padhi, Karthikeyan Natesan Ramamurthy, Erik Miehling, Pierre Dognin, Manish Nagireddy, Amit Dhurandhar https://arxiv.org/abs/2409.05907
Source code in steerability/algorithms/state_control/common/gating.py
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 | |
_projector_cache = {}
instance-attribute
directions = _extract_directions(directions, type(self).__name__)
instance-attribute
location = location
instance-attribute
model_fingerprint = model_fingerprint
instance-attribute
wire_kind = 'projected_cosine'
class-attribute
__call__(pooled, layer_id)
Return [B] projected-cosine values for layer_id (zeros if the layer is absent).
Source code in steerability/algorithms/state_control/common/gating.py
287 288 289 290 291 292 293 | |
__init__(directions, location=None, model_fingerprint=None)
Source code in steerability/algorithms/state_control/common/gating.py
264 265 266 267 268 269 270 271 272 273 | |
_projector(layer_id, device)
Cached [H, H] rank-one projector for a layer, or None when the layer is absent.
Source code in steerability/algorithms/state_control/common/gating.py
275 276 277 278 279 280 281 282 283 284 285 | |
export(layer_ids)
The projected_cosine wire form: directions [L, H] row-aligned with layer_ids.
Source code in steerability/algorithms/state_control/common/gating.py
295 296 297 298 299 300 301 302 303 304 | |
Readout
Bases: Protocol
Per-layer map from pooled hidden state to a per-row value.
Callable as (pooled [B, H], layer_id) -> Tensor [B] (float32, cpu). Readouts are
stateless per-layer functions of pooled hidden states; pooling is declared once, on
Evidence. location and model_fingerprint are validated by Intervention.bind when
non-None. export(layer_ids) returns the wire form (kind plus row-aligned tensors) or
None; wire_kind is the class-level kind name, or None for readouts with no wire form.
Source code in steerability/algorithms/state_control/common/gating.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
location
instance-attribute
model_fingerprint
instance-attribute
wire_kind
class-attribute
__call__(pooled, layer_id)
Source code in steerability/algorithms/state_control/common/gating.py
132 | |
export(layer_ids)
Source code in steerability/algorithms/state_control/common/gating.py
134 | |
Rule
Bases: Protocol
Pure decision over per-layer evidence values. Stateless.
decide maps the collected values (one [num_rows] tensor per layer) to a [num_rows]
boolean row tensor; is_complete reports whether the collected evidence suffices to
decide; export() returns the wire form or None; wire_kind is the class-level kind
name, or None for rules with no wire form.
Source code in steerability/algorithms/state_control/common/gating.py
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | |
wire_kind
class-attribute
decide(values, num_rows)
Source code in steerability/algorithms/state_control/common/gating.py
375 | |
export()
Source code in steerability/algorithms/state_control/common/gating.py
379 | |
is_complete(seen, expected)
Source code in steerability/algorithms/state_control/common/gating.py
377 | |
SumThreshold
Open where sum over layers of values + bias >= 0 (ties open).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bias
|
float
|
Offset added to the summed values before the zero comparison. |
0.0
|
Source code in steerability/algorithms/state_control/common/gating.py
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | |
bias = float(bias)
instance-attribute
wire_kind = 'sum_threshold'
class-attribute
__init__(bias=0.0)
Source code in steerability/algorithms/state_control/common/gating.py
391 392 | |
decide(values, num_rows)
Per-row decision at the bias; all-closed when no values have arrived.
Source code in steerability/algorithms/state_control/common/gating.py
394 395 396 397 398 399 | |
export()
The sum_threshold wire form with the inline bias param.
Source code in steerability/algorithms/state_control/common/gating.py
405 406 407 408 409 | |
is_complete(seen, expected)
True once every expected layer has reported.
Source code in steerability/algorithms/state_control/common/gating.py
401 402 403 | |
_extract_directions(artifact, who)
Validate and extract a concrete per-layer directions mapping from an artifact.
Source code in steerability/algorithms/state_control/common/gating.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
_feature_row(direction)
The [H] feature row of a direction; [K, H] artifacts use row 0.
Source code in steerability/algorithms/state_control/common/gating.py
110 111 112 113 114 | |
gate_from_probe(probe, *, allow_model_mismatch=False)
A gate reproducing the probe's decision: affine evidence summed at the calibrated bias.
The gate reads the probe's layers at the probe's pooling, scores each layer's pooled state
as weights[layer] . pooled, and opens where the sum plus probe.bias is at or above
zero (ties open), matching Probe.predict bit-for-bit for the same hidden states (affine
pooling commutes with scoring).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probe
|
Probe
|
The fitted probe whose decision admits the intervention. |
required |
allow_model_mismatch
|
bool
|
When True, the readout's |
False
|
Returns:
| Type | Description |
|---|---|
Gate
|
The assembled |
Source code in steerability/algorithms/state_control/common/gating.py
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | |
projected_cosine_similarity(hidden_state, projector)
Projected-cosine score of one aggregated hidden state.
Projects the hidden state through the condition subspace projector, applies tanh, then computes cosine similarity with the original.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_state
|
Tensor
|
Shape |
required |
projector
|
Tensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
float
|
Cosine similarity as a float. |
Source code in steerability/algorithms/state_control/common/gating.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
projected_cosine_similarity_tensor(hidden, projector)
Cosine similarity between rows of hidden and their tanh'd projections, one score per row.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
projector
|
Tensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Scores of shape |
Source code in steerability/algorithms/state_control/common/gating.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
rank_one_projector(direction)
Build the rank-one projector cc^T / (c^T c) for a direction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
direction
|
Tensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Projection matrix of shape |
Source code in steerability/algorithms/state_control/common/gating.py
34 35 36 37 38 39 40 41 42 43 44 45 46 | |
hook_utils
Utilities for hook registration and model inspection.
extract_hidden_states(input_args, input_kwargs)
Extract hidden_states tensor from a pre-hook's arguments.
HuggingFace transformer layers receive hidden_states either as the first positional argument or as a keyword argument.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_args
|
tuple
|
Positional args from the pre-hook. |
required |
input_kwargs
|
dict
|
Keyword args from the pre-hook. |
required |
Returns:
| Type | Description |
|---|---|
Tensor | None
|
The hidden_states tensor, or None if not found. |
Source code in steerability/algorithms/state_control/common/hook_utils.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
get_model_layer_list(model)
Return (layer_modules, layer_name_strings) for a HuggingFace model.
Supports the decoder-stack roots model.layers (Llama/Mistral/Qwen/Gemma text),
model.language_model.layers (composite multimodal wrappers), and transformer.h (GPT-2),
including PEFT-wrapped models.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
A HuggingFace causal LM. |
required |
Returns:
| Type | Description |
|---|---|
tuple[list, list[str]]
|
Tuple of (list of nn.Module layers, list of dotted name strings). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If model architecture is not recognized. |
Source code in steerability/algorithms/state_control/common/hook_utils.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
get_norm_module_names(model)
Return (layer_id, module_path) pairs for the per-layer normalization sub-modules.
Returns the residual-stream normalization sub-modules named by the resolved layout:
gemma_style:input_layernorm,pre_feedforward_layernorm.llama_style(Llama/Mistral/Qwen):input_layernorm,post_attention_layernorm.gpt2_style:ln_1,ln_2.
Only names that exist on the module are returned, sorted by (layer_id, module_path).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
A HuggingFace causal LM. |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[int, str]]
|
List of |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the model architecture is not recognized. |
Source code in steerability/algorithms/state_control/common/hook_utils.py
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 | |
replace_hidden_states(input_args, input_kwargs, new_hidden)
Return modified (input_args, input_kwargs) with hidden_states replaced.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_args
|
tuple
|
Original positional args. |
required |
input_kwargs
|
dict
|
Original keyword args. |
required |
new_hidden
|
Tensor
|
Replacement hidden states tensor. |
required |
Returns:
| Type | Description |
|---|---|
tuple[tuple, dict]
|
Tuple of (new_input_args, new_input_kwargs). |
Source code in steerability/algorithms/state_control/common/hook_utils.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
layout_facts
Structural model facts for steer-time preparation.
State controls consume structural facts (layer count, dtype, hidden size) from the steering
session's ModelFacts so preparation works the same whether the steering backend holds a live
model or only a layout. Module-path resolution stays out of this module; hook module names are
resolved from the module tree at get_hooks() time.
cast_steering_vector(steering_vector, layout)
A clone of steering_vector with per-layer directions cast to the layout dtype.
Device placement is untouched; transforms move tensors to the stream device at apply time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steering_vector
|
SteeringVector
|
The |
required |
layout
|
ModelFacts
|
The structural layout naming the target dtype. |
required |
Returns:
| Type | Description |
|---|---|
SteeringVector
|
The cast clone. |
Source code in steerability/algorithms/state_control/common/layout_facts.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
layout_torch_dtype(layout)
The torch dtype named by layout.dtype.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/state_control/common/layout_facts.py
86 87 88 89 90 91 92 93 94 95 | |
resolve_layout(model=None, session=None)
Structural facts from the session's layout, else derived from the live model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
A live model, consulted only when |
None
|
session
|
SteeringSession | None
|
A |
None
|
Returns:
| Type | Description |
|---|---|
ModelFacts
|
The structural |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither a session nor a model is available. |
Source code in steerability/algorithms/state_control/common/layout_facts.py
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 | |
lowering
The wire compiler from bound interventions to intervention-spec payloads.
lower_interventions compiles a bound Intervention tuple into an InterventionSpec for
intervention-capable backends, folding each component's wire form and content-addressing
tensor payloads via artifact_id_for. Its counterpart, build_hooks in runtime.py,
compiles the same IR into torch hooks for one generation.
_lower_gate(gate, boundary, num_layers, register)
The wire gate for one intervention, or None (raised to the caller as hook-only).
A None gate lowers to an ungated op (the caller omits the gate field). The gate's evidence layers are mapped to wire indices at the readout's declared boundary (falling back to the intervention's boundary when the readout declares none), preserving the readout tensor's row alignment since the mapping is order-preserving.
Source code in steerability/algorithms/state_control/common/lowering.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
_map_behavior_layer(layer_id, boundary, site, num_layers)
Map a toolkit behavior layer onto its wire layer index, or None when unmappable.
A wire op applies at the residual-stream boundary after decoder layer N. A
"layer_output" hook at layer l is wire layer l; a "layer_input" hook at layer l
is wire layer l - 1 (layer 0 has no wire form); the "o_proj" site keeps its layer
index, matching the wire head_additive placement.
Source code in steerability/algorithms/state_control/common/lowering.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
_map_condition_layers(layer_ids, boundary, num_layers)
Map toolkit condition layers onto wire layer indices, or None when unmappable.
A wire gate's condition layers read the materialized input of decoder layer N, so
layers read at "layer_output" shift to l + 1.
Source code in steerability/algorithms/state_control/common/lowering.py
64 65 66 67 68 69 70 71 72 73 74 75 76 | |
artifact_id_for(tensors)
The content-addressed artifact id and prepared tensors for a tensor payload.
Tensors are prepared as float32, contiguous, CPU copies (cloned before the cast, so the
live steering artifacts are never mutated or aliased), and the id is the SHA-256 over the
safetensors serialization with sorted tensor names, matching the plugin registry's write
byte-for-byte. Identical logical content therefore yields identical ids regardless of the
producing device or dtype.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensors
|
Mapping[str, Tensor]
|
Mapping from tensor name to tensor. |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, dict[str, Tensor]]
|
The |
Source code in steerability/algorithms/state_control/common/lowering.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
lower_interventions(interventions, *, num_layers)
Lower bound interventions to an InterventionSpec, or None when any element has no
wire form.
Folds each component's export, unwrap_modifiers, the scope export, and the gate's
export. One wire op is emitted per (intervention, layer), in intervention order then
ascending layer order; artifact ids are content hashes, so layers sharing a tensor share
one artifact. The assembled spec is pre-flight validated with the plugin's
parse_intervention_spec, so a malformed spec fails here with the same E_* code and
JSON path the server would return.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
interventions
|
Sequence[Intervention]
|
Bound interventions, in application order. |
required |
num_layers
|
int
|
Decoder layer count from the model layout. |
required |
Returns:
| Type | Description |
|---|---|
'InterventionSpec | None'
|
The validated spec with tensor payloads attached, or None. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the assembled spec fails pre-flight validation (a toolkit-side
serialization bug; the message carries the |
ModuleNotFoundError
|
If |
Source code in steerability/algorithms/state_control/common/lowering.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
model_layout
Compatibility re-export; the layout lives in steerability.algorithms.core.internals.model_layout.
runtime
Shared hook runtime for transform-based state controls.
TransformHookRuntime builds the hook closures used by residual-stream state controls and
owns one control's per-generation mutable state. It covers hidden-state extraction and
re-wrapping, KV-cache position tracking, token-scope masking, condition scoring, and gated
transform application. Four behaviors define the runtime's contract:
-
Position tracking: Each pass's absolute position offset is read from the hooked module's pass positions when it supplies them (from the
cache_positionkwarg, or reconstructed fromposition_ids; decoder layers receiveposition_idson every pass), so positions are exact per forwarded sequence even when a decoding driver issues severalgeneratecalls or an output control forwards the model mid-step. Hook points whose modules receive neither kwarg (attention output projections, norm sub-modules) fall back to counting, which assumes the model processes the full prompt on the prefill pass and one new token per decode pass; exactly one designated pass-opener hook advances the shared offset by the observed sequence length once per pass, and every other hook in that pass reads the opener's snapshot. The fallback assumes a singlegeneratecall per generation. -
Row gating: Gates hold one decision per logical row, one per prompt. HuggingFace
generatemay expand the hidden batch toB_logical * num_beamsviarepeat_interleave. The runtime collapses condition scores from the expanded batch to logical rows before callinggate.update(), and expandsgate.open_rows()back to the hidden batch before masking hidden states. Beam siblings of one prompt share that prompt's decision, and each prompt in a batch is gated independently. -
Condition scoring: A condition hook computes evidence values only while its gate has not frozen its decision. Scoring stops for the remainder of the generation once
gate.is_ready()returns True. -
Auxiliary passes: Forwards marked via
auxiliary_pass()(same-model candidate scoring, variant-prompt branches) never feed condition scorers or gates and never advance the fallback counter. Trajectory-aligned auxiliary passes are transformed at their true positions when the pass positions are available; detached ones are never transformed.
HookPoint = Literal['layer_output', 'layer_input']
module-attribute
TransformHookRuntime
Builds hook closures and owns the per-generation position/prefill/mask state for one control.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hook_point
|
HookPoint
|
Where the control intervenes. |
'layer_output'
|
Source code in steerability/algorithms/state_control/common/runtime.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | |
_clock_seen = False
instance-attribute
_offset = 0
instance-attribute
_opener_built = False
instance-attribute
_pass_offset = 0
instance-attribute
_prefill_seen = False
instance-attribute
_prompt_lens = None
instance-attribute
_prompt_mask = None
instance-attribute
_warned = set()
instance-attribute
hook_point = hook_point
instance-attribute
num_logical_rows
property
Logical batch size (one row per prompt); 0 before reset.
__init__(*, hook_point='layer_output')
Source code in steerability/algorithms/state_control/common/runtime.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
_apply(hidden, layer_id, transform, gate, token_scope, last_k, from_position, is_pass_opener, forward_kwargs=None)
Mask the current pass by token scope and per-row gate decision, then apply the transform.
The pass's absolute position offset is forwarded to transform.apply as
position_offset, so position-dependent transforms place their edits in absolute
sequence coordinates. A None gate leaves every row open. Auxiliary passes without a
resolvable position are returned unchanged.
Source code in steerability/algorithms/state_control/common/runtime.py
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | |
_claim_opener(is_pass_opener)
Enforce that at most one hook per generation is designated the pass opener.
Two openers would advance the shared offset twice per forward pass, silently skewing
every position-dependent token scope (e.g. after_prompt would steer the whole
prompt). Controls must designate exactly one opener; when a layer hosts both a
condition and a behavior hook, the one registered first opens the pass. The opener only
matters for the fallback counter; when positions come from cache_position, every hook
resolves its offset independently.
Source code in steerability/algorithms/state_control/common/runtime.py
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | |
_collapse_to_rows(values, hidden_batch)
Collapse per-hidden-row evidence values down to the logical rows the gate holds.
Beam search expands the batch via repeat_interleave ([i0, i0, i1, i1]), so the first
member of each group represents its logical row, and that row is taken as the group's
value. Values already at logical size pass through; a bare float passes through for the
gate to validate (accepted only when num_rows == 1).
Source code in steerability/algorithms/state_control/common/runtime.py
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
_extract_pass_positions(forward_kwargs, seq_len)
staticmethod
The pass's cache-axis positions from the hooked module's kwargs, when recoverable.
Prefers the cache_position kwarg (transformers threads it into decoder layers only when
the model caller passes it explicitly). When absent, the padded-cache-axis offset is
reconstructed from position_ids, which transformers v5 forwards to decoder layers on
every pass: the longest row of a batch is unpadded, so its positions coincide with the
padded cache axis and max(position_ids) - (seq_len - 1) is the pass's start offset.
Neither kwarg reaches non-decoder hook points (e.g. o_proj inputs), which keep the
counting fallback.
Source code in steerability/algorithms/state_control/common/runtime.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
_position_offset(seq_len, cache_position, is_pass_opener)
Resolve the absolute position offset for the current pass, or None to skip the pass.
Auxiliary passes (marked via auxiliary_pass()) never advance the fallback counter. An
aligned auxiliary pass is positioned by the pass positions when the hooked module supplies
them (from cache_position or position_ids) and skipped otherwise; a detached auxiliary
pass is always skipped. Ordinary passes take their offset from the pass positions when
present. The opener maintains the fallback counter on every ordinary pass, so hook points
without either kwarg keep the one-pass-one-step accounting unchanged and an anomalous pass
missing them degrades to counting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seq_len
|
int
|
The sequence length seen by this hook on this call. |
required |
cache_position
|
Tensor | None
|
The pass positions (from |
required |
is_pass_opener
|
bool
|
Whether this hook is the designated pass opener. |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
The absolute position offset to use when building the token mask, or None when the |
int | None
|
pass must be skipped. |
Warns:
| Type | Description |
|---|---|
UserWarning
|
Once per generation for each of: an aligned auxiliary pass at a hook point without pass positions (its transform is skipped); a multi-token ordinary pass after prefill at such a hook point (a multi-call decode pattern that counting cannot place); pass positions disappearing after having been observed. |
Source code in steerability/algorithms/state_control/common/runtime.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
_prefill_prompt_mask(hidden, pass_offset)
The stored prompt mask aligned to the hidden batch, on the prefill pass only.
The first pass may be longer than the prompt when a teacher-forced continuation is
appended (e.g. compute_logprobs forwards [prompt; ref] in one pass). The continuation
columns are not prompt, so the mask is extended with False there, and condition
aggregation then covers exactly the real prompt tokens, reproducing generation-time
scoring. A first pass shorter than the stored mask indicates misuse and raises.
Source code in steerability/algorithms/state_control/common/runtime.py
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | |
_row_mask_for(gate, hidden)
Per-row gate decision expanded to the hidden batch as a [B_hidden, 1] mask.
Returns None when every row is closed (caller short-circuits). align_mask_to_batch
performs the beam expansion and validates divisibility.
Source code in steerability/algorithms/state_control/common/runtime.py
279 280 281 282 283 284 285 286 287 288 289 | |
_warn_once(key, message)
Emit message as a UserWarning at most once per generation (keyed by key).
Source code in steerability/algorithms/state_control/common/runtime.py
172 173 174 175 176 177 | |
build_behavior_hook(*, layer_id, transform, gate, token_scope, last_k=None, from_position=None, is_pass_opener=False, hook_point=None)
Build a hook that applies transform to the residual stream at layer_id, gated by gate.
The transform fires at the intersection of the token-scope mask and the gate's per-row decision (expanded across beams); a fully closed gate is a no-op, and a None gate leaves every row open.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_id
|
int
|
Index of the hooked layer (used to index per-layer transform artifacts). |
required |
transform
|
BaseTransform
|
The transform to apply at masked positions of open rows. |
required |
gate
|
Gate | None
|
Gate consulted per call, or None for unconditional application; row |
required |
token_scope
|
ScopeKind
|
Which positions to steer (see |
required |
last_k
|
int | None
|
Required when |
None
|
from_position
|
int | None
|
Required when |
None
|
is_pass_opener
|
bool
|
Whether this hook advances the shared position offset. |
False
|
hook_point
|
HookPoint | None
|
Per-hook boundary override; defaults to the runtime's constructor value, so one runtime can host hooks at both boundaries. |
None
|
Returns:
| Type | Description |
|---|---|
Callable
|
A hook callable suitable for the effective hook point (a forward hook for |
Callable
|
|
Source code in steerability/algorithms/state_control/common/runtime.py
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
build_condition_hook(*, layer_id, gate, is_pass_opener=False, hook_point=None)
Build a read-only hook that scores the residual stream at layer_id and updates gate.
The hook never modifies hidden states. On each pass where the gate has not frozen its
decision (not gate.is_ready()), it pools the hidden states per the gate's evidence
(passing the pad-aware prompt mask on the prefill pass), computes per-row values via
the evidence readout, collapses beam-expanded values to logical rows, and calls
gate.update(rows, key=layer_id). Once the gate is ready, scoring is skipped
entirely, and a gate whose rule never reports complete keeps re-scoring every pass.
The hook still participates in pass-opener bookkeeping when the lowest hooked layer is
a condition layer. Auxiliary passes are ignored entirely: no scoring, no gate update,
no accounting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_id
|
int
|
Index of the hooked layer. |
required |
gate
|
Gate
|
Gate whose evidence is read at this layer and fed the per-row values. |
required |
is_pass_opener
|
bool
|
Whether this hook advances the shared position offset. |
False
|
hook_point
|
HookPoint | None
|
Per-hook boundary override; defaults to the runtime's constructor value. |
None
|
Returns:
| Type | Description |
|---|---|
Callable
|
A hook callable suitable for the effective hook point. |
Source code in steerability/algorithms/state_control/common/runtime.py
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | |
reset(prompt_lens, prompt_mask=None)
Clear position/prefill state and store the prompt lengths/mask for this generation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt_lens
|
LongTensor
|
Per-row prompt lengths of shape |
required |
prompt_mask
|
Tensor | None
|
Optional pad-aware prompt attention mask of shape
|
None
|
Source code in steerability/algorithms/state_control/common/runtime.py
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 115 116 117 118 119 120 121 | |
_submodule_exists(model, module_path)
True when module_path resolves on the model's module tree.
Source code in steerability/algorithms/state_control/common/runtime.py
639 640 641 642 643 644 645 | |
build_hooks(interventions, layout, prompt_lens, prompt_mask=None, model=None)
Compile bound interventions to torch hooks for one logical generation.
Creates a fresh TransformHookRuntime (per-generation position state is born here), resets
every intervention's gate to the logical batch size (gate reset is idempotent, so a gate
instance shared across interventions is reset harmlessly more than once), and emits one
behavior hook per (intervention, layer) plus one condition hook per
(intervention.gate.evidence, layer). An intervention whose gate is None builds no condition
hooks and its behavior hooks apply with every row open; an intervention marked
gate_driven_externally builds no condition hooks either, since another intervention's
hooks feed its shared gate. Condition hooks precede behavior hooks so a gate update runs
before the transform at a shared layer. Exactly one hook opens each pass: the first-firing
hook of the lowest hooked layer across the tuple.
Module paths derive from each intervention's resolved site: decoder layers for residual
transforms, the attention output projection for head_additive, and each layer's
normalization sub-modules for the "norm_input" site. The intervention's boundary picks
the hook phase ("layer_output" builds forward hooks, "layer_input" forward pre-hooks);
the o_proj and "norm_input" sites hook module inputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
interventions
|
Sequence['Intervention']
|
Bound interventions, in application order. |
required |
layout
|
'ModelFacts'
|
The module-path |
required |
prompt_lens
|
Tensor
|
Per-row prompt lengths of shape |
required |
prompt_mask
|
Tensor | None
|
Optional pad-aware prompt attention mask of shape |
None
|
model
|
'PreTrainedModel | None'
|
Optional live model, consulted only to skip norm sub-modules a layer does not
define at the |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, list]
|
Hook specifications keyed by phase ( |
dict[str, list]
|
mapping with |
Raises:
| Type | Description |
|---|---|
ValueError
|
If an intervention is unbound, a layer has no module path in |
Source code in steerability/algorithms/state_control/common/runtime.py
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 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | |
selectors
Selector components for state control.
base
Base class for selectors that choose control sites and parameters.
T = TypeVar('T')
module-attribute
BaseSelector
Bases: ABC, Generic[T]
Selects where and how to apply a control, given a model and artifacts.
The type parameter T describes the selection output (e.g., a list of layer ids, or a named tuple of (layer_id, threshold, comparator)).
Source code in steerability/algorithms/state_control/common/selectors/base.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
select(**kwargs)
abstractmethod
Run selection logic and return the result.
Returns:
| Type | Description |
|---|---|
T
|
Selection result of type T. |
Source code in steerability/algorithms/state_control/common/selectors/base.py
15 16 17 18 19 20 21 22 | |
condition_point
Condition point search: find optimal (layer, threshold, comparator).
logger = logging.getLogger(__name__)
module-attribute
ConditionPoint
dataclass
Result of a condition point search, reusable as a self-contained CAST condition argument.
A ConditionPoint carries everything CAST needs to gate without re-searching: the layer,
threshold, comparator, and (when populated by the selector) the runtime aggregation mode. Pass
one directly to CASTArgs.condition_point to reuse a searched point, or flipped() to condition
on the complement.
Attributes:
| Name | Type | Description |
|---|---|---|
layer_id |
int
|
The condition layer (0-based). |
threshold |
float
|
The gate threshold. |
comparator |
Comparator
|
The gate comparator ("ge" opens when score >= threshold; "le" when score <= threshold). |
f1 |
float
|
F1 of the class separation achieved by the search at this point. |
margin |
float
|
Geometric margin: distance from the decision boundary to the nearest calibration point. Positive means the calibration classes are cleanly separated at this threshold. |
comparison_mode |
CompMode | None
|
The runtime token-aggregation mode ("mean" or "last") the search was run
for, or None when unset. Populated by |
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
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 | |
comparator
instance-attribute
comparison_mode = None
class-attribute
instance-attribute
f1
instance-attribute
layer_id
instance-attribute
margin = 0.0
class-attribute
instance-attribute
threshold
instance-attribute
__init__(layer_id, threshold, comparator, f1, margin=0.0, comparison_mode=None)
flipped()
Return a copy with the comparator inverted ("ge" <-> "le").
Conditions on the complement of this point (e.g. gate on scores at or below the threshold
instead of at or above it). All other fields are preserved: f1 and margin describe the
original search and are carried over unchanged.
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
ConditionPointSelector
Bases: BaseSelector[ConditionPoint]
Grid-searches for the (layer, threshold, comparator) that best separates positive from negative examples using projected cosine similarity.
Examples are rendered via render_for_model according to
fit_spec.prompt_format and tokenized with add_special_tokens=False for
chat-templated text (matching the inference rendering of the condition gate).
The returned comparator is one of "ge"/"le" ("ge" opens the gate when
score >= threshold), consumed directly by the PerKeyThreshold gate rule.
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 319 320 321 322 | |
select(*, model, tokenizer, condition_directions, data, fit_spec, search_spec, comparison_mode=None, score='projected_cosine', session=None)
Run the grid search.
Calibration extracts hidden states at location="layer_input", matching the residual-stream
boundary CAST's runtime condition pre-hook observes, and scores with the same score function
the runtime scorer will apply, so selector and runtime scores agree for the same input.
A fit_spec whose location is not "layer_input" means the condition direction was fit
at a different boundary than it is calibrated and scored against, and triggers a
UserWarning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
Model for hidden state extraction. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding. |
required |
condition_directions
|
dict[int, Tensor]
|
Per-layer direction tensors (from estimator). |
required |
data
|
ContrastivePairs
|
Contrastive pairs to evaluate separation on. |
required |
fit_spec
|
VectorTrainSpec
|
How hidden states were accumulated (for span selection). |
required |
search_spec
|
ConditionSearchSpec
|
Search grid configuration. |
required |
comparison_mode
|
CompMode | None
|
The runtime condition aggregation mode CAST will use. Accepted for
caller symmetry with CAST; calibration pools over |
None
|
session
|
'SteeringSession | None'
|
A |
None
|
score
|
Literal['projected_cosine', 'cosine']
|
Score function applied to the calibration examples, matching the runtime
scorer the caller will build. |
'projected_cosine'
|
Returns:
| Type | Description |
|---|---|
ConditionPoint
|
ConditionPoint with the best (layer, threshold, comparator, f1). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 319 320 321 322 | |
_best_point_for_layer(sims_p, sims_n, grid)
Best (f1, margin, threshold, comparator) for one layer's calibration scores.
F1 saturates at 1.0 across many (threshold, comparator) points when the calibration set is small -- 10 pairs against a 100-point grid and 2 comparators leaves thousands of candidates, so a perfect fit carries little evidence. Ties are therefore broken by the geometric margin: the distance from the decision boundary to the nearest calibration point. Maximising it centres the threshold in the widest gap and prefers layers whose classes are genuinely far apart over layers that separate by luck.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sims_p
|
Tensor
|
[N_pos] condition scores for positives. |
required |
sims_n
|
Tensor
|
[N_neg] condition scores for negatives. |
required |
grid
|
Tensor
|
Candidate thresholds. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
dict with keys "f1", "margin", "thr", "comparator". |
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
_threshold_grid(threshold_range, step)
Build a half-open, step-exact threshold grid [low, high).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold_range
|
tuple[float, float]
|
|
required |
step
|
float
|
Grid increment (must be positive). |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
1-D tensor of candidate thresholds; |
Source code in steerability/algorithms/state_control/common/selectors/condition_point.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
fixed_layer
Selector that returns an explicit, user-specified layer.
FixedLayerSelector
Bases: BaseSelector[int]
Selects a single layer specified at construction time.
Use when the caller already knows the target layer (e.g., from a config file or a previous search).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer_id
|
int
|
The layer index to select. |
required |
Source code in steerability/algorithms/state_control/common/selectors/fixed_layer.py
7 8 9 10 11 12 13 14 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 | |
component_kind = 'fixed_layer'
class-attribute
layer_id = layer_id
instance-attribute
__init__(layer_id)
Source code in steerability/algorithms/state_control/common/selectors/fixed_layer.py
19 20 21 22 | |
from_config(params)
classmethod
Rebuild the selector from its serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/fixed_layer.py
28 29 30 31 | |
select(*, num_layers)
Return the fixed layer id after bounds-checking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_layers
|
int
|
Total number of layers in the model. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The stored layer id. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If layer_id >= num_layers. |
Source code in steerability/algorithms/state_control/common/selectors/fixed_layer.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
to_config()
The selector's serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/fixed_layer.py
24 25 26 | |
fractional_depth
Selector that picks a layer at a given fractional depth of the model.
FractionalDepthSelector
Bases: BaseSelector[int]
Selects a layer at a specified fraction of total model depth.
For example, FractionalDepthSelector(0.4) on a 32-layer model returns
layer 12 (≈ 40% depth), matching the CAA paper's finding that layer 13/32
is near-optimal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fraction
|
float
|
Target depth as a fraction in (0, 1). |
required |
minimum
|
int
|
Floor for the returned layer id (default 0). Useful when very early layers should be excluded (e.g., ActAdd avoids layer 0). |
0
|
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
7 8 9 10 11 12 13 14 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 | |
component_kind = 'fractional_depth'
class-attribute
fraction = fraction
instance-attribute
minimum = minimum
instance-attribute
__init__(fraction, minimum=0)
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
22 23 24 25 26 27 28 | |
from_config(params)
classmethod
Rebuild the selector from its serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
34 35 36 37 | |
select(*, num_layers)
Compute and return the target layer id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_layers
|
int
|
Total number of layers in the model. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Layer index at approximately |
int
|
to |
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
39 40 41 42 43 44 45 46 47 48 49 50 51 | |
to_config()
The selector's serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
30 31 32 | |
LateThirdSelector
Bases: BaseSelector[list[int]]
Selects the late third of the model's layers.
The default behavior-layer heuristic for conditional activation steering.
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
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 | |
component_kind = 'late_third'
class-attribute
from_config(params)
classmethod
Rebuild the selector from its serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
66 67 68 69 | |
select(*, num_layers)
Return the last third of the layer indices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_layers
|
int
|
Total number of layers in the model. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
The selected layer ids, ascending. |
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
71 72 73 74 75 76 77 78 79 80 81 82 | |
to_config()
The selector's serialized parameters (none).
Source code in steerability/algorithms/state_control/common/selectors/fractional_depth.py
62 63 64 | |
top_k_head
Selector that returns top-K heads by probe accuracy.
logger = logging.getLogger(__name__)
module-attribute
TopKHeadSelector
Bases: BaseSelector[list[tuple[int, int]]]
Selects the top-K (layer_id, head_id) pairs by probe accuracy.
Used by ITI to select which attention heads to intervene on based on
linear probe training accuracy scores. "Probe" here is ITI's per-head fit-time
classifier used to rank heads, distinct from the toolkit's Probe detector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
Number of top heads to select. |
required |
Source code in steerability/algorithms/state_control/common/selectors/top_k_head.py
11 12 13 14 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 | |
component_kind = 'top_k_head'
class-attribute
k = k
instance-attribute
__init__(k)
Source code in steerability/algorithms/state_control/common/selectors/top_k_head.py
24 25 26 27 | |
from_config(params)
classmethod
Rebuild the selector from its serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/top_k_head.py
33 34 35 36 | |
select(*, steering_vector)
Return the top-K (layer_id, head_id) pairs sorted by accuracy descending.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steering_vector
|
SteeringVector
|
A SteeringVector with probe_accuracies populated. |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[int, int]]
|
List of top-K (layer_id, head_id) tuples, sorted by accuracy descending. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the steering vector has no probe_accuracies. |
Source code in steerability/algorithms/state_control/common/selectors/top_k_head.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
to_config()
The selector's serialized parameters.
Source code in steerability/algorithms/state_control/common/selectors/top_k_head.py
29 30 31 | |
utils
Selector utility modules.
__all__ = ['late_third']
module-attribute
late_third(num_layers)
Return layer ids for the last third of the model.
This is the default heuristic for behavior layer selection when the user does not specify explicit layer ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_layers
|
int
|
Total number of layers in the model. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
List of layer ids. |
Source code in steerability/algorithms/state_control/common/selectors/utils/layer_heuristics.py
4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
layer_heuristics
Heuristic layer selection strategies.
late_third(num_layers)
Return layer ids for the last third of the model.
This is the default heuristic for behavior layer selection when the user does not specify explicit layer ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_layers
|
int
|
Total number of layers in the model. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
List of layer ids. |
Source code in steerability/algorithms/state_control/common/selectors/utils/layer_heuristics.py
4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
sources
Sources: recipes that resolve to concrete steering elements for a given model.
This module provides the ArtifactSource protocol with its fit recipes (ContrastiveFit,
SinglePairFit) and the gate source ConditionPointSearch. A transform holds either a
concrete artifact (a SteeringVector or a per-layer directions mapping) or a source; an
Intervention's gate slot holds either a concrete gate or a gate source. Intervention.bind
resolves sources, so steer-time computations (fits, searches) have a declarative home.
resolve returns a defensive clone, and the underlying fit is memoized per model.
ArtifactSource
Bases: Protocol
A recipe for obtaining a steering artifact for a specific model.
Implementations MUST return a defensive clone from resolve (callers may move/mutate their
copy) and SHOULD memoize the underlying fit per model so repeated resolves against one model
(e.g., a parameter sweep) fit only once. Implementations whose fitted directions are
positional ([T, H] with T > 1) declare it with a class-level produces_positional =
True, which transform factories read for kind planning before the fit runs.
Source code in steerability/algorithms/state_control/common/sources.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
resolve(model, tokenizer, *, session=None)
Return the steering artifact for this model (a fresh clone each call).
session is a SteeringSession a capture-backed fit may extract hidden states
through; sources whose fit requires a live model ignore it.
Source code in steerability/algorithms/state_control/common/sources.py
54 55 56 57 58 59 60 61 62 | |
ConditionPointSearch
dataclass
A gate recipe: contrastive condition data plus how to find the gate point.
Occupies an Intervention's gate slot. resolve_gate fits (or clones) the condition
vector, resolves the condition point by grid search when search enables it and no manual
layers are given, and assembles the gate: projected-cosine evidence over the condition
directions at the resolved layers, decided by a per-layer threshold rule. An unconditional
configuration (no condition vector or no resolved point) resolves to None.
The projected-cosine readout and the per-layer threshold rule both have wire forms, so an
intervention gated this way lowers to intervention-capable backends
(wire_readouts/wire_rules declare the kinds for pre-steer support checks).
Attributes:
| Name | Type | Description |
|---|---|---|
condition_vector |
SteeringVector | None
|
Precomputed condition directions, cloned rather than refit. |
condition_data |
ContrastivePairs | dict | None
|
Contrastive pairs used to fit the condition vector and calibrate the search. |
condition_fit |
VectorTrainSpec
|
Fit configuration for the condition vector. |
search |
ConditionSearchSpec
|
Condition point search configuration. |
layer_ids |
Sequence[int] | None
|
Manual condition layers; disables the search when set. |
threshold |
float | None
|
Manual gate threshold, required with |
comparator |
Comparator
|
Gate comparator for the manual point ( |
comparison_mode |
CompMode
|
Runtime token aggregation for condition scoring. |
resolved_point |
dict | None
|
The |
Source code in steerability/algorithms/state_control/common/sources.py
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 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 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | |
access = ModelAccess.MODULE
class-attribute
artifact_class = 'calibrated'
class-attribute
comparator = 'ge'
class-attribute
instance-attribute
comparison_mode = 'mean'
class-attribute
instance-attribute
condition_data = None
class-attribute
instance-attribute
condition_fit = field(default_factory=lambda: VectorTrainSpec(prompt_format='chat_prompt', location='layer_input'))
class-attribute
instance-attribute
condition_vector = None
class-attribute
instance-attribute
layer_ids = None
class-attribute
instance-attribute
resolved_point = field(default=None, init=False, repr=False, compare=False)
class-attribute
instance-attribute
search = field(default_factory=ConditionSearchSpec)
class-attribute
instance-attribute
threshold = None
class-attribute
instance-attribute
wire_readouts = frozenset({'projected_cosine'})
class-attribute
wire_rules = frozenset({'per_key_threshold'})
class-attribute
__init__(condition_vector=None, condition_data=None, condition_fit=(lambda: VectorTrainSpec(prompt_format='chat_prompt', location='layer_input'))(), search=ConditionSearchSpec(), layer_ids=None, threshold=None, comparator='ge', comparison_mode='mean')
__post_init__()
Source code in steerability/algorithms/state_control/common/sources.py
470 471 472 473 474 | |
resolve_gate(model, tokenizer, *, layout=None, session=None)
Resolve the gate for model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel | None
|
The model to search against; required when the search runs or the condition vector is fitted from data. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer used to encode the condition data. |
required |
layout
|
'ModelFacts | None'
|
Structural facts, used to bounds-check condition layers. |
None
|
session
|
'SteeringSession | None'
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
'Gate | None'
|
The gate, or None for unconditional configurations. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a manual threshold is set without a condition vector, or a condition layer lacks a direction. |
Source code in steerability/algorithms/state_control/common/sources.py
476 477 478 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 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | |
ContrastiveFit
dataclass
A fit recipe: contrastive pairs plus how to extract a per-layer direction.
The five spec fields (method, accumulate, batch_size, prompt_format, location) drive
the built-in estimators. "mean_diff" dispatches to MeanDifferenceEstimator, everything else
to ContrastiveDirectionEstimator, and the fitted artifact records its extraction boundary as
meta["location"], which Intervention.bind checks against the consuming intervention's
boundary. When a custom estimator is supplied, the spec fields are ignored (a warning is
emitted), no location is recorded, and fitting delegates to
estimator.fit(model, tokenizer, data=<coerced pairs>, **(estimator_kwargs or {})).
The fitted master vector is memoized in a single weakref slot keyed by model identity. The same
model resolved repeatedly fits once, a different model refits, and alternating models (A→B→A)
refit on each switch. Every resolve returns an independent clone, so a consumer may freely
.to(...) or mutate its copy without touching the master.
Attributes:
| Name | Type | Description |
|---|---|---|
data |
ContrastivePairs | dict
|
Contrastive pairs (or a dict coerced via |
method |
str
|
Direction-extraction method used to fit the per-layer direction. |
accumulate |
str
|
Hidden-state span selection for the fit. |
batch_size |
int
|
Forward-pass batch size used during fitting. |
prompt_format |
PromptFormat
|
How to render pairs into model-ready text. |
location |
HiddenStateLocation
|
Residual-stream boundary to fit at. |
normalize |
bool
|
L2-normalize the fitted master per layer once, before caching. |
estimator |
BaseEstimator | None
|
Optional custom |
estimator_kwargs |
dict | None
|
Extra kwargs forwarded to a custom |
Source code in steerability/algorithms/state_control/common/sources.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
_master = field(default=None, init=False, repr=False, compare=False)
class-attribute
instance-attribute
_model_ref = field(default=None, init=False, repr=False, compare=False)
class-attribute
instance-attribute
access
property
ModelAccess.CAPTURE for the built-in estimators, whose extraction runs through
session capture; a custom estimator may need the live model, so it declares
ModelAccess.MODULE.
accumulate = 'all'
class-attribute
instance-attribute
artifact_class = 'direction'
class-attribute
batch_size = 8
class-attribute
instance-attribute
data
instance-attribute
estimator = None
class-attribute
instance-attribute
estimator_kwargs = None
class-attribute
instance-attribute
location = 'layer_output'
class-attribute
instance-attribute
method = 'pca_pairwise'
class-attribute
instance-attribute
normalize = False
class-attribute
instance-attribute
produces_positional = False
class-attribute
prompt_format = 'chat_completion'
class-attribute
instance-attribute
__init__(data, method='pca_pairwise', accumulate='all', batch_size=8, prompt_format='chat_completion', location='layer_output', normalize=False, estimator=None, estimator_kwargs=None)
__post_init__()
Source code in steerability/algorithms/state_control/common/sources.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
_fit(model, tokenizer, session=None)
Fit the master steering vector (no caching, no cloning).
Source code in steerability/algorithms/state_control/common/sources.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
resolve(model, tokenizer, *, session=None)
Return a fresh clone of the fitted artifact for model, fitting once and memoizing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to fit against (or a memo hit for the same model), or None to
fit through |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer used to encode the contrastive pairs when fitting. |
required |
session
|
'SteeringSession | None'
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
An independent |
Source code in steerability/algorithms/state_control/common/sources.py
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
LayerFilteredFit
dataclass
Wraps a source and restricts the resolved directions to a layer range.
Access, artifact class, and positional-ness delegate to the wrapped source. The filtered result keeps the inner artifact's metadata and per-layer statistics for the surviving layers.
Attributes:
| Name | Type | Description |
|---|---|---|
inner |
'ArtifactSource'
|
The wrapped source. |
layer_range |
tuple[int, int] | None
|
0-based half-open |
Source code in steerability/algorithms/state_control/common/sources.py
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | |
access
property
artifact_class
property
inner
instance-attribute
layer_range = None
class-attribute
instance-attribute
produces_positional
property
__init__(inner, layer_range=None)
resolve(model, tokenizer, *, session=None)
Resolve the inner source and filter its directions to layer_range.
Source code in steerability/algorithms/state_control/common/sources.py
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | |
SinglePairFit
dataclass
A fit recipe for a positional steering vector: per-token differences of one contrast pair.
Produces [T, H] directions per layer (the ActAdd extraction), captured at the layer-input
boundary and recorded as meta["location"] = "layer_input". Fitting requires a live model,
since the pair is tokenized and co-padded as one batch and remote capture serves per-prompt
layouts that do not preserve the co-padded positional structure. The fitted master is
memoized per model; every resolve returns an independent clone.
Attributes:
| Name | Type | Description |
|---|---|---|
positive_prompt |
str
|
The steering-direction prompt. |
negative_prompt |
str
|
The contrast prompt. |
normalize |
bool
|
L2-normalize each per-position vector once, before caching. |
Source code in steerability/algorithms/state_control/common/sources.py
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | |
_master = field(default=None, init=False, repr=False, compare=False)
class-attribute
instance-attribute
_model_ref = field(default=None, init=False, repr=False, compare=False)
class-attribute
instance-attribute
access = ModelAccess.MODULE
class-attribute
artifact_class = 'direction'
class-attribute
negative_prompt
instance-attribute
normalize = False
class-attribute
instance-attribute
positive_prompt
instance-attribute
produces_positional = True
class-attribute
__init__(positive_prompt, negative_prompt, normalize=False)
resolve(model, tokenizer, *, session=None)
Return a fresh clone of the fitted artifact for model, fitting once and memoizing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to fit against (or a memo hit for the same model). |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer used to encode the prompt pair. |
required |
session
|
'SteeringSession | None'
|
Ignored; the positional fit requires a live model. |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
An independent |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/state_control/common/sources.py
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | |
VerifiedPrecomputed
A precomputed source that enforces recorded provenance at resolve time.
Wraps a concrete SteeringVector together with the fingerprints of the side that produced
it. Resolution is model-free (ModelAccess.FACTS) and reads structural facts from the
session layout (or the live model when one is given): the vector's model_type and width
are always checked, and the recorded model fingerprint is checked per the policy. A
"calibrated" artifact on a mismatched model raises under policy="strict" and warns
under "warn"; a "direction" artifact warns under both, since transferring a direction
across fine-tunes of one architecture is a deliberate act. policy="off" skips every
check. Checks that cannot run (no layout available, or no recorded value) are skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
steering_vector
|
SteeringVector
|
The concrete artifact. |
required |
provenance
|
Mapping | None
|
Producing-side fingerprints (mapping or |
None
|
artifact_class
|
str
|
|
'direction'
|
policy
|
str
|
|
'strict'
|
Source code in steerability/algorithms/state_control/common/sources.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | |
access = ModelAccess.FACTS
class-attribute
artifact_class = artifact_class
instance-attribute
policy = policy
instance-attribute
produces_positional
property
provenance = dict(provenance or {})
instance-attribute
steering_vector = steering_vector
instance-attribute
__init__(steering_vector, provenance=None, artifact_class='direction', policy='strict')
Source code in steerability/algorithms/state_control/common/sources.py
233 234 235 236 237 238 239 240 241 242 243 244 245 | |
_check(layout)
Source code in steerability/algorithms/state_control/common/sources.py
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 | |
_report(message, *, hard)
Source code in steerability/algorithms/state_control/common/sources.py
251 252 253 254 255 256 | |
resolve(model, tokenizer, *, session=None)
Check provenance against the resolution venue and return a fresh clone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The live model, or None when a session layout supplies the facts. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Unused. |
required |
session
|
'SteeringSession | None'
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
An independent |
Raises:
| Type | Description |
|---|---|
ValueError
|
Under |
Source code in steerability/algorithms/state_control/common/sources.py
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | |
_Precomputed
A trivially-resolved source wrapping a concrete SteeringVector (internal).
Lets resolvers treat concrete artifacts and sources uniformly, so precomputed vectors take
the same bind path as fitted ones (defensive clone, device/dtype cast). Resolution is
model-free, so the source declares ModelAccess.FACTS and runs no fit. Not part of the
public API; users pass vectors, mappings, or sources directly.
Source code in steerability/algorithms/state_control/common/sources.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | |
_steering_vector = steering_vector
instance-attribute
access = ModelAccess.FACTS
class-attribute
produces_positional
property
__init__(steering_vector)
Source code in steerability/algorithms/state_control/common/sources.py
198 199 | |
resolve(model, tokenizer, *, session=None)
Source code in steerability/algorithms/state_control/common/sources.py
205 206 207 208 | |
_as_artifact_source(x)
Coerce a concrete artifact or source into an ArtifactSource (internal).
Accepts an ArtifactSource (returned as-is), a SteeringVector (wrapped in _Precomputed), or
a Mapping[int, torch.Tensor] of per-layer directions (wrapped in a SteeringVector with
model_type="unknown" then _Precomputed). Anything else raises TypeError.
Source code in steerability/algorithms/state_control/common/sources.py
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | |
specs
The intervention IR for state control components.
The intervention IR (TokenScope, Intervention) is the single declarative statement of a
residual-stream state control's behavior. Both compilers read it: runtime.build_hooks turns
a bound intervention tuple into torch hooks for one generation, and
lowering.lower_interventions turns it into an InterventionSpec for intervention-capable
backends. Components describe their own wire form (WireForm via each component's export),
so no layer of the system re-derives another layer's configuration by introspection.
Boundary = Literal['layer_output', 'layer_input']
module-attribute
ScopeKind = Literal['all', 'after_prompt', 'last_k', 'from_position']
module-attribute
Site = Literal['decoder_layer', 'o_proj', 'norm_input']
module-attribute
CoveredLayers
Layer selector resolving to the bound transform's covered layers.
Used when the behavior layers are a fact of the artifact rather than of the model, e.g. a
steering plane supplied for a subset of layers. Intervention.bind binds the transform
first and takes its covered_layer_ids (intersected with the model's layer range, and
with within when given) as the behavior layers, raising when none remain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
within
|
'Sequence[int] | BaseSelector | None'
|
Optional base selection the covered layers are intersected with, as explicit layer ids or a selector resolved against the model's layer count. |
None
|
Source code in steerability/algorithms/state_control/common/specs.py
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 115 116 117 118 119 120 121 122 123 124 125 126 | |
within = tuple(int(lid) for lid in within) if isinstance(within, (list, tuple)) else within
instance-attribute
__init__(within=None)
Source code in steerability/algorithms/state_control/common/specs.py
98 99 | |
resolve(covered, num_layers)
The covered layers intersected with the model range and the base selection.
Raises:
| Type | Description |
|---|---|
ValueError
|
If no layer survives the intersection. |
Source code in steerability/algorithms/state_control/common/specs.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
Intervention
dataclass
One activation edit: apply transform at layers, at scope positions, on the
boundary side of the layer, whenever gate is open.
Declared unbound at control construction: layers may be a layer selector, the transform
may carry an ArtifactSource (or be a factory over a TransformContext), and the gate may
be given as a GateSource. bind(model, tokenizer, layout=...) returns the resolved form
with layer coverage validated. Kind identity (wire_kinds) is readable on the unbound
form, which is what lets check() run before steer().
Interventions are generation-invariant: prompt lengths, pad masks, and position offsets
are runtime facts consumed by build_hooks in process and resolved per request by the
worker on the wire. Nothing prompt-dependent appears here.
IR dataclasses never use instance defaults for object-valued fields; object-valued
defaults use default_factory only.
Attributes:
| Name | Type | Description |
|---|---|---|
layers |
tuple[int, ...] | 'BaseSelector' | CoveredLayers
|
Behavior layers (0-based decoder-layer indices), a selector resolved at bind
time, or |
transform |
'BaseTransform'
|
The transform applied at masked positions of open rows. |
scope |
TokenScope
|
Token positions to steer. |
gate |
'Gate | GateSource | None'
|
The gate consulted at apply time, a source resolving to one, or None for unconditional application. |
gate_driven_externally |
bool
|
Follower mode for shared-gate composition. When True, another
intervention's condition hooks feed the shared |
boundary |
Boundary
|
Which side of the hooked module the edit applies at. |
site |
Site | None
|
The hooked module family. None derives it from the transform kind
( |
require_coverage |
bool
|
When True (default), |
Source code in steerability/algorithms/state_control/common/specs.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | |
boundary = 'layer_output'
class-attribute
instance-attribute
gate = None
class-attribute
instance-attribute
gate_driven_externally = False
class-attribute
instance-attribute
is_unbound
property
True when binding must run model-side work: a layer selector to resolve, a transform source or factory to fit, or a gate source to search.
layers
instance-attribute
require_coverage = True
class-attribute
instance-attribute
scope = field(default_factory=_default_scope)
class-attribute
instance-attribute
site = None
class-attribute
instance-attribute
transform
instance-attribute
__init__(layers, transform, scope=_default_scope(), gate=None, gate_driven_externally=False, boundary='layer_output', site=None, require_coverage=True)
__post_init__()
Source code in steerability/algorithms/state_control/common/specs.py
182 183 184 185 186 187 188 | |
_validate_readout(readout, layout)
Check a readout's declared boundary and model identity against this intervention.
Source code in steerability/algorithms/state_control/common/specs.py
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | |
_validate_transform_artifact(transform)
Check the bound transform's recorded artifact extraction boundary against this intervention.
The check validates recorded provenance only: an artifact whose metadata carries no
"location" key has unknown extraction provenance and passes, with the boundary
requirement documented on the consuming control's args instead.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the artifact records a |
Source code in steerability/algorithms/state_control/common/specs.py
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | |
bind(model, tokenizer, *, layout=None, session=None)
Resolve every declared element against model (or a session layout).
Resolves the layer selector, binds the transform (fitting artifact sources and
invoking factories), resolves gate sources, validates layer coverage and readout
compatibility, and returns the bound intervention. Never mutates self.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
'PreTrainedModel | None'
|
The live model, or None for concrete-artifact configurations bound against a session layout. |
required |
tokenizer
|
'PreTrainedTokenizerBase'
|
Tokenizer used when fitting sources. |
required |
layout
|
'ModelFacts | None'
|
Structural facts ( |
None
|
session
|
'SteeringSession | None'
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
'Intervention'
|
The bound intervention. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a layer is out of range, the transform lacks coverage for a behavior layer, the transform's artifact records an extraction location that differs from this intervention's boundary, or the gate's readout is incompatible with the boundary or model. |
Source code in steerability/algorithms/state_control/common/specs.py
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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 | |
resolved_site()
The module family this intervention hooks, deriving None from the transform kind.
Source code in steerability/algorithms/state_control/common/specs.py
204 205 206 207 208 209 210 211 212 213 214 | |
wire_kinds()
The wire kind names this configuration lowers to, or None when hook-only.
Readable on the unbound form: sources and components declare kind identity at
construction, so check() consults this before steer(). Artifact-dependent
inexpressibility (e.g. a resolved artifact missing a direction for an uncovered
behavior layer) is undetectable here and is caught by eager steer-time lowering.
Source code in steerability/algorithms/state_control/common/specs.py
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | |
TokenScope
dataclass
A token-position selector with its parameters.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
ScopeKind
|
One of |
last_k |
int | None
|
Number of trailing positions, required when |
from_position |
int | None
|
Absolute start position (inclusive), required when
|
Source code in steerability/algorithms/state_control/common/specs.py
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 | |
from_position = None
class-attribute
instance-attribute
kind
instance-attribute
last_k = None
class-attribute
instance-attribute
__init__(kind, last_k=None, from_position=None)
__post_init__()
Source code in steerability/algorithms/state_control/common/specs.py
68 69 70 71 72 73 74 | |
export()
The scope's wire form. Total, since every scope kind is a wire kind.
Source code in steerability/algorithms/state_control/common/specs.py
76 77 78 79 80 81 82 | |
WireForm
dataclass
One component's form on the wire: the kind name, scalar params, and named tensors.
params follow the plugin's KIND_PARAMS table for the kind; tensors follow its
ARTIFACT_TENSORS table.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
The permanent wire kind name. |
params |
Mapping[str, float | int | bool | str | tuple[int, ...] | list[int]]
|
Scalar parameters, inlined next to |
tensors |
Mapping[str, Tensor]
|
Named tensor payloads, materialized as one content-addressed artifact. |
Source code in steerability/algorithms/state_control/common/specs.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | |
kind
instance-attribute
params = field(default_factory=dict)
class-attribute
instance-attribute
tensors = field(default_factory=dict)
class-attribute
instance-attribute
__init__(kind, params=dict(), tensors=dict())
_default_scope()
Source code in steerability/algorithms/state_control/common/specs.py
129 130 | |
combine_kinds(kind_sets)
Union InterventionKinds across an iterable, propagating None (hook-only).
Source code in steerability/algorithms/state_control/common/specs.py
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | |
steering_vector
Steering vector: per-layer direction vectors learned by an estimator.
logger = logging.getLogger(__name__)
module-attribute
SteeringVector
dataclass
Per-layer direction tensors for activation steering.
Directions are stored as [K, D] tensors per layer, where K and D are interpreted by the consuming transform:
CAA, CAST: K=1, D=hidden_size (single broadcast direction)
ActAdd: K=T, D=hidden_size (positional directions)
Angular Steering: K=2, D=hidden_size (orthonormal basis pair)
ITI: K=num_heads, D=head_dim (per-head directions)
The container is agnostic to what K and D mean (varies depending on the method). Semantics come from the consumer (transform).
Attributes:
| Name | Type | Description |
|---|---|---|
model_type |
str
|
HuggingFace model_type string (e.g., "llama"). |
directions |
dict[int, Tensor]
|
Mapping from layer_id to direction tensor of shape [K, D]. |
num_heads |
int | None
|
Number of attention heads per layer. |
head_dim |
int | None
|
Dimension of each head's output. |
explained_variances |
dict[int, float] | None
|
Optional mapping from layer_id to explained variance scalar. Only meaningful for estimators that produce a real variance (e.g., PCA-based). None when not applicable. |
probe_accuracies |
dict[tuple[int, int], float] | None
|
Optional mapping from (layer_id, head_id) to linear
probe validation accuracy (used for head selection in ITI). "Probe" here is
ITI's per-head fit-time classifier used to rank heads, distinct from the
toolkit's |
meta |
dict
|
Provenance record (model, config, tokenizer, and chat-template fingerprints, package version). May be empty for hand-constructed vectors, which disarms cross-backend fingerprint checks. |
Source code in steerability/algorithms/state_control/common/steering_vector.py
13 14 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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
directions
instance-attribute
explained_variances = None
class-attribute
instance-attribute
head_dim = None
class-attribute
instance-attribute
is_positional
property
True if the vector carries per-token positional structure (K > 1).
meta = field(default_factory=dict)
class-attribute
instance-attribute
model_type
instance-attribute
num_heads = None
class-attribute
instance-attribute
num_tokens
property
Number of token positions in the steering vector (K dimension).
probe_accuracies = None
class-attribute
instance-attribute
__init__(model_type, directions, num_heads=None, head_dim=None, explained_variances=None, probe_accuracies=None, meta=dict())
clone()
Return a deep copy with independent direction tensors and metadata dicts.
Use this before to() / normalization when the vector is caller-supplied and may be
reused (e.g., shared across controls or across a ControlSpec sweep).
Source code in steerability/algorithms/state_control/common/steering_vector.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
load(file_path)
classmethod
Load a SteeringVector from a JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
Path to load from. ".svec" extension added if not present. |
required |
Returns:
| Type | Description |
|---|---|
SteeringVector
|
Loaded SteeringVector instance. |
Source code in steerability/algorithms/state_control/common/steering_vector.py
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
normalized()
Return a per-layer L2-normalized deep clone.
Each direction tensor is normalized by its own L2 norm (over all elements). Rows with a
zero (or near-zero) norm are left unchanged. This is the bound-mode twin of
ContrastiveFit(normalize=True): the original vector is untouched, so a shared/caller-held
vector stays intact.
Returns:
| Type | Description |
|---|---|
SteeringVector
|
A new |
Source code in steerability/algorithms/state_control/common/steering_vector.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
save(file_path)
Save the SteeringVector to a JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
Path to save to. ".svec" extension added if not present. |
required |
Source code in steerability/algorithms/state_control/common/steering_vector.py
190 191 192 193 194 195 196 197 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 | |
scaled_to_norms(target_norms, scale=1.0)
Return a deep clone whose per-layer directions are rescaled to a target L2 norm.
At each layer present in both target_norms and self.directions, the direction is rescaled
to L2 norm scale * target_norms[layer] while keeping its orientation, scaling each direction
to a caller-chosen (typically residual-norm-relative) magnitude. The original vector is
untouched.
Semantics are defined for broadcast directions only (K == 1), where every steered
token in the layer receives the same vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_norms
|
Mapping[int, float]
|
Mapping from layer id to the per-layer base norm to scale to (e.g. the
output of |
required |
scale
|
float
|
Multiplier applied to each target norm (the "dose"). Must be positive. |
1.0
|
Returns:
| Type | Description |
|---|---|
SteeringVector
|
A new |
SteeringVector
|
each direction stored as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/state_control/common/steering_vector.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
to(device, dtype=None)
Move all direction tensors to device/dtype.
This mutates self.directions in place and returns self (so callers may chain).
To leave the original untouched, clone() first.
Source code in steerability/algorithms/state_control/common/steering_vector.py
65 66 67 68 69 70 71 72 73 74 75 | |
validate()
Validate that required fields are populated.
Raises:
| Type | Description |
|---|---|
ValueError
|
If model_type or directions are empty. |
Source code in steerability/algorithms/state_control/common/steering_vector.py
179 180 181 182 183 184 185 186 187 188 | |
token_scope
Token scope utilities for computing position masks.
align_mask_to_batch(mask, hidden_batch)
Expand a [B, T] mask to the hidden-state batch dimension.
Masks are built with B = prompt batch size, but HuggingFace generate expands hidden
states to B * num_beams via repeat_interleave for beam search. Row order is therefore
[item0, item0, ..., item1, item1, ...]; this replicates the mask the same way so it aligns
when a transform broadcasts it against the expanded hidden states.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
BoolTensor
|
Boolean mask of shape |
required |
hidden_batch
|
int
|
The batch size of the hidden states the mask will be applied to. |
required |
Returns:
| Type | Description |
|---|---|
BoolTensor
|
A |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If |
Source code in steerability/algorithms/state_control/common/token_scope.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
compute_prompt_lens(input_ids, pad_token_id=None)
Compute per-batch-item prompt lengths from input_ids.
For the "after_prompt" token scope, the prompt length should represent the absolute position where generation begins. With KV-cached generation, this is always the full input sequence length (seq_len), regardless of padding side or pad token count. The model's KV cache covers all input positions including pads, and generation continues from position seq_len.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
LongTensor
|
Shape [B, T] or [T]. |
required |
pad_token_id
|
int | None
|
Unused. Kept for API compatibility. |
None
|
Returns:
| Type | Description |
|---|---|
LongTensor
|
Tensor of shape [B] where each value is seq_len. |
Source code in steerability/algorithms/state_control/common/token_scope.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
make_token_mask(scope, *, seq_len, prompt_lens, last_k=None, from_position=None, position_offset=0)
Build a [B, T] boolean mask selecting which tokens to transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
ScopeKind
|
Which tokens to include. "all" - every position is True. "after_prompt" - only positions beyond the prompt are True. During autoregressive generation with KV cache, the hook may see only newly generated tokens (seq_len=1). Use position_offset to indicate the cumulative position in the full sequence. "last_k" - only the last k positions are True. "from_position" - positions >= from_position are True. Useful for single forward pass evaluation (e.g., logit scoring) where you want to steer from a specific point within the prompt. |
required |
seq_len
|
int
|
Current sequence length T (may be 1 during KV-cached generation). |
required |
prompt_lens
|
LongTensor
|
Shape [B], per-item prompt lengths. |
required |
last_k
|
int | None
|
Required when scope == "last_k". |
None
|
from_position
|
int | None
|
Required when scope == "from_position". The absolute position from which to start steering (inclusive). |
None
|
position_offset
|
int
|
Cumulative position offset for KV-cached generation. When the model processes token N in the sequence but only passes a single token to the hook (seq_len=1), set position_offset=N so that "after_prompt" correctly identifies generated tokens. |
0
|
Returns:
| Type | Description |
|---|---|
BoolTensor
|
Boolean tensor of shape [B, T]. |
Source code in steerability/algorithms/state_control/common/token_scope.py
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 | |
transforms
Transform components for state control.
additive
Additive activation steering transform.
AdditiveTransform
Bases: BaseTransform
Adds scaled direction vector(s) to hidden states.
Two modes, selected by the positional flag:
Broadcast (default, e.g., CAA):
h'[pos] = h[pos] + mask[pos] * strength * direction[0]
The same `[1, H]` vector is added at every masked position. The ``alignment``
parameter is unused.
Positional (e.g., ActAdd):
h'[p] = h[p] + mask[p] * strength * direction[p - alignment]
Row `t` of a `[T, H]` direction is added at absolute sequence position
``alignment + t``. The window ``[alignment, alignment + T)`` is evaluated in
absolute positions, so during KV-cached generation a window inside the prompt
fires only on the prefill pass, and a window extending past the prompt fires at
exactly the covered generated positions, once each.
Direction tensors are canonicalized to [T, H] at construction or bind (a 1-D [H]
tensor becomes [1, H]). A direction with T > 1 requires positional=True, since
broadcast semantics are undefined for multi-row directions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact
|
SteeringVector | Mapping[int, Tensor] | ArtifactSource
|
The steering artifact, given as a |
required |
strength
|
float
|
Global scaling factor. |
1.0
|
alignment
|
int
|
Absolute token position of the first direction row (default: 0). Used
only when |
0
|
positional
|
bool
|
Selects per-position injection. When False (default), the direction
broadcasts over masked positions and every layer's direction must have |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If a concrete direction has |
TypeError
|
If |
Source code in steerability/algorithms/state_control/common/transforms/additive.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
_artifact_meta = None
instance-attribute
_source = None
instance-attribute
alignment = alignment
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
directions = None
instance-attribute
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = False
class-attribute
positional = positional
instance-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
strength = strength
instance-attribute
wire_kind = 'additive'
class-attribute
__init__(artifact, strength=1.0, alignment=0, positional=False)
Source code in steerability/algorithms/state_control/common/transforms/additive.py
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 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
apply(hidden_states, *, layer_id, token_mask, position_offset=0, **kwargs)
Apply additive steering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape [B, T_seq, H]. |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape [B, T_seq]. True at positions to modify. |
required |
position_offset
|
int
|
Absolute position of the pass's first token. Consumed in
positional mode, where the local slice covering absolute positions
|
0
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/additive.py
190 191 192 193 194 195 196 197 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/additive.py
123 124 125 126 127 128 129 130 131 | |
export(layer_id)
The additive wire form for layer_id, or None for positional transforms.
Semantics are defined for broadcast directions only, where every steered token receives the same vector.
Source code in steerability/algorithms/state_control/common/transforms/additive.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | |
export_modifier(layer_id)
The wrapper's wire modifier form at layer_id, or None to contribute no modifier
at that layer.
Meaningful only on wrapper transforms (is_modifier True); kind-level
inexpressibility is reported by modifier_wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
159 160 161 162 163 164 165 166 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild an additive transform from its serialized form.
Source code in steerability/algorithms/state_control/common/transforms/additive.py
153 154 155 156 157 158 159 160 161 | |
modifier_wire_kind(core_kind)
The wire modifier kind this wrapper contributes over a core transform kind, or None when the combination has no wire form.
Meaningful only on wrapper transforms (is_modifier True). The default returns the
class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
150 151 152 153 154 155 156 157 | |
to_config()
The (params, artifact, inner) serialized form under the additive kind.
The artifact slot carries the concrete directions as a SteeringVector when bound,
or the unresolved source when not.
Source code in steerability/algorithms/state_control/common/transforms/additive.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
wire_plan()
"additive" for broadcast transforms; None when positional is True.
Positional injection has no wire form regardless of T.
Source code in steerability/algorithms/state_control/common/transforms/additive.py
163 164 165 166 167 168 | |
_canonical_directions(directions, positional)
Canonicalize per-layer directions to [T, H], validating shape against the mode.
A 1-D [H] tensor becomes [1, H]. Broadcast mode (positional=False) requires
T == 1 at every layer.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a direction is not 1-D or 2-D, or has |
Source code in steerability/algorithms/state_control/common/transforms/additive.py
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 | |
alignment_adaptive
Alignment-adaptive filtering: a transform decorator that gates by feature alignment.
AlignmentAdaptiveTransform
Bases: BaseTransform
Applies an inner transform only at tokens aligned with a feature direction.
Computes each token's projection onto a chosen direction and keeps only positions whose
alignment exceeds threshold; those at or below are removed from the token mask before the
inner transform runs. With threshold=0.0 this applies the Adaptive Angular Steering gate
mask = max(0, sign(h·d_feat)) (Eq. 3 of Vu and Nguyen), which rotates only tokens already
positively aligned with the feature axis. Because it only narrows the mask, it composes with
any BaseTransform.
The transform carries two artifacts, the inner transform's and its own alignment axis, and is
bound iff both are bound. bind recurses into the inner and resolves its own source; the two
may share the same source instance, in which case memoization runs the shared fit once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inner
|
BaseTransform
|
The transform to apply at the surviving positions. |
required |
artifact
|
SteeringVector | Mapping[int, Tensor] | ArtifactSource
|
The steering artifact whose per-layer directions supply the alignment axis, given
as a |
required |
threshold
|
float
|
Alignment cutoff; positions with alignment |
0.0
|
direction_index
|
int
|
Row of the per-layer direction tensor to use as the alignment axis (row 0 = feature axis for angular steering). |
0
|
use_cosine
|
bool
|
If True, alignment is cosine similarity; otherwise it is the projection onto the unit-normalized direction. |
False
|
Reference:
- "Angular Steering: Behavior Control via Rotation in Activation Space" Hieu M. Vu, Tan M. Nguyen https://arxiv.org/abs/2510.26243
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
_source = None
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
direction_index = int(direction_index)
instance-attribute
inner = inner
instance-attribute
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = True
class-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
steering_vector = None
instance-attribute
threshold = float(threshold)
instance-attribute
use_cosine = bool(use_cosine)
instance-attribute
wire_kind = 'alignment_adaptive'
class-attribute
__init__(inner, artifact, threshold=0.0, direction_index=0, use_cosine=False)
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
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 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
Narrow the token mask by feature alignment, then delegate to the inner transform.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
87 88 89 90 91 92 93 94 95 96 97 | |
export(layer_id)
This configuration's wire form at layer_id, or None when the configuration is
not expressible in the wire vocabulary.
Exportability is a property of a configuration, not a class; an artifact whose shape
has no wire semantics (e.g. a positional direction) returns None even though the
class names a wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
132 133 134 135 136 137 138 139 140 | |
export_modifier(layer_id)
The alignment_adaptive wire modifier form at layer_id.
The modifier's wire vector is the resolved per-layer alignment axis
(directions[layer_id][direction_index]). A layer without an alignment axis
contributes no modifier, matching the in-process behavior where the mask is left
unnarrowed there.
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild an alignment_adaptive wrapper from its serialized form.
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
113 114 115 116 117 118 119 120 121 122 | |
modifier_wire_kind(core_kind)
"alignment_adaptive", or None over a per-head core.
Like norm_preserving, the wire modifier operates on the residual stream; a wrapped
head_additive is hook-only.
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
124 125 126 127 128 129 130 131 132 | |
to_config()
The (params, artifact, inner) serialized form under the alignment_adaptive kind.
Source code in steerability/algorithms/state_control/common/transforms/alignment_adaptive.py
103 104 105 106 107 108 109 110 111 | |
wire_plan()
The wire transform kind this configuration serializes to, or None when hook-only.
Readable on the unbound form: a source-carrying transform consults its source's
declared shape rather than resolving it. The default returns the class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
142 143 144 145 146 147 148 | |
base
Base class for hidden-state transforms.
BaseTransform
Bases: ABC
Applies a modification to hidden states at a given layer.
All transforms receive
- hidden_states shaped [B, T, H]
- the layer_id so the transform can index per-layer artifacts
- a token_mask shaped [B, T] (True where the transform should apply)
Transforms MUST NOT modify hidden_states in-place if the original tensor is needed later (e.g., for norm-preserving wrappers); return a new tensor.
Artifact-carrying transforms take their artifact as the first positional argument, typed
SteeringVector | Mapping[int, Tensor] | ArtifactSource and required. A concrete artifact
binds the transform immediately (validated at __init__); an ArtifactSource leaves it
unbound until bind(ctx) resolves the source (validated then). Subclass recipe:
- store the concrete artifact and set `is_bound=True`, or store the source and set
`is_bound=False`;
- override `bind(ctx)` to return a freshly constructed bound instance, never mutating
`self` and never using `copy.copy`, so that derived caches stay valid;
- override `covered_layer_ids` to report the layers the (bound) artifact covers;
- call `self._require_bound()` as the first line of `apply`.
Transforms with no steering artifact keep the defaults (always bound, no coverage).
Class attributes
wire_kind: The permanent wire kind name this class serializes to, or None when the
class has no wire form. Wire names mirror toolkit class names, so the mapping is
definitional rather than maintained.
is_modifier: True for wrapper transforms that hold an inner transform and serialize
as a wire modifier rather than a transform kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
14 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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = False
class-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
wire_kind = None
class-attribute
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
abstractmethod
Apply the transform and return modified hidden states.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape [B, T, H]. |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape [B, T]. True at positions to modify. |
required |
**kwargs
|
Any
|
Transform-specific extra arguments. |
{}
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/base.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/base.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | |
export(layer_id)
This configuration's wire form at layer_id, or None when the configuration is
not expressible in the wire vocabulary.
Exportability is a property of a configuration, not a class; an artifact whose shape
has no wire semantics (e.g. a positional direction) returns None even though the
class names a wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
132 133 134 135 136 137 138 139 140 | |
export_modifier(layer_id)
The wrapper's wire modifier form at layer_id, or None to contribute no modifier
at that layer.
Meaningful only on wrapper transforms (is_modifier True); kind-level
inexpressibility is reported by modifier_wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
159 160 161 162 163 164 165 166 | |
modifier_wire_kind(core_kind)
The wire modifier kind this wrapper contributes over a core transform kind, or None when the combination has no wire form.
Meaningful only on wrapper transforms (is_modifier True). The default returns the
class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
150 151 152 153 154 155 156 157 | |
wire_plan()
The wire transform kind this configuration serializes to, or None when hook-only.
Readable on the unbound form: a source-carrying transform consults its source's
declared shape rather than resolving it. The default returns the class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
142 143 144 145 146 147 148 | |
unwrap_modifiers(transform)
Split a possibly wrapper-chained transform into its core and its modifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
transform
|
BaseTransform
|
The transform, possibly wrapped in modifier transforms. |
required |
Returns:
| Type | Description |
|---|---|
BaseTransform
|
The core transform and the modifiers in application order, innermost wrapper first, |
tuple[BaseTransform, ...]
|
matching the wire interpreter's composition order. |
Source code in steerability/algorithms/state_control/common/transforms/base.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
context
Context handed to transforms (and transform factories) at steer() time.
TransformContext
dataclass
Fully-resolved layer/sizing context passed to a transform's bind or a factory.
A transform slot may be a BaseTransform instance (bound, or source-carrying and bound via
bind(ctx)) or a factory Callable[[TransformContext], BaseTransform]. Either way it receives
this context after the behavior layers are resolved, so it can turn a source into a concrete
artifact (ctx.resolve(...)) and size any per-layer or per-head buffers to the model.
Transforms never touch the model directly: fit orchestration lives behind resolve, a closure
the adapter builds over (model, tokenizer, device, dtype) that coerces the input, resolves the
source (memoized master, cloned), and moves the clone onto the model's device/dtype.
Attributes:
| Name | Type | Description |
|---|---|---|
layer_ids |
list[int]
|
The resolved behavior layer(s). |
num_layers |
int
|
Total number of transformer layers in the model. |
hidden_size |
int
|
Residual-stream width |
num_heads |
int | None
|
Number of attention heads per layer, or None if unavailable from the config. |
head_dim |
int | None
|
Dimension of each attention head, or None if unavailable from the config. |
dtype |
dtype
|
The model's parameter dtype. |
device |
device
|
The model's device. |
resolve |
Callable[[ArtifactSource | SteeringVector | Mapping[int, Tensor]], SteeringVector]
|
Turns a |
Source code in steerability/algorithms/state_control/common/transforms/context.py
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 | |
device
instance-attribute
dtype
instance-attribute
head_dim
instance-attribute
hidden_size
instance-attribute
layer_ids
instance-attribute
num_heads
instance-attribute
num_layers
instance-attribute
resolve
instance-attribute
__init__(layer_ids, num_layers, hidden_size, num_heads, head_dim, dtype, device, resolve)
_build_context(model, tokenizer, layer_ids, layout=None, session=None)
Build the TransformContext for the given behavior layers.
With a live model, reads device/dtype/layer-count from the model and hidden_size from the
text config; num_heads/head_dim come from the first behavior layer's head geometry read
off the module tree (head_geometry), so a per-head transform reshapes with the geometry that
layer actually uses. With no behavior layer given, or when no behavior layer carries an
attention module (a residual-stream transform on the non-attention layers of a hybrid stack),
the head geometry falls back to the text config. The resolve closure coerces any artifact to a
source, resolves it against the model,
and moves the result onto the model's device and dtype. With model=None, sizes come from
layout (a structural core.execution.ModelFacts), the device is CPU, and the resolve
closure serves concrete artifacts only, since fitting a source requires a live model.
Source code in steerability/algorithms/state_control/common/transforms/context.py
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 115 116 117 118 119 120 121 122 | |
resolve_transform_slot(slot, model, tokenizer, layer_ids, layout=None, require_coverage=True, session=None)
Turn a transform slot into a bound, coverage-checked BaseTransform for the given model.
Shared by every control that exposes a transform slot (ActivationAdapter.transform, CAST's
behavior_transform), so the resolution contract lives in one place. It runs three stages:
- Context construction: introspect the model (device, dtype, layer count, hidden size,
head count/dim) and build a
TransformContextwhoseresolveclosure fits/resolves a source on the steered model and moves the result onto its device/dtype (_build_context). - Slot resolution: a
BaseTransforminstance is bound if unbound (else used as-is); a factory is invoked with the context and its result is bound if unbound. Either branch is validated to yield a boundBaseTransform, so a factory returning a source-carrying transform is bound here rather than failing later inapply. - Coverage check: when the resolved transform reports
covered_layer_ids, every layer inlayer_idsmust be covered; a transform reportingNoneopts out of the check.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slot
|
BaseTransform | Callable[[TransformContext], BaseTransform]
|
A |
required |
model
|
PreTrainedModel | None
|
The steered model to introspect and resolve sources against, or None to build the
context from |
required |
tokenizer
|
PreTrainedTokenizerBase | None
|
Tokenizer used when a source fits from data; may be None for concrete artifacts. |
required |
layer_ids
|
Sequence[int]
|
The resolved behavior layers the transform must cover. |
required |
layout
|
ModelFacts | None
|
Structural |
None
|
require_coverage
|
bool
|
When False, skip the coverage check; uncovered layers are hooked and pass through unchanged at apply time. |
True
|
session
|
SteeringSession | None
|
Optional |
None
|
Returns:
| Type | Description |
|---|---|
BaseTransform
|
A bound |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a factory returns a non- |
ValueError
|
If the transform covers only some of |
Source code in steerability/algorithms/state_control/common/transforms/context.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |
head_additive
Head-level additive transform for activation steering.
HeadAdditiveTransform
Bases: BaseTransform
Adds scaled direction vectors to specific head slices.
For each selected (layer, head) pair, it adds a direction vector to the slice [h * head_dim : (h+1) * head_dim].
For ITI, this operates in pre-o_proj space: the input to the output projection where each head_dim-sized slice corresponds to an individual attention head's output. The directions must be computed in the same space.
Expects a SteeringVector whose directions are shaped [num_heads, head_dim]
per layer, with num_heads and head_dim metadata set. Only head indices
present in active_heads are applied; other heads are left untouched.
A bare directions mapping cannot carry the required num_heads/head_dim metadata and is
rejected; supply a SteeringVector (or an ArtifactSource resolving to one).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact
|
SteeringVector | Mapping[int, Tensor] | ArtifactSource
|
A |
required |
active_heads
|
dict[int, set[int]]
|
Mapping from layer_id to set of head indices to intervene on. |
required |
strength
|
float
|
Global scaling factor (alpha in ITI). |
1.0
|
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
_source = None
instance-attribute
active_heads = active_heads
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers the transform can act on: layers with directions and active heads.
head_dim = None
instance-attribute
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = False
class-attribute
num_heads = None
instance-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
steering_vector = None
instance-attribute
strength = strength
instance-attribute
wire_kind = 'head_additive'
class-attribute
__init__(artifact, active_heads, strength=1.0)
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
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 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
_validate_artifact()
Validate the artifact carries num_heads/head_dim metadata.
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
72 73 74 75 76 77 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
Apply head-level additive steering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape [B, T, H] where H = num_heads * head_dim. |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape [B, T]. True at positions to modify. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
89 90 91 92 | |
export(layer_id)
The head_additive wire form for layer_id.
The wire vector is [num_heads, head_dim] with zeros at heads outside active_heads,
so the broadcast wire addition reproduces the selective per-head addition exactly.
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
export_modifier(layer_id)
The wrapper's wire modifier form at layer_id, or None to contribute no modifier
at that layer.
Meaningful only on wrapper transforms (is_modifier True); kind-level
inexpressibility is reported by modifier_wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
159 160 161 162 163 164 165 166 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild a head_additive transform from its serialized form.
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
118 119 120 121 122 | |
modifier_wire_kind(core_kind)
The wire modifier kind this wrapper contributes over a core transform kind, or None when the combination has no wire form.
Meaningful only on wrapper transforms (is_modifier True). The default returns the
class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
150 151 152 153 154 155 156 157 | |
to_config()
The (params, artifact, inner) serialized form under the head_additive kind.
active_heads serializes with string layer keys and sorted head lists.
Source code in steerability/algorithms/state_control/common/transforms/head_additive.py
105 106 107 108 109 110 111 112 113 114 115 116 | |
wire_plan()
The wire transform kind this configuration serializes to, or None when hook-only.
Readable on the unbound form: a source-carrying transform consults its source's
declared shape rather than resolving it. The default returns the class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
142 143 144 145 146 147 148 | |
norm_preserving
Wrapper that rescales hidden states to preserve original norms.
NormPreservingTransform
Bases: BaseTransform
Wraps an inner transform and rescales to maintain original norms.
After applying the inner transform, if the norm increased at any position, rescale those positions back to original norm. This prevents distribution shift from large steering vectors.
Binding and coverage delegate to the inner transform: the wrapper is bound iff the inner is,
bind returns a new wrapper around the bound inner, and coverage is the inner's coverage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inner
|
BaseTransform
|
The transform to wrap. |
required |
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.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 115 116 117 118 119 120 121 | |
_inner = inner
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
inner
property
The wrapped transform.
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = True
class-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
wire_kind = 'norm_preserving'
class-attribute
__init__(inner)
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
32 33 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
Apply inner transform then rescale to preserve norms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape [B, T, H]. |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape [B, T]. True at positions to modify. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states with preserved norms. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If NaN or Inf detected after transform. |
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
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 115 116 117 118 119 120 121 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
48 49 50 51 | |
export(layer_id)
This configuration's wire form at layer_id, or None when the configuration is
not expressible in the wire vocabulary.
Exportability is a property of a configuration, not a class; an artifact whose shape
has no wire semantics (e.g. a positional direction) returns None even though the
class names a wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
132 133 134 135 136 137 138 139 140 | |
export_modifier(layer_id)
The norm_preserving wire modifier form (no params, no tensors).
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
77 78 79 80 81 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild a norm_preserving wrapper around its decoded inner transform.
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
61 62 63 64 | |
modifier_wire_kind(core_kind)
"norm_preserving", or None over a per-head core.
The wire modifier rescales over the last tensor dimension, which matches the hook
semantics on the residual stream only; a wrapped head_additive (per-head stream) is
hook-only.
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
66 67 68 69 70 71 72 73 74 75 | |
to_config()
The (params, artifact, inner) serialized form under the norm_preserving kind.
Source code in steerability/algorithms/state_control/common/transforms/norm_preserving.py
57 58 59 | |
wire_plan()
The wire transform kind this configuration serializes to, or None when hook-only.
Readable on the unbound form: a source-carrying transform consults its source's
declared shape rather than resolving it. The default returns the class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
142 143 144 145 146 147 148 | |
projection
Projection transform: projects learned directions out of the residual stream.
ProjectionTransform
Bases: BaseTransform
Removes one or more learned directions from hidden states by projection.
For an orthonormal set of directions {d_1..d_k} at a layer (rows of a [K, H] tensor):
h' = h - alpha * sum_i (h . d_i) d_i (applied at masked positions)
K=1 is single-direction ablation (the abliteration / directional-ablation technique of
Arditi et al.); K>1 ablates the whole subspace. alpha in [0, 1] scales the removal:
1.0 fully removes the component (h'.d_i == 0), values < 1.0 give graded partial
suppression.
This is a projection, not a translation or a rotation:
- It is idempotent at
alpha=1(P^2 = P). - It is norm-reducing, since it drops a component.
The stored rows need not be orthonormal; they are orthonormalized via Gram-Schmidt and cached
per (layer_id, device, dtype) so K>1 removal is basis-correct and order-independent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact
|
SteeringVector | Mapping[int, Tensor] | ArtifactSource
|
The steering artifact, given as a |
required |
alpha
|
float
|
Ablation strength in |
1.0
|
Reference:
- "Refusal in Language Models Is Mediated by a Single Direction" Andy Arditi, Oscar Obeso, Aaquib Syed, Daniel Paleka, Nina Panickssery, Wes Gurnee, Neel Nanda https://arxiv.org/abs/2406.11717
Source code in steerability/algorithms/state_control/common/transforms/projection.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
_artifact_meta = None
instance-attribute
_basis_cache = {}
instance-attribute
_source = None
instance-attribute
alpha = float(alpha)
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
directions = None
instance-attribute
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = False
class-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
wire_kind = 'projection'
class-attribute
__init__(artifact, alpha=1.0)
Source code in steerability/algorithms/state_control/common/transforms/projection.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
_basis(layer_id, device, dtype)
Return the cached orthonormal [K, H] basis for a layer, computing it on first use.
Source code in steerability/algorithms/state_control/common/transforms/projection.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
Project the learned directions out of each masked hidden state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/projection.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/projection.py
86 87 88 89 | |
export(layer_id)
The projection wire form for layer_id, or None when the configuration is
hook-only (K > 1 or alpha != 1.0).
Source code in steerability/algorithms/state_control/common/transforms/projection.py
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
export_modifier(layer_id)
The wrapper's wire modifier form at layer_id, or None to contribute no modifier
at that layer.
Meaningful only on wrapper transforms (is_modifier True); kind-level
inexpressibility is reported by modifier_wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
159 160 161 162 163 164 165 166 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild a projection transform from its serialized form.
Source code in steerability/algorithms/state_control/common/transforms/projection.py
106 107 108 109 | |
modifier_wire_kind(core_kind)
The wire modifier kind this wrapper contributes over a core transform kind, or None when the combination has no wire form.
Meaningful only on wrapper transforms (is_modifier True). The default returns the
class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
150 151 152 153 154 155 156 157 | |
to_config()
The (params, artifact, inner) serialized form under the projection kind.
Source code in steerability/algorithms/state_control/common/transforms/projection.py
95 96 97 98 99 100 101 102 103 104 | |
wire_plan()
"projection" for single-direction full removal; None otherwise.
The wire kind removes a single direction's component in full, so only K == 1
directions at alpha == 1.0 serialize; subspace ablation (K > 1) and graded
removal (alpha < 1.0) are hook-only.
Source code in steerability/algorithms/state_control/common/transforms/projection.py
111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
rotation
Angular (rotational) activation steering transform.
RotationMode = Literal['target', 'offset']
module-attribute
RotationTransform
Bases: BaseTransform
Rotates hidden states within a per-layer 2D steering plane.
Given an orthonormal basis pair (b1, b2) per layer, decompose each hidden state into its
in-plane coordinates (c1, c2) = (h·b1, h·b2) and an out-of-plane remainder
h_perp = h - c1 b1 - c2 b2, rotate the in-plane part, then reconstruct. The out-of-plane
component is untouched; because a 2D rotation is orthogonal the in-plane magnitude (hence the
full activation norm) is preserved by construction.
Modes:
"target": rotate the in-plane component TO the absolute angleanglemeasured fromb1(paper Eq. 2). Sweeping over[0, 2*pi)traces the behavior circle."offset": rotate the in-plane component BYangle(the same rotation for every token); recovers vector-addition / ablation as special cases.
The stored basis need not be orthonormal; it is re-orthonormalized via Gram-Schmidt and cached
per (layer_id, device, dtype). Only positions selected by token_mask are modified; at every
other position the input is returned unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
artifact
|
SteeringVector | Mapping[int, Tensor] | ArtifactSource
|
The steering artifact whose per-layer directions are |
required |
angle
|
float
|
Rotation angle in radians. Interpreted as an absolute target angle in |
0.0
|
mode
|
RotationMode
|
Either |
'target'
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If any layer's directions are not shaped |
Reference:
- "Angular Steering: Behavior Control via Rotation in Activation Space" Hieu M. Vu, Tan M. Nguyen https://arxiv.org/abs/2510.26243
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
_basis_cache = {}
instance-attribute
_source = None
instance-attribute
angle = float(angle)
instance-attribute
artifact_meta
property
Provenance metadata of the transform's steering artifact, or None.
Populated when the artifact was supplied or resolved as a SteeringVector carrying
meta (fit fingerprints); consumers cross-check it against a serving engine's model
identity. Wrappers delegate to their inner transform. The default returns None.
covered_layer_ids
property
Layers this transform can act on; None = unknown (opts out of adapter validation).
Artifact transforms report set(directions.keys()) when bound and None when unbound;
wrappers delegate to their inner transform.
is_bound
property
True when the transform can be applied as-is (artifact concrete).
Default True: transforms that take no steering artifact are always bound.
is_modifier = False
class-attribute
mode = mode
instance-attribute
source
property
The unresolved ArtifactSource this transform carries, or None when concrete.
steering_vector = None
instance-attribute
wire_kind = 'rotation'
class-attribute
__init__(artifact, angle=0.0, mode='target')
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
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 | |
_basis(layer_id, device, dtype)
Return the cached orthonormal (b1, b2) for a layer, computing it on first use.
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
144 145 146 147 148 149 150 151 152 153 154 155 | |
_require_bound()
Raise a clear RuntimeError if this transform is unbound.
Called as the first line of every artifact-consuming apply.
Source code in steerability/algorithms/state_control/common/transforms/base.py
111 112 113 114 115 116 117 118 119 120 121 | |
_validate_artifact()
Validate the per-layer directions are [2, H] basis pairs.
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
89 90 91 92 93 94 95 96 | |
apply(hidden_states, *, layer_id, token_mask, **kwargs)
Rotate the in-plane component of each masked hidden state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden_states
|
Tensor
|
Shape |
required |
layer_id
|
int
|
Which layer this is being applied at. |
required |
token_mask
|
BoolTensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Modified hidden states, same shape as input. |
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
bind(ctx)
Return a fully-bound transform for this context.
Contract:
- MUST NOT mutate `self`; instances and sources are shared across adapters and
`ControlSpec` grid points, whose params objects are reused per point.
- Returns `self` when already bound (idempotent).
- When source-carrying, returns a NEW instance of the same class constructed with
`ctx.resolve(self._source)` and all hyperparameters copied, built by fresh
construction rather than `copy.copy`.
Default: returns self.
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
108 109 110 111 | |
export(layer_id)
The rotation wire form for layer_id (angle, mode, and the [2, H] basis).
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
export_modifier(layer_id)
The wrapper's wire modifier form at layer_id, or None to contribute no modifier
at that layer.
Meaningful only on wrapper transforms (is_modifier True); kind-level
inexpressibility is reported by modifier_wire_kind. The default returns None.
Source code in steerability/algorithms/state_control/common/transforms/base.py
159 160 161 162 163 164 165 166 | |
from_config(params, *, artifact=None, inner=None)
classmethod
Rebuild a rotation transform from its serialized form.
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
123 124 125 126 | |
modifier_wire_kind(core_kind)
The wire modifier kind this wrapper contributes over a core transform kind, or None when the combination has no wire form.
Meaningful only on wrapper transforms (is_modifier True). The default returns the
class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
150 151 152 153 154 155 156 157 | |
to_config()
The (params, artifact, inner) serialized form under the rotation kind.
Source code in steerability/algorithms/state_control/common/transforms/rotation.py
117 118 119 120 121 | |
wire_plan()
The wire transform kind this configuration serializes to, or None when hook-only.
Readable on the unbound form: a source-carrying transform consults its source's
declared shape rather than resolving it. The default returns the class wire_kind.
Source code in steerability/algorithms/state_control/common/transforms/base.py
142 143 144 145 146 147 148 | |