PRewrite
steerability.algorithms.input_control.prewrite
args
Arguments for the PRewrite input control.
control
PRewrite, an RL-trained instruction rewriter.
Reference:
- "PRewrite: Prompt Rewriting with Reinforcement Learning" Weize Kong, Spurthi Amba Hombaiah, Mingyang Zhang, Qiaozhu Mei, Michael Bendersky https://arxiv.org/abs/2401.08189
logger = logging.getLogger(__name__)
module-attribute
PRewrite
Bases: InputControl
Train (or load) an LLM rewriter that rewrites a seed instruction; optionally select the best rewrite by dev-set evaluation, then apply it as the system prompt at inference time.
When train_rewriter=True, the rewriter is trained with GRPO (group-relative policy optimization).
The reward is downstream task performance, computed by applying each rewrite with the frozen task
model over a dev set and scoring with a per-row SampleScorer, or a user-supplied reward_fn.
Memory shape: TextMemory(slots={"instruction": str}).
Reference:
- "PRewrite: Prompt Rewriting with Reinforcement Learning" Weize Kong, Spurthi Amba Hombaiah, Mingyang Zhang, Qiaozhu Mei, Michael Bendersky https://arxiv.org/abs/2401.08189
Source code in steerability/algorithms/input_control/prewrite/control.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | |
RUNTIME_KWARGS_SCHEMA = []
class-attribute
instance-attribute
args = self.Args.validate(*args, **kwargs)
instance-attribute
dev_set = None
class-attribute
instance-attribute
enabled = True
class-attribute
instance-attribute
eval_gen_kwargs = None
class-attribute
instance-attribute
grpo_config = None
class-attribute
instance-attribute
initial_instruction = ''
class-attribute
instance-attribute
k_candidates = 10
class-attribute
instance-attribute
memory = None
class-attribute
instance-attribute
meta_prompt = None
class-attribute
instance-attribute
reward_dev_size = None
class-attribute
instance-attribute
reward_fn = None
class-attribute
instance-attribute
rewriter_gen_kwargs = None
class-attribute
instance-attribute
rewriter_model = None
class-attribute
instance-attribute
rewriter_model_name_or_path = None
class-attribute
instance-attribute
rewriter_tokenizer = None
class-attribute
instance-attribute
row_scorer = None
class-attribute
instance-attribute
strategy = 'search'
class-attribute
instance-attribute
supports_batching = True
class-attribute
instance-attribute
tokenizer = None
class-attribute
instance-attribute
train_rewriter = False
class-attribute
instance-attribute
training_seeds = None
class-attribute
instance-attribute
trust_remote_code = False
class-attribute
instance-attribute
adapt(input_ids, runtime_kwargs=None)
Transform input_ids into a steered prompt.
May read instance state (e.g. self.memory) that was populated by steer().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_ids
|
list[int] | Tensor
|
The user's prompt token IDs. |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters. |
None
|
Returns:
| Type | Description |
|---|---|
list[int] | Tensor
|
The transformed token IDs. |
Source code in steerability/algorithms/input_control/prewrite/control.py
266 267 268 269 270 271 272 273 274 275 | |
adapt_messages(messages, runtime_kwargs=None)
Optional message-level adaptation, called BEFORE chat-template tokenization.
Default returns None (no message-level changes). Subclasses that modify chat structure (set/replace system
prompt, insert example turns) override this. When this method returns a non-None result for a chat-input
generation, the pipeline does NOT additionally call this control's adapt() for that call; a control may
therefore implement both entry points (message-level for chat input, token-level for raw text/tensor input)
without being applied twice. Other input controls in the pipeline still run per their own phase.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[list[dict]]
|
A batch of chats; outer list is the batch, inner list is the message sequence for one chat. |
required |
runtime_kwargs
|
dict | None
|
Per-call parameters. |
None
|
Returns:
| Type | Description |
|---|---|
list[list[dict]] | None
|
The transformed messages, or None to indicate no change. |
Source code in steerability/algorithms/input_control/prewrite/control.py
257 258 259 260 261 262 263 264 | |
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 | |
export_state()
The optimized instruction memory under the "memory" key (after steer()).
Source code in steerability/algorithms/input_control/prewrite/control.py
85 86 87 | |
fit_identity()
The optimizer-relevant args (everything except memory), or None when the recipe
already carries a memory.
Source code in steerability/algorithms/input_control/prewrite/control.py
98 99 100 101 102 103 104 105 106 107 108 | |
frozen_form(state)
A same-class frozen form: the recipe args with memory= set to the optimized
memory (the search-only args stay inert).
Source code in steerability/algorithms/input_control/prewrite/control.py
89 90 91 92 93 94 95 96 | |
requirements()
Backend requirements computed from this instance's configuration, per phase.
Input controls transform the prompt client-side, so the generate phase requires nothing
beyond the session contract on any backend. A control whose steer() reads the live
pipeline model (e.g. for rollouts or scoring) overrides this with a steer-phase
Capability.IN_PROCESS_TORCH requirement.
Returns:
| Type | Description |
|---|---|
Requirements
|
The control's phase-keyed requirements. |
Source code in steerability/algorithms/input_control/base.py
124 125 126 127 128 129 130 131 132 133 134 135 | |
steer(model=None, tokenizer=None, session=None, **kwargs)
Optional offline preparation. Default is no-op.
session is a SteeringSession on the steering backend, provided by the pipeline.
Source code in steerability/algorithms/input_control/prewrite/control.py
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 | |
steer_access()
ModelAccess.ROLLOUTS; rewriting and dev-set scoring generate through the
session, and adaptation is a formatter. With a precomputed memory, steering is
model-free (ModelAccess.FACTS).
Source code in steerability/algorithms/input_control/prewrite/control.py
77 78 79 80 81 82 83 | |
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 | |
utils
meta_prompts
Meta-prompt templates for PRewrite.
Wording matches Appendix B of Kong et al., 2024 (arXiv:2401.08189) up to format-string adaptation for
LLMMetaPromptProposer. The {seed} placeholder receives the initial instruction.
DEFAULT = 'You are a prompt engineer. Rewrite the following instruction to make it clearer, more specific, and more effective for a downstream language model, while preserving its intent.\n\nOriginal instruction:\n{seed}\n\nRewritten instruction:'
module-attribute
reward
Reward-function adapters for GRPO-trained PRewrite rewriters.
Wraps a TaskEvaluationScorer into the callable shape TRL's GRPOTrainer expects,
reward_func(prompts, completions, **kwargs), returning one float per completion. The reward applies
the rewritten instruction with the frozen task model over a dev set and scores the answers with a
per-row SampleScorer (Kong et al., 2024).
For a callable reward on trl==0.16.1, GRPOTrainer calls
reward_func(prompts=prompts, completions=completions, **reward_kwargs). Completions are plain strings
when the dataset "prompt" column is text (the PRewrite case) and conversational message lists when it
is a chat. Both shapes are handled here.
make_scorer_reward_func(scorer, parse_fn=None)
Wrap a TaskEvaluationScorer as a GRPO reward function.
Each completion is a candidate rewritten instruction; its reward is the scorer's dev-set score for that instruction. Identical rewrites are scored once and the result reused. PRewrite rewrites are input-agnostic (the rewriter sees only the seed meta-prompt, not the task inputs), so a generation group often contains duplicates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scorer
|
TaskEvaluationScorer
|
Configured |
required |
parse_fn
|
Callable[[str], list[str]] | None
|
Optional parser applied to each completion before scoring (e.g.
|
None
|
Returns:
| Type | Description |
|---|---|
Callable
|
A callable |
Source code in steerability/algorithms/input_control/prewrite/utils/reward.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |