You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,10 +30,10 @@
30
30
31
31
32
32
- ⚔️ **Red-team LLMs out of the box:** Craft jailbreaks and other LLM attacks with **30+ ready-to-run recipes** — spanning white- and black-box methods (GCG, BEAST, MAC, GASLITE, …) — each invocable in a single call, to evaluate model and defense robustness.
33
-
- 🔁 **Extend to any NLP model:** Seamlessly port existing optimization schemes (e.g., LLM jailreabks) to any model (e.g., retrievers, classifiers, multimodal systems), or to novel tasks (e.g., new attack vectors, interpretability research).
33
+
- 🔁 **Extend to any NLP model:** Seamlessly port existing optimization schemes (e.g., LLM jailbreaks) to any model (e.g., retrievers, classifiers, multimodal systems), or to novel tasks (e.g., new attack vectors, interpretability research).
34
34
- 🧩 **Compose new optimization recipes:** Mix and match any optimizer (gradient-based, continuous-relaxation, black-box) with any loss (logits, embeddings, attention, activations, LM-as-judge) to create adaptive and novel optimization recipes in new domains.
35
-
- 🔬 **Build new optimizers and losses:** Build **new optimizers** leveraging TROPT's standardized, lightweight optimizer implementation and its exetensive toolkit. Or, **customize loss** by only defining its core logic. TROPT **automatcally integrate** new optimizers and losses to with any model and recipe (including batching, trigger combination, gradients), avoiding annoying yet subtle boierplate.
36
-
- 🛡️ **Reliable Benchmarking:** Run fair, reproducible comparisons of optimizers and their enhancements on shared infrastructure and a rich bank of optimziers, losses, etc.
35
+
- 🔬 **Build new optimizers and losses:** Build **new optimizers** leveraging TROPT's standardized, lightweight optimizer implementation and its extensive toolkit. Or, **customize loss** by only defining its core logic. TROPT **automatically integrates** new optimizers and losses with any model and recipe (including batching, trigger combination, gradients), avoiding annoying yet subtle boilerplate.
36
+
- 🛡️ **Reliable Benchmarking:** Run fair, reproducible comparisons of optimizers and their enhancements on shared infrastructure and a rich bank of optimizers, losses, etc.
Copy file name to clipboardExpand all lines: skills/tropt/SKILL.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,11 +37,11 @@ optimizer (declares model_requirements, drives the search)──┘
37
37
Two design principles to keep in mind: *modularity* (each component swaps largely independently) and *backend–frontend separation* (tokenization, batching, gradient computation live in the model "backend"; losses and optimizers stay lightweight "frontend").
38
38
39
39
-**Model** (`tropt/model/`) — wraps the target model and exposes capabilities via **access mixins**. The optimizer declares which mixins it needs; `BaseOptimizer.__init__` validates the model satisfies them. Common mixins: `LossTokenAccessMixin` (grey-box loss from tokens), `GradientTokenAccessMixin` (white-box gradients), `LossTextAccessMixin` (black-box, text-only), `LogitsTokenAccessMixin`, `GradientEmbedAccessMixin`. Backends: `LMHFModel` (HF causal LMs — most mixins), `EncoderHFModel`, `EncoderOpenAIModel`, `LiteLLMModel`, `EncoderGeminiModel`.
40
-
-**Loss** (`tropt/loss/`) — pure objective. Receives fields from `ModelOutput` / `ModelInput` / `MessageTargets` by **parameter-name matching** in its `__call__` signature (the one rule). Categories: `LogitBasedLoss`, `EmbeddingBasedLoss`, `TextBasedLoss`, `AttentionBasedLoss`, `HiddenStateBasedLoss`, `CombinedLoss`.
40
+
-**Loss** (`tropt/loss/`) — pure objective. Receives fields from `ModelOutput` / `ModelInput` / `MessageTargets` by **parameter-name matching** in its `__call__` signature (the one rule). Categories: `PrefillBasedLoss`, `TriggerLogitBasedLoss`, `EmbeddingBasedLoss`, `TextBasedLoss`, `AttentionBasedLoss`, `HiddenStateBasedLoss`, `ClassificationBasedLoss`, `CombinedLoss`.
41
41
-**Optimizer** (`tropt/optimizer/`) — the search algorithm. Self-contained, one file per optimizer (HuggingFace "Repeat Yourself"). Declares `model_requirements = (Mixin1, Mixin2)` at class level.
42
42
-**Inputs & targets** — the user-supplied input template(s) carrying the `{{OPTIMIZED_TRIGGER}}` placeholder, plus a `Targets` dataclass holding per-template targets (`target_response_strs`, `target_vectors`, `target_directions`, `target_class_idx`, …). Each set field has length `n_templates`. Templates and targets are passed to `optimizer.optimize_trigger(templates=..., targets=...)`; the framework handles trigger/template combination internally.
43
43
44
-
The **Recipe Hub** (`tropt/recipe_hub/`) ships ~30 pre-wired (Model, Loss, Optimizer, defaults) combinations as one-call functions. That's almost always the right starting point.
44
+
The **Recipe Hub** (`tropt/recipe_hub/`) ships ~38 pre-wired (Model, Loss, Optimizer, defaults) combinations as one-call functions. That's almost always the right starting point.
45
45
46
46
## 3. Install or update TROPT
47
47
@@ -185,17 +185,17 @@ These apply across optimizers and recipes — surface them when relevant rather
185
185
-**Missing `{{OPTIMIZED_TRIGGER}}`** in templates → optimizer raises. Every template must contain the placeholder string (exported as `tropt.common.OPTIMIZED_TRIGGER_PLACEHOLDER`).
186
186
-**Mixin mismatch** — pairing a black-box `LiteLLMModel` with `GCGOptimizer` (which needs `GradientTokenAccessMixin`) fails at construction time, not silently. If the user wants a gradient-free attack on a black-box model, point them at `prs__andriushchenko2024` / `rs_emb` / `gcgp_blackbox__hayase2024`.
187
187
-**`Targets` field length mismatch** — every set field must have length `n_templates`. Universal triggers across N templates need N targets (often repeated: `["Sure, here is"] * N`).
188
-
-**Thinking-model target misalignment (Qwen3, etc.)** — these models prefix every emits a `<think>...</think>` block, so the affirmative target the optimizer chases (e.g. `"Sure, here's how:"`) never appears at position 0 of the generation. Prepend the empty thinking block to the target: `target = "<think>\n\n</think>\n\n" + "Sure, here's how:"`. Without this fix, prefill-CE losses chase a position the model will never write to.
188
+
-**Thinking-model target misalignment (Qwen3, etc.)** — these models always emit a `<think>...</think>` block first, so the affirmative target the optimizer chases (e.g. `"Sure, here's how:"`) never appears at position 0 of the generation. Prepend the empty thinking block to the target: `target = "<think>\n\n</think>\n\n" + "Sure, here's how:"`. Without this fix, prefill-CE losses chase a position the model will never write to.
189
189
-**Some losses impose model-construction requirements** beyond just the access mixins. Check the loss's docstring before pairing it with a recipe:
190
190
-`AttentionBasedLoss` family (e.g. `AttentionEnhLoss`) needs the model loaded with `use_eager_attention=True` — FlashAttention/SDPA paths don't return attention weights. `LMHFModel(..., use_eager_attention=True)`.
191
-
-`AttentionEnhLoss` with `dst=INPUT_AFTER` (and other suffix-position-dependent losses) requires the trigger to be a **true suffix** of the user message — strip any trailing punctuation after `{{OPTIMIZED_TRIGGER}}` in the template (`"... harmful thing. {{OPTIMIZED_TRIGGER}}"` → `"... harmful thing {{OPTIMIZED_TRIGGER}}"`).
191
+
-`AttentionEnhLoss` with `dst_slc_name=SliceKey.INPUT_AFTER` (and other suffix-position-dependent losses) requires the trigger to be a **true suffix** of the user message — strip any trailing punctuation after `{{OPTIMIZED_TRIGGER}}` in the template (`"... harmful thing. {{OPTIMIZED_TRIGGER}}"` → `"... harmful thing {{OPTIMIZED_TRIGGER}}"`).
192
192
-`TriggerPerplexityLoss` and other trigger-slice-dependent losses require `use_prefix_cache=False` on the model — prefix caching shifts the trigger slice's start position.
193
193
- Hidden-state / activation losses (`SteeringActivationLoss`, etc.) often need pre-computed direction vectors (e.g. `compute_refusal_directions(model, n_samples=128)`) passed via `Targets(target_directions=...)`.
194
194
-**Stop by budget, not just by `num_steps`** — TROPT optimizers support `optimizer.set_budget(BUDGET, metric="total_flops")` (white-box) and `set_budget(BUDGET, metric="total_tokens", scope="target")` (black-box / API), letting you cap compute or API cost directly instead of guessing a step count. Pair with `model.set_flop_counting("manual")` on the model. Far more reliable across optimizers with different per-step costs.
195
-
-**Initial trigger init** — prefer `tropt.optimizer.utils.token_initializers.get_printable_random_trigger(trigger_len, tokenizer, blacklist_ids=TokenConstraints().get_blacklist_ids(tokenizer))` over hand-crafted `"! ! ! ! !"` strings. The hand-crafted form depends on the tokenizer treating `!` as a single token (not universal) and gives every position the same starting gradient, which hurts on some models.
195
+
-**Initial trigger init** — prefer `tropt.optimizer.utils.token_initializers.get_printable_random_trigger(trigger_len, tokenizer=tokenizer, blacklist_ids=TokenConstraints().get_blacklist_ids(tokenizer))` over hand-crafted `"! ! ! ! !"` strings. The hand-crafted form depends on the tokenizer treating `!` as a single token (not universal) and gives every position the same starting gradient, which hurts on some models.
196
196
-**Pass `TokenConstraints` to the optimizer, not just to trigger init** — without `token_constraints=`, optimizers may emit triggers with non-ASCII Unicode, model special tokens (`<|im_start|>`, `<bos>`, etc.), or other artifacts that break downstream evaluation, leak chat-template structure, or are trivially filterable. For red-teaming / robustness work the safe default is `TokenConstraints(disallow_non_ascii=True, disallow_special_tokens=True)`, passed both to the optimizer and to `get_blacklist_ids(tokenizer)` for trigger init. Recipe Hub recipes already do this; raw `Pattern B` compositions in user scripts often forget.
197
197
-**Multi-model OOM** — when a recipe needs a *second* model (teacher for IRIS / FLRT distillation, proxy for PAL/RAL/QCG in black-box mode, utility LM for AdvDecoding/BeamSearch), do not let it co-reside with the victim. Standard pattern: load aux → generate / extract what you need → `del aux._model; del aux; gc.collect(); torch.cuda.empty_cache(); torch.cuda.synchronize()` → THEN load victim. Holding both on one GPU blows memory on most consumer setups.
198
-
-**Black-box loss is not the same as white-box loss** — `PrefillCELoss` reads `full_logits`, which an API/LiteLLM model doesn't expose. For API targets swap to `FirstTokenNLLLoss(target_token="Sure")` (or another text/first-token-based loss). Optimizer-side, the model itself also flips to `LiteLLMModel`, and only optimizers declaring `LossTextAccessMixin` in their `model_requirements` will accept it.
198
+
-**Black-box loss is not the same as white-box loss** — `PrefillCELoss` reads `prefill_response_logits` (target prefill), which an API/LiteLLM model can't provide. For API targets swap to `FirstTokenNLLLoss(target_token="Sure")` (or another text/first-token-based loss). Optimizer-side, the model itself also flips to `LiteLLMModel`, and only optimizers declaring `LossTextAccessMixin` in their `model_requirements` will accept it.
199
199
-**Large models on a small machine** — don't suggest `meta-llama/Llama-3.1-8B-Instruct` for someone debugging locally on a laptop. Default to `google/gemma-3-270m-it` or `google/gemma-3-1b-it` for smoke tests; the recipe still reproduces, just with weaker results.
200
200
-**Recipe naming** — `foo__year2024` means it reproduces the paper's algorithm + hyperparameters. Bare `foo` means it's a variant or a setting-port. When recommending a recipe for paper reproduction, prefer the tagged form.
201
201
-**WandB tracking is opt-in** — instantiate `WandbTracker()` and pass it to the optimizer; otherwise nothing logs. `LiveLossPlot` is the lighter local alternative.
Note that it requires setting `use_eager_attention=True` when loading the model (for explicit attention computations); also it
357
-
is some slices are not supported when LM prefix caching is enabled, so it should be set to `use_prefix_cache=False` when loading the model.
356
+
Note that it requires setting `use_eager_attention=True` when loading the model (for explicit attention computations); also, some slices are not supported when LM prefix caching is enabled, so set `use_prefix_cache=False` when loading the model.
logger.debug("Note: `INPUT_AFTER` slice is currently only correct for LMs and on suffix attacks. If the usage is different, somethings may break, or worse -- be wrong.")
369
+
logger.debug("Note: `INPUT_AFTER` slice is currently only correct for LMs and on suffix attacks. If the usage is different, something may break, or worse -- be wrong.")
0 commit comments