Compare commits

...

2 Commits

Author SHA1 Message Date
localai-org-maint-bot
ef9d1f9012 fix(config): register original diffusers config field
Expose original_config_file through the model configuration metadata registry so registry completeness checks and generated configuration surfaces stay in sync.

Assisted-by: Codex:gpt-5 [systematic-debugging]
2026-07-31 19:08:55 +00:00
localai-org-maint-bot
cc3472be36 fix(diffusers): forward original config for single files
Assisted-by: Codex:gpt-5
2026-07-31 12:03:08 +00:00
10 changed files with 86 additions and 10 deletions

View File

@@ -498,6 +498,7 @@ message ModelOptions {
// applied verbatim to the backend's engine constructor (e.g. vLLM AsyncEngineArgs).
// Unknown keys produce an error at LoadModel time.
string EngineArgs = 73;
string OriginalConfigFile = 76;
// Proxy carries the cloud-proxy backend's per-model configuration.
// Empty for non-proxy backends.

View File

@@ -35,6 +35,7 @@ from diffusers_dynamic_loader import (
get_available_pipelines,
load_diffusers_pipeline,
)
from load_options import single_file_load_kwargs
# Import specific items still needed for special cases and safety checker
from diffusers import DiffusionPipeline, ControlNetModel
@@ -464,6 +465,9 @@ class BackendServicer(backend_pb2_grpc.BackendServicer):
# Build kwargs for dynamic loading
load_kwargs = {"torch_dtype": torchType}
load_kwargs.update(
single_file_load_kwargs(request.OriginalConfigFile, from_single_file)
)
# Add variant if not loading from single file
if not from_single_file and variant:

View File

@@ -0,0 +1,7 @@
# SPDX-License-Identifier: MIT
def single_file_load_kwargs(original_config_file: str, from_single_file: bool) -> dict:
if from_single_file and original_config_file:
return {"original_config_file": original_config_file}
return {}

View File

@@ -0,0 +1,26 @@
# SPDX-License-Identifier: MIT
import unittest
from backend.python.diffusers.load_options import single_file_load_kwargs
class SingleFileLoadKwargsTest(unittest.TestCase):
def test_includes_original_config_for_single_file(self):
self.assertEqual(
single_file_load_kwargs("configs/v1-inference.yaml", True),
{"original_config_file": "configs/v1-inference.yaml"},
)
def test_omits_original_config_for_pretrained_model(self):
self.assertEqual(
single_file_load_kwargs("configs/v1-inference.yaml", False),
{},
)
def test_omits_empty_original_config(self):
self.assertEqual(single_file_load_kwargs("", True), {})
if __name__ == "__main__":
unittest.main()

View File

@@ -425,6 +425,7 @@ func grpcModelOpts(c config.ModelConfig, modelPath string) *pb.ModelOptions {
EnableScore: c.HasUsecases(config.FLAG_SCORE),
CLIPSkip: int32(c.Diffusers.ClipSkip),
ControlNet: c.Diffusers.ControlNet,
OriginalConfigFile: c.Diffusers.OriginalConfigFile,
ContextSize: int32(ctxSize),
Seed: getSeed(c),
NBatch: int32(b),

View File

@@ -44,6 +44,21 @@ var _ = Describe("grpcModelOpts EngineArgs", func() {
})
})
var _ = Describe("grpcModelOpts Diffusers options", func() {
It("forwards original_config_file without rewriting it", func() {
threads := 1
cfg := config.ModelConfig{
Threads: &threads,
Diffusers: config.Diffusers{
OriginalConfigFile: "configs/v1-inference.yaml",
},
}
opts := grpcModelOpts(cfg, "/tmp/models")
Expect(opts.OriginalConfigFile).To(Equal("configs/v1-inference.yaml"))
})
})
// Guards the DisableReasoning -> enable_thinking metadata conversion that the
// per-request reasoning_effort feature (issue #10072) relies on: the request
// merge sets ReasoningConfig.DisableReasoning, and gRPCPredictOpts is where it

View File

@@ -793,11 +793,19 @@ func DefaultRegistry() map[string]FieldMetaOverride {
Options: DiffusersSchedulerOptions,
Order: 81,
},
"diffusers.original_config_file": {
Section: "diffusers",
Label: "Original Config File",
Description: "Original model configuration file used when loading a single-file checkpoint",
Component: "input",
Advanced: true,
Order: 82,
},
"diffusers.cuda": {
Section: "diffusers",
Label: "CUDA",
Description: "Enable CUDA for diffusers",
Order: 82,
Order: 83,
},
// --- PII filtering (per-model) ---

View File

@@ -1104,15 +1104,16 @@ type GRPC struct {
// @Description Diffusers configuration
type Diffusers struct {
CUDA bool `yaml:"cuda,omitempty" json:"cuda,omitempty"`
PipelineType string `yaml:"pipeline_type,omitempty" json:"pipeline_type,omitempty"`
SchedulerType string `yaml:"scheduler_type,omitempty" json:"scheduler_type,omitempty"`
EnableParameters string `yaml:"enable_parameters,omitempty" json:"enable_parameters,omitempty"` // A list of comma separated parameters to specify
IMG2IMG bool `yaml:"img2img,omitempty" json:"img2img,omitempty"` // Image to Image Diffuser
ClipSkip int `yaml:"clip_skip,omitempty" json:"clip_skip,omitempty"` // Skip every N frames
ClipModel string `yaml:"clip_model,omitempty" json:"clip_model,omitempty"` // Clip model to use
ClipSubFolder string `yaml:"clip_subfolder,omitempty" json:"clip_subfolder,omitempty"` // Subfolder to use for clip model
ControlNet string `yaml:"control_net,omitempty" json:"control_net,omitempty"`
CUDA bool `yaml:"cuda,omitempty" json:"cuda,omitempty"`
PipelineType string `yaml:"pipeline_type,omitempty" json:"pipeline_type,omitempty"`
SchedulerType string `yaml:"scheduler_type,omitempty" json:"scheduler_type,omitempty"`
OriginalConfigFile string `yaml:"original_config_file,omitempty" json:"original_config_file,omitempty"`
EnableParameters string `yaml:"enable_parameters,omitempty" json:"enable_parameters,omitempty"` // A list of comma separated parameters to specify
IMG2IMG bool `yaml:"img2img,omitempty" json:"img2img,omitempty"` // Image to Image Diffuser
ClipSkip int `yaml:"clip_skip,omitempty" json:"clip_skip,omitempty"` // Skip every N frames
ClipModel string `yaml:"clip_model,omitempty" json:"clip_model,omitempty"` // Clip model to use
ClipSubFolder string `yaml:"clip_subfolder,omitempty" json:"clip_subfolder,omitempty"` // Subfolder to use for clip model
ControlNet string `yaml:"control_net,omitempty" json:"control_net,omitempty"`
}
// @Description LLMConfig is a struct that holds the configuration that are generic for most of the LLM backends.

View File

@@ -715,6 +715,7 @@ For image generation models using the `diffusers` backend:
| `diffusers.cuda` | bool | Enable CUDA for diffusers |
| `diffusers.pipeline_type` | string | Pipeline type (e.g., `stable-diffusion`, `stable-diffusion-xl`) |
| `diffusers.scheduler_type` | string | Scheduler type (e.g., `euler`, `ddpm`) |
| `diffusers.original_config_file` | string | Local path or URL to the original configuration for loading a single-file checkpoint |
| `diffusers.enable_parameters` | string | Comma-separated parameters to enable |
| `diffusers.cfg_scale` | float32 | Classifier-free guidance scale |
| `diffusers.img2img` | bool | Enable image-to-image transformation |

View File

@@ -224,6 +224,18 @@ diffusers:
cfg_scale: 8
```
For an offline single-file checkpoint that needs its original Diffusers configuration, keep both files in the mounted models directory:
```yaml
name: offline-stable-diffusion
parameters:
model: model.safetensors
backend: diffusers
diffusers:
pipeline_type: StableDiffusionPipeline
original_config_file: /models/v1-inference.yaml
```
#### Configuration parameters
The following parameters are available in the configuration file: