Internals
steerability.algorithms.core.internals
Tools for reading and characterizing model internals (the model's activations and statistics) without steering them.
The root modules provide the shared signal-reading layer used by detection and by steering estimation:
capture: hooked/forward capture of hidden states at module boundaries.encoding: text-to-tensor tokenization entry points.pooling: token, span, and position aggregation.render:ContrastivePairsto model-ready text.data: contrastive and labeled-example data containers.stats: ambient activation statistics and residual-norm characterization.fingerprint: digests identifying the model a fitted artifact was estimated on.
Layering rules:
- The root is signal acquisition and characterization; subpackages are capabilities built from
the readings. Root modules never import from subpackages, and each
__init__.pyre-exports its own level only. - Modules here may import the
corefoundations (base_args,types,core/utils) andsteerability.utils; they never import the*_controlcategory packages at module level. - New signals (attention patterns, per-head capture, MLP activations) extend root modules; new capabilities become sibling subpackages.
HiddenStateLocation = Literal['layer_output', 'layer_input']
module-attribute
ActivationStats
dataclass
Per-layer mean and variance of a model's ambient activation distribution.
The statistics support per-coordinate centering and scaling of pooled activations
(standardize), the whitening used by diagonal-LDA probe fitting. Covariance is diagonal,
since the dominant effects in residual-stream geometry (a large shared component in every
activation and rogue dimensions dominating inner products) are axis-aligned, so per-coordinate
centering and scaling removes most of the effect, and a full covariance is hard to estimate
reliably and expensive to invert at a few thousand samples.
Under pooling="tokens", every retained real token position is one sample of the ambient
distribution, and exclude_first_n (default 1) drops the leading real positions per sequence,
since the first real position (BOS or an opening delimiter) carries known massive-activation
outliers that distort the mean disproportionately. "mean" and "last" pool per prompt first,
yielding one sample per prompt, and ignore exclude_first_n.
count is the number of pooled samples accumulated, i.e., tokens under pooling="tokens" and
prompts otherwise. estimate warns when count falls below its min_samples argument; a few
hundred varied texts clears the default under token pooling, while "mean" and "last" need a
few thousand prompts.
Attributes:
| Name | Type | Description |
|---|---|---|
model_type |
str
|
HuggingFace |
model_fingerprint |
str
|
Identity digest of that model, recorded at estimate time. |
location |
str
|
Residual-stream boundary the statistics were measured at. |
count |
int
|
Number of pooled samples accumulated. |
mean |
dict[int, Tensor]
|
Per-layer mean, |
var |
dict[int, Tensor]
|
Per-layer variance, |
var_floor |
float
|
Lower bound applied to every variance coordinate. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
count
instance-attribute
location
instance-attribute
mean
instance-attribute
model_fingerprint
instance-attribute
model_type
instance-attribute
var
instance-attribute
var_floor = 1e-06
class-attribute
instance-attribute
estimate(model, tokenizer, texts, *, layer_ids=None, location='layer_input', pooling='tokens', exclude_first_n=1, batch_size=8, min_samples=5000, session=None)
classmethod
Estimate per-layer activation statistics over texts.
Texts are tokenized in chunks of batch_size, captured at location, and pooled per
pooling. Sequences with no real tokens contribute no samples, and duplicate entries in
layer_ids are collapsed. Accumulation is streaming (per-chunk Welford merge) in float32
on CPU, so the full feature matrix is never materialized. Capture runs under torch.no_grad() with
use_cache=False, wrapped in auxiliary_pass(aligned=True), so co-resident state
controls' condition scorers, gates, and position counters ignore the passes while
"all"-scoped behavior transforms still apply (the statistics measure the stream as
deployed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
Model to capture activations from. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding |
required |
texts
|
Sequence[str]
|
Texts whose activations define the ambient distribution. |
required |
layer_ids
|
Sequence[int] | None
|
Layers to estimate (0-based). None selects all decoder layers. |
None
|
location
|
str
|
Residual-stream boundary to measure at. |
'layer_input'
|
pooling
|
Literal['mean', 'last', 'tokens']
|
|
'tokens'
|
exclude_first_n
|
int
|
Leading real token positions dropped per sequence under
|
1
|
batch_size
|
int
|
Batch size for the capture forward passes. |
8
|
min_samples
|
int
|
Pooled-sample count below which a low-sample warning is emitted. |
5000
|
Returns:
| Type | Description |
|---|---|
ActivationStats
|
An |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Warns:
| Type | Description |
|---|---|
UserWarning
|
When the accumulated pooled-sample |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
fingerprint()
Digest of this artifact (not of the model it was estimated on).
Returns:
| Type | Description |
|---|---|
str
|
A 16-character lowercase hex digest over the metadata and tensor contents. |
Source code in steerability/algorithms/core/internals/stats.py
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | |
load(dir_path)
classmethod
Load an artifact saved by save.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dir_path
|
str | Path
|
Directory containing the safetensors file and JSON sidecar. |
required |
Returns:
| Type | Description |
|---|---|
ActivationStats
|
The loaded |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the artifact-format version is unsupported. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
save(dir_path)
Save the artifact to a directory (safetensors for tensors, JSON sidecar for metadata).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dir_path
|
str | Path
|
Directory to write to; created if missing. |
required |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
standardize(features, layer_id)
Center and scale features per coordinate with this artifact's layer statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
features
|
Tensor
|
Tensor of shape |
required |
layer_id
|
int
|
Layer whose statistics to apply. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in steerability/algorithms/core/internals/stats.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
ContrastivePairs
dataclass
Paired positive/negative text data for contrastive estimation.
The token sequence the model sees for each example is produced by
render_for_model according to the consumer's prompt format, and the
rendered string is tokenized with add_special_tokens=False for
chat-templated text.
Attributes:
| Name | Type | Description |
|---|---|---|
positives |
Sequence[str]
|
Texts exhibiting the target behavior. Treated as completions
under |
negatives |
Sequence[str]
|
Texts not exhibiting the target behavior (see |
prompts |
Sequence[str] | None
|
Optional shared prompts. Used as the user turn under
|
Source code in steerability/algorithms/core/internals/data.py
6 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 | |
negatives
instance-attribute
positives
instance-attribute
prompts = None
class-attribute
instance-attribute
HeadGeometry
dataclass
Attention head geometry of one decoder layer.
Attributes:
| Name | Type | Description |
|---|---|---|
num_heads |
int
|
Number of attention heads. |
head_dim |
int
|
Per-head dimension. |
Source code in steerability/algorithms/core/internals/model_layout.py
306 307 308 309 310 311 312 313 314 315 316 | |
head_dim
instance-attribute
num_heads
instance-attribute
LabeledExamples
dataclass
Independent positive/negative text data with binary labels.
The positive and negative lists need not be the same length. Applies to methods where positive and negative examples are independent and unpaired, and the estimator concatenates them. Optional group keys mark statements that must not straddle a train/validation split (e.g. the source question of each answer); estimators that do not split ignore them.
Attributes:
| Name | Type | Description |
|---|---|---|
positives |
Sequence[str]
|
Texts exhibiting the target behavior (label=1). |
negatives |
Sequence[str]
|
Texts not exhibiting the target behavior (label=0). |
positive_groups |
Sequence[str | int] | None
|
Group key per positive, same length as |
negative_groups |
Sequence[str | int] | None
|
Group key per negative, same length as |
Source code in steerability/algorithms/core/internals/data.py
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 | |
groups
property
Whether the data carries group keys (positive/negative groups both present).
negative_groups = None
class-attribute
instance-attribute
negatives
instance-attribute
positive_groups = None
class-attribute
instance-attribute
positives
instance-attribute
ModelLayout
dataclass
Architecture-specific module paths for one model family.
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
Family label ( |
layer_prefix |
str
|
Dotted prefix of the decoder layer list (e.g. |
num_layers |
int
|
Number of decoder layers. |
attn_suffix |
str
|
Suffix of the per-layer attention module ( |
oproj_suffix |
str
|
Suffix of the attention output projection ( |
norm_attrs |
tuple[str, ...]
|
The per-layer normalization sub-module attribute names whose input is the
residual stream ( |
attention_layer_ids |
tuple[int, ...] | None
|
The decoder layers carrying the attention module at |
Source code in steerability/algorithms/core/internals/model_layout.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 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 | |
attention_layer_ids = None
class-attribute
instance-attribute
attention_layers
property
The decoder layers carrying an attention module, ascending; every layer when
attention_layer_ids is None.
attn_names
property
Dotted paths of every layer's attention module, index-aligned with layer_names. On a
hybrid stack, entries outside attention_layers name modules the model does not have.
attn_suffix
instance-attribute
family
instance-attribute
is_hybrid
property
True when some decoder layer carries no attention module.
layer_names
property
Dotted paths of every decoder layer, [f"{layer_prefix}.{i}"].
layer_prefix
instance-attribute
norm_attrs
instance-attribute
num_layers
instance-attribute
oproj_names
property
Dotted paths of every layer's attention output projection, index-aligned with
layer_names. On a hybrid stack, entries outside attention_layers name modules the
model does not have.
oproj_suffix
instance-attribute
has_attention(layer_id)
True when decoder layer layer_id carries the attention module at attn_suffix.
Source code in steerability/algorithms/core/internals/model_layout.py
115 116 117 | |
RenderedContrastive
dataclass
Rendered text for a ContrastivePairs, plus tokenization policy.
Attributes:
| Name | Type | Description |
|---|---|---|
pos_texts |
list[str]
|
Rendered positive examples. |
neg_texts |
list[str]
|
Rendered negative examples. |
prompt_texts |
list[str] | None
|
User-turn-only renders for suffix-only span computation, or None when there is no separate prompt/completion split. |
add_special_tokens |
bool
|
Flag callers must pass to the tokenizer for all of the above (False for chat modes, True for raw). |
effective_mode |
PromptFormat
|
The mode actually applied after raw fallbacks. |
Source code in steerability/algorithms/core/internals/render.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
add_special_tokens
instance-attribute
effective_mode
instance-attribute
neg_texts
instance-attribute
pos_texts
instance-attribute
prompt_texts
instance-attribute
StatsSpec
dataclass
Deferred recipe for ActivationStats; holds every argument except the model.
Attributes:
| Name | Type | Description |
|---|---|---|
texts |
Sequence[str]
|
Texts whose activations define the ambient distribution. |
layer_ids |
Sequence[int] | None
|
Layers to estimate (0-based). None selects all decoder layers. |
location |
str
|
Residual-stream boundary the statistics are measured at. |
pooling |
Literal['mean', 'last', 'tokens']
|
Sample construction. |
exclude_first_n |
int
|
Number of leading real token positions dropped per sequence under
|
batch_size |
int
|
Batch size for the capture forward passes. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
batch_size = 8
class-attribute
instance-attribute
exclude_first_n = 1
class-attribute
instance-attribute
layer_ids = None
class-attribute
instance-attribute
location = 'layer_input'
class-attribute
instance-attribute
pooling = 'tokens'
class-attribute
instance-attribute
texts
instance-attribute
estimate(model, tokenizer, session=None)
Estimate ActivationStats on model with this recipe's settings.
Source code in steerability/algorithms/core/internals/stats.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
aggregate_condition_hidden(hidden, mode, attention_mask=None)
Aggregate [B, T, H] hidden states to [B, H] using non-pad tokens only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
mode
|
Literal['mean', 'last']
|
"mean" pools over all real tokens; "last" selects the last real token per row. |
required |
attention_mask
|
Tensor | None
|
Shape |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Aggregated tensor of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a row has no real tokens, or the mode is unsupported. |
Source code in steerability/algorithms/core/internals/pooling.py
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 | |
as_contrastive_pairs(x)
Normalize input to ContrastivePairs.
Accepts:
- An existing `ContrastivePairs` instance (returned as-is).
- A dict with keys `"positives"`, `"negatives"`, and optionally `"prompts"`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ContrastivePairs | dict
|
Input to normalize. |
required |
Returns:
| Type | Description |
|---|---|
ContrastivePairs
|
A |
Raises:
| Type | Description |
|---|---|
TypeError
|
If input is neither |
Source code in steerability/algorithms/core/internals/data.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
as_labeled_examples(x)
Normalize input to LabeledExamples.
Accepts:
- An existing `LabeledExamples` instance (returned as-is).
- A `ContrastivePairs` instance (converted; pairing is dropped).
- A dict with keys `"positives"` and `"negatives"`, and optionally `"positive_groups"`
and `"negative_groups"`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
LabeledExamples | ContrastivePairs | dict
|
Input to normalize. |
required |
Returns:
| Type | Description |
|---|---|
LabeledExamples
|
A |
Raises:
| Type | Description |
|---|---|
TypeError
|
If input is not |
Source code in steerability/algorithms/core/internals/data.py
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 | |
get_last_token_positions(attention_mask, seq_len, num_samples)
Find the last non-pad token position for each sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attention_mask
|
Tensor | None
|
Shape |
required |
seq_len
|
int
|
Sequence length |
required |
num_samples
|
int
|
Number of samples |
required |
Returns:
| Type | Description |
|---|---|
LongTensor
|
Tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
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 | |
head_geometry(model, layout, layer_id)
Per-layer attention head geometry, read from the module tree.
head_dim comes from the attention module's head_dim attribute, else the text config;
num_heads is the output projection's input width divided by head_dim. GPT-2's Conv1D
stores its weight as [in, out], so the width is read from weight.shape[0] when
in_features is absent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The live model (or PEFT wrapper) carrying the attention modules. |
required |
layout
|
ModelLayout
|
The resolved |
required |
layer_id
|
int
|
The decoder layer index. |
required |
Returns:
| Type | Description |
|---|---|
HeadGeometry
|
The layer's |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/model_layout.py
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 | |
layerwise_tokenwise_hidden(model, enc, batch_size=8, on_batch=None, *, location='layer_output')
Extract per-layer hidden states for all tokens.
outputs.hidden_states is a tuple of num_layers + 1 tensors: index 0 is the embedding output
(the input to layer 0) and index i is the output of layer i - 1, except the final entry,
which transformers returns with the model's final norm already applied.
location="layer_output": keylmaps to the raw output boundary of layerl(hidden_states[l + 1]forl < num_layers - 1; the final layer is re-captured pre-norm by a forward hook on the last decoder layer, matching hook runtimes and engine capture).location="layer_input": keylmaps to the input of layerl, i.e. the output of layerl - 1(hidden_states[l]), the boundary a layer pre-hook observes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to extract from. |
required |
enc
|
dict[str, Tensor]
|
Tokenized input with |
required |
batch_size
|
int
|
Batch size for forward passes. |
8
|
on_batch
|
Callable[[], None] | None
|
Optional callable invoked after each batch finishes. Used by callers to surface progress to the UI. |
None
|
location
|
HiddenStateLocation
|
Which residual-stream boundary each layer key maps to. |
'layer_output'
|
Returns:
| Type | Description |
|---|---|
dict[int, Tensor]
|
Dict mapping |
dict[int, Tensor]
|
outside |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/capture.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 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 | |
masked_mean(hidden, attention_mask)
Mean-pool [N, T, H] hidden states over real (non-pad) positions.
Falls back to an unmasked mean over all positions when no attention mask is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
attention_mask
|
Tensor | None
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Pooled tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
measure_residual_norms(model, tokenizer, layer_ids, prompts, *, location='layer_output', stat='median', prompt_format='chat_prompt', batch_size=8)
Typical per-token residual-stream norm at each requested layer boundary.
The statistic is aggregated over the real (non-pad) tokens of prompts at the residual-stream
boundary named by location. Residual norms grow with depth, so the returned per-layer norms
let a caller rescale a direction to a fixed fraction of the norm at each layer (see
SteeringVector.scaled_to_norms).
Prompts are rendered via render_for_model(tokenizer, prompt=p, mode=prompt_format). The default
prompt_format="chat_prompt" renders with add_generation_prompt=True, matching what inference
produces for a prompt. The rendered string is tokenized with add_special_tokens=False whenever
a chat template was applied, matching how the estimators consume contrastive text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
Model to extract hidden states from. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for rendering and encoding the prompts. |
required |
layer_ids
|
Sequence[int] | None
|
Layers to measure (0-based). |
required |
prompts
|
Sequence[str]
|
Calibration prompts. Use fit-distribution, inference-style prompts rather than a held-out evaluation set. |
required |
location
|
HiddenStateLocation
|
Residual-stream boundary each layer key maps to. |
'layer_output'
|
stat
|
Literal['median', 'mean']
|
Aggregation over the pooled real-token norms, |
'median'
|
prompt_format
|
PromptFormat
|
How each prompt is rendered into model-ready text (via |
'chat_prompt'
|
batch_size
|
int
|
Batch size for the extraction forward passes. |
8
|
Returns:
| Type | Description |
|---|---|
dict[int, float]
|
Mapping from layer id to the aggregated per-token residual norm, as a Python |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
model_fingerprint(model)
Compute a deterministic digest identifying a model, from its configuration, dtype, and a sample of its weights.
The digest is a sha256 over (a) model.config.to_json_string(), (b) str(model.dtype), and
(c) for up to 8 evenly spaced named parameters, the parameter name plus its first 64 elements
flattened and cast to float32 bytes, truncated to 16 hex characters.
Properties:
- The same checkpoint at the same dtype yields equal digests in any process or device
placement, since parameter values are deterministic under
from_pretrained. - Any weight edit that touches the sampled slices (SFT, DPO, merging, LoRA merge) changes the digest; so does attaching unmerged adapters, since parameter names change.
- dtype is part of the identity, since a calibrated operating point is a numeric artifact and the same checkpoint loaded at a different dtype is a different runtime model for detection purposes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to fingerprint. |
required |
Returns:
| Type | Description |
|---|---|
str
|
A 16-character lowercase hex digest. |
Source code in steerability/algorithms/core/internals/fingerprint.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 | |
pool_over_spans(hidden, spans)
Mean-pool hidden states over specified spans.
A degenerate span (start >= end) falls back to the sample's last token position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
spans
|
list[tuple[int, int]]
|
List of |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Pooled tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
register_layout_detector(detector, *, prepend=True)
Register a callable mapping a model to a ModelLayout (or None to decline).
Registered detectors run before the built-in root and convention probing, in registration
order (prepend=True puts the new detector first). Registration is process-global.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
detector
|
Callable[[PreTrainedModel], ModelLayout | None]
|
A callable that returns a |
required |
prepend
|
bool
|
When True (the default), the detector runs before previously registered ones. |
True
|
Source code in steerability/algorithms/core/internals/model_layout.py
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
render_contrastive(tokenizer, data, mode)
Render both sides of a contrastive dataset under mode.
Accepts ContrastivePairs (paired, with optional shared prompts) or
LabeledExamples (unpaired classes, rendered independently). Resolves the
effective mode (with raw fallbacks and warnings), renders
positives/negatives, renders the prompt-only strings used for suffix-only
span computation, and reports the add_special_tokens flag the tokenizer
must use for all of the above.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer whose chat template defines the rendering. |
required |
data
|
ContrastivePairs | LabeledExamples
|
|
required |
mode
|
PromptFormat
|
Requested rendering policy. |
required |
Returns:
| Type | Description |
|---|---|
RenderedContrastive
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/render.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 112 113 114 115 | |
resolve_model_layout(model)
Resolve the ModelLayout for a HuggingFace causal LM.
Consults registered detectors first, then locates the decoder stack at one of the built-in
roots and selects a naming convention whose norm markers exist on the first decoder layer and
whose attention module exists on at least one layer. A hybrid stack that interleaves attention
layers with another token mixer resolves to its attention layers' family, with those layers
recorded in attention_layer_ids. PEFT wrappers are peeled before resolution and their prefix
is carried on the resolved layer_prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
A HuggingFace causal LM, a multimodal wrapper whose text decoder sits at a known root, or a PEFT-wrapped model. |
required |
Returns:
| Type | Description |
|---|---|
ModelLayout
|
The matching |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no detector and no built-in root/convention matches the model. |
Source code in steerability/algorithms/core/internals/model_layout.py
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 | |
select_at_positions(hidden, positions)
Select hidden states at specified positions for each sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
positions
|
LongTensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
select_spans(enc, prompt_enc, accumulate)
Determine token spans to pool over for each sample.
Span bounds are derived from the attention mask, so pads on either padding side are excluded.
Under accumulate="suffix-only", the per-sample prompt length (the number of real tokens in
prompt_enc) is skipped at the start of each span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enc
|
dict[str, Tensor]
|
Tokenized full sequences (prompts + completions). |
required |
prompt_enc
|
dict[str, Tensor] | None
|
Tokenized prompts only (if accumulate == "suffix-only"). |
required |
accumulate
|
str
|
"all", "suffix-only", or "last_token". |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[int, int]]
|
List of (start, end) tuples, one per sample. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/pooling.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 | |
text_config(model_or_config)
The config carrying the text decoder's structural facts.
Composite multimodal configs (text plus vision or audio sub-configs) return their text
sub-config; plain configs return themselves. Numeric structural facts (hidden_size,
num_attention_heads, head_dim, num_hidden_layers, intermediate_size) are read from the
returned config; identity facts (model_type, the fingerprint JSON, _attn_implementation)
stay on the composite model.config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_or_config
|
PreTrainedModel | PretrainedConfig
|
A model (its |
required |
Returns:
| Type | Description |
|---|---|
PretrainedConfig
|
The text config. |
Source code in steerability/algorithms/core/internals/model_layout.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
tokenize_pairs(tokenizer, pos_texts, neg_texts, device, *, add_special_tokens=True)
Tokenize positive/negative pairs together to ensure consistent padding.
Interleaves pairs before tokenization so each (pos, neg) pair shares the same padding length, keeping shared prefixes token-aligned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer to use. |
required |
pos_texts
|
Sequence[str]
|
List of positive text strings. |
required |
neg_texts
|
Sequence[str]
|
List of negative text strings (same length as |
required |
device
|
device | str
|
Target device. |
required |
add_special_tokens
|
bool
|
Whether to add special tokens (e.g. BOS). Pass False for chat-templated text that already contains them. |
True
|
Returns:
| Type | Description |
|---|---|
tuple[dict[str, Tensor], dict[str, Tensor]]
|
Tuple of |
Source code in steerability/algorithms/core/internals/encoding.py
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 | |
tokenize_texts(tokenizer, texts, device=None, *, add_special_tokens=True, max_length=None)
Tokenize a flat list of texts independently.
Each text is tokenized on its own, without interleaving. Use this when positive and negative examples are independent and do not need co-padding for token alignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer to use. |
required |
texts
|
Sequence[str]
|
List of text strings. |
required |
device
|
device | str | None
|
Target device for the returned tensors. When None, tensors are returned on the device the tokenizer produces them on (CPU). |
None
|
add_special_tokens
|
bool
|
Whether to add special tokens (e.g. BOS). Pass False for chat-templated text that already contains them. |
True
|
max_length
|
int | None
|
Truncation bound. When None, truncation falls back to the tokenizer's model maximum length. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Tensor]
|
Dictionary with |
Source code in steerability/algorithms/core/internals/encoding.py
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 | |
capture
Hooked/forward capture of hidden states at module boundaries.
HiddenStateLocation = Literal['layer_output', 'layer_input']
module-attribute
capture_hidden(enc, *, model=None, session=None, batch_size=8, on_batch=None, location='layer_output')
Extract per-layer hidden states for enc using a live model or a capture session.
With a live model (given directly, or reachable through an in-process session), the
extraction runs layerwise_tokenwise_hidden with the caller's batch size and progress
callback, preserving the in-process layout, i.e., the returned mask is enc's own. With a
remote capture-capable session, each row of enc becomes a token-id prompt (padding
positions dropped) served by session.capture over every decoder layer; the returned
tensors are right-padded to the batch's longest prompt and the returned mask describes
that layout, so pooling must use the returned mask rather than enc's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enc
|
dict[str, Tensor]
|
Tokenized input with |
required |
model
|
PreTrainedModel | None
|
A live model, used when no session provides one. |
None
|
session
|
SteeringSession | None
|
A |
None
|
batch_size
|
int
|
Forward batch size on the in-process path. |
8
|
on_batch
|
Callable[[], None] | None
|
Per-batch progress callback on the in-process path. |
None
|
location
|
HiddenStateLocation
|
Which residual-stream boundary each layer key maps to. |
'layer_output'
|
Returns:
| Type | Description |
|---|---|
tuple[dict[int, Tensor], Tensor | None]
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither a live model nor a session is available. |
Source code in steerability/algorithms/core/internals/capture.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 | |
layerwise_tokenwise_hidden(model, enc, batch_size=8, on_batch=None, *, location='layer_output')
Extract per-layer hidden states for all tokens.
outputs.hidden_states is a tuple of num_layers + 1 tensors: index 0 is the embedding output
(the input to layer 0) and index i is the output of layer i - 1, except the final entry,
which transformers returns with the model's final norm already applied.
location="layer_output": keylmaps to the raw output boundary of layerl(hidden_states[l + 1]forl < num_layers - 1; the final layer is re-captured pre-norm by a forward hook on the last decoder layer, matching hook runtimes and engine capture).location="layer_input": keylmaps to the input of layerl, i.e. the output of layerl - 1(hidden_states[l]), the boundary a layer pre-hook observes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to extract from. |
required |
enc
|
dict[str, Tensor]
|
Tokenized input with |
required |
batch_size
|
int
|
Batch size for forward passes. |
8
|
on_batch
|
Callable[[], None] | None
|
Optional callable invoked after each batch finishes. Used by callers to surface progress to the UI. |
None
|
location
|
HiddenStateLocation
|
Which residual-stream boundary each layer key maps to. |
'layer_output'
|
Returns:
| Type | Description |
|---|---|
dict[int, Tensor]
|
Dict mapping |
dict[int, Tensor]
|
outside |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/capture.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 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 | |
data
Contrastive data containers shared by detection and steering estimation.
ContrastivePairs
dataclass
Paired positive/negative text data for contrastive estimation.
The token sequence the model sees for each example is produced by
render_for_model according to the consumer's prompt format, and the
rendered string is tokenized with add_special_tokens=False for
chat-templated text.
Attributes:
| Name | Type | Description |
|---|---|---|
positives |
Sequence[str]
|
Texts exhibiting the target behavior. Treated as completions
under |
negatives |
Sequence[str]
|
Texts not exhibiting the target behavior (see |
prompts |
Sequence[str] | None
|
Optional shared prompts. Used as the user turn under
|
Source code in steerability/algorithms/core/internals/data.py
6 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 | |
negatives
instance-attribute
positives
instance-attribute
prompts = None
class-attribute
instance-attribute
LabeledExamples
dataclass
Independent positive/negative text data with binary labels.
The positive and negative lists need not be the same length. Applies to methods where positive and negative examples are independent and unpaired, and the estimator concatenates them. Optional group keys mark statements that must not straddle a train/validation split (e.g. the source question of each answer); estimators that do not split ignore them.
Attributes:
| Name | Type | Description |
|---|---|---|
positives |
Sequence[str]
|
Texts exhibiting the target behavior (label=1). |
negatives |
Sequence[str]
|
Texts not exhibiting the target behavior (label=0). |
positive_groups |
Sequence[str | int] | None
|
Group key per positive, same length as |
negative_groups |
Sequence[str | int] | None
|
Group key per negative, same length as |
Source code in steerability/algorithms/core/internals/data.py
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 | |
groups
property
Whether the data carries group keys (positive/negative groups both present).
negative_groups = None
class-attribute
instance-attribute
negatives
instance-attribute
positive_groups = None
class-attribute
instance-attribute
positives
instance-attribute
as_contrastive_pairs(x)
Normalize input to ContrastivePairs.
Accepts:
- An existing `ContrastivePairs` instance (returned as-is).
- A dict with keys `"positives"`, `"negatives"`, and optionally `"prompts"`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
ContrastivePairs | dict
|
Input to normalize. |
required |
Returns:
| Type | Description |
|---|---|
ContrastivePairs
|
A |
Raises:
| Type | Description |
|---|---|
TypeError
|
If input is neither |
Source code in steerability/algorithms/core/internals/data.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
as_labeled_examples(x)
Normalize input to LabeledExamples.
Accepts:
- An existing `LabeledExamples` instance (returned as-is).
- A `ContrastivePairs` instance (converted; pairing is dropped).
- A dict with keys `"positives"` and `"negatives"`, and optionally `"positive_groups"`
and `"negative_groups"`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
LabeledExamples | ContrastivePairs | dict
|
Input to normalize. |
required |
Returns:
| Type | Description |
|---|---|
LabeledExamples
|
A |
Raises:
| Type | Description |
|---|---|
TypeError
|
If input is not |
Source code in steerability/algorithms/core/internals/data.py
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 | |
encoding
Text-to-tensor tokenization entry points.
tokenize_pairs(tokenizer, pos_texts, neg_texts, device, *, add_special_tokens=True)
Tokenize positive/negative pairs together to ensure consistent padding.
Interleaves pairs before tokenization so each (pos, neg) pair shares the same padding length, keeping shared prefixes token-aligned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer to use. |
required |
pos_texts
|
Sequence[str]
|
List of positive text strings. |
required |
neg_texts
|
Sequence[str]
|
List of negative text strings (same length as |
required |
device
|
device | str
|
Target device. |
required |
add_special_tokens
|
bool
|
Whether to add special tokens (e.g. BOS). Pass False for chat-templated text that already contains them. |
True
|
Returns:
| Type | Description |
|---|---|
tuple[dict[str, Tensor], dict[str, Tensor]]
|
Tuple of |
Source code in steerability/algorithms/core/internals/encoding.py
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 | |
tokenize_texts(tokenizer, texts, device=None, *, add_special_tokens=True, max_length=None)
Tokenize a flat list of texts independently.
Each text is tokenized on its own, without interleaving. Use this when positive and negative examples are independent and do not need co-padding for token alignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer to use. |
required |
texts
|
Sequence[str]
|
List of text strings. |
required |
device
|
device | str | None
|
Target device for the returned tensors. When None, tensors are returned on the device the tokenizer produces them on (CPU). |
None
|
add_special_tokens
|
bool
|
Whether to add special tokens (e.g. BOS). Pass False for chat-templated text that already contains them. |
True
|
max_length
|
int | None
|
Truncation bound. When None, truncation falls back to the tokenizer's model maximum length. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Tensor]
|
Dictionary with |
Source code in steerability/algorithms/core/internals/encoding.py
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 | |
fingerprint
Digests identifying the model a fitted artifact was estimated on.
artifact_provenance_meta(model, tokenizer=None)
Provenance fingerprints for a fitted steering artifact.
Always records the toolkit model fingerprint; when vllm_hook_plugins is installed, adds
the plugin's config and chat-template fingerprint recipes, which cross-check against a
serving engine's discovery payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model the artifact was fitted on. |
required |
tokenizer
|
PreTrainedTokenizerBase | None
|
The tokenizer used during fitting, for the chat-template fingerprint. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
The provenance mapping. Keys: |
dict
|
|
Source code in steerability/algorithms/core/internals/fingerprint.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 | |
is_absent_chat_template_fingerprint(fingerprint)
Whether fingerprint denotes an absent chat template under the plugin recipe.
A serving engine that exposes no chat template reports the fingerprint of an empty
template, so a mismatch against such a value reflects exposure rather than divergence
and comparisons should skip it. Uses the plugin recipe when vllm_hook_plugins is
installed and falls back to the recipe's stable digest of an empty template otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fingerprint
|
str | None
|
The reported fingerprint, or None when none was reported. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True when the fingerprint denotes an absent chat template. |
Source code in steerability/algorithms/core/internals/fingerprint.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
model_fingerprint(model)
Compute a deterministic digest identifying a model, from its configuration, dtype, and a sample of its weights.
The digest is a sha256 over (a) model.config.to_json_string(), (b) str(model.dtype), and
(c) for up to 8 evenly spaced named parameters, the parameter name plus its first 64 elements
flattened and cast to float32 bytes, truncated to 16 hex characters.
Properties:
- The same checkpoint at the same dtype yields equal digests in any process or device
placement, since parameter values are deterministic under
from_pretrained. - Any weight edit that touches the sampled slices (SFT, DPO, merging, LoRA merge) changes the digest; so does attaching unmerged adapters, since parameter names change.
- dtype is part of the identity, since a calibrated operating point is a numeric artifact and the same checkpoint loaded at a different dtype is a different runtime model for detection purposes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to fingerprint. |
required |
Returns:
| Type | Description |
|---|---|
str
|
A 16-character lowercase hex digest. |
Source code in steerability/algorithms/core/internals/fingerprint.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 | |
session_artifact_identity(session)
(model_type, meta) recorded for a session-fitted artifact, from the session layout.
The meta carries the layout's model_fingerprint and model_ref when present, so
identity checks against the venue that will read the artifact stay possible without a
live model. Returns ("unknown", {}) when no session layout is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SteeringSession | None
|
The |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, dict]
|
The model type and the provenance mapping. |
Source code in steerability/algorithms/core/internals/fingerprint.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 | |
model_layout
Architecture-specific module paths for reading and steering a model's decoder stack.
ModelLayout names the decoder layer prefix, attention/output-projection suffixes, and
normalization sub-module attributes for one model family. resolve_model_layout maps a
PreTrainedModel to its layout by locating the decoder stack at one of an ordered set of dotted
roots and probing the first decoder layer's attributes to select a naming convention.
Decoder-stack roots, in probe order:
model.layers: text-only decoder language models (Llama, Mistral, Qwen, Gemma text).model.language_model.layers: composite multimodal wrappers (the transformers >= 5 layout, e.g. Gemma 3/4, Llava, Qwen-VL), where the toolkit steers the text decoder under text-only prompting.transformer.h: GPT-2-style models.
Per-layer naming conventions, in probe order (gemma_style precedes llama_style because a Gemma
decoder layer also carries the Llama markers):
gemma_style:self_attn, residual-stream normsinput_layernormandpre_feedforward_layernorm.llama_style:self_attn, residual-stream normsinput_layernormandpost_attention_layernorm.gpt2_style:attn, residual-stream normsln_1andln_2.
A convention matches when its norm markers exist on the first decoder layer and its attention
module exists on at least one decoder layer. Hybrid stacks that interleave attention layers with
another token mixer (Qwen3.5 and Qwen3-Next, where three Gated DeltaNet linear_attn layers
precede each self_attn layer) therefore resolve to the convention of their attention layers,
and the layout records which layers carry attention in attention_layer_ids. Residual-stream
sites (decoder-layer boundaries and the norm inputs) exist on every layer of such a stack;
attention sites (attn_names, oproj_names, head_geometry) exist only on the attention
layers, and consumers check has_attention before resolving them.
PEFT wrappers are peeled before resolution: PeftModel.base_model is the tuner and the tuner's
model attribute is the wrapped model, both registered submodules, so each wrapper contributes the
prefix "base_model.model." and the resulting paths resolve through get_submodule without relying
on attribute forwarding.
register_layout_detector adds a callable consulted before the built-in resolution, so a user on an
unlisted family is not blocked on a toolkit release.
logger = logging.getLogger(__name__)
module-attribute
HeadGeometry
dataclass
Attention head geometry of one decoder layer.
Attributes:
| Name | Type | Description |
|---|---|---|
num_heads |
int
|
Number of attention heads. |
head_dim |
int
|
Per-head dimension. |
Source code in steerability/algorithms/core/internals/model_layout.py
306 307 308 309 310 311 312 313 314 315 316 | |
head_dim
instance-attribute
num_heads
instance-attribute
ModelLayout
dataclass
Architecture-specific module paths for one model family.
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
Family label ( |
layer_prefix |
str
|
Dotted prefix of the decoder layer list (e.g. |
num_layers |
int
|
Number of decoder layers. |
attn_suffix |
str
|
Suffix of the per-layer attention module ( |
oproj_suffix |
str
|
Suffix of the attention output projection ( |
norm_attrs |
tuple[str, ...]
|
The per-layer normalization sub-module attribute names whose input is the
residual stream ( |
attention_layer_ids |
tuple[int, ...] | None
|
The decoder layers carrying the attention module at |
Source code in steerability/algorithms/core/internals/model_layout.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 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 | |
attention_layer_ids = None
class-attribute
instance-attribute
attention_layers
property
The decoder layers carrying an attention module, ascending; every layer when
attention_layer_ids is None.
attn_names
property
Dotted paths of every layer's attention module, index-aligned with layer_names. On a
hybrid stack, entries outside attention_layers name modules the model does not have.
attn_suffix
instance-attribute
family
instance-attribute
is_hybrid
property
True when some decoder layer carries no attention module.
layer_names
property
Dotted paths of every decoder layer, [f"{layer_prefix}.{i}"].
layer_prefix
instance-attribute
norm_attrs
instance-attribute
num_layers
instance-attribute
oproj_names
property
Dotted paths of every layer's attention output projection, index-aligned with
layer_names. On a hybrid stack, entries outside attention_layers name modules the
model does not have.
oproj_suffix
instance-attribute
has_attention(layer_id)
True when decoder layer layer_id carries the attention module at attn_suffix.
Source code in steerability/algorithms/core/internals/model_layout.py
115 116 117 | |
head_geometry(model, layout, layer_id)
Per-layer attention head geometry, read from the module tree.
head_dim comes from the attention module's head_dim attribute, else the text config;
num_heads is the output projection's input width divided by head_dim. GPT-2's Conv1D
stores its weight as [in, out], so the width is read from weight.shape[0] when
in_features is absent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The live model (or PEFT wrapper) carrying the attention modules. |
required |
layout
|
ModelLayout
|
The resolved |
required |
layer_id
|
int
|
The decoder layer index. |
required |
Returns:
| Type | Description |
|---|---|
HeadGeometry
|
The layer's |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/model_layout.py
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 | |
register_layout_detector(detector, *, prepend=True)
Register a callable mapping a model to a ModelLayout (or None to decline).
Registered detectors run before the built-in root and convention probing, in registration
order (prepend=True puts the new detector first). Registration is process-global.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
detector
|
Callable[[PreTrainedModel], ModelLayout | None]
|
A callable that returns a |
required |
prepend
|
bool
|
When True (the default), the detector runs before previously registered ones. |
True
|
Source code in steerability/algorithms/core/internals/model_layout.py
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
resolve_model_layout(model)
Resolve the ModelLayout for a HuggingFace causal LM.
Consults registered detectors first, then locates the decoder stack at one of the built-in
roots and selects a naming convention whose norm markers exist on the first decoder layer and
whose attention module exists on at least one layer. A hybrid stack that interleaves attention
layers with another token mixer resolves to its attention layers' family, with those layers
recorded in attention_layer_ids. PEFT wrappers are peeled before resolution and their prefix
is carried on the resolved layer_prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
A HuggingFace causal LM, a multimodal wrapper whose text decoder sits at a known root, or a PEFT-wrapped model. |
required |
Returns:
| Type | Description |
|---|---|
ModelLayout
|
The matching |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no detector and no built-in root/convention matches the model. |
Source code in steerability/algorithms/core/internals/model_layout.py
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 | |
text_config(model_or_config)
The config carrying the text decoder's structural facts.
Composite multimodal configs (text plus vision or audio sub-configs) return their text
sub-config; plain configs return themselves. Numeric structural facts (hidden_size,
num_attention_heads, head_dim, num_hidden_layers, intermediate_size) are read from the
returned config; identity facts (model_type, the fingerprint JSON, _attn_implementation)
stay on the composite model.config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_or_config
|
PreTrainedModel | PretrainedConfig
|
A model (its |
required |
Returns:
| Type | Description |
|---|---|
PretrainedConfig
|
The text config. |
Source code in steerability/algorithms/core/internals/model_layout.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
pooling
Token, span, and position aggregation primitives for captured hidden states.
aggregate_condition_hidden(hidden, mode, attention_mask=None)
Aggregate [B, T, H] hidden states to [B, H] using non-pad tokens only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
mode
|
Literal['mean', 'last']
|
"mean" pools over all real tokens; "last" selects the last real token per row. |
required |
attention_mask
|
Tensor | None
|
Shape |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Aggregated tensor of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a row has no real tokens, or the mode is unsupported. |
Source code in steerability/algorithms/core/internals/pooling.py
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 | |
get_last_token_positions(attention_mask, seq_len, num_samples)
Find the last non-pad token position for each sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attention_mask
|
Tensor | None
|
Shape |
required |
seq_len
|
int
|
Sequence length |
required |
num_samples
|
int
|
Number of samples |
required |
Returns:
| Type | Description |
|---|---|
LongTensor
|
Tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
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 | |
masked_mean(hidden, attention_mask)
Mean-pool [N, T, H] hidden states over real (non-pad) positions.
Falls back to an unmasked mean over all positions when no attention mask is available.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
attention_mask
|
Tensor | None
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Pooled tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
pool_over_spans(hidden, spans)
Mean-pool hidden states over specified spans.
A degenerate span (start >= end) falls back to the sample's last token position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
spans
|
list[tuple[int, int]]
|
List of |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Pooled tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
select_at_positions(hidden, positions)
Select hidden states at specified positions for each sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
Tensor
|
Shape |
required |
positions
|
LongTensor
|
Shape |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Tensor of shape |
Source code in steerability/algorithms/core/internals/pooling.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
select_spans(enc, prompt_enc, accumulate)
Determine token spans to pool over for each sample.
Span bounds are derived from the attention mask, so pads on either padding side are excluded.
Under accumulate="suffix-only", the per-sample prompt length (the number of real tokens in
prompt_enc) is skipped at the start of each span.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enc
|
dict[str, Tensor]
|
Tokenized full sequences (prompts + completions). |
required |
prompt_enc
|
dict[str, Tensor] | None
|
Tokenized prompts only (if accumulate == "suffix-only"). |
required |
accumulate
|
str
|
"all", "suffix-only", or "last_token". |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[int, int]]
|
List of (start, end) tuples, one per sample. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/pooling.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 | |
render
Render ContrastivePairs into model-ready text.
The general, tokenizer-level rendering primitives live in
steerability.utils.rendering; this module adds the data-specific renderer
that turns a ContrastivePairs into model-ready text under a PromptFormat.
logger = logging.getLogger(__name__)
module-attribute
RenderedContrastive
dataclass
Rendered text for a ContrastivePairs, plus tokenization policy.
Attributes:
| Name | Type | Description |
|---|---|---|
pos_texts |
list[str]
|
Rendered positive examples. |
neg_texts |
list[str]
|
Rendered negative examples. |
prompt_texts |
list[str] | None
|
User-turn-only renders for suffix-only span computation, or None when there is no separate prompt/completion split. |
add_special_tokens |
bool
|
Flag callers must pass to the tokenizer for all of the above (False for chat modes, True for raw). |
effective_mode |
PromptFormat
|
The mode actually applied after raw fallbacks. |
Source code in steerability/algorithms/core/internals/render.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
add_special_tokens
instance-attribute
effective_mode
instance-attribute
neg_texts
instance-attribute
pos_texts
instance-attribute
prompt_texts
instance-attribute
render_contrastive(tokenizer, data, mode)
Render both sides of a contrastive dataset under mode.
Accepts ContrastivePairs (paired, with optional shared prompts) or
LabeledExamples (unpaired classes, rendered independently). Resolves the
effective mode (with raw fallbacks and warnings), renders
positives/negatives, renders the prompt-only strings used for suffix-only
span computation, and reports the add_special_tokens flag the tokenizer
must use for all of the above.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer whose chat template defines the rendering. |
required |
data
|
ContrastivePairs | LabeledExamples
|
|
required |
mode
|
PromptFormat
|
Requested rendering policy. |
required |
Returns:
| Type | Description |
|---|---|
RenderedContrastive
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/render.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 112 113 114 115 | |
stats
Estimate per-layer activation moments and characterize residual-stream norms.
STATS_FORMAT_VERSION = 1
module-attribute
logger = logging.getLogger(__name__)
module-attribute
ActivationStats
dataclass
Per-layer mean and variance of a model's ambient activation distribution.
The statistics support per-coordinate centering and scaling of pooled activations
(standardize), the whitening used by diagonal-LDA probe fitting. Covariance is diagonal,
since the dominant effects in residual-stream geometry (a large shared component in every
activation and rogue dimensions dominating inner products) are axis-aligned, so per-coordinate
centering and scaling removes most of the effect, and a full covariance is hard to estimate
reliably and expensive to invert at a few thousand samples.
Under pooling="tokens", every retained real token position is one sample of the ambient
distribution, and exclude_first_n (default 1) drops the leading real positions per sequence,
since the first real position (BOS or an opening delimiter) carries known massive-activation
outliers that distort the mean disproportionately. "mean" and "last" pool per prompt first,
yielding one sample per prompt, and ignore exclude_first_n.
count is the number of pooled samples accumulated, i.e., tokens under pooling="tokens" and
prompts otherwise. estimate warns when count falls below its min_samples argument; a few
hundred varied texts clears the default under token pooling, while "mean" and "last" need a
few thousand prompts.
Attributes:
| Name | Type | Description |
|---|---|---|
model_type |
str
|
HuggingFace |
model_fingerprint |
str
|
Identity digest of that model, recorded at estimate time. |
location |
str
|
Residual-stream boundary the statistics were measured at. |
count |
int
|
Number of pooled samples accumulated. |
mean |
dict[int, Tensor]
|
Per-layer mean, |
var |
dict[int, Tensor]
|
Per-layer variance, |
var_floor |
float
|
Lower bound applied to every variance coordinate. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
count
instance-attribute
location
instance-attribute
mean
instance-attribute
model_fingerprint
instance-attribute
model_type
instance-attribute
var
instance-attribute
var_floor = 1e-06
class-attribute
instance-attribute
estimate(model, tokenizer, texts, *, layer_ids=None, location='layer_input', pooling='tokens', exclude_first_n=1, batch_size=8, min_samples=5000, session=None)
classmethod
Estimate per-layer activation statistics over texts.
Texts are tokenized in chunks of batch_size, captured at location, and pooled per
pooling. Sequences with no real tokens contribute no samples, and duplicate entries in
layer_ids are collapsed. Accumulation is streaming (per-chunk Welford merge) in float32
on CPU, so the full feature matrix is never materialized. Capture runs under torch.no_grad() with
use_cache=False, wrapped in auxiliary_pass(aligned=True), so co-resident state
controls' condition scorers, gates, and position counters ignore the passes while
"all"-scoped behavior transforms still apply (the statistics measure the stream as
deployed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
Model to capture activations from. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for encoding |
required |
texts
|
Sequence[str]
|
Texts whose activations define the ambient distribution. |
required |
layer_ids
|
Sequence[int] | None
|
Layers to estimate (0-based). None selects all decoder layers. |
None
|
location
|
str
|
Residual-stream boundary to measure at. |
'layer_input'
|
pooling
|
Literal['mean', 'last', 'tokens']
|
|
'tokens'
|
exclude_first_n
|
int
|
Leading real token positions dropped per sequence under
|
1
|
batch_size
|
int
|
Batch size for the capture forward passes. |
8
|
min_samples
|
int
|
Pooled-sample count below which a low-sample warning is emitted. |
5000
|
Returns:
| Type | Description |
|---|---|
ActivationStats
|
An |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Warns:
| Type | Description |
|---|---|
UserWarning
|
When the accumulated pooled-sample |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
fingerprint()
Digest of this artifact (not of the model it was estimated on).
Returns:
| Type | Description |
|---|---|
str
|
A 16-character lowercase hex digest over the metadata and tensor contents. |
Source code in steerability/algorithms/core/internals/stats.py
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | |
load(dir_path)
classmethod
Load an artifact saved by save.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dir_path
|
str | Path
|
Directory containing the safetensors file and JSON sidecar. |
required |
Returns:
| Type | Description |
|---|---|
ActivationStats
|
The loaded |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the artifact-format version is unsupported. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
save(dir_path)
Save the artifact to a directory (safetensors for tensors, JSON sidecar for metadata).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dir_path
|
str | Path
|
Directory to write to; created if missing. |
required |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
standardize(features, layer_id)
Center and scale features per coordinate with this artifact's layer statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
features
|
Tensor
|
Tensor of shape |
required |
layer_id
|
int
|
Layer whose statistics to apply. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
Source code in steerability/algorithms/core/internals/stats.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
StatsSpec
dataclass
Deferred recipe for ActivationStats; holds every argument except the model.
Attributes:
| Name | Type | Description |
|---|---|---|
texts |
Sequence[str]
|
Texts whose activations define the ambient distribution. |
layer_ids |
Sequence[int] | None
|
Layers to estimate (0-based). None selects all decoder layers. |
location |
str
|
Residual-stream boundary the statistics are measured at. |
pooling |
Literal['mean', 'last', 'tokens']
|
Sample construction. |
exclude_first_n |
int
|
Number of leading real token positions dropped per sequence under
|
batch_size |
int
|
Batch size for the capture forward passes. |
Source code in steerability/algorithms/core/internals/stats.py
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 | |
batch_size = 8
class-attribute
instance-attribute
exclude_first_n = 1
class-attribute
instance-attribute
layer_ids = None
class-attribute
instance-attribute
location = 'layer_input'
class-attribute
instance-attribute
pooling = 'tokens'
class-attribute
instance-attribute
texts
instance-attribute
estimate(model, tokenizer, session=None)
Estimate ActivationStats on model with this recipe's settings.
Source code in steerability/algorithms/core/internals/stats.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
measure_residual_norms(model, tokenizer, layer_ids, prompts, *, location='layer_output', stat='median', prompt_format='chat_prompt', batch_size=8)
Typical per-token residual-stream norm at each requested layer boundary.
The statistic is aggregated over the real (non-pad) tokens of prompts at the residual-stream
boundary named by location. Residual norms grow with depth, so the returned per-layer norms
let a caller rescale a direction to a fixed fraction of the norm at each layer (see
SteeringVector.scaled_to_norms).
Prompts are rendered via render_for_model(tokenizer, prompt=p, mode=prompt_format). The default
prompt_format="chat_prompt" renders with add_generation_prompt=True, matching what inference
produces for a prompt. The rendered string is tokenized with add_special_tokens=False whenever
a chat template was applied, matching how the estimators consume contrastive text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
Model to extract hidden states from. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for rendering and encoding the prompts. |
required |
layer_ids
|
Sequence[int] | None
|
Layers to measure (0-based). |
required |
prompts
|
Sequence[str]
|
Calibration prompts. Use fit-distribution, inference-style prompts rather than a held-out evaluation set. |
required |
location
|
HiddenStateLocation
|
Residual-stream boundary each layer key maps to. |
'layer_output'
|
stat
|
Literal['median', 'mean']
|
Aggregation over the pooled real-token norms, |
'median'
|
prompt_format
|
PromptFormat
|
How each prompt is rendered into model-ready text (via |
'chat_prompt'
|
batch_size
|
int
|
Batch size for the extraction forward passes. |
8
|
Returns:
| Type | Description |
|---|---|
dict[int, float]
|
Mapping from layer id to the aggregated per-token residual norm, as a Python |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/core/internals/stats.py
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 | |