From 0878863c2116478fb89243c6755d2551f85f3a0e Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sun, 26 Jul 2026 21:35:13 -0400 Subject: [PATCH] docs(config): disclose legacy device precedence in generation_devices auto copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The schema description, Settings UI copy, and configuration guide's behavior table all said `generation_devices: auto` uses every available GPU, but TorchDevice.get_generation_devices() deliberately resolves it to the single pinned legacy `device` when one is set — only a later docs note disclosed the exception. An upgraded install with `device: cuda:1` displayed "Auto (all GPUs)" while starting one worker. - config_default.py: the field description now states the precedence (and that an explicit list overrides `device`). - Settings UI: the badge is "Auto" (not "Auto (all GPUs)") and the help text explains the legacy-device exception and the override. - invokeai-yaml.mdx: the behavior table row for `auto` states the exception where the value is introduced, not only in the notes. - Regenerated docs/src/generated/settings.json, openapi.json, schema.ts from the description source. - New test asserts all four copy locations describe the precedence. Follow-up to PR #9263 (JPPhoto review, 2026-07-25). Co-Authored-By: Claude Fable 5 --- .../docs/configuration/invokeai-yaml.mdx | 2 +- docs/src/generated/settings.json | 2 +- .../app/services/config/config_default.py | 2 +- invokeai/frontend/web/openapi.json | 2 +- invokeai/frontend/web/public/locales/en.json | 4 +-- .../frontend/web/src/services/api/schema.ts | 2 +- .../config/test_config_generation_devices.py | 30 +++++++++++++++++++ 7 files changed, 37 insertions(+), 7 deletions(-) diff --git a/docs/src/content/docs/configuration/invokeai-yaml.mdx b/docs/src/content/docs/configuration/invokeai-yaml.mdx index a0c10ef9560..51b60c4ecb0 100644 --- a/docs/src/content/docs/configuration/invokeai-yaml.mdx +++ b/docs/src/content/docs/configuration/invokeai-yaml.mdx @@ -126,7 +126,7 @@ generation_devices: auto # default value | Value | Behavior | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `auto` | Use every available CUDA GPU, running one generation session per GPU concurrently. This is the default. | +| `auto` | Use every available CUDA GPU, running one generation session per GPU concurrently. This is the default. Exception: if the legacy `device` setting is pinned to a specific device, `auto` uses only that device (see Notes below). | | `[cuda:0,cuda:1]` | Use the specific devices listed, one session per device. Useful for reserving a GPU for other work. | | `[cuda:0]` | Use a single specific device. Generation runs serially, as it did before multi-GPU support. | diff --git a/docs/src/generated/settings.json b/docs/src/generated/settings.json index 2c183f55400..a3d8a9bf6a5 100644 --- a/docs/src/generated/settings.json +++ b/docs/src/generated/settings.json @@ -515,7 +515,7 @@ { "category": "DEVICE", "default": "auto", - "description": "Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users. Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)", + "description": "Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users \u2014 unless the legacy `device` setting is pinned to a specific device, in which case `auto` uses only that device (preserving configs that pinned `device` before multi-GPU support existed). Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices regardless of `device`, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)", "env_var": "INVOKEAI_GENERATION_DEVICES", "literal_values": [], "name": "generation_devices", diff --git a/invokeai/app/services/config/config_default.py b/invokeai/app/services/config/config_default.py index ae1e38e0ccc..3de35caf14f 100644 --- a/invokeai/app/services/config/config_default.py +++ b/invokeai/app/services/config/config_default.py @@ -214,7 +214,7 @@ class InvokeAIAppConfig(BaseSettings): # DEVICE device: str = Field(default="auto", description="Preferred execution device. `auto` will choose the device depending on the hardware platform and the installed torch capabilities.
Valid values: `auto`, `cpu`, `cuda`, `mps`, `cuda:N` (where N is a device number)", pattern=r"^(auto|cpu|mps|cuda(:\d+)?)$") - generation_devices: Union[Literal["auto"], list[str]] = Field(default="auto", description="Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users. Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)") + generation_devices: Union[Literal["auto"], list[str]] = Field(default="auto", description="Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users — unless the legacy `device` setting is pinned to a specific device, in which case `auto` uses only that device (preserving configs that pinned `device` before multi-GPU support existed). Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices regardless of `device`, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)") offload_text_encoders_to_idle_gpus: bool = Field(default=True, description="When running on multiple GPUs, load text encoders onto a currently-idle GPU instead of the one running the denoise pipeline. This avoids churning the denoise model in and out of VRAM to make room for the encoder, and lets a cached encoder be reused across generations. Has no effect unless at least two `generation_devices` are configured and a GPU is idle; under full load encoders run on the session's own GPU as before.") precision: PRECISION = Field(default="auto", description="Floating point precision. `float16` will consume half the memory of `float32` but produce slightly lower-quality images. The `auto` setting will guess the proper precision based on your video card and operating system.") diff --git a/invokeai/frontend/web/openapi.json b/invokeai/frontend/web/openapi.json index 2f6b07d1744..0b0e85ff851 100644 --- a/invokeai/frontend/web/openapi.json +++ b/invokeai/frontend/web/openapi.json @@ -46056,7 +46056,7 @@ } ], "title": "Generation Devices", - "description": "Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users. Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)", + "description": "Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users \u2014 unless the legacy `device` setting is pinned to a specific device, in which case `auto` uses only that device (preserving configs that pinned `device` before multi-GPU support existed). Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices regardless of `device`, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number)", "default": "auto" }, "offload_text_encoders_to_idle_gpus": { diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 4e03cce9888..437bb4a1ded 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1928,8 +1928,8 @@ "general": "General", "generation": "Generation", "generationDevices": "Generation Devices", - "generationDevicesAuto": "Auto (all GPUs)", - "generationDevicesHelp": "Select which devices to use for parallel generation, one session per device. \"Auto\" uses every available GPU.", + "generationDevicesAuto": "Auto", + "generationDevicesHelp": "Select which devices to use for parallel generation, one session per device. \"Auto\" uses every available GPU — unless the legacy 'device' setting in invokeai.yaml pins a specific device, in which case only that device is used. An explicit selection here overrides 'device'.", "generationDevicesRestart": "Restart InvokeAI for changes to take effect.", "generationDevicesSaveFailed": "Failed to save Generation Devices", "imageSubfolderStrategy": "Image Subfolder Strategy", diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts index 63187c368a5..4ba5846065e 100644 --- a/invokeai/frontend/web/src/services/api/schema.ts +++ b/invokeai/frontend/web/src/services/api/schema.ts @@ -18044,7 +18044,7 @@ export type components = { device?: string; /** * Generation Devices - * @description Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users. Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number) + * @description Devices to use for parallel generation. `auto` (the default) uses every available GPU, running one generation session per GPU concurrently and distributing jobs fairly across users — unless the legacy `device` setting is pinned to a specific device, in which case `auto` uses only that device (preserving configs that pinned `device` before multi-GPU support existed). Provide an explicit list (e.g. `[cuda:0, cuda:1]`) to use specific devices regardless of `device`, or a single-device list (e.g. `[cuda:0]`) to run serially. On systems without a GPU, `auto` resolves to the single `cpu`/`mps` device.
Valid values: `auto`, or a list whose entries are each `cpu`, `cuda`, `mps`, or `cuda:N` (where N is a device number) * @default auto */ generation_devices?: "auto" | string[]; diff --git a/tests/app/services/config/test_config_generation_devices.py b/tests/app/services/config/test_config_generation_devices.py index e589b35dd3d..6264f45afb0 100644 --- a/tests/app/services/config/test_config_generation_devices.py +++ b/tests/app/services/config/test_config_generation_devices.py @@ -36,3 +36,33 @@ def test_empty_list_is_rejected(): def test_invalid_device_name_is_rejected(): with pytest.raises(ValidationError): InvokeAIAppConfig(generation_devices=["gpu0"]) + + +def test_auto_copy_documents_legacy_device_precedence(): + """`generation_devices: auto` resolves to the single pinned legacy `device` when one is set + (see TorchDevice.get_generation_devices), so every user-facing description of `auto` must + disclose that exception instead of promising "every available GPU" unconditionally. Checks the + schema description (source of the API docs and generated settings docs), the generated docs + settings.json, the Settings UI copy, and the configuration guide's behavior table.""" + import json + from pathlib import Path + + repo_root = Path(__file__).parents[4] + + field_description = InvokeAIAppConfig.model_fields["generation_devices"].description + assert field_description is not None + assert "legacy `device`" in field_description + + generated_settings = json.loads((repo_root / "docs/src/generated/settings.json").read_text()) + generated_description = next( + s["description"] for s in generated_settings["settings"] if s["name"] == "generation_devices" + ) + assert "legacy `device`" in generated_description + + locales = json.loads((repo_root / "invokeai/frontend/web/public/locales/en.json").read_text(encoding="utf-8")) + assert locales["settings"]["generationDevicesAuto"] == "Auto" # not "Auto (all GPUs)" + assert "'device'" in locales["settings"]["generationDevicesHelp"] + + guide = (repo_root / "docs/src/content/docs/configuration/invokeai-yaml.mdx").read_text(encoding="utf-8") + auto_row = next(line for line in guide.splitlines() if line.startswith("| `auto`")) + assert "legacy `device`" in auto_row