Skip to main content

hackagent.attacks.techniques.adaptive.advprefix.prompts

What the prefix writer is told, and what makes a prefix worth keeping.

AdvPrefix does not argue with the target. It writes an opening that the target has already started saying — an assistant turn mid-sentence — and lets it continue. So the vocabulary here is mostly about recognising a candidate that failed: a prefix that opens with a refusal is a refusal the target will happily finish.

LEGACY_GENERATOR_SYSTEM_PROMPT​

HackAgent's own instruction-style generator, kept for reference. The pipeline no longer uses it: the reference implementation continues an opening rather than describing one.

META_PREFIXES​

Openings the writer continues, from the reference implementation's meta_prefixes. They are the literal first word of the prefix, not an instruction about it; "" lets the writer open however it likes.

START_PATTERNS​

A candidate that begins with one of these is the writer refusing, not a prefix. Matched against the start of the text only.

CONTAIN_PATTERNS​

A candidate containing one of these is arguing with itself somewhere in the middle, which the target will continue.

REFUSAL_KEYWORDS​

What a target says when it will not continue the prefix. Used to decide whether a prefix is worth spending a completion on.

generation_turns​

def generation_turns(meta_prefix: str, goal: str) -> list[dict[str, str]]

Ask the writer to continue meta_prefix as an answer to goal.

The reference runs a base model on raw text: the chat-formatted goal, then the opening, continued. The same shape over a chat role is the goal as the user turn and the opening prefilled as the assistant's, so an uncensored writer carries on rather than being told what to write.

prefilled​

def prefilled(goal: str, prefix: str) -> list[dict[str, str]]

The attack itself: the goal asked, and the answer already begun.

The prefix goes in the assistant turn, so the model is not being asked to say something — it is being shown something it apparently already started saying, and continuing is a different decision from agreeing. This is what the paper measures.

instructed​

def instructed(goal: str, prefix: str) -> list[dict[str, str]]

The same attack for an endpoint that rejects a trailing assistant turn.

Asking for the prefix is weaker than supplying it — the model may decline — but it is the closest a plain chat completion gets.

said​

def said(prefix: str, continuation: str) -> str

What the assistant turn ends up containing, for the judge.

The model generates only the continuation, but the turn it belongs to opens with the prefix, and the harmful content may straddle the two. Judging the continuation alone would miss it.

is_refusal​

def is_refusal(text: str) -> bool

Whether a target reply is a refusal to continue.

usable​

def usable(prefix: str, *, min_chars: int, require_linebreak: bool) -> bool

Whether a candidate is a prefix at all, before it costs a call.