update flux kontext implementation to include flux kontext dev non-api models

This commit is contained in:
Mary Hipp
2025-07-02 16:03:08 -04:00
committed by psychedelicious
parent e7ce08cffa
commit 605cc7369d
6 changed files with 45 additions and 10 deletions

View File

@@ -88,7 +88,7 @@ export const getDefaultRefImageConfig = (
return config;
}
if (base === 'flux-kontext') {
if (base === 'flux-kontext' || (base === 'flux' && mainModelConfig?.name?.toLowerCase().includes('kontext'))) {
const config = deepClone(initialFluxKontextReferenceImage);
config.model = zModelIdentifierField.parse(mainModelConfig);
return config;

View File

@@ -275,7 +275,12 @@ export const selectIsSD3 = createParamsSelector((params) => params.model?.base =
export const selectIsCogView4 = createParamsSelector((params) => params.model?.base === 'cogview4');
export const selectIsImagen3 = createParamsSelector((params) => params.model?.base === 'imagen3');
export const selectIsImagen4 = createParamsSelector((params) => params.model?.base === 'imagen4');
export const selectIsFluxKontext = createParamsSelector((params) => params.model?.base === 'flux-kontext');
export const selectIsFluxKontextApi = createParamsSelector((params) => params.model?.base === 'flux-kontext');
export const selectIsFluxKontext = createParamsSelector(
(params) =>
params.model?.base === 'flux-kontext' ||
(params.model?.base === 'flux' && params.model?.name?.toLowerCase().includes('kontext'))
);
export const selectIsChatGPT4o = createParamsSelector((params) => params.model?.base === 'chatgpt-4o');
export const selectModel = createParamsSelector((params) => params.model);
@@ -311,8 +316,8 @@ export const selectNegativePrompt = createParamsSelector((params) => params.nega
export const selectNegativePromptWithFallback = createParamsSelector((params) => params.negativePrompt ?? '');
export const selectHasNegativePrompt = createParamsSelector((params) => params.negativePrompt !== null);
export const selectModelSupportsNegativePrompt = createSelector(
[selectIsFLUX, selectIsChatGPT4o],
(isFLUX, isChatGPT4o) => !isFLUX && !isChatGPT4o
[selectIsFLUX, selectIsChatGPT4o, selectIsFluxKontext],
(isFLUX, isChatGPT4o, isFluxKontext) => !isFLUX && !isChatGPT4o && !isFluxKontext
);
export const selectPositivePrompt2 = createParamsSelector((params) => params.positivePrompt2);
export const selectNegativePrompt2 = createParamsSelector((params) => params.negativePrompt2);

View File

@@ -121,7 +121,10 @@ export const refImagesSlice = createSlice({
return;
}
if (entity.config.model.base === 'flux-kontext') {
if (
entity.config.model.base === 'flux-kontext' ||
(entity.config.model.base === 'flux' && entity.config.model.name?.toLowerCase().includes('kontext'))
) {
// Switching to flux-kontext ref image
entity.config = {
...initialFluxKontextReferenceImage,

View File

@@ -87,6 +87,15 @@ export const buildFLUXGraph = async (arg: GraphBuilderArg): Promise<GraphBuilder
guidance = 30;
}
const isFluxKontextDev = model.name.includes('kontext');
if (isFluxKontextDev) {
if (generationMode !== 'txt2img') {
throw new UnsupportedGenerationModeError(t('toast.imagenIncompatibleGenerationMode', { model: 'FLUX Kontext' }));
}
guidance = 30;
}
const { positivePrompt } = selectPresetModifiedPrompts(state);
const g = new Graph(getPrefixedId('flux_graph'));
@@ -108,6 +117,7 @@ export const buildFLUXGraph = async (arg: GraphBuilderArg): Promise<GraphBuilder
type: 'collect',
id: getPrefixedId('pos_cond_collect'),
});
const denoise = g.addNode({
type: 'flux_denoise',
id: getPrefixedId('flux_denoise'),
@@ -125,6 +135,17 @@ export const buildFLUXGraph = async (arg: GraphBuilderArg): Promise<GraphBuilder
id: getPrefixedId('flux_vae_decode'),
});
if (isFluxKontextDev) {
const kontextConditioning = g.addNode({
type: 'flux_kontext',
id: getPrefixedId('flux_kontext'),
image: {
image_name: refImages.entities[0]?.config.image?.image_name ?? '',
},
});
g.addEdge(kontextConditioning, 'kontext_cond', denoise, 'kontext_conditioning');
}
g.addEdge(modelLoader, 'transformer', denoise, 'transformer');
g.addEdge(modelLoader, 'vae', denoise, 'controlnet_vae');
g.addEdge(modelLoader, 'vae', l2i, 'vae');

View File

@@ -1,7 +1,7 @@
import { useAppSelector } from 'app/store/storeHooks';
import {
selectIsChatGPT4o,
selectIsFluxKontext,
selectIsFluxKontextApi,
selectIsImagen3,
selectIsImagen4,
} from 'features/controlLayers/store/paramsSlice';
@@ -9,8 +9,8 @@ import {
export const useIsApiModel = () => {
const isImagen3 = useAppSelector(selectIsImagen3);
const isImagen4 = useAppSelector(selectIsImagen4);
const isFluxKontext = useAppSelector(selectIsFluxKontext);
const isFluxKontextApi = useAppSelector(selectIsFluxKontextApi);
const isChatGPT4o = useAppSelector(selectIsChatGPT4o);
return isImagen3 || isImagen4 || isChatGPT4o || isFluxKontext;
return isImagen3 || isImagen4 || isChatGPT4o || isFluxKontextApi;
};

View File

@@ -280,7 +280,10 @@ const getReasonsWhyCannotEnqueueGenerateTab = (arg: {
// Flux Kontext only supports 1x Reference Image at a time.
const referenceImageCount = refImages.entities.length;
if (model?.base === 'flux-kontext' && referenceImageCount > 1) {
if (
(model?.base === 'flux-kontext' || (model?.base === 'flux' && model?.name?.toLowerCase().includes('kontext'))) &&
referenceImageCount > 1
) {
reasons.push({ content: i18n.t('parameters.invoke.fluxKontextMultipleReferenceImages') });
}
@@ -634,7 +637,10 @@ const getReasonsWhyCannotEnqueueCanvasTab = (arg: {
// Flux Kontext only supports 1x Reference Image at a time.
const referenceImageCount = refImages.entities.filter((entity) => entity.isEnabled).length;
if (model?.base === 'flux-kontext' && referenceImageCount > 1) {
if (
(model?.base === 'flux-kontext' || (model?.base === 'flux' && model?.name?.toLowerCase().includes('kontext'))) &&
referenceImageCount > 1
) {
reasons.push({ content: i18n.t('parameters.invoke.fluxKontextMultipleReferenceImages') });
}