|
| 1 | +--- |
| 2 | +applyTo: "pyrit/setup/initializers/techniques/**" |
| 3 | +--- |
| 4 | + |
| 5 | +# Setup Technique Catalog Guidelines |
| 6 | + |
| 7 | +**Responsibility**: This directory is the canonical catalog of `AttackTechniqueFactory` |
| 8 | +instances — the declarative "which attack, configured how" entries that scenarios select by |
| 9 | +name. Each group module (`core.py`, `extra.py`) exposes `get_technique_factories()`; |
| 10 | +`technique_initializer.py` aggregates the groups, injects the group name as a technique tag, |
| 11 | +and registers them into the `AttackTechniqueRegistry`. |
| 12 | + |
| 13 | +**Does not own** (see [framework.md](../../doc/code/framework.md)): attack algorithms, |
| 14 | +converters, scorers, or datasets. A factory only *packages* existing bricks as configuration. |
| 15 | +If an entry needs new branching, prompt scaffolding, or transformation logic, that logic |
| 16 | +belongs in an attack / converter / scorer — not here. See also |
| 17 | +[scenarios.instructions.md](scenarios.instructions.md) for the `AttackTechniqueFactory` API. |
| 18 | + |
| 19 | +## Define factories inline |
| 20 | + |
| 21 | +Define each `AttackTechniqueFactory` **inline** in the `get_technique_factories()` list, not in |
| 22 | +a per-technique `_build_<name>_technique()` helper. A factory is declarative configuration, so |
| 23 | +keeping every entry in the one list makes the whole catalog readable at a glance. |
| 24 | + |
| 25 | +**No module-level constants or helper functions for factory arguments.** Do not hoist a |
| 26 | +factory's arguments — YAML paths, turn counts, converter stacks, path-building helpers like |
| 27 | +`_role_play_yaml(name)`, or numeric constants like `ROLE_PLAY_SIMULATED_NUM_TURNS` — into |
| 28 | +module-level names or functions. Even when several factories repeat the same literal (e.g. the |
| 29 | +same `next_message_system_prompt_path` or `num_turns=2`), write the literal inline in each entry. |
| 30 | +Repetition here is intentional: it keeps every factory self-contained and readable at a glance, |
| 31 | +and it is the single most common thing that gets "snuck back in" during a refactor. If you catch |
| 32 | +yourself extracting a `_CONSTANT`, a `_build_*`/`_*_yaml` helper, or a shared config object, |
| 33 | +stop — put the value back inline. |
| 34 | + |
| 35 | +- If an entry needs a few lines of setup (a `seed_technique`, a converter stack), prefer a |
| 36 | + reusable model/config constructor over a bespoke module-level builder — e.g. |
| 37 | + `AttackTechniqueSeedGroup.from_system_prompt(...)` for a system-prompt technique. If you find |
| 38 | + yourself writing a builder, consider whether the reusable piece belongs on the model instead. |
| 39 | +- Reach for a helper function **only** when construction is genuinely dynamic (e.g. a |
| 40 | + `@cache`-decorated builder for a dynamically-enumerated set of techniques). A helper that just |
| 41 | + concatenates a path or returns a fixed literal does not qualify — inline it. |
| 42 | +- Keep entries free of long explanatory comments and paper citations. The factory should read as |
| 43 | + plain configuration; if a technique's mechanics are subtle, document them on the reusable |
| 44 | + converter/model it uses, or here in this file, not as an inline comment block. |
0 commit comments