Factory.ai

Open-Source Wikis

/

Stable Diffusion WebUI

/

How to contribute

/

Patterns and conventions

AUTOMATIC1111/stable-diffusion-webui

Patterns and conventions

A reference of recurring patterns in the codebase. New code should follow these unless there's a specific reason not to.

Module shape

  • One responsibility per module under modules/. There is no package layering: every module is a sibling.
  • Module names follow snake_case. Private helpers are prefixed with _.
  • Each module imports the small shared globals it needs from modules/shared.py: cmd_opts, opts, state, sd_model, sd_upscalers, face_restorers. shared is loaded early and is the project's de-facto service locator.
from modules.shared import opts, cmd_opts, state
import modules.shared as shared

# Use shared.sd_model for "the currently loaded checkpoint"
# Use opts.SOMETHING for user-editable settings
# Use cmd_opts.something for command-line flags
# Use shared.state for progress / interrupt

The p convention

Any function that touches generation accepts a p: StableDiffusionProcessing. Scripts mutate p in place:

def process(self, p, *args):
    p.extra_generation_params["My setting"] = args[0]
    p.steps = max(p.steps, 10)

Extending the param dict via p.extra_generation_params makes the value appear in the saved infotext. Adding fields directly to p is fine, but they won't survive serialisation.

Settings

User-editable options are declared in modules/shared_options.py by appending to options_templates:

options_templates.update(options_section(("category", "Category Label"), {
    "my_setting": OptionInfo(default_value, "Label", gr.Component, {"...": ...}).info("Tooltip"),
}))

options_section, OptionInfo and friends are in modules/options.py. Extensions should register settings inside an on_ui_settings callback (see systems/script-callbacks.md), so they don't pollute the core list.

Read with opts.my_setting. Write with opts.set("my_setting", value). Always read at use-time, never cache the value at import-time — the user can change settings while the server is running.

Error handling

The repo deliberately swallows errors that originate in user-supplied code (extensions, scripts, custom YAML configs) so a single broken extension doesn't crash the whole server:

from modules import errors

try:
    do_something_extension()
except Exception:
    errors.report(f"Error in {extension.name}", exc_info=True)

errors.report in modules/errors.py prints a banner header and the traceback. For errors in core code, just raise — the wrapping wrap_gradio_call (in modules/call_queue.py) will convert it to a user-visible Gradio error.

Hijacking is the extension mechanism for ML code

The ldm (Latent Diffusion Model) package is vendored from upstream and not modified directly. Instead, modules/sd_hijack.py and friends monkey-patch its classes at runtime:

  • model_hijack.hijack(sd_model) swaps in custom CLIP wrappers, optimised attention, and prompt parsing.
  • model_hijack.undo_hijack(sd_model) reverses the changes when the model is unloaded.
  • All hijacks live under modules/sd_hijack_*.py and are documented in systems/sd-hijack.md.

When adding new ML behaviour, prefer hijacks over forking ldm.

Prompt mutation: extra_networks

If your script needs to consume new <my:foo:1.0> syntax in prompts, register an ExtraNetwork subclass in modules/extra_networks.py. The framework parses these tokens out of the prompt before encoding and passes them to your activate(p, params_list) and deactivate(p) methods. The Lora extension is the canonical example — see systems/extra-networks.md.

Building UI components

Most UI work happens in modules/ui.py and the ui_*.py modules. Conventions:

  • Wrap groups of related controls in gr.Accordion(label, open=False) to keep the page compact.
  • For settings that round-trip via PNG-info, append the (component, key) pair to the local paste_fields list — this is how the "Read generation parameters" button works.
  • Use ui_components.FormRow, FormColumn, FormGroup (in modules/ui_components.py) for compact form layouts.
  • Use InputAccordion (also in ui_components.py) when the accordion's "open" state should itself be a parameter sent through the API.
  • Keep custom JavaScript in javascript/ and reference it from a Gradio component via _js="myFunctionName". Files in javascript/ are auto-loaded on page load.

The wrap_gradio_call convention

Every event handler that does GPU work or accesses shared.state is wrapped with one of:

Wrapper Purpose
wrap_gradio_call Catches exceptions; turns them into a user-visible error
wrap_gradio_gpu_call Adds the call queue lock so only one GPU job runs at a time
wrap_gradio_call_no_job Catches exceptions but doesn't update state.job (added in v1.10 to fix progress bar resets)

All three live in modules/call_queue.py. New event handlers should use the appropriate wrapper.

Lazy imports

Heavy modules — torch, safetensors, gradio, transformers — are imported lazily inside functions wherever practical. This keeps python launch.py --help and --dump-sysinfo fast and lets the launch script print its banner before any GPU work happens. When adding a new dependency, follow the same pattern unless the code path always uses it.

Public extension API

When changing things that extensions might depend on, keep the following stable:

  • The Script class signature (process, before_process, postprocess, postprocess_image, etc.).
  • The set of named callbacks in modules/script_callbacks.py. New ones can be added; existing ones must keep their signatures.
  • StableDiffusionProcessing field names. Renames need a deprecation alias.
  • The <lora:name:weight> and <hypernet:name:weight> extra-network syntaxes.
  • The /sdapi/v1/* route paths and request/response shapes.

The extension community is large and reactive; breaking changes here usually result in user-visible regressions immediately after merge.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Patterns and conventions – Stable Diffusion WebUI wiki | Factory