How Prompt Syntax Works in AUTOMATIC1111: Attention and Emphasis Modifiers Explained
AUTOMATIC1111's stable-diffusion-webui uses parentheses () and square brackets [] to increase or decrease token weights by factors of 1.1× and 0.9× respectively, with nested modifiers multiplying these effects and explicit decimal weights allowing precise control over how CLIP processes individual prompt tokens.
The AUTOMATIC1111/stable-diffusion-webui repository implements a sophisticated prompt syntax system that lets users control image generation through attention and emphasis modifiers. These modifiers manipulate how the CLIP text encoder weights individual tokens before feeding them into the diffusion model. Understanding this syntax requires examining the parsing logic in modules/prompt_parser.py and the weight application mechanism in modules/sd_hijack_clip.py.
Core Attention Modifiers
The parser recognizes two primary bracket types for adjusting token emphasis. These are processed character-by-character to build a parallel list of floating-point weights that correspond to each token in the prompt.
Increasing Attention with Parentheses
Wrapping text in ( ) increases the weight of those tokens by a factor of 1.1× by default. Nesting parentheses multiplies the effect: ((text)) applies 1.1 × 1.1 = 1.21×, while (((text))) yields 1.331×.
For precise control, use explicit weight notation: (text:1.5) assigns exactly 1.5× weight regardless of nesting level. This overrides the default 1.1× multiplier and is parsed by the weight detection logic in modules/prompt_parser.py.
Decreasing Attention with Square Brackets
Wrapping text in [ ] decreases token weights by a factor of 0.9× per bracket pair. Similar to parentheses, nesting multiplies the effect: [[text]] results in 0.9 × 0.9 = 0.81×, and [[[text]]] yields 0.729×.
Explicit weights work identically for reduction: [text:0.6] forces a 0.6× multiplier, which is useful when the default 0.9× decrement is too subtle for your prompt syntax needs.
How the Parser Processes Prompt Syntax
The transformation from raw string to weighted token embeddings follows a specific pipeline implemented across several modules.
1. Initial Parsing
The entry point is parse_prompt() in modules/prompt_parser.py. This function coordinates the conversion of the user's prompt string into a structured format suitable for the CLIP encoder.
2. Attention Parsing
The parse_prompt_attention() function walks the character stream and maintains a weight stack that tracks the current nesting level of parentheses and brackets. When the parser encounters an opening (, it pushes a 1.1× multiplier onto the stack; for [, it pushes 0.9×. Closing brackets pop these values.
3. Explicit Weight Detection
When the parser encounters a colon followed by a number inside brackets—such as (dragon:2.0)—it treats this as an explicit weight override. The numeric value replaces the default multiplier for that specific text segment.
4. Tokenization and Weight Assignment
After parsing, the text is tokenized using the CLIP tokenizer. The parser returns two parallel lists: token IDs and their corresponding floating-point weights. This ensures each subword token inherits the weight assigned to its parent phrase.
Emphasis Modes and Weight Application
Once the parser generates the weight list, the system applies these values differently depending on the selected Emphasis Mode.
Emphasis Mode Selection
The UI option defined in modules/shared_options.py under the "emphasis" key determines how weights are interpreted. The available modes are implemented in modules/sd_emphasis.py, including:
- Original: Applies weights exactly as parsed (1.1×, 0.9×, or explicit values)
- Prompt Weight: Normalizes weights so the average remains 1.0, preventing overall prompt strength drift
- Fixed Emphasis: Applies a consistent scaling factor regardless of parsing
Each mode implements a __call__(self, tokens, weights, ...) method that can transform the raw weights before they reach the encoder.
CLIP Weight Application
In modules/sd_hijack_clip.py, the actual weighting occurs after tokenization. The code applies the computed weights to the token embeddings using element-wise multiplication:
emb = emb * weights[:, None]
This operation scales each token's embedding vector by its assigned weight before the tensor is fed into the diffusion model. Higher weights cause the model to "pay more attention" to those concepts during image generation, while lower weights suppress their influence.
Practical Prompt Syntax Examples
The following examples demonstrate valid syntax patterns recognized by the parser:
# Example 1 – Simple increase and decrease
prompt = "a photo of (sunset) on the [beach]"
# (sunset) → 1.1×, [beach] → 0.9×
# Example 2 – Custom explicit weights
prompt = "portrait of (woman:1.5) with [soft lighting:0.6]"
# woman gets 1.5×, soft lighting gets 0.6×
# Example 3 – Nested emphasis with mixed modifiers
prompt = "((highly detailed) illustration of a (dragon:2.0))"
# inner (dragon:2.0) = 2.0 × outer 1.1 = 2.2×
# outer "highly detailed" = 1.1² = 1.21×
# Example 4 – Complex nesting
prompt = "([masterpiece:1.4] of a ((beautiful)) landscape)"
# masterpiece: 1.4× (explicit overrides bracket default)
# beautiful: 1.21× (nested parentheses)
When using the "Prompt Weight" emphasis mode via the UI, the same prompt strings are parsed identically, but the weights are renormalized so that the average weight across all tokens equals 1.0. This prevents high overall prompt weights from destabilizing the diffusion process.
Summary
- Parentheses
(text)increase attention by 1.1× per level, while square brackets[text]decrease it by 0.9× per level according to the logic inmodules/prompt_parser.py. - Explicit weights using the
(text:1.5)syntax override default multipliers and provide precise control over individual token emphasis. - The weight stack mechanism in
parse_prompt_attention()handles nested brackets by multiplying their effects, allowing compound modifiers like((text))for 1.21× emphasis. - Emphasis modes defined in
modules/sd_emphasis.pydetermine how raw parsed weights are transformed before application, with options ranging from raw values to normalized distributions. - Final weight application occurs in
modules/sd_hijack_clip.pythrough multiplication of token embeddings, directly influencing the diffusion model's interpretation of the prompt syntax.
Frequently Asked Questions
What is the default weight multiplier for parentheses in AUTOMATIC1111?
By default, single parentheses (text) apply a 1.1× multiplier to the enclosed tokens, while square brackets [text] apply 0.9×. These defaults are hardcoded in the parsing logic of modules/prompt_parser.py and serve as the base values before any nesting or explicit overrides are calculated.
How does nesting attention modifiers work?
Each nesting level multiplies the effect of the brackets. For parentheses, ((text)) equals 1.1 × 1.1 = 1.21×, and (((text))) equals 1.331×. For square brackets, [[text]] equals 0.9 × 0.9 = 0.81×. The parser maintains a stack of these multipliers during the parse_prompt_attention() execution, applying the cumulative product to tokens based on their nesting depth.
What is the difference between Original and Prompt Weight emphasis modes?
Original mode applies the weights exactly as parsed from the prompt syntax, allowing the average prompt weight to vary based on your use of modifiers. Prompt Weight mode, implemented in modules/sd_emphasis.py, automatically rescales all weights so their mean equals 1.0, preventing the overall prompt strength from increasing or decreasing due to heavy use of attention brackets.
Where in the codebase are prompt weights actually applied to token embeddings?
The final application occurs in modules/sd_hijack_clip.py, specifically in the code that executes emb = emb * weights[:, None]. This multiplication happens after tokenization but before the embeddings are passed to the diffusion model, ensuring that the attention modifiers directly influence the CLIP encoding process that guides image generation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →