Diffusion pipeline runtime matching
The diffusionPipeline field on a runtime's supportedModelFormats limits auto-selection to the diffusers pipelines and components it can serve.
Set diffusionPipeline on an entry in a serving runtime's supportedModelFormats to limit the entry to the diffusion pipelines the runtime can serve. OME compares it with the pipeline recorded on the BaseModel or ClusterBaseModel, and the entry matches only models that pass. The entry's modelArchitecture already checks the pipeline class, and diffusionPipeline can also require components, such as a transformer from the diffusers library. The check is pass or fail: it decides which runtimes OME can pick, and adds nothing to their score. The catalog's diffusion runtimes, srt-qwen-image and srt-qwen-image-edit, leave it unset and match on the class through modelArchitecture.
The matching rule¶
An entry's diffusionPipeline has the same fields as the model's: className, the components scheduler, textEncoder, tokenizer, transformer and vae, and additionalComponents, keyed by the component's name in model_index.json. Each component has a library and a type. Every field is optional, so set only what the runtime depends on. Each field you set adds a requirement:
| The entry sets | The check fails when the model has |
|---|---|
diffusionPipeline, even an empty one ({}) |
No diffusionPipeline. |
className |
A different class, or none. |
scheduler, textEncoder, tokenizer, transformer or vae, even an empty one |
No such component. |
library in a component |
A different library in that component, or none. |
type in a component |
A different type in that component, or none. |
A key in additionalComponents |
No component under that key, or one whose library or type differs from what the key sets. |
Values are compared as exact, case-sensitive strings. An entry without diffusionPipeline passes for every model. DiffusionPipelineSpec in the API reference describes each field.
Declare a pipeline in a runtime¶
The rest of the entry must match the model too:
- Set
modelArchitectureto the pipeline class. OME records the class as the model's architecture, and an entry needs an architecture when the model has one. - Set
modelFormatandmodelFrameworktodiffusers, each with the model's diffusers version. A dev or pre-release version, such as0.34.0.dev0, matches only the same version, whatever the entry'soperator. See Model version matching.
This ClusterServingRuntime serves QwenImagePipeline models at diffusers version 0.34.0.dev0 whose transformer comes from the diffusers library:
apiVersion: ome.io/v1beta1
kind: ClusterServingRuntime
metadata:
name: srt-qwen-image-pipeline
spec:
supportedModelFormats:
- modelFormat:
name: diffusers
version: "0.34.0.dev0"
modelFramework:
name: diffusers
version: "0.34.0.dev0"
modelArchitecture: QwenImagePipeline
diffusionPipeline:
className: QwenImagePipeline
transformer:
library: diffusers
autoSelect: true
priority: 2
engineConfig:
runner:
name: ome-container
image: sglang:0.5.6-diffusion-cuda129-amd64
ports:
- containerPort: 8080
name: http1
protocol: TCP
command:
- sglang
- serve
- --host
- "0.0.0.0"
- --port
- "8080"
- --model-path
- $(MODEL_PATH)
- --served-model-name
- Qwen/Qwen-Image
resources:
requests:
cpu: "32"
memory: 100Gi
nvidia.com/gpu: 1
limits:
cpu: "32"
memory: 100Gi
nvidia.com/gpu: 1kubectl apply -f runtime.yamlclusterservingruntime.ome.io/srt-qwen-image-pipeline createdpriority: 2 makes OME prefer this runtime to srt-qwen-image when both match a model. See Runtime selection scoring. A runtime that serves several pipelines has an entry for each, as srt-qwen-image-edit does for QwenImageEditPlusPipeline and QwenImageEditPipeline.
Adding diffusionPipeline to a runtime that OME already picks for pvc:// models stops it from matching them, because they have no recorded pipeline. Set spec.diffusionPipeline on those models first.
What OME records for the model¶
When the model agent downloads a diffusion model, it reads model_index.json instead of config.json, and OME fills in these fields:
| Field | What OME records |
|---|---|
diffusionPipeline |
The pipeline class and its components, from model_index.json. |
modelArchitecture |
The pipeline class, such as QwenImagePipeline. |
modelFormat |
diffusers, with the version from _diffusers_version. |
modelFramework |
diffusers, with the same version. |
OME fills in only empty fields, so a diffusionPipeline that you set stays as written, even one that lists only some components.
The keys of model_index.json become these diffusionPipeline fields:
model_index.json key |
diffusionPipeline field |
|---|---|
_class_name |
className |
text_encoder |
textEncoder |
transformer or unet |
transformer |
scheduler, tokenizer and vae |
The same name |
| Any other key whose value is a component | additionalComponents, under the same key |
A component's value lists its library and then its type, as in ["diffusers", "AutoencoderKL"]. For example, OME reads this model_index.json:
{
"_class_name": "StableDiffusionPipeline",
"_diffusers_version": "0.24.0",
"scheduler": ["diffusers", "EulerDiscreteScheduler"],
"text_encoder": ["transformers", "CLIPTextModel"],
"tokenizer": ["transformers", "CLIPTokenizer"],
"unet": ["diffusers", "UNet2DConditionModel"],
"vae": ["diffusers", "AutoencoderKL"],
"safety_checker": ["diffusers", "StableDiffusionSafetyChecker"]
}and records this pipeline:
diffusionPipeline:
className: StableDiffusionPipeline
scheduler:
library: diffusers
type: EulerDiscreteScheduler
textEncoder:
library: transformers
type: CLIPTextModel
tokenizer:
library: transformers
type: CLIPTokenizer
transformer:
library: diffusers
type: UNet2DConditionModel
vae:
library: diffusers
type: AutoencoderKL
additionalComponents:
safety_checker:
library: diffusers
type: StableDiffusionSafetyCheckerunet becomes transformer, and safety_checker, which has no field of its own, goes under additionalComponents.
Models without a recorded pipeline¶
OME records no pipeline for a pvc:// model: its metadata Job fills in the architecture, format and framework, but not diffusionPipeline. Other models get none of these fields if they're vendor:// models, if the agent can't read their files, or if they have the annotation ome.oracle.com/skip-config-parsing: "true", so set them yourself.
To check a model, print its architecture and pipeline. For qwen-image-pvc, a ClusterBaseModel served from a PVC at diffusers version 0.34.0.dev0, the pipeline is empty:
kubectl get clusterbasemodel qwen-image-pvc \
-o 'custom-columns=ARCHITECTURE:.spec.modelArchitecture,PIPELINE:.spec.diffusionPipeline'ARCHITECTURE PIPELINE
QwenImagePipeline <none>For a BaseModel, use basemodel and add -n with its namespace.
To match an entry that sets diffusionPipeline, set one on the model yourself, with at least the fields that the entry requires. This patch makes qwen-image-pvc match srt-qwen-image-pipeline:
kubectl patch clusterbasemodel qwen-image-pvc --type merge \
-p '{"spec":{"diffusionPipeline":{"className":"QwenImagePipeline","transformer":{"library":"diffusers"}}}}'clusterbasemodel.ome.io/qwen-image-pvc patchedOME doesn't check InferenceServices again when a model changes. Apply a rejected InferenceService again, or change an existing one, as Step 5: Verify recovery shows.
Where a rejection shows up¶
An entry that fails the pipeline check, or sets no modelArchitecture, gets one of these reasons. The pipeline check names only its first mismatch, so fix it and check again.
| Reason | Cause |
|---|---|
diffusion pipeline required by runtime but not specified in model |
The model has no pipeline. See Models without a recorded pipeline. |
pipeline class mismatch (model=QwenImageEditPipeline, runtime=QwenImagePipeline) |
The classes differ, or the model's pipeline has none (model=<nil>). |
component transformer required by runtime but not specified in model |
The model's pipeline has no such component. |
transformer library mismatch (model=transformers, runtime=diffusers) |
The libraries differ, or the model's component has none (an empty model=). |
scheduler type mismatch (model=EulerDiscreteScheduler, runtime=FlowMatchEulerDiscreteScheduler) |
The types differ, or the model's component has none. |
diffusion pipeline missing required additional components |
The entry sets additionalComponents, and the model has none. |
diffusion component safety_checker missing in model |
The model's additionalComponents has no such key. |
model has architecture QwenImagePipeline but runtime has no architecture requirement |
The entry doesn't set modelArchitecture. Set it to the pipeline class. |
When no runtime matches qwen-image-pvc, OME lists the example runtime among the runtimes it excluded:
srt-qwen-image-pipeline (model format 'mt:diffusers:0.34.0.dev0:QwenImagePipeline:diffusers:0.34.0.dev0' not in supported formats: diffusion pipeline required by runtime but not specified in model)| When | What you see |
|---|---|
| Another runtime matches | OME picks from the runtimes that match, with no event. Since v1.3, kubectl ome runtime explain --model shows this one as No, with the reason. |
| No runtime matches | The webhook rejects the InferenceService if it has an engine section and no runner image of its own. After admission, OME sets RuntimeReady to False and records a Warning event, both with reason RuntimeNotFound (since v1.3). Running pods keep serving. See Troubleshoot runtime selection. |
| The InferenceService names the runtime | OME uses it anyway. Since v1.3, the webhook warns does not declare support for model when the InferenceService has an engine. OME records a RuntimeCompatibilityAdvisory Warning event, unless spec.runtime.autoSync is false. See Reference a runtime explicitly. |
Related pages¶
- Troubleshoot runtime selection: find out why OME can't choose a runtime for a model.
- Serving runtimes: how a runtime declares the models it supports.
- Runtime selection scoring: how OME ranks the runtimes that match.
- Model version matching: how OME compares format and framework versions.
- Reference a runtime explicitly: name a runtime on an InferenceService instead of letting OME choose one.
kubectl ome runtime: see why a runtime was skipped.