Common library
steerability.algorithms.output_control.common
Output control component library.
Factors the output category into reusable components: candidate policies, per-candidate value
functions, full-vocabulary logit sources, sequence scorers, a segment-search driver, a phased
driver, composable stopping criteria, KV-cache utilities, and the PrefixKeyedProcessor base
for stateful logits processors.
candidate_forward
Same-model forward of candidate continuations with prefix KV-cache reuse.
Some candidate values require forwarding the pipeline's own model mid-step to read candidate
hidden states; CandidateForward performs those forwards. The states it reports lie at the raw
output boundary of the final decoder layer (location="layer_output" in the capture utilities),
before the model's final norm. These passes are marked as auxiliary via
auxiliary_pass(aligned=True), so state-control accounting keeps them out of condition
scoring and gate updates while transforms still apply at the candidates' true positions (prefix
and candidate positions lie on the generation's own coordinate axis). At hook points where the
state runtime cannot read pass positions, it skips transforming these passes and
warns once. Values scored by an auxiliary model are unaffected.
CandidateForward
Batched forward of (prefix + candidate_k) for all K candidates on a given model.
Maintains an internal prefix KV cache keyed on the prefix ids. When a call's prefix extends the
cached one, only the delta tokens are forwarded to extend the cache (one 1-token forward per
decode step in the common case); any non-extension (rewind, restart, new generation, scoring
replay from an unrelated prefix) rebuilds from scratch. The candidate evaluation then repeats a
fresh copy of the cache across the K candidates, so the incremental cache survives the call.
Explicit cache_position is passed on every forward, including the prefix rebuild (this is what
generate does internally), and the model derives token positions from it, so the prefix must
be unpadded: an attention mask containing zeros is rejected. Supports batch size 1 only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The model to forward through (the pipeline's own model for same-model values). |
required |
Source code in steerability/algorithms/output_control/common/candidate_forward.py
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 | |
_cache = None
instance-attribute
_cached_ids = None
instance-attribute
_cached_mask = None
instance-attribute
_final_layer = model.get_submodule(resolve_model_layout(model).layer_names[-1])
instance-attribute
model = model
instance-attribute
__init__(model)
Source code in steerability/algorithms/output_control/common/candidate_forward.py
39 40 41 42 43 44 | |
_sync_cache(prefix_ids, full_mask)
Bring the internal cache up to prefix_ids (extend by the delta, or rebuild).
Source code in steerability/algorithms/output_control/common/candidate_forward.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
last_hidden_states(prefix_ids, candidate_ids, attention_mask=None)
Return final-layer hidden states at the candidate position for each candidate.
The returned states lie at the raw output boundary of the final decoder layer
(location="layer_output" in the capture utilities), before the model's final norm,
recovered with a forward hook on that layer. The hook is registered per call, around the
candidate forward only, so it observes the output after any session-registered
state-control hooks on the same module.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prefix_ids
|
Tensor
|
|
required |
candidate_ids
|
Tensor
|
|
required |
attention_mask
|
Tensor | None
|
Optional prefix mask; right-extended with ones to the prefix length. Must contain no zeros. |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
A tensor |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the prefix batch size is not 1, or the attention mask contains zeros. |
RuntimeError
|
If the candidate forward does not pass through the final decoder layer exactly once. |
Source code in steerability/algorithms/output_control/common/candidate_forward.py
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 | |
candidates
Candidate token policies for step-shaped output controls.
A candidate policy turns a full-vocabulary score row into the small set of tokens a per-candidate
value function will evaluate. Composition position matters and is a feature: a value-guided
processor with policy="surviving" placed after other processors steers exactly the distribution
they left behind (SASA's behavior with a composed processor stack).
CandidatePolicy = Literal['top_k', 'top_p', 'surviving']
module-attribute
select_candidates(scores, policy, *, k=None, p=None)
Return (candidate_ids [B, K], candidate_scores [B, K]) under policy.
Policies:
- `top_k`: the `k` highest-scoring tokens per row (batch-safe).
- `top_p`: the smallest nucleus with cumulative probability >= `p`. Batch size 1 only
(K varies per row); raises on `B > 1`.
- `surviving`: every token with a finite score, i.e. whatever earlier processors in the
composed stack left finite. Batch size 1 only, for the same reason.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
Tensor
|
Next-token logits |
required |
policy
|
CandidatePolicy
|
One of |
required |
k
|
int | None
|
Number of candidates for |
None
|
p
|
float | None
|
Nucleus threshold for |
None
|
Returns:
| Type | Description |
|---|---|
tuple[Tensor, Tensor]
|
A tuple |
Raises:
| Type | Description |
|---|---|
ValueError
|
On an unknown policy, a missing |
Source code in steerability/algorithms/output_control/common/candidates.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 | |
criteria
Composable stopping criteria.
Plain StoppingCriteria usable both as pipeline-composed criteria (via
OutputControl.get_stopping_criteria) and inside phased-driver phases. Each returns a per-row
boolean tensor: True where that row should stop.
BudgetTokens
Bases: StoppingCriteria
Stop a row once it has generated n tokens past prompt_len.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Token budget (new tokens) before stopping. |
required |
prompt_len
|
int
|
Number of prompt tokens (the budget counts tokens beyond this length). |
required |
Source code in steerability/algorithms/output_control/common/criteria.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
_n = n
instance-attribute
_prompt_len = prompt_len
instance-attribute
__call__(input_ids, scores, **kwargs)
Source code in steerability/algorithms/output_control/common/criteria.py
75 76 77 | |
__init__(n, prompt_len)
Source code in steerability/algorithms/output_control/common/criteria.py
71 72 73 | |
StopOnSubstring
Bases: StoppingCriteria
Stop a row once the newly generated text contains text.
Decodes only the tokens generated after prompt_len per check (so the substring test runs on
the continuation, not the prompt). Decoding per step is the cost of a text-level stop condition;
for token-level stops prefer StopOnTokens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer used to decode the continuation. |
required |
text
|
str
|
The substring that triggers stopping. |
required |
prompt_len
|
int
|
Number of prompt tokens to skip when decoding the continuation. |
required |
Source code in steerability/algorithms/output_control/common/criteria.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 | |
_prompt_len = prompt_len
instance-attribute
_text = text
instance-attribute
_tokenizer = tokenizer
instance-attribute
__call__(input_ids, scores, **kwargs)
Source code in steerability/algorithms/output_control/common/criteria.py
33 34 35 36 37 38 39 40 | |
__init__(tokenizer, text, prompt_len)
Source code in steerability/algorithms/output_control/common/criteria.py
28 29 30 31 | |
StopOnTokens
Bases: StoppingCriteria
Stop a row once its last token is one of ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ids
|
Iterable[int]
|
Token ids that trigger stopping. |
required |
Source code in steerability/algorithms/output_control/common/criteria.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
_ids = set(int(i) for i in ids)
instance-attribute
__call__(input_ids, scores, **kwargs)
Source code in steerability/algorithms/output_control/common/criteria.py
53 54 55 56 57 58 59 60 | |
__init__(ids)
Source code in steerability/algorithms/output_control/common/criteria.py
50 51 | |
drivers
Decoding drivers (segment search and phased splicing) and their support components.
frontier
Top-k, finished, and best-so-far bookkeeping for the segment search in SearchDriver.
Frontier
Keep top-k beams by score, track per-beam finished flags and best-so-far.
Because beams arrive right-padded to a common length, a kept beam's continuation is first
stripped of trailing pad_token_id positions to recover its true length. The beam is
finished when the stripped continuation ends in a token of the eos set, or when its
stripped length reaches max_new_tokens. A beam cut by a caller-supplied stopping
criterion classifies as unfinished.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keep_k
|
int
|
Number of beams to retain each iteration. |
required |
eos_token_id
|
int | list[int] | None
|
Finished-beam token id(s), as an int, a list of ints, or None (disables the EOS check). |
required |
input_length
|
int
|
Prompt length, used to slice each beam's continuation. |
required |
max_new_tokens
|
int | None
|
Global token budget (None disables the budget check). |
required |
pad_token_id
|
int | None
|
Padding token id stripped from continuation tails, or None (no stripping). |
None
|
Source code in steerability/algorithms/output_control/common/drivers/frontier.py
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 | |
best_ids = None
instance-attribute
best_score = float('-inf')
instance-attribute
eos_token_id = eos_token_id
instance-attribute
input_length = input_length
instance-attribute
keep_k = keep_k
instance-attribute
max_new_tokens = max_new_tokens
instance-attribute
pad_token_id = pad_token_id
instance-attribute
__init__(keep_k, eos_token_id, input_length, max_new_tokens, pad_token_id=None)
Source code in steerability/algorithms/output_control/common/drivers/frontier.py
44 45 46 47 48 49 50 51 52 | |
keep(beams, scores)
Select the top-k beams, update best-so-far, and compute finished flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
beams
|
Tensor
|
Candidate beam sequences |
required |
scores
|
list[float]
|
One score per beam. |
required |
Returns:
| Type | Description |
|---|---|
FrontierStep
|
A |
Source code in steerability/algorithms/output_control/common/drivers/frontier.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 83 | |
FrontierStep
dataclass
Result of keeping the top-k beams for one search iteration.
Attributes:
| Name | Type | Description |
|---|---|---|
kept_ids |
Tensor
|
The top-k beam sequences |
kept_scores |
list[float]
|
Their scores. |
finished_flags |
list[bool]
|
Per-kept-beam finished flag (EOS hit or budget reached). |
Source code in steerability/algorithms/output_control/common/drivers/frontier.py
11 12 13 14 15 16 17 18 19 20 21 22 23 | |
finished_flags
instance-attribute
kept_ids
instance-attribute
kept_scores
instance-attribute
__init__(kept_ids, kept_scores, finished_flags)
phased
Phase-plan types (Fixed, Generated) and PhasedDriver, which executes a plan by splicing
token streams.
A phase plan is a list of Fixed (append text without generating) and Generated (generate until a
boundary) phases. Every Generated phase delegates to model.generate with the received stacks
(the driver contract satisfied per phase). An extract_after output rule reproduces
ThinkingIntervention's tail extraction.
Fixed
dataclass
Splice this text's tokens into the stream without generating.
Attributes:
| Name | Type | Description |
|---|---|---|
text |
str | Callable[[str, dict], str]
|
A literal string, or a callable |
replace |
bool
|
When True, this phase's tokens replace the current stream rather than being appended. Used to model a prompt-rewriting transform (ThinkingIntervention) whose text already contains the prompt. |
add_special_tokens |
bool
|
Whether to add special tokens when tokenizing (True for a replacing phase that becomes the new prompt; False for an appended snippet). |
Source code in steerability/algorithms/output_control/common/drivers/phased.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
add_special_tokens = False
class-attribute
instance-attribute
replace = False
class-attribute
instance-attribute
text
instance-attribute
__init__(text, replace=False, add_special_tokens=False)
Generated
dataclass
Generate until a boundary: the until substring, any token in until_token_ids, or the
token budget, whichever occurs first.
All three compose with the pipeline's criteria for the phase. until_token_ids is the
backend-portable form of a delimiter that tokenizes to a special token, which a stop string
cannot express (skip_special_tokens=True strips it before a vLLM stop-string match).
Attributes:
| Name | Type | Description |
|---|---|---|
until |
str | None
|
Substring that ends the phase (via |
until_token_ids |
tuple[int, ...]
|
Token ids any one of which ends the phase once it is the last generated
token (via |
budget |
int | None
|
Max new tokens for the phase (via |
Source code in steerability/algorithms/output_control/common/drivers/phased.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
budget = None
class-attribute
instance-attribute
until = None
class-attribute
instance-attribute
until_token_ids = ()
class-attribute
instance-attribute
__init__(until=None, until_token_ids=(), budget=None)
__post_init__()
Source code in steerability/algorithms/output_control/common/drivers/phased.py
61 62 | |
PhasedDriver
Bases: DecodingDriver
Execute a per-example phase plan by splicing token streams.
Subclasses / callers provide plan(prompt_text, params) -> list[Fixed | Generated]. Every
Generated phase delegates to model.generate with the received stacks. An extract_after
output rule reproduces ThinkingIntervention's tail extraction: decode, rsplit on the marker, keep
the original prompt's token prefix + the re-tokenized remainder.
Plans are per example; batched inputs are handled by looping over rows.
Source code in steerability/algorithms/output_control/common/drivers/phased.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 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 | |
RUNTIME_KWARGS_SCHEMA = [{'name': 'params', 'type': 'dict', 'scope': 'call', 'help': 'Phase-plan parameters for this call: a mapping whose scalar values apply to every prompt row and whose list values carry one entry per row, of batch length.'}]
class-attribute
instance-attribute
args = self.Args.validate(*args, **kwargs)
instance-attribute
enabled = True
class-attribute
instance-attribute
extract_after = extract_after
instance-attribute
include_in_scoring = True
class-attribute
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
supports_batching = False
class-attribute
instance-attribute
tokenizer = None
instance-attribute
__init__(extract_after=None)
Source code in steerability/algorithms/output_control/common/drivers/phased.py
88 89 90 | |
_configure()
Post-construction hook, called after Args fields are mirrored onto the instance.
Driver presets override this to map their mirrored args onto the fields their generic base
reads, so subclasses never bypass a parent __init__. Default no-op.
Source code in steerability/algorithms/core/base_control.py
67 68 69 70 71 72 73 | |
_finalize(out_ids, original_length)
Apply the extract_after output rule (or return the full spliced sequence).
Source code in steerability/algorithms/output_control/common/drivers/phased.py
226 227 228 229 230 231 232 233 234 235 236 237 238 | |
_generate_phase(phase, current, base_generate, via_session, logits_processors, stopping_criteria, gen_kwargs)
Run one Generated phase, composing its boundary with the pipeline's stop rules.
On the session path the boundary lowers to normalized parameters (until as a stop
string, until_token_ids as extra stop token ids, budget as a tightened
max_new_tokens), so the phase runs on any backend; a raw generate callable receives the
boundary as prompt-anchored criteria instead.
Source code in steerability/algorithms/output_control/common/drivers/phased.py
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 | |
_params_per_example(runtime_kwargs, batch_size)
Slice a dict-of-lists params per example (ThinkingIntervention's convention).
Source code in steerability/algorithms/output_control/common/drivers/phased.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
_run_plan(plan, row_ids, prompt_text, params, base_generate, via_session, logits_processors, stopping_criteria, gen_kwargs)
Execute one example's plan; return the full spliced sequence [1, L].
Source code in steerability/algorithms/output_control/common/drivers/phased.py
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
cleanup()
Release resources allocated during steer().
Override in subclasses that allocate GPU memory or other resources during steering. Default no-op.
Source code in steerability/algorithms/core/base_control.py
195 196 197 198 199 200 201 | |
clone_for_call(seed=None)
A configuration-preserving shallow clone for one generation call.
The clone shares steer-time artifacts (memories, steering vectors, attached tokenizers)
with the original but has its own attribute namespace, so per-call attribute mutation on
the clone never races another call using the original. When seed is given and the
control defines reseed(seed), the clone's client-side RNG is re-seeded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int | None
|
Optional seed forwarded to the clone's |
None
|
Returns:
| Type | Description |
|---|---|
BaseControl
|
The clone. |
Source code in steerability/algorithms/core/base_control.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
decode(input_ids, attention_mask, model, logits_processors, stopping_criteria, runtime_kwargs, session=None, **gen_kwargs)
Run the decoding procedure; return full sequence ids (prompt + continuation).
Source code in steerability/algorithms/output_control/common/drivers/phased.py
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 | |
export_constraint(runtime_kwargs=None)
The control's declarative constrained-decoding source, or None.
A control whose per-step masking compiles from a declarative source returns a
ConstraintSource; on a backend advertising Capability.GUIDED_DECODING the pipeline
renders it onto the engine's native structured-output parameters in place of the
control's live processor. The default returns None, which keeps the control on the live
processor mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
ConstraintSource | None
|
The constraint source, or None. |
Source code in steerability/algorithms/output_control/base.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
export_generation_params(runtime_kwargs=None)
The control's sampling-expressible contribution, or None.
A control whose behavior is expressible as normalized generation parameters returns a
mapping over a subset of stop_strings, stop_token_ids, max_new_tokens, and
min_new_tokens; the pipeline merges it into the call's GenerationParams (stop rules
union with the caller's; token bounds only tighten) and does not additionally collect
the control's live processors and criteria for that call, so the control executes on
every backend through the session's composed stop rules. The default returns None, which
keeps the control on the live processor/criteria mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
Mapping[str, Any] | None
|
The parameter contribution, or None. |
Source code in steerability/algorithms/output_control/base.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
export_processor_spec(runtime_kwargs=None)
The control's engine-hosted processor form, or None.
A control whose per-step logit math is expressible in an engine's served processor
vocabulary returns a ProcessorSpec; on a backend advertising
Capability.PER_STEP_LOGIT_SPECS with the spec's kind, the pipeline submits it as a
ProcessorSpecEntry in place of the control's live processor. The default returns
None, which keeps the control on the live processor mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
ProcessorSpec | None
|
The processor spec, or None. |
Source code in steerability/algorithms/output_control/base.py
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | |
export_state()
Steer-time state to persist when freezing, keyed by logical name.
Values are typed artifacts (SteeringVector, Probe, ProbeSet, a Memory
implementation, CheckpointArtifact, LoRAArtifact, torch.Tensor, or a Path to an
on-disk product). Must be called after steer(). The default returns an empty mapping
(nothing to persist).
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Mapping from logical name to artifact value. |
Source code in steerability/algorithms/core/base_control.py
117 118 119 120 121 122 123 124 125 126 127 128 | |
fit_identity()
The object whose canonical form defines this control's fit digest, or None.
The digest detects recipe edits that invalidate frozen artifacts, so the returned object should cover exactly the inputs a re-fit would consume (training data, fit specs) and exclude inert application parameters (strengths, multipliers). The default returns None (no fits).
Returns:
| Type | Description |
|---|---|
Any | None
|
The fit-identity object, or None. |
Source code in steerability/algorithms/core/base_control.py
161 162 163 164 165 166 167 168 169 170 171 172 | |
frozen_form(state)
The (registry method key, constructor kwargs) of this control's frozen form.
state is the output of export_state(); artifact values inside the returned kwargs
are replaced by store references at encode time. When steer_fits() is empty and
state is empty, the recipe is the frozen form and the control's own key and recipe
args are returned unchanged. A control whose freeze expands into several entries may
return a list of (method key, kwargs) pairs instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
dict[str, Any]
|
The output of |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, dict[str, Any]]
|
The frozen method key and its constructor kwargs. |
Raises:
| Type | Description |
|---|---|
NotFreezableError
|
If the control produces fits or state but declares no frozen form. |
Source code in steerability/algorithms/core/base_control.py
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 | |
get_logits_processors(input_ids, runtime_kwargs, **kwargs)
The control's logits processors for the current generation.
Called once per generate() / compute_logprobs() call, after input and state
controls have prepared the prompt (mirrors StateControl.get_hooks). **kwargs
carries attention_mask and the caller's generation kwargs. Returned objects
follow the HF LogitsProcessor convention; in-list order is preserved by the composition.
A processor must behave as a function of (prefix_ids, scores). Internal state is
permitted only as memoization keyed on the prefix and must re-derive on a prefix mismatch,
since drivers may restart, rewind, or reorder sequences, and scoring replays prefixes
teacher-forced (subclass common.processors.base.PrefixKeyedProcessor to satisfy this
mechanically). Return fresh processor instances from this hook; it is invoked once per call
precisely so that per-generation state is isolated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
Tensor
|
The steered prompt token ids |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of HF |
Source code in steerability/algorithms/output_control/base.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
get_stopping_criteria(input_ids, runtime_kwargs, **kwargs)
The control's stopping criteria.
Not applied during scoring (there is no loop to stop). Same call convention as
get_logits_processors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
Tensor
|
The steered prompt token ids |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of HF |
Source code in steerability/algorithms/output_control/base.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
max_rollouts_per_query()
None: the phase plan is per example, so the base class declares no static bound.
Subclasses with a fixed plan (e.g. PhasedDecoding, BudgetForcing) override it.
Source code in steerability/algorithms/output_control/common/drivers/phased.py
92 93 94 95 | |
plan(prompt_text, params)
Return the phase plan for one example. Subclasses override.
Source code in steerability/algorithms/output_control/common/drivers/phased.py
102 103 104 | |
requirements()
Phase splicing is client-side and generated phases run through the session, so no phase requires anything beyond the session contract.
Source code in steerability/algorithms/output_control/common/drivers/phased.py
97 98 99 100 | |
steer(model, tokenizer=None, session=None, **kwargs)
Optional one-time preparation (e.g., load a reward model, fit a probe).
session is a SteeringSession on the steering backend, provided by the pipeline.
Source code in steerability/algorithms/output_control/base.py
207 208 209 210 211 212 | |
steer_access()
The model access this instance's steer step requires, on the ModelAccess ladder.
The default is ModelAccess.FACTS (layout and tokenizer only). A control whose steer
step generates or scores through the session declares ROLLOUTS, one that captures
hidden states declares CAPTURE, and one that touches the model as a live
torch.nn.Module declares MODULE. Configuration determines the result. The pipeline
hands steer() a session scoped to the declared rung, and the live model only at
MODULE. A control may retain the pipeline model beyond steer() only if its
generate phase requires Capability.IN_PROCESS_TORCH.
Returns:
| Type | Description |
|---|---|
ModelAccess
|
The declared access rung. |
Source code in steerability/algorithms/core/base_control.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
steer_fits()
The fit artifacts this instance's steer step will produce, for the steer plan.
Each entry is (artifact, artifact_class), where artifact is the fit source or
recipe class name and artifact_class is "direction" or "calibrated". The default
is an empty tuple (no fits).
Returns:
| Type | Description |
|---|---|
tuple[tuple[str, str], ...]
|
The declared fit artifacts, in declaration order. |
Source code in steerability/algorithms/core/base_control.py
105 106 107 108 109 110 111 112 113 114 115 | |
proposer
Rollout proposal for SearchDriver.
The composed logits and stopping stacks are forwarded into every rollout (each only when non-empty,
following HFGenerateDriver's pattern), so a step-level control such as RAD steers every proposed
continuation.
SegmentProposer
Propose n continuations of up to segment_len tokens from a frontier of sequences.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
str
|
|
'beam'
|
Source code in steerability/algorithms/output_control/common/drivers/proposer.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 | |
mode = mode
instance-attribute
__init__(mode='beam')
Source code in steerability/algorithms/output_control/common/drivers/proposer.py
25 26 27 28 | |
propose(frontier_ids, *, n, segment_len, processors, criteria, model, base_generate=None, attention_mask=None, **gen_kwargs)
Roll out n continuations of segment_len tokens from frontier_ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frontier_ids
|
Tensor
|
Current context |
required |
n
|
int
|
Number of continuations to produce. |
required |
segment_len
|
int
|
Max new tokens per rollout. |
required |
processors
|
LogitsProcessorList
|
The composed |
required |
criteria
|
StoppingCriteriaList
|
The composed |
required |
model
|
PreTrainedModel
|
The language model. |
required |
base_generate
|
Callable[..., Tensor] | None
|
Optional override for the generate callable (else |
None
|
attention_mask
|
Tensor | None
|
Optional attention mask matching |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Full sequences |
Source code in steerability/algorithms/output_control/common/drivers/proposer.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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
search
Segment-search decoding driver: propose continuations, score them, keep the top k, iterate.
Every rollout receives the composed stacks, so step-level controls steer every lookahead of every segment-search driver.
SearchDriver
Bases: DecodingDriver
Segment-search decoding driver: propose, sequence-score, keep top-k, iterate.
Supports batch size 1 only (raises otherwise). decode() pops max_new_tokens as the global
budget, builds a SegmentProposer with the received stacks, and runs the loop. A kept beam is
finished when its continuation, with trailing pad tokens stripped, ends in a token of the eos
set (the tokenizer's eos plus any ids on the model's generation config) or when its stripped
length reaches the global budget. Finished beams leave the frontier, and a beam cut by a
caller-supplied stopping criterion classifies as unfinished. The reward_params runtime kwarg
is row-scoped, so its per-row form is one mapping, merged into the scorer's params on every
scoring call, and a batched delivery is a one-element sequence holding that mapping (the driver
handles one prompt per call).
Can be constructed directly (its positional constructor below) or as a preset: a subclass with an
Args dataclass maps its mirrored args onto these fields in _configure() (see DeAL), so it never
bypasses this __init__.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scorer
|
SequenceScorer
|
A |
required |
segment_len
|
int
|
Max new tokens per rollout. |
required |
num_candidates
|
int
|
Number of continuations proposed per iteration. |
required |
keep_k
|
int
|
Number of beams retained each iteration. |
required |
max_iterations
|
int
|
Maximum search iterations. |
required |
propose_mode
|
str
|
|
'beam'
|
Source code in steerability/algorithms/output_control/common/drivers/search.py
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 | |
RUNTIME_KWARGS_SCHEMA = [{'name': 'reward_params', 'type': 'dict', 'scope': 'row', 'help': "Entries merged into the scorer's params mapping on every scoring call of this generation. The per-row form is one mapping; the driver handles one prompt per call, so a batched delivery is a one-element sequence holding that mapping. A per-sample mapping (for example a reference answer under 'reference') reaches the scorer's row through SampleSequenceScorer."}]
class-attribute
instance-attribute
args = self.Args.validate(*args, **kwargs)
instance-attribute
enabled = True
class-attribute
instance-attribute
include_in_scoring = True
class-attribute
instance-attribute
keep_k = keep_k
instance-attribute
max_iterations = max_iterations
instance-attribute
num_candidates = num_candidates
instance-attribute
propose_mode = propose_mode
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
scorer = scorer
instance-attribute
segment_len = segment_len
instance-attribute
supports_batching = False
class-attribute
instance-attribute
tokenizer = None
instance-attribute
__init__(scorer, segment_len, num_candidates, keep_k, max_iterations, propose_mode='beam')
Source code in steerability/algorithms/output_control/common/drivers/search.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | |
_configure()
Post-construction hook, called after Args fields are mirrored onto the instance.
Driver presets override this to map their mirrored args onto the fields their generic base
reads, so subclasses never bypass a parent __init__. Default no-op.
Source code in steerability/algorithms/core/base_control.py
67 68 69 70 71 72 73 | |
cleanup()
Release resources allocated during steer().
Override in subclasses that allocate GPU memory or other resources during steering. Default no-op.
Source code in steerability/algorithms/core/base_control.py
195 196 197 198 199 200 201 | |
clone_for_call(seed=None)
A configuration-preserving shallow clone for one generation call.
The clone shares steer-time artifacts (memories, steering vectors, attached tokenizers)
with the original but has its own attribute namespace, so per-call attribute mutation on
the clone never races another call using the original. When seed is given and the
control defines reseed(seed), the clone's client-side RNG is re-seeded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int | None
|
Optional seed forwarded to the clone's |
None
|
Returns:
| Type | Description |
|---|---|
BaseControl
|
The clone. |
Source code in steerability/algorithms/core/base_control.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
decode(input_ids, attention_mask, model, logits_processors, stopping_criteria, runtime_kwargs, session=None, **gen_kwargs)
Run the decoding procedure; return full sequence ids (prompt + continuation).
Source code in steerability/algorithms/output_control/common/drivers/search.py
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 | |
export_constraint(runtime_kwargs=None)
The control's declarative constrained-decoding source, or None.
A control whose per-step masking compiles from a declarative source returns a
ConstraintSource; on a backend advertising Capability.GUIDED_DECODING the pipeline
renders it onto the engine's native structured-output parameters in place of the
control's live processor. The default returns None, which keeps the control on the live
processor mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
ConstraintSource | None
|
The constraint source, or None. |
Source code in steerability/algorithms/output_control/base.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | |
export_generation_params(runtime_kwargs=None)
The control's sampling-expressible contribution, or None.
A control whose behavior is expressible as normalized generation parameters returns a
mapping over a subset of stop_strings, stop_token_ids, max_new_tokens, and
min_new_tokens; the pipeline merges it into the call's GenerationParams (stop rules
union with the caller's; token bounds only tighten) and does not additionally collect
the control's live processors and criteria for that call, so the control executes on
every backend through the session's composed stop rules. The default returns None, which
keeps the control on the live processor/criteria mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
Mapping[str, Any] | None
|
The parameter contribution, or None. |
Source code in steerability/algorithms/output_control/base.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
export_processor_spec(runtime_kwargs=None)
The control's engine-hosted processor form, or None.
A control whose per-step logit math is expressible in an engine's served processor
vocabulary returns a ProcessorSpec; on a backend advertising
Capability.PER_STEP_LOGIT_SPECS with the spec's kind, the pipeline submits it as a
ProcessorSpecEntry in place of the control's live processor. The default returns
None, which keeps the control on the live processor mechanism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
None
|
Returns:
| Type | Description |
|---|---|
ProcessorSpec | None
|
The processor spec, or None. |
Source code in steerability/algorithms/output_control/base.py
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | |
export_state()
Steer-time state to persist when freezing, keyed by logical name.
Values are typed artifacts (SteeringVector, Probe, ProbeSet, a Memory
implementation, CheckpointArtifact, LoRAArtifact, torch.Tensor, or a Path to an
on-disk product). Must be called after steer(). The default returns an empty mapping
(nothing to persist).
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Mapping from logical name to artifact value. |
Source code in steerability/algorithms/core/base_control.py
117 118 119 120 121 122 123 124 125 126 127 128 | |
fit_identity()
The object whose canonical form defines this control's fit digest, or None.
The digest detects recipe edits that invalidate frozen artifacts, so the returned object should cover exactly the inputs a re-fit would consume (training data, fit specs) and exclude inert application parameters (strengths, multipliers). The default returns None (no fits).
Returns:
| Type | Description |
|---|---|
Any | None
|
The fit-identity object, or None. |
Source code in steerability/algorithms/core/base_control.py
161 162 163 164 165 166 167 168 169 170 171 172 | |
frozen_form(state)
The (registry method key, constructor kwargs) of this control's frozen form.
state is the output of export_state(); artifact values inside the returned kwargs
are replaced by store references at encode time. When steer_fits() is empty and
state is empty, the recipe is the frozen form and the control's own key and recipe
args are returned unchanged. A control whose freeze expands into several entries may
return a list of (method key, kwargs) pairs instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
dict[str, Any]
|
The output of |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, dict[str, Any]]
|
The frozen method key and its constructor kwargs. |
Raises:
| Type | Description |
|---|---|
NotFreezableError
|
If the control produces fits or state but declares no frozen form. |
Source code in steerability/algorithms/core/base_control.py
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 | |
get_logits_processors(input_ids, runtime_kwargs, **kwargs)
The control's logits processors for the current generation.
Called once per generate() / compute_logprobs() call, after input and state
controls have prepared the prompt (mirrors StateControl.get_hooks). **kwargs
carries attention_mask and the caller's generation kwargs. Returned objects
follow the HF LogitsProcessor convention; in-list order is preserved by the composition.
A processor must behave as a function of (prefix_ids, scores). Internal state is
permitted only as memoization keyed on the prefix and must re-derive on a prefix mismatch,
since drivers may restart, rewind, or reorder sequences, and scoring replays prefixes
teacher-forced (subclass common.processors.base.PrefixKeyedProcessor to satisfy this
mechanically). Return fresh processor instances from this hook; it is invoked once per call
precisely so that per-generation state is isolated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
Tensor
|
The steered prompt token ids |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of HF |
Source code in steerability/algorithms/output_control/base.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
get_stopping_criteria(input_ids, runtime_kwargs, **kwargs)
The control's stopping criteria.
Not applied during scoring (there is no loop to stop). Same call convention as
get_logits_processors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
Tensor
|
The steered prompt token ids |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters supplied to |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of HF |
Source code in steerability/algorithms/output_control/base.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
max_rollouts_per_query()
num_candidates * (1 + (max_iterations - 1) * keep_k).
The first iteration proposes num_candidates continuations from the single-row prompt;
each later iteration proposes num_candidates from each of up to keep_k retained
beams.
Source code in steerability/algorithms/output_control/common/drivers/search.py
119 120 121 122 123 124 125 126 | |
requirements()
Rollouts run through the session, so sampled proposals require nothing beyond the
session contract; beam proposals require Capability.BEAM_PROPOSALS.
Source code in steerability/algorithms/output_control/common/drivers/search.py
128 129 130 131 132 133 134 135 136 | |
steer(model, tokenizer=None, session=None, **kwargs)
Optional one-time preparation (e.g., load a reward model, fit a probe).
session is a SteeringSession on the steering backend, provided by the pipeline.
Source code in steerability/algorithms/output_control/base.py
207 208 209 210 211 212 | |
steer_access()
The model access this instance's steer step requires, on the ModelAccess ladder.
The default is ModelAccess.FACTS (layout and tokenizer only). A control whose steer
step generates or scores through the session declares ROLLOUTS, one that captures
hidden states declares CAPTURE, and one that touches the model as a live
torch.nn.Module declares MODULE. Configuration determines the result. The pipeline
hands steer() a session scoped to the declared rung, and the live model only at
MODULE. A control may retain the pipeline model beyond steer() only if its
generate phase requires Capability.IN_PROCESS_TORCH.
Returns:
| Type | Description |
|---|---|
ModelAccess
|
The declared access rung. |
Source code in steerability/algorithms/core/base_control.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
steer_fits()
The fit artifacts this instance's steer step will produce, for the steer plan.
Each entry is (artifact, artifact_class), where artifact is the fit source or
recipe class name and artifact_class is "direction" or "calibrated". The default
is an empty tuple (no fits).
Returns:
| Type | Description |
|---|---|
tuple[tuple[str, str], ...]
|
The declared fit artifacts, in declaration order. |
Source code in steerability/algorithms/core/base_control.py
105 106 107 108 109 110 111 112 113 114 115 | |
_resolve_reward_params(runtime_kwargs)
The reward_params mapping for this call, from either delivery form.
A mapping is one row's value (a direct call); a sequence is the row-aligned form (a batched caller or the evaluation collator) and must hold exactly one element, since the driver handles one prompt per call. A missing key or a None value gives an empty mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runtime_kwargs
|
Mapping[str, Any]
|
The call's runtime kwargs. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A new mapping of the row's reward params, empty when the key is absent or None. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a sequence does not hold exactly one element. |
TypeError
|
If the value, or the sequence's element, is not a mapping. |
Source code in steerability/algorithms/output_control/common/drivers/search.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 | |
granite_heads
Sequence-classification heads for the Granite and GraniteMoeHybrid architectures.
transformers ships no AutoModelForSequenceClassification head for the Granite families, so a Granite
causal-LM checkpoint cannot be loaded as a scalar-head reward model out of the box. These two classes
supply the head by mixing GenericForSequenceClassification (the pooled-last-token classifier the
Llama and Qwen heads use) with each family's PreTrainedModel. Callers select the loading class with
sequence_classifier_class, which reads the checkpoint config and returns the toolkit head for a
Granite family and AutoModelForSequenceClassification otherwise, so a head shipped by a future
transformers version wins.
GRANITE_SEQUENCE_CLASSIFIERS = {GraniteConfig: GraniteForSequenceClassification, GraniteMoeHybridConfig: GraniteMoeHybridForSequenceClassification}
module-attribute
_HUB_KWARGS = ('cache_dir', 'force_download', 'local_files_only', 'proxies', 'revision', 'subfolder', 'token', 'trust_remote_code')
module-attribute
GraniteForSequenceClassification
Bases: GenericForSequenceClassification, GranitePreTrainedModel
Sequence-classification head for the granite architecture.
Source code in steerability/algorithms/output_control/common/granite_heads.py
26 27 | |
GraniteMoeHybridForSequenceClassification
Bases: GenericForSequenceClassification, GraniteMoeHybridPreTrainedModel
Sequence-classification head for the granitemoehybrid architecture.
Source code in steerability/algorithms/output_control/common/granite_heads.py
30 31 | |
sequence_classifier_class(model_id, **from_pretrained_kwargs)
The class that loads model_id as a sequence classifier.
Reads the checkpoint config (the hub-related entries of from_pretrained_kwargs are forwarded) and
returns AutoModelForSequenceClassification when its mapping covers the config class, the toolkit
head from GRANITE_SEQUENCE_CLASSIFIERS when the config is a Granite family the mapping does not
cover, and AutoModelForSequenceClassification otherwise (its from_pretrained then raises the
standard unrecognized-config error). The resolution is explicit rather than through
AutoModelForSequenceClassification.register, which transformers 5.13 and later ignore for native
config classes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_id
|
str
|
HF hub id or local path. |
required |
**from_pretrained_kwargs
|
The kwargs the caller will pass to |
{}
|
Returns:
| Type | Description |
|---|---|
type
|
The class to call |
Source code in steerability/algorithms/output_control/common/granite_heads.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
kv_cache
KV-cache utilities for same-model candidate evaluation.
repeat_cache / select_cache handle the cache-format compatibility that same-model value
functions need: repeat a prefix cache across K candidates, then select the chosen candidate's slice.
extends_prefix / full_prefix_mask are the pure tensor helpers an incremental prefix cache needs:
whether a new prefix extends the cached one, and the full attention mask spanning a prefix.
Mutation contract: both functions may mutate the input cache in-place on some paths
(batch_repeat_interleave, in-place per-layer tensor reassignment) and return a fresh cache on
others (the raw-tuple path). Treat the input cache as consumed after the call and use only the
returned handle. The exception is repeat_cache(..., preserve_input=True), which never mutates the
input (it builds a fresh DynamicCache from the input's per-layer tensors); use it when the input
cache must survive the call (e.g. an incremental prefix cache repeated across candidates).
Cache layouts handled, in dispatch order: Cache objects exposing per-layer tensors through
cache.layers[i].keys / cache.layers[i].values (the transformers v5 layout), objects exposing
key_cache / value_cache tensor lists, and raw per-layer (key, value) tuples.
_layer_tensors(cache)
The per-layer (keys, values) tensors of a layer-based Cache, or None.
Reads the transformers v5 layout (cache.layers[i].keys / cache.layers[i].values). Returns
None when cache exposes no layers sequence of that shape.
Source code in steerability/algorithms/output_control/common/kv_cache.py
69 70 71 72 73 74 75 76 77 78 79 80 81 | |
extends_prefix(cached_ids, ids)
Whether ids extends cached_ids row-for-row (a shared, no-shorter prefix).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cached_ids
|
Tensor | None
|
The previously cached prefix ids |
required |
ids
|
Tensor
|
The candidate new prefix ids |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True when |
bool
|
over its first |
bool
|
which must trigger a cache rebuild). |
Source code in steerability/algorithms/output_control/common/kv_cache.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
full_prefix_mask(prefix_ids, attention_mask)
The provided mask right-extended with ones to the prefix length.
The mask must span the full prefix; generated tokens are always real, so right-extension with ones is exact.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prefix_ids
|
Tensor
|
The prefix ids |
required |
attention_mask
|
Tensor | None
|
The prefix mask |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
An attention mask |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in steerability/algorithms/output_control/common/kv_cache.py
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 | |
repeat_cache(cache, n, *, preserve_input=False)
Repeat every cache entry n times along the batch dimension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache
|
Cache | tuple
|
A KV cache (a layer-based |
required |
n
|
int
|
Number of repeats per entry. |
required |
preserve_input
|
bool
|
When True, never mutate |
False
|
Returns:
| Type | Description |
|---|---|
Cache | tuple
|
The repeated cache (may alias the input unless |
Cache | tuple
|
mutation contract). |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the cache type is unsupported, or if |
Source code in steerability/algorithms/output_control/common/kv_cache.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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | |
select_cache(cache, idx)
Select cache entries along the batch dimension by index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cache
|
Cache | tuple
|
A KV cache (a layer-based |
required |
idx
|
Tensor
|
1-D index tensor of rows to keep. |
required |
Returns:
| Type | Description |
|---|---|
Cache | tuple
|
The selected cache (may alias the input; see the module mutation contract). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If the cache type is unsupported. |
Source code in steerability/algorithms/output_control/common/kv_cache.py
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 | |
loading
The one auxiliary sequence-classifier loader.
Loads and configures an AutoModelForSequenceClassification reward model / attribute classifier
the way the output category needs it: eval mode, pad-token fallback to EOS, right padding, and a
clamp of the sentinel model_max_length some tokenizers carry onto a plain max_length attribute
that RewardModelValue reads. Used by the reward_model / classifier value loaders, the
reward_model scorer loader, and RAD's HF-classifier path. Granite checkpoints, for which transformers
ships no head, resolve through the toolkit heads selected by sequence_classifier_class.
logger = logging.getLogger(__name__)
module-attribute
load_sequence_classifier(model_id, *, device, hf_model_kwargs=None, max_length_clamp=512)
Load an HF sequence classifier and its tokenizer, configured for candidate/continuation scoring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_id
|
str
|
HF hub id or local path for an |
required |
device
|
str | device
|
Device to move the loaded model onto. |
required |
hf_model_kwargs
|
dict | None
|
Extra kwargs forwarded to |
None
|
max_length_clamp
|
int
|
Value to use for |
512
|
Returns:
| Type | Description |
|---|---|
tuple
|
A tuple |
tuple
|
|
tuple
|
attribute. |
Source code in steerability/algorithms/output_control/common/loading.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 | |
logit_sources
Full-vocabulary logit sources for contrastive mixing.
A logit source produces next-token log-probs [B, V] for the current prefix from some
distribution, either an auxiliary LM (expert / anti-expert / amateur) or the pipeline's own model on
a transformed prompt (classifier-free guidance's unconditional branch). Sources own their model
handles and any prefix-keyed KV caching.
AuxModelSource
Bases: BaseLogitSource
A separate causal LM (expert, anti-expert, amateur, class-conditional guide).
Loads its own model in prepare() and maintains its own tokenizer. Optionally applies a prompt
transform (e.g. prepend a control code) before its tokenization. The auxiliary vocabulary must
match the base model's; pass shared_vocab=True to assert this, since the contrast family in the
literature assumes shared vocabularies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name_or_path
|
str
|
HF hub id or local path for the auxiliary LM. |
required |
base_tokenizer
|
PreTrainedTokenizerBase | None
|
The base model's tokenizer (candidate ids are the base vocabulary). |
None
|
prompt_transform
|
Callable[[str], str] | None
|
Optional |
None
|
shared_vocab
|
bool
|
When True (default), validate that the auxiliary vocabulary matches the base vocabulary and raise on mismatch. The mixture assumes shared vocabularies; setting False only skips the check. |
True
|
hf_model_kwargs
|
dict | None
|
Extra kwargs for |
None
|
Source code in steerability/algorithms/output_control/common/logit_sources.py
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 | |
_base_pad_id = None
instance-attribute
_device = None
instance-attribute
base_tokenizer = base_tokenizer
instance-attribute
hf_model_kwargs = hf_model_kwargs or {}
instance-attribute
model = None
instance-attribute
name_or_path = name_or_path
instance-attribute
prompt_transform = prompt_transform
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
shared_vocab = shared_vocab
instance-attribute
tokenizer = None
instance-attribute
__init__(name_or_path, base_tokenizer=None, prompt_transform=None, shared_vocab=True, hf_model_kwargs=None)
Source code in steerability/algorithms/output_control/common/logit_sources.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
cleanup()
Drop the auxiliary model / tokenizer references and reclaim memory.
Source code in steerability/algorithms/output_control/common/logit_sources.py
143 144 145 146 147 148 149 150 | |
logprobs(prefix_ids)
Next-token log-probs [B, V]. Mask-correct for left-padded batches; ragged-batch
equivalence is exact only up to the aux model's own padding-invariance.
Source code in steerability/algorithms/output_control/common/logit_sources.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup (e.g. load the auxiliary model), invoked from the owning control's
steer(). Default no-op (mirrors the input-control selector prepare() convention).
Source code in steerability/algorithms/output_control/common/logit_sources.py
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 | |
set_model(model, tokenizer)
Bind an already-loaded auxiliary model/tokenizer directly (bypasses prepare loading).
Source code in steerability/algorithms/output_control/common/logit_sources.py
115 116 117 118 119 120 121 122 123 | |
BaseLogitSource
Bases: ABC
Produce next-token log-probs [B, V] for the current prefix from another distribution.
Class attributes
same_model_forwards: Whether this source issues additional forward passes through the
pipeline's own model during decoding. Such passes must be wrapped in
auxiliary_pass() (see steerability.algorithms.core.utils.auxiliary_pass), which
keeps them out of state-control condition scoring, gate updates, and fallback
position counting. Defaults to False; the flag is declarative metadata and is not
read by the pipeline.
Source code in steerability/algorithms/output_control/common/logit_sources.py
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 | |
same_model_forwards = False
class-attribute
instance-attribute
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/logit_sources.py
45 46 47 | |
logprobs(prefix_ids)
abstractmethod
Return next-token log-probabilities [B, V] for prefix_ids.
Source code in steerability/algorithms/output_control/common/logit_sources.py
35 36 37 38 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup (e.g. load the auxiliary model), invoked from the owning control's
steer(). Default no-op (mirrors the input-control selector prepare() convention).
Source code in steerability/algorithms/output_control/common/logit_sources.py
40 41 42 43 | |
CallableSource
Bases: BaseLogitSource
Adapt a (prefix_ids) -> Tensor[B, V] log-prob callable into a BaseLogitSource.
The escape hatch of the source family: any function returning next-token log-probs for the
current prefix becomes a source without a subclass. The wrapped function must return a
[B, V] tensor aligned with the base model's vocabulary.
same_model_forwards keeps the BaseLogitSource default of False, since it cannot be inferred
from a bare callable. A callable that forwards the pipeline's model should be wrapped in a
component that declares same_model_forwards.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[Tensor], Tensor]
|
A callable mapping |
required |
Source code in steerability/algorithms/output_control/common/logit_sources.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
fn = fn
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
__init__(fn)
Source code in steerability/algorithms/output_control/common/logit_sources.py
222 223 224 225 | |
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/logit_sources.py
45 46 47 | |
logprobs(prefix_ids)
Return next-token log-probabilities [B, V] for prefix_ids.
Source code in steerability/algorithms/output_control/common/logit_sources.py
227 228 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup (e.g. load the auxiliary model), invoked from the owning control's
steer(). Default no-op (mirrors the input-control selector prepare() convention).
Source code in steerability/algorithms/output_control/common/logit_sources.py
40 41 42 43 | |
PromptVariantSource
Bases: BaseLogitSource
The pipeline's own model on a transformed prompt (CFG's unconditional branch, CAD's context-free branch, self-debias's biased branch).
This source forwards the pipeline's own model, so it declares same_model_forwards=True and
marks its forwards via auxiliary_pass(aligned=False). The variant prompt is a different
sequence whose positions do not map onto the generation, so state-control transforms, condition
scoring, and gate updates all skip these passes, and the variant branch reflects the unsteered
model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prompt_transform
|
Callable[[str], str]
|
|
required |
base_tokenizer
|
PreTrainedTokenizerBase | None
|
The base model's tokenizer. |
None
|
Source code in steerability/algorithms/output_control/common/logit_sources.py
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 | |
_device = None
instance-attribute
base_tokenizer = base_tokenizer
instance-attribute
model = None
instance-attribute
prompt_transform = prompt_transform
instance-attribute
same_model_forwards = True
class-attribute
instance-attribute
__init__(prompt_transform, base_tokenizer=None)
Source code in steerability/algorithms/output_control/common/logit_sources.py
170 171 172 173 174 | |
cleanup()
Drop the (pipeline-owned) model reference; the pipeline owns the model's lifecycle.
Source code in steerability/algorithms/output_control/common/logit_sources.py
197 198 199 200 201 202 203 204 | |
logprobs(prefix_ids)
Next-token log-probs [B, V]. Mask-correct for left-padded batches; ragged-batch
equivalence is exact only up to the model's own padding-invariance.
Source code in steerability/algorithms/output_control/common/logit_sources.py
184 185 186 187 188 189 190 191 192 193 194 195 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup (e.g. load the auxiliary model), invoked from the owning control's
steer(). Default no-op (mirrors the input-control selector prepare() convention).
Source code in steerability/algorithms/output_control/common/logit_sources.py
176 177 178 179 180 181 182 | |
processors
Output-control logits processors (composed into the decoding stack).
base
Base class for stateful logits processors.
A processor must behave as a function of (prefix_ids, scores); subclasses key any internal state
on the prefix and re-derive it on a prefix mismatch, so drivers may restart, rewind, or reorder
sequences and scoring may replay prefixes teacher-forced.
PrefixKeyedProcessor
Bases: LogitsProcessor
A LogitsProcessor whose internal state is memoization keyed on the prefix.
Drivers restart, rewind, and reorder sequences (segment search re-enters from a shorter
frontier; beam reordering permutes rows; compute_logprobs replays prefixes teacher-forced). A
processor holding hidden per-call state silently corrupts under any of these. This base makes
the purity contract of OutputControl.get_logits_processors structural: process() runs only
after the base has verified the observed input_ids extend the last-seen prefix row-for-row;
otherwise reset_state() re-derives from scratch.
Subclasses implement:
- `reset_state(input_ids)`: rebuild all internal state for this (possibly new) prefix.
- `process(input_ids, scores) -> scores`: the actual logits edit.
Stateless subclasses implement process and inherit the no-op reset_state.
Source code in steerability/algorithms/output_control/common/processors/base.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 | |
_last_ids = None
instance-attribute
__call__(input_ids, scores)
Source code in steerability/algorithms/output_control/common/processors/base.py
48 49 50 51 52 53 | |
__init__()
Source code in steerability/algorithms/output_control/common/processors/base.py
31 32 | |
_extends(ids)
Source code in steerability/algorithms/output_control/common/processors/base.py
34 35 36 37 38 | |
process(input_ids, scores)
Apply the logits edit. Subclasses must override.
Source code in steerability/algorithms/output_control/common/processors/base.py
44 45 46 | |
reset_state(input_ids)
Rebuild internal state for a new/rewound prefix. Default no-op (stateless subclass).
Source code in steerability/algorithms/output_control/common/processors/base.py
40 41 42 | |
constraint
ConstraintProcessor, the integration point for constrained decoding.
Takes an automaton object exposing reset(prefix_ids) and allowed(prefix_ids) -> LongTensor of
permitted token ids, and masks everything else to -inf. Grammar, JSON-schema, or regex backends
plug in here by supplying the automaton (outlines-core / xgrammar adapted to the automaton
protocol); no FSM engine is built in-repo.
ConstraintAutomaton
Bases: Protocol
Minimal automaton protocol a ConstraintProcessor drives.
Source code in steerability/algorithms/output_control/common/processors/constraint.py
17 18 19 20 21 22 23 24 25 26 | |
allowed(prefix_ids)
Return a 1-D LongTensor of token ids permitted at the current step.
Source code in steerability/algorithms/output_control/common/processors/constraint.py
24 25 26 | |
reset(prefix_ids)
Reset automaton state for a new/rewound prefix.
Source code in steerability/algorithms/output_control/common/processors/constraint.py
20 21 22 | |
ConstraintProcessor
Bases: PrefixKeyedProcessor
Mask all logits except the automaton's currently permitted token ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
automaton
|
ConstraintAutomaton
|
An object implementing the |
required |
Source code in steerability/algorithms/output_control/common/processors/constraint.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
_last_ids = None
instance-attribute
automaton = automaton
instance-attribute
__call__(input_ids, scores)
Source code in steerability/algorithms/output_control/common/processors/base.py
48 49 50 51 52 53 | |
__init__(automaton)
Source code in steerability/algorithms/output_control/common/processors/constraint.py
36 37 38 | |
_extends(ids)
Source code in steerability/algorithms/output_control/common/processors/base.py
34 35 36 37 38 | |
process(input_ids, scores)
Apply the logits edit. Subclasses must override.
Source code in steerability/algorithms/output_control/common/processors/constraint.py
43 44 45 46 47 | |
reset_state(input_ids)
Rebuild internal state for a new/rewound prefix. Default no-op (stateless subclass).
Source code in steerability/algorithms/output_control/common/processors/constraint.py
40 41 | |
contrastive_mixture
Mix full-vocabulary log-prob sources into the base distribution.
scores' = w0 * log p_base + sum_i w_i * log p_source_i, with an optional plausibility mask
keep = {t : p_base(t) >= alpha * max_t p_base(t)} applied before mixing (contrastive decoding's
alpha-filter; alpha=None disables; masked-out tokens -> -inf). Mixing is in log-prob space; the
return is unnormalized scores, which HF's loop accepts.
ContrastiveMixtureProcessor
Bases: PrefixKeyedProcessor
Mix the base log-probs with weighted auxiliary log-prob sources.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sources
|
list[tuple[BaseLogitSource, float]]
|
A list of |
required |
base_weight
|
float
|
Weight |
1.0
|
alpha
|
float | None
|
Plausibility-mask threshold in |
None
|
Source code in steerability/algorithms/output_control/common/processors/contrastive_mixture.py
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 | |
_last_ids = None
instance-attribute
alpha = alpha
instance-attribute
base_weight = base_weight
instance-attribute
sources = sources
instance-attribute
__call__(input_ids, scores)
Source code in steerability/algorithms/output_control/common/processors/base.py
48 49 50 51 52 53 | |
__init__(sources, *, base_weight=1.0, alpha=None)
Source code in steerability/algorithms/output_control/common/processors/contrastive_mixture.py
26 27 28 29 30 31 32 33 34 35 36 | |
_extends(ids)
Source code in steerability/algorithms/output_control/common/processors/base.py
34 35 36 37 38 | |
process(input_ids, scores)
Apply the logits edit. Subclasses must override.
Source code in steerability/algorithms/output_control/common/processors/contrastive_mixture.py
43 44 45 46 47 48 49 50 51 52 53 54 | |
reset_state(input_ids)
Rebuild internal state for a new/rewound prefix. Default no-op (stateless subclass).
Source code in steerability/algorithms/output_control/common/processors/contrastive_mixture.py
38 39 40 41 | |
value_guided
Shift candidate-token logits by a per-candidate value (select candidates, score, combine).
One processor covers many methods. RAD = (RewardModelValue, top_k, clamp, mask=True). SASA =
(SubspaceMarginValue, surviving, softmax, mask=False). FUDGE = (ClassifierValue, top_k, none,
beta=1). ARGS = (RewardModelValue, top_k, none).
LARGE_CANDIDATE_SET_WARN_THRESHOLD = 1024
module-attribute
Normalize = Literal['none', 'minmax', 'softmax', 'clamp']
module-attribute
ValueGuidedProcessor
Bases: PrefixKeyedProcessor
scores[cand] += beta * normalize(value(prefix, cand)); optionally -inf elsewhere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
BaseCandidateValue
|
A |
required |
policy
|
str
|
Candidate policy ( |
'top_k'
|
k
|
int | None
|
Candidate count for |
20
|
p
|
float | None
|
Nucleus threshold for |
None
|
beta
|
float
|
Shift scale. |
1.0
|
normalize
|
Normalize
|
|
'none'
|
invert
|
bool
|
Post-normalization |
False
|
mask_non_candidates
|
bool
|
Set non-candidate logits to |
True
|
max_candidates
|
int | None
|
Optional clamp on the candidate-set size. After the policy selects candidates,
keep only the top |
None
|
lm_tokenizer
|
PreTrainedTokenizerBase | None
|
The language-model tokenizer, forwarded into |
None
|
model
|
PreTrainedModel | None
|
The pipeline's model (for same-model values), forwarded into |
None
|
attention_mask
|
Tensor | None
|
The prefix attention mask, forwarded into |
None
|
trace
|
list | None
|
Optional caller-owned list that receives one |
None
|
Source code in steerability/algorithms/output_control/common/processors/value_guided.py
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 | |
_last_ids = None
instance-attribute
_warned_large_set = False
instance-attribute
attention_mask = attention_mask
instance-attribute
beta = beta
instance-attribute
invert = invert
instance-attribute
k = k
instance-attribute
lm_tokenizer = lm_tokenizer
instance-attribute
mask_non_candidates = mask_non_candidates and policy != 'surviving'
instance-attribute
max_candidates = max_candidates
instance-attribute
model = model
instance-attribute
normalize = normalize
instance-attribute
p = p
instance-attribute
policy = policy
instance-attribute
trace = trace
instance-attribute
value = value
instance-attribute
__call__(input_ids, scores)
Source code in steerability/algorithms/output_control/common/processors/base.py
48 49 50 51 52 53 | |
__init__(value, *, policy='top_k', k=20, p=None, beta=1.0, normalize='none', invert=False, mask_non_candidates=True, max_candidates=None, lm_tokenizer=None, model=None, attention_mask=None, trace=None)
Source code in steerability/algorithms/output_control/common/processors/value_guided.py
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 | |
_extends(ids)
Source code in steerability/algorithms/output_control/common/processors/base.py
34 35 36 37 38 | |
process(input_ids, scores)
Apply the logits edit. Subclasses must override.
Source code in steerability/algorithms/output_control/common/processors/value_guided.py
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 | |
reset_state(input_ids)
Rebuild internal state for a new/rewound prefix. Default no-op (stateless subclass).
Source code in steerability/algorithms/output_control/common/processors/base.py
40 41 42 | |
ValueStepRecord
dataclass
One ValueGuidedProcessor.process step, recorded for the caller-owned trace.
All tensors are detached and on CPU. candidate_scores are the processor's input scores for
the candidates before the shift; normalized is the value after normalize and invert, i.e.
the quantity the processor multiplies by beta.
Attributes:
| Name | Type | Description |
|---|---|---|
prefix_length |
int
|
The prefix length at this step ( |
candidate_ids |
Tensor
|
Selected candidate token ids |
candidate_scores |
Tensor
|
Input scores of the candidates before the shift |
values |
Tensor
|
Raw per-candidate value output |
normalized |
Tensor
|
Values after |
Source code in steerability/algorithms/output_control/common/processors/value_guided.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
candidate_ids
instance-attribute
candidate_scores
instance-attribute
normalized
instance-attribute
prefix_length
instance-attribute
values
instance-attribute
__init__(prefix_length, candidate_ids, candidate_scores, values, normalized)
_normalize(v, mode, invert)
Normalize per-candidate values row-wise, then optionally invert.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v
|
Tensor
|
Values |
required |
mode
|
Normalize
|
|
required |
invert
|
bool
|
When True, |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
Normalized values |
Source code in steerability/algorithms/output_control/common/processors/value_guided.py
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 | |
resolve
Component-spec resolution for the generic output controls.
The generics expose the common slots (values, sources, scorers) through flat Args, and resolve
a spec into a live component at steer() time, when the base model and tokenizer are available. A
spec is one of:
- an instance of the target protocol (its `prepare(model=, tokenizer=)` is called, then it is
returned);
- a callable (wrapped: values -> `CallableValue`, sources -> `CallableSource`, scorers are
already `SequenceScorer`s and are returned as-is);
- a str (sources only: shorthand for an auxiliary model);
- a dict with a `"kind"` key (dispatched to a loader; see the tables below).
Sweepability rule: ControlSpec sweeps flat constructor kwargs, so scalar knobs (beta, alpha,
k, policy, weights, budgets) are top-level Args fields and dict specs are treated as
identities; you sweep over configs by listing whole dicts in a spec's vars, not by reaching
inside them.
SampleSequenceScorer is served by passing an instance (it wraps a per-row SampleScorer
callable, which has no meaningful string form); no dict kind is added for it.
_require(spec, key, kind)
Read a required key from a dict spec, raising a ValueError that names the offending kind.
Source code in steerability/algorithms/output_control/common/resolve.py
46 47 48 49 50 | |
resolve_scorer(spec, *, device)
Resolve a scorer spec into a SequenceScorer.
Accepted forms: any SequenceScorer callable (returned as-is, such as a plain function, a
MajorityVoteScorer, or a SampleSequenceScorer); or a dict with a "kind" key:
- `"reward_model"`: `model_id` (required); `score_index=0`, `batch_size=8`,
`hf_model_kwargs`. Loads a classifier and wraps it in a `RewardModelScorer`.
- `"majority_vote"`: `answer_extractor` (optional). Builds a `MajorityVoteScorer`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
The scorer spec. |
required |
device
|
device | str
|
Device to load an auxiliary reward model onto. |
required |
Returns:
| Type | Description |
|---|---|
SequenceScorer
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
On an unknown kind or a malformed dict spec. |
Source code in steerability/algorithms/output_control/common/resolve.py
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 | |
resolve_source(spec, *, model, tokenizer)
Resolve a source spec into a prepared BaseLogitSource.
Accepted forms: a BaseLogitSource instance; a (prefix_ids) -> Tensor[B, V] callable (wrapped
in CallableSource); a str (shorthand for {"kind": "aux_model", "name_or_path": <str>}); or
a dict with a "kind" key:
- `"aux_model"`: `name_or_path` (required); `prompt_transform`, `hf_model_kwargs`,
`shared_vocab=True`. Builds an `AuxModelSource` (its `prepare` loads and vocab-checks).
- `"prompt_variant"`: `prompt_transform` (required). Builds a `PromptVariantSource`
(see its compatibility note on same-model forwards).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
The source spec. |
required |
model
|
PreTrainedModel
|
The pipeline's base model. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
The base tokenizer. |
required |
Returns:
| Type | Description |
|---|---|
BaseLogitSource
|
A prepared |
Raises:
| Type | Description |
|---|---|
ValueError
|
On an unknown kind or a malformed dict spec. |
Source code in steerability/algorithms/output_control/common/resolve.py
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 | |
resolve_value(spec, *, model, tokenizer, device)
Resolve a value spec into a BaseCandidateValue.
Accepted forms: a BaseCandidateValue instance; a (StepContext) -> Tensor[B, K] callable
(wrapped in CallableValue); or a dict with a "kind" key:
- `"reward_model"`: `model_id` (required); `score_index=0`, `score_transform="none"`,
`hf_model_kwargs`. Loads an `AutoModelForSequenceClassification` and wraps it in a
`RewardModelValue` (the text-round-trip path; `shared_vocab` defaults False).
- `"classifier"`: `model_id` or `fn` (required); `label_index=1`, `hf_model_kwargs`.
Wraps a loaded classifier (or a `list[str] -> Tensor` callable) in a `ClassifierValue`.
- `"subspace_margin"`: `probe_path` or `data` (required); `batch_size=4`,
`max_length=1024`, `save_path`. Loads a probe from a directory artifact (`Probe.load`)
or a single-file checkpoint (`.probe` JSON or legacy `{'wv', 'mu_mu'}` tensor), or fits
one on the base model via `fit_probe` (fisher direction over last-token features at the
raw final-layer boundary, midpoint calibration); `save_path` writes the fitted probe's
directory artifact.
- `"callable"`: `fn` (required); `supports_batching`, `scoring_cost`. Wraps `fn` in a
`CallableValue` with explicit flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Any
|
The value spec. |
required |
model
|
PreTrainedModel
|
The pipeline's base model. |
required |
tokenizer
|
PreTrainedTokenizerBase
|
The base tokenizer. |
required |
device
|
device | str
|
Device to load auxiliary models / align probes onto. |
required |
Returns:
| Type | Description |
|---|---|
BaseCandidateValue
|
A prepared |
Raises:
| Type | Description |
|---|---|
ValueError
|
On an unknown kind or a malformed dict spec. |
Source code in steerability/algorithms/output_control/common/resolve.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 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 | |
scorers
Sequence scorers (score whole continuations, per-sequence floats).
base
SequenceScorer — the sequence-level scoring protocol.
DeAL's reward_func signature is adopted verbatim as the library convention, so every existing
user-supplied callable is already a SequenceScorer.
SequenceScorer
Bases: Protocol
Score continuations of a prompt; higher = more desired.
A callable (prompt, continuations, params) -> list[float], one score per continuation.
Source code in steerability/algorithms/output_control/common/scorers/base.py
11 12 13 14 15 16 17 18 19 | |
__call__(prompt, continuations, params)
Source code in steerability/algorithms/output_control/common/scorers/base.py
18 19 | |
majority_vote
MajorityVoteScorer — self-consistency scoring by answer agreement.
MajorityVoteScorer
Score each continuation by how many others share its extracted answer.
Used under BestOfN, this is self-consistency (Wang et al. 2022): the continuation whose answer
the plurality agrees with wins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
answer_extractor
|
Callable[[str], str] | None
|
|
None
|
Source code in steerability/algorithms/output_control/common/scorers/majority_vote.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
answer_extractor = answer_extractor or _final_line
instance-attribute
__call__(prompt, continuations, params)
Source code in steerability/algorithms/output_control/common/scorers/majority_vote.py
28 29 30 31 32 | |
__init__(answer_extractor=None)
Source code in steerability/algorithms/output_control/common/scorers/majority_vote.py
25 26 | |
_final_line(text)
Default answer extractor: the last non-empty line, stripped.
Source code in steerability/algorithms/output_control/common/scorers/majority_vote.py
8 9 10 11 | |
reward_model
RewardModelScorer — score prompt + continuation with an HF sequence classifier.
RewardModelScorer
Score each continuation with an HF sequence classifier over prompt + continuation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
PreTrainedModel
|
The reward model (HF sequence classifier, in eval mode). |
required |
tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for the reward model. |
required |
score_index
|
int
|
Logit index to read as the scalar reward. |
0
|
batch_size
|
int
|
Batch size for scoring. |
8
|
Source code in steerability/algorithms/output_control/common/scorers/reward_model.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 | |
_device = next(model.parameters()).device
instance-attribute
batch_size = batch_size
instance-attribute
model = model
instance-attribute
score_index = score_index
instance-attribute
tokenizer = tokenizer
instance-attribute
__call__(prompt, continuations, params)
Source code in steerability/algorithms/output_control/common/scorers/reward_model.py
31 32 33 34 35 36 37 38 39 40 41 42 | |
__init__(model, tokenizer, score_index=0, batch_size=8)
Source code in steerability/algorithms/output_control/common/scorers/reward_model.py
18 19 20 21 22 23 24 25 26 27 28 29 | |
sample
SampleSequenceScorer: score continuations with a per-row SampleScorer.
SampleSequenceScorer
Score each continuation with a per-row SampleScorer.
Each continuation is scored individually against a row built from the prompt and the call's
scoring params, as row_scorer(continuation, {"input": prompt, **params}). The row always
carries the prompt as "input".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
row_scorer
|
SampleScorer
|
|
required |
Source code in steerability/algorithms/output_control/common/scorers/sample.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
row_scorer = row_scorer
instance-attribute
__call__(prompt, continuations, params)
Source code in steerability/algorithms/output_control/common/scorers/sample.py
21 22 23 | |
__init__(row_scorer)
Source code in steerability/algorithms/output_control/common/scorers/sample.py
18 19 | |
values
Per-candidate value functions (score candidate continuations of a prefix).
base
StepContext and BaseCandidateValue, the candidate-value interface.
values/ scores candidates (per-token scalars for one decode step); the sibling scorers/ scores
continuations (per-sequence floats). Values are consumed by ValueGuidedProcessor.
BaseCandidateValue
Bases: ABC
Score candidate continuations of a prefix; higher = more desired.
score() returns a float tensor [B, K] aligned with ctx.candidate_ids. Values must be pure
in the PrefixKeyedProcessor sense; any caching keys on the prefix.
Class attributes
supports_batching: Whether the value handles B > 1 candidate rows.
scoring_cost: Rough cost tier, surfaced so controls can warn when scoring with expensive
values is enabled. "cheap" (no model forward), "aux_forward" (an auxiliary-model
forward), or "model_forward" (a forward of the pipeline's own model).
same_model_forwards: Whether this value issues additional forward passes through the
pipeline's own model during decoding. Such passes must be wrapped in
auxiliary_pass() (see steerability.algorithms.core.utils.auxiliary_pass), which
keeps them out of state-control condition scoring, gate updates, and fallback
position counting. Defaults to False; the flag is declarative metadata and is not
read by the pipeline.
Source code in steerability/algorithms/output_control/common/values/base.py
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 | |
same_model_forwards = False
class-attribute
instance-attribute
scoring_cost = 'cheap'
class-attribute
instance-attribute
supports_batching = False
class-attribute
instance-attribute
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/values/base.py
71 72 73 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
abstractmethod
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/base.py
58 59 60 61 | |
StepContext
dataclass
Everything a candidate value may consult at one decoding step.
Attributes:
| Name | Type | Description |
|---|---|---|
prefix_ids |
Tensor
|
The current prefix token ids |
candidate_ids |
Tensor
|
The candidate next-token ids |
lm_tokenizer |
PreTrainedTokenizerBase
|
The language model's tokenizer. |
model |
PreTrainedModel | None
|
The pipeline's model (only used by same-model values; see |
attention_mask |
Tensor | None
|
The prefix attention mask |
Source code in steerability/algorithms/output_control/common/values/base.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
attention_mask = None
class-attribute
instance-attribute
candidate_ids
instance-attribute
lm_tokenizer
instance-attribute
model = None
class-attribute
instance-attribute
prefix_ids
instance-attribute
__init__(prefix_ids, candidate_ids, lm_tokenizer, model=None, attention_mask=None)
callable
Wrap a user function as a candidate value.
The escape hatch of the value family: any (StepContext) -> Tensor[B, K] callable becomes a
BaseCandidateValue without a subclass. The wrapped function is responsible for returning
per-candidate scores aligned with ctx.candidate_ids; the batching and cost flags are supplied
explicitly at construction (they cannot be inferred from a bare callable).
CallableValue
Bases: BaseCandidateValue
Adapt a (StepContext) -> Tensor[B, K] callable into a BaseCandidateValue.
same_model_forwards keeps the BaseCandidateValue default of False, since it cannot be
inferred from a bare callable. A callable that forwards the pipeline's model should be wrapped in
a component that declares same_model_forwards.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
Callable[[StepContext], Tensor]
|
A callable mapping a |
required |
supports_batching
|
bool
|
Whether |
False
|
scoring_cost
|
Literal['cheap', 'aux_forward', 'model_forward']
|
Cost tier surfaced to owning controls ( |
'cheap'
|
Source code in steerability/algorithms/output_control/common/values/callable.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 | |
fn = fn
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
scoring_cost = scoring_cost
instance-attribute
supports_batching = supports_batching
instance-attribute
__init__(fn, *, supports_batching=False, scoring_cost='cheap')
Source code in steerability/algorithms/output_control/common/values/callable.py
32 33 34 35 36 37 38 39 40 41 42 43 | |
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/values/base.py
71 72 73 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/callable.py
45 46 | |
classifier
ClassifierValue (FUDGE-family) — candidate value from an attribute classifier.
Returns log p(attribute | prefix + candidate) per candidate. Accepts either an HF sequence
classifier (with a label_index selecting the attribute logit) or any callable mapping a list of
texts to a [batch] tensor of attribute log-probabilities.
ClassifierValue
Bases: BaseCandidateValue
Score prefix + candidate with an attribute classifier (FUDGE-family).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classifier
|
Callable[[list[str]], Tensor] | PreTrainedModel
|
Either a callable |
required |
classifier_tokenizer
|
PreTrainedTokenizerBase | None
|
Tokenizer for an HF classifier (required when |
None
|
label_index
|
int
|
Index of the attribute logit for an HF classifier. |
1
|
Note
scoring_cost="aux_forward", supports_batching=True.
Source code in steerability/algorithms/output_control/common/values/classifier.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 | |
_callable = not hasattr(classifier, 'parameters')
instance-attribute
_device = None if self._callable else next(classifier.parameters()).device
instance-attribute
classifier = classifier
instance-attribute
classifier_tokenizer = classifier_tokenizer
instance-attribute
label_index = label_index
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
scoring_cost = 'aux_forward'
class-attribute
instance-attribute
supports_batching = True
class-attribute
instance-attribute
__init__(classifier, classifier_tokenizer=None, label_index=1)
Source code in steerability/algorithms/output_control/common/values/classifier.py
33 34 35 36 37 38 39 40 41 42 43 | |
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/values/base.py
71 72 73 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/classifier.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
reward_model
Candidate values from an auxiliary sequence classifier.
For each row-candidate, scores prefix + candidate with an auxiliary reward model. Loading and
configuration of the reward model is done by the owning control (RAD), which constructs the value
with the loaded model and tokenizer.
Two values live here. RewardModelValue scores each step statelessly. When the reward model shares
the language model's vocabulary (shared_vocab=True) it feeds the raw prefix + candidate ids to
the reward model; otherwise it decodes to text and re-encodes with the reward-model tokenizer (the
mismatched-vocabulary fallback). CachedRewardModelValue produces the same scores as
RewardModelValue(shared_vocab=True) at lower cost by memoizing the reward model's prefix
past_key_values across decode steps.
ScoreTransform = Literal['none', 'sigmoid', 'softmax']
module-attribute
CachedRewardModelValue
Bases: BaseCandidateValue
Score prefix + candidate with a unidirectional reward model, caching prefix activations.
Produces the same scores as RewardModelValue(shared_vocab=True) under the same score_index
and score_transform, differing only in cost. The reward model's prefix past_key_values are
memoized keyed on the prefix ids: each step forwards only the delta tokens to extend the cache,
then evaluates the K candidates as single-token forwards over a repeated copy of the cache. Any
non-extension of the cached prefix (rewind, reorder, restart, teacher-forced replay) rebuilds the
cache from scratch, which reproduces a fresh full forward.
The reward model must be decoder-only (accept past_key_values and cache_position) and share
the language model's vocabulary; the owning control checks both preconditions and a smoke forward
at steer time and falls back to RewardModelValue(shared_vocab=True) on failure. Batch size 1
only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reward_model
|
PreTrainedModel
|
The loaded unidirectional reward model (in eval mode). |
required |
rm_tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for the reward model. Its |
required |
score_index
|
int
|
Column of the reward model's output read as the score. |
0
|
score_transform
|
ScoreTransform
|
Map the reward model's output to a score before selecting |
'none'
|
Note
scoring_cost="aux_forward" and supports_batching=False.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
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 | |
_cache = None
instance-attribute
_cached_ids = None
instance-attribute
_device = next(reward_model.parameters()).device
instance-attribute
reward_model = reward_model
instance-attribute
rm_tokenizer = rm_tokenizer
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
score_index = score_index
instance-attribute
score_transform = score_transform
instance-attribute
scoring_cost = 'aux_forward'
class-attribute
instance-attribute
supports_batching = False
instance-attribute
__init__(reward_model, rm_tokenizer, score_index=0, score_transform='none')
Source code in steerability/algorithms/output_control/common/values/reward_model.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
_score_no_cache(prefix_ids, candidate_ids, full_mask, max_length)
Full forward over the left-truncated prefix + candidate for an over-length prefix.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | |
_sync_cache(prefix_ids, full_mask)
Bring the internal cache up to prefix_ids (extend by the delta, or rebuild).
Source code in steerability/algorithms/output_control/common/values/reward_model.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
cleanup()
Release the reward model and cached activations.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
290 291 292 293 294 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
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 | |
RewardModelValue
Bases: BaseCandidateValue
Score prefix + candidate with an auxiliary reward model (RAD).
When shared_vocab is True, the prefix and candidate ids are fed to the reward model directly
(no text round-trip), so the reward model scores exactly the sequence the language model
generated. When False, the ids are decoded to text and re-encoded with the reward-model
tokenizer, which is the correct behavior for a reward model whose vocabulary differs from the
language model's. The two paths are not numerically equivalent (the text round-trip may drop
special tokens and re-segment the boundary token), so a reward model that shares the vocabulary
should use the id path. On the id path a reward model with a score head is read at the
candidate position explicitly (the last position of every row), so a candidate equal to the
reward model's pad id is scored as a candidate rather than pooled onto the prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reward_model
|
PreTrainedModel
|
The loaded auxiliary reward model (in eval mode). |
required |
rm_tokenizer
|
PreTrainedTokenizerBase
|
Tokenizer for the reward model. Its |
required |
score_index
|
int
|
Column of the reward model's output read as the score. |
0
|
score_transform
|
ScoreTransform
|
Map the reward model's output to a score before selecting |
'none'
|
shared_vocab
|
bool
|
When True, score via the raw-id path (requires the reward-model vocabulary to equal the language model's). When False (default), score via the text round-trip. |
False
|
Note
scoring_cost="aux_forward" and supports_batching=True; candidate scoring batches B * K
rows through the auxiliary model.
Source code in steerability/algorithms/output_control/common/values/reward_model.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 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 | |
_device = next(reward_model.parameters()).device
instance-attribute
reward_model = reward_model
instance-attribute
rm_tokenizer = rm_tokenizer
instance-attribute
same_model_forwards = False
class-attribute
instance-attribute
score_index = score_index
instance-attribute
score_transform = score_transform
instance-attribute
scoring_cost = 'aux_forward'
class-attribute
instance-attribute
shared_vocab = shared_vocab
instance-attribute
supports_batching = True
instance-attribute
__init__(reward_model, rm_tokenizer, score_index=0, score_transform='none', shared_vocab=False)
Source code in steerability/algorithms/output_control/common/values/reward_model.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
_score_ids(ctx)
Score by feeding raw prefix + candidate ids to the reward model (shared-vocab path).
Source code in steerability/algorithms/output_control/common/values/reward_model.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 | |
_score_text(ctx)
Score by decoding prefix + candidate to text and re-encoding (mismatched-vocab path).
The ids are decoded with skip_special_tokens=True, so a special-token candidate such as
eos contributes nothing to the scored text.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
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 | |
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/values/base.py
71 72 73 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/reward_model.py
101 102 103 104 105 | |
extract_score(output, score_index, score_transform)
Read a per-row scalar score from a reward-model output.
Takes output.logits when present, else the raw output tensor [N, C]. Applies the transform
over the class dimension, then selects column score_index:
- `"none"`: select the column directly (a raw, possibly unbounded logit).
- `"sigmoid"`: element-wise sigmoid, then select.
- `"softmax"`: softmax over the class dimension, then select.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output
|
Any
|
The reward model's output (a classifier output with |
required |
score_index
|
int
|
Column of the class dimension read as the score. |
required |
score_transform
|
ScoreTransform
|
One of |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
A tensor |
Source code in steerability/algorithms/output_control/common/values/reward_model.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 | |
subspace_margin
Candidate value from a linear-probe margin, plus the single-file probe checkpoint loader.
For each candidate token, SubspaceMarginValue forwards prefix + candidate through the
pipeline's own model via CandidateForward and reads the final-layer hidden state h at the raw
output boundary; the value is the probe score h @ w + bias. This is the value underlying SASA.
SubspaceMarginValue
Bases: BaseCandidateValue
Per-candidate margin against a fitted single-layer Probe.
The margin of a candidate hidden state h is h @ w + bias, with w the probe's weight
vector at its single layer and bias its calibrated offset (the documented Probe score).
Hidden states are read by CandidateForward at the raw output boundary of the final decoder
layer, so the probe is expected to be fitted at that boundary (location="layer_output",
pooling="last", final decoder layer).
This value forwards the pipeline's own model per candidate, so it declares
same_model_forwards=True; the forwards run inside auxiliary_pass(aligned=True) (via
CandidateForward), so state-control transforms apply to them at the candidates' true
positions while condition scoring and gates ignore them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
probe
|
Probe
|
The fitted single-layer |
required |
Note
scoring_cost="model_forward" and supports_batching is False (the prefix cache tracks a
single row).
Source code in steerability/algorithms/output_control/common/values/subspace_margin.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 | |
_aligned = None
instance-attribute
_forward = None
instance-attribute
_weights = None
instance-attribute
probe = probe
instance-attribute
same_model_forwards = True
class-attribute
instance-attribute
scoring_cost = 'model_forward'
class-attribute
instance-attribute
supports_batching = False
class-attribute
instance-attribute
__init__(probe)
Source code in steerability/algorithms/output_control/common/values/subspace_margin.py
98 99 100 101 102 | |
_align_probe(device, dtype)
Cache the probe weights aligned to (device, dtype); the probe is fixed per generation.
Source code in steerability/algorithms/output_control/common/values/subspace_margin.py
104 105 106 107 108 | |
cleanup()
Release any resources allocated during prepare().
Source code in steerability/algorithms/output_control/common/values/base.py
71 72 73 | |
prepare(model=None, tokenizer=None, **kwargs)
Optional offline setup, invoked from the owning control's steer().
Mirrors the input-control selector prepare() convention: a default no-op that the parent
control calls during its own steer() when the value needs preparation.
Source code in steerability/algorithms/output_control/common/values/base.py
63 64 65 66 67 68 69 | |
score(ctx)
Return per-candidate values [B, K] aligned with ctx.candidate_ids.
Source code in steerability/algorithms/output_control/common/values/subspace_margin.py
110 111 112 113 114 115 116 117 118 119 120 | |
load_single_file_probe(file_path, layer_id)
Load a single-file probe checkpoint into a Probe.
Accepts two forms: a .probe JSON file with direction and midpoint lists, and a legacy
{'wv', 'mu_mu'} torch tensor checkpoint. Both record a direction and a class-mean midpoint
and no space metadata; they are assumed fitted at the raw output boundary of the final decoder
layer over last-token features. The returned probe carries the direction as the weight vector
of layer_id, bias = -direction . midpoint (so its score equals the margin
direction . (h - midpoint)), location="layer_output", pooling="last",
model_type="unknown", and empty meta (which disarms fingerprint checks).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_path
|
str
|
Path to the checkpoint. |
required |
layer_id
|
int
|
Layer id the direction is registered under (the model's final decoder layer). |
required |
Returns:
| Type | Description |
|---|---|
Probe
|
The adapted |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the checkpoint is not one of the supported forms. |
Source code in steerability/algorithms/output_control/common/values/subspace_margin.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 | |