feat(z-image): add metadata recall for VAE and Qwen3 encoder

Add support for saving and recalling Z-Image component models (VAE and
Qwen3 Encoder) in image metadata.

Backend:
- Add qwen3_encoder field to CoreMetadataInvocation (version 2.1.0)

Frontend:
- Add vae and qwen3_encoder to Z-Image graph metadata
- Add Qwen3EncoderModel metadata handler for recall
- Add ZImageVAEModel metadata handler (uses zImageVaeModelSelected
  instead of vaeSelected to set Z-Image-specific VAE state)
- Add qwen3Encoder translation key

This enables "Recall Parameters" / "Remix Image" to restore the VAE
and Qwen3 Encoder settings used for Z-Image generations.
This commit is contained in:
Alexander Eichhorn 2025-12-09 07:12:36 +01:00
parent e9d52734d1
commit 841372944f
4 changed files with 57 additions and 1 deletions

View File

@ -170,7 +170,7 @@ GENERATION_MODES = Literal[
title="Core Metadata",
tags=["metadata"],
category="metadata",
version="2.0.0",
version="2.1.0",
classification=Classification.Internal,
)
class CoreMetadataInvocation(BaseInvocation):
@ -221,6 +221,10 @@ class CoreMetadataInvocation(BaseInvocation):
default=None,
description="The VAE used for decoding, if the main model's default was not used",
)
qwen3_encoder: Optional[ModelIdentifierField] = InputField(
default=None,
description="The Qwen3 text encoder model used for Z-Image inference",
)
# High resolution fix metadata.
hrf_enabled: Optional[bool] = InputField(

View File

@ -839,6 +839,7 @@
"parameterSet": "Parameter {{parameter}} set",
"parsingFailed": "Parsing Failed",
"positivePrompt": "Positive Prompt",
"qwen3Encoder": "Qwen3 Encoder",
"recallParameters": "Recall Parameters",
"recallParameter": "Recall {{label}}",
"scheduler": "Scheduler",

View File

@ -31,6 +31,8 @@ import {
setSteps,
vaeSelected,
widthChanged,
zImageQwen3EncoderModelSelected,
zImageVaeModelSelected,
} from 'features/controlLayers/store/paramsSlice';
import { refImagesRecalled } from 'features/controlLayers/store/refImagesSlice';
import type { CanvasMetadata, LoRA, RefImageState } from 'features/controlLayers/store/types';
@ -694,6 +696,51 @@ const VAEModel: SingleMetadataHandler<ParameterVAEModel> = {
};
//#endregion VAEModel
//#region Qwen3EncoderModel
const Qwen3EncoderModel: SingleMetadataHandler<ModelIdentifierField> = {
[SingleMetadataKey]: true,
type: 'Qwen3EncoderModel',
parse: async (metadata, store) => {
const raw = getProperty(metadata, 'qwen3_encoder');
const parsed = await parseModelIdentifier(raw, store, 'qwen3_encoder');
assert(parsed.type === 'qwen3_encoder');
return Promise.resolve(parsed);
},
recall: (value, store) => {
store.dispatch(zImageQwen3EncoderModelSelected(value));
},
i18nKey: 'metadata.qwen3Encoder',
LabelComponent: MetadataLabel,
ValueComponent: ({ value }: SingleMetadataValueProps<ModelIdentifierField>) => (
<MetadataPrimitiveValue value={`${value.name} (${value.base.toUpperCase()})`} />
),
};
//#endregion Qwen3EncoderModel
//#region ZImageVAEModel
const ZImageVAEModel: SingleMetadataHandler<ModelIdentifierField> = {
[SingleMetadataKey]: true,
type: 'ZImageVAEModel',
parse: async (metadata, store) => {
const raw = getProperty(metadata, 'vae');
const parsed = await parseModelIdentifier(raw, store, 'vae');
assert(parsed.type === 'vae');
// Only recall if the current main model is Z-Image
const base = selectBase(store.getState());
assert(base === 'z-image', 'ZImageVAEModel handler only works with Z-Image models');
return Promise.resolve(parsed);
},
recall: (value, store) => {
store.dispatch(zImageVaeModelSelected(value));
},
i18nKey: 'metadata.vae',
LabelComponent: MetadataLabel,
ValueComponent: ({ value }: SingleMetadataValueProps<ModelIdentifierField>) => (
<MetadataPrimitiveValue value={`${value.name} (${value.base.toUpperCase()})`} />
),
};
//#endregion ZImageVAEModel
//#region LoRAs
const LoRAs: CollectionMetadataHandler<LoRA[]> = {
[CollectionMetadataKey]: true,
@ -928,6 +975,8 @@ export const ImageMetadataHandlers = {
RefinerDenoisingStart,
MainModel,
VAEModel,
Qwen3EncoderModel,
ZImageVAEModel,
LoRAs,
CanvasLayers,
RefImages,

View File

@ -123,6 +123,8 @@ export const buildZImageGraph = async (arg: GraphBuilderArg): Promise<GraphBuild
negative_prompt: prompts.negative,
model: Graph.getModelMetadataField(modelConfig),
steps,
vae: zImageVaeModel ?? undefined,
qwen3_encoder: zImageQwen3EncoderModel ?? undefined,
});
g.addEdgeToMetadata(seed, 'value', 'seed');
g.addEdgeToMetadata(positivePrompt, 'value', 'positive_prompt');