Move Concept and Consistency into the Image v2 LoRA chain.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+65
-98
@@ -833,41 +833,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-3">
|
<div class="grid grid-cols-2 gap-3">
|
||||||
<template v-if="v2ConceptLoraEnabled">
|
|
||||||
<label class="block text-sm">
|
|
||||||
<span class="mb-1 block text-zinc-400">Concept LoRA — Model</span>
|
|
||||||
<input
|
|
||||||
v-model.number="v2SnofsModel"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
max="2"
|
|
||||||
step="0.05"
|
|
||||||
:disabled="v2Engine === 'krea' && !kreaConceptConfigured"
|
|
||||||
class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
<label class="block text-sm">
|
|
||||||
<span class="mb-1 block text-zinc-400">Concept LoRA — CLIP</span>
|
|
||||||
<input
|
|
||||||
v-model.number="v2SnofsClip"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
max="2"
|
|
||||||
step="0.05"
|
|
||||||
:disabled="v2Engine === 'krea' && !kreaConceptConfigured"
|
|
||||||
class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
<p v-if="v2Engine === 'krea' && !kreaConceptConfigured" class="col-span-2 text-xs text-zinc-500">No Krea concept LoRA is configured.</p>
|
|
||||||
</template>
|
|
||||||
<label v-if="v2Mode !== 'generate' && v2Engine !== 'krea'" class="block text-sm">
|
|
||||||
<span class="mb-1 block text-zinc-400">Consistency — Model</span>
|
|
||||||
<input v-model.number="v2ConsistencyModel" type="number" min="0" max="2" step="0.05" class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2">
|
|
||||||
</label>
|
|
||||||
<label v-if="v2Mode !== 'generate' && v2Engine !== 'krea'" class="block text-sm">
|
|
||||||
<span class="mb-1 block text-zinc-400">Consistency — CLIP</span>
|
|
||||||
<input v-model.number="v2ConsistencyClip" type="number" min="0" max="2" step="0.05" class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2">
|
|
||||||
</label>
|
|
||||||
<label class="block text-sm">
|
<label class="block text-sm">
|
||||||
<span class="mb-1 block text-zinc-400">Steps</span>
|
<span class="mb-1 block text-zinc-400">Steps</span>
|
||||||
<input v-model.number="v2Steps" type="number" :min="IMAGE_STEPS_MIN" :max="IMAGE_STEPS_MAX" step="1" :disabled="v2Turbo" class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2 disabled:opacity-50">
|
<input v-model.number="v2Steps" type="number" :min="IMAGE_STEPS_MIN" :max="IMAGE_STEPS_MAX" step="1" :disabled="v2Turbo" class="w-full rounded-xl border border-white/10 bg-zinc-950 px-3 py-2 text-sm outline-none ring-amber-300/40 focus:ring-2 disabled:opacity-50">
|
||||||
@@ -2032,8 +1997,7 @@ import {
|
|||||||
} from '~/utils/libraryGeneration'
|
} from '~/utils/libraryGeneration'
|
||||||
import {
|
import {
|
||||||
IMAGE_V2_CFG_DEFAULT,
|
IMAGE_V2_CFG_DEFAULT,
|
||||||
IMAGE_V2_CONSISTENCY_CLIP,
|
IMAGE_V2_CONSISTENCY_LORA,
|
||||||
IMAGE_V2_CONSISTENCY_MODEL,
|
|
||||||
IMAGE_V2_DENOISE_DEFAULT,
|
IMAGE_V2_DENOISE_DEFAULT,
|
||||||
IMAGE_V2_DENOISE_MAX,
|
IMAGE_V2_DENOISE_MAX,
|
||||||
IMAGE_V2_DENOISE_MIN,
|
IMAGE_V2_DENOISE_MIN,
|
||||||
@@ -2050,13 +2014,16 @@ import {
|
|||||||
IMAGE_V2_REFINE_FACE_PROMPT,
|
IMAGE_V2_REFINE_FACE_PROMPT,
|
||||||
IMAGE_V2_REFINE_HAND,
|
IMAGE_V2_REFINE_HAND,
|
||||||
IMAGE_V2_REFINE_HEAVY,
|
IMAGE_V2_REFINE_HEAVY,
|
||||||
IMAGE_V2_SNOFS_CLIP,
|
IMAGE_V2_SNOFS_LORA,
|
||||||
IMAGE_V2_SNOFS_MODEL,
|
|
||||||
IMAGE_V2_STEPS_DEFAULT,
|
IMAGE_V2_STEPS_DEFAULT,
|
||||||
clampImageV2Denoise,
|
clampImageV2Denoise,
|
||||||
clampImageV2Size,
|
clampImageV2Size,
|
||||||
clampImageV2Strength,
|
defaultImageV2LoraStack,
|
||||||
|
isImageV2ConceptLora,
|
||||||
|
isImageV2ConsistencyLora,
|
||||||
|
mergeLegacyImageV2Loras,
|
||||||
parseImageV2Engine,
|
parseImageV2Engine,
|
||||||
|
upsertImageV2Lora,
|
||||||
type ImageV2Engine,
|
type ImageV2Engine,
|
||||||
type ImageV2GenerateAspect,
|
type ImageV2GenerateAspect,
|
||||||
type ImageV2Mode,
|
type ImageV2Mode,
|
||||||
@@ -2340,12 +2307,7 @@ const editRefPreview = ref('')
|
|||||||
const v2Mode = ref<ImageV2Mode>('edit')
|
const v2Mode = ref<ImageV2Mode>('edit')
|
||||||
const v2Engine = ref<ImageV2Engine>('flux')
|
const v2Engine = ref<ImageV2Engine>('flux')
|
||||||
const v2Task = ref<ImageV2Task>('scene')
|
const v2Task = ref<ImageV2Task>('scene')
|
||||||
const kreaConceptConfigured = computed(() => Boolean(String(runtimeConfig.public.kreaConceptLora || IMAGE_V2_KREA_CONCEPT_LORA || '').trim()))
|
|
||||||
const v2Negative = ref('')
|
const v2Negative = ref('')
|
||||||
const v2SnofsModel = ref(isXaigenStudio(runtimeConfig.public) ? IMAGE_V2_SNOFS_MODEL : 0)
|
|
||||||
const v2SnofsClip = ref(isXaigenStudio(runtimeConfig.public) ? IMAGE_V2_SNOFS_CLIP : 0)
|
|
||||||
const v2ConsistencyModel = ref(IMAGE_V2_CONSISTENCY_MODEL)
|
|
||||||
const v2ConsistencyClip = ref(IMAGE_V2_CONSISTENCY_CLIP)
|
|
||||||
const v2Steps = ref(IMAGE_V2_STEPS_DEFAULT)
|
const v2Steps = ref(IMAGE_V2_STEPS_DEFAULT)
|
||||||
const v2Cfg = ref(IMAGE_V2_CFG_DEFAULT)
|
const v2Cfg = ref(IMAGE_V2_CFG_DEFAULT)
|
||||||
const v2Megapixels = ref(1)
|
const v2Megapixels = ref(1)
|
||||||
@@ -2401,6 +2363,23 @@ const v2ConceptLoraEnabled = computed(() => isXaigenStudio({
|
|||||||
studio: runtimeConfig.public.studio,
|
studio: runtimeConfig.public.studio,
|
||||||
instanceName: instanceName.value
|
instanceName: instanceName.value
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
function imageV2EngineLoras(stack?: unknown) {
|
||||||
|
return filterLoraStackForImageEngine(
|
||||||
|
filterLoraStackForStudio(stack ?? imageV2LoraStack.value, ltxEnabled.value),
|
||||||
|
v2Engine.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function seedImageV2LorasIfEmpty() {
|
||||||
|
if (imageV2LoraStack.value.length) return
|
||||||
|
imageV2LoraStack.value = defaultImageV2LoraStack({
|
||||||
|
engine: v2Engine.value,
|
||||||
|
mode: v2Mode.value,
|
||||||
|
xaigen: v2ConceptLoraEnabled.value,
|
||||||
|
kreaConcept: String(runtimeConfig.public.kreaConceptLora || IMAGE_V2_KREA_CONCEPT_LORA || '').trim()
|
||||||
|
})
|
||||||
|
}
|
||||||
const folders = ref<LibraryFolder[]>([])
|
const folders = ref<LibraryFolder[]>([])
|
||||||
const clips = ref<LibraryClip[]>([])
|
const clips = ref<LibraryClip[]>([])
|
||||||
const stills = ref<LibraryStill[]>([])
|
const stills = ref<LibraryStill[]>([])
|
||||||
@@ -3345,6 +3324,7 @@ onMounted(async () => {
|
|||||||
videoLoraStack.value = readStoredLoraStack('aigen-video-lora')
|
videoLoraStack.value = readStoredLoraStack('aigen-video-lora')
|
||||||
imageLoraStack.value = readStoredLoraStack('aigen-image-lora')
|
imageLoraStack.value = readStoredLoraStack('aigen-image-lora')
|
||||||
imageV2LoraStack.value = readStoredLoraStack('aigen-image-v2-lora')
|
imageV2LoraStack.value = readStoredLoraStack('aigen-image-v2-lora')
|
||||||
|
seedImageV2LorasIfEmpty()
|
||||||
globalLocks.value = localStorage.getItem(LOCKS_STORE) || ''
|
globalLocks.value = localStorage.getItem(LOCKS_STORE) || ''
|
||||||
try {
|
try {
|
||||||
const savedRefs = JSON.parse(localStorage.getItem(REFS_STORE) || '')
|
const savedRefs = JSON.parse(localStorage.getItem(REFS_STORE) || '')
|
||||||
@@ -3707,10 +3687,10 @@ function currentPresetSnapshot() {
|
|||||||
engine: v2Engine.value,
|
engine: v2Engine.value,
|
||||||
task: v2Mode.value === 'compose' ? v2Task.value : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'generate' ? 't2i' : 'scene',
|
task: v2Mode.value === 'compose' ? v2Task.value : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'generate' ? 't2i' : 'scene',
|
||||||
negative: v2Negative.value,
|
negative: v2Negative.value,
|
||||||
snofsModel: v2ConceptLoraEnabled.value ? clampImageV2Strength(v2SnofsModel.value, IMAGE_V2_SNOFS_MODEL) : 0,
|
snofsModel: imageV2EngineLoras().find(item => isImageV2ConceptLora(item.name))?.strengthModel ?? 0,
|
||||||
snofsClip: v2ConceptLoraEnabled.value ? clampImageV2Strength(v2SnofsClip.value, IMAGE_V2_SNOFS_CLIP) : 0,
|
snofsClip: imageV2EngineLoras().find(item => isImageV2ConceptLora(item.name))?.strengthClip ?? 0,
|
||||||
consistencyModel: v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(v2ConsistencyModel.value, IMAGE_V2_CONSISTENCY_MODEL),
|
consistencyModel: imageV2EngineLoras().find(item => isImageV2ConsistencyLora(item.name))?.strengthModel ?? 0,
|
||||||
consistencyClip: v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(v2ConsistencyClip.value, IMAGE_V2_CONSISTENCY_CLIP),
|
consistencyClip: imageV2EngineLoras().find(item => isImageV2ConsistencyLora(item.name))?.strengthClip ?? 0,
|
||||||
steps: clampImageSteps(v2Steps.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT),
|
steps: clampImageSteps(v2Steps.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT),
|
||||||
cfg: clampImageCfg(v2Cfg.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT),
|
cfg: clampImageCfg(v2Cfg.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT),
|
||||||
megapixels: v2Mode.value === 'generate' ? undefined : clampImageScaleMegapixels(v2Megapixels.value, 1),
|
megapixels: v2Mode.value === 'generate' ? undefined : clampImageScaleMegapixels(v2Megapixels.value, 1),
|
||||||
@@ -3760,10 +3740,16 @@ function applyGenerationPreset(preset: GenerationPreset) {
|
|||||||
v2Engine.value = parseImageV2Engine(settings.engine, 'flux')
|
v2Engine.value = parseImageV2Engine(settings.engine, 'flux')
|
||||||
v2Task.value = v2Mode.value === 'compose' ? (settings.task || 'scene') : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'generate' ? 't2i' : 'scene'
|
v2Task.value = v2Mode.value === 'compose' ? (settings.task || 'scene') : v2Mode.value === 'refine' ? 'refine' : v2Mode.value === 'generate' ? 't2i' : 'scene'
|
||||||
if (typeof settings.negative === 'string') v2Negative.value = settings.negative
|
if (typeof settings.negative === 'string') v2Negative.value = settings.negative
|
||||||
v2SnofsModel.value = v2ConceptLoraEnabled.value ? clampImageV2Strength(settings.snofsModel, IMAGE_V2_SNOFS_MODEL) : 0
|
imageV2LoraStack.value = mergeLegacyImageV2Loras(filterLoraStackForImageEngine(stack, v2Engine.value), {
|
||||||
v2SnofsClip.value = v2ConceptLoraEnabled.value ? clampImageV2Strength(settings.snofsClip, IMAGE_V2_SNOFS_CLIP) : 0
|
engine: v2Engine.value,
|
||||||
v2ConsistencyModel.value = v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(settings.consistencyModel, IMAGE_V2_CONSISTENCY_MODEL)
|
mode: v2Mode.value,
|
||||||
v2ConsistencyClip.value = v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(settings.consistencyClip, IMAGE_V2_CONSISTENCY_CLIP)
|
xaigen: v2ConceptLoraEnabled.value,
|
||||||
|
snofsModel: settings.snofsModel,
|
||||||
|
snofsClip: settings.snofsClip,
|
||||||
|
consistencyModel: settings.consistencyModel,
|
||||||
|
consistencyClip: settings.consistencyClip,
|
||||||
|
kreaConcept: String(runtimeConfig.public.kreaConceptLora || IMAGE_V2_KREA_CONCEPT_LORA || '').trim()
|
||||||
|
})
|
||||||
v2Steps.value = clampImageSteps(settings.steps, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT)
|
v2Steps.value = clampImageSteps(settings.steps, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT)
|
||||||
v2Cfg.value = clampImageCfg(settings.cfg, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT)
|
v2Cfg.value = clampImageCfg(settings.cfg, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT)
|
||||||
v2Megapixels.value = clampImageScaleMegapixels(settings.megapixels, 1)
|
v2Megapixels.value = clampImageScaleMegapixels(settings.megapixels, 1)
|
||||||
@@ -3774,7 +3760,6 @@ function applyGenerationPreset(preset: GenerationPreset) {
|
|||||||
v2Width.value = size.width
|
v2Width.value = size.width
|
||||||
v2Height.value = size.height
|
v2Height.value = size.height
|
||||||
}
|
}
|
||||||
imageV2LoraStack.value = filterLoraStackForImageEngine(stack, v2Engine.value)
|
|
||||||
void ensureRefineCanvas()
|
void ensureRefineCanvas()
|
||||||
imageV2PresetId.value = preset.id
|
imageV2PresetId.value = preset.id
|
||||||
imageV2PresetName.value = preset.name
|
imageV2PresetName.value = preset.name
|
||||||
@@ -5044,17 +5029,6 @@ function applyStillSettings(still: LibraryStill) {
|
|||||||
v2Engine.value = parseImageV2Engine(settings?.engine, 'flux')
|
v2Engine.value = parseImageV2Engine(settings?.engine, 'flux')
|
||||||
if (!settings) return
|
if (!settings) return
|
||||||
if (typeof settings.negative === 'string') v2Negative.value = settings.negative
|
if (typeof settings.negative === 'string') v2Negative.value = settings.negative
|
||||||
if (v2ConceptLoraEnabled.value) {
|
|
||||||
if (settings.snofsModel != null) v2SnofsModel.value = clampImageV2Strength(settings.snofsModel, IMAGE_V2_SNOFS_MODEL)
|
|
||||||
if (settings.snofsClip != null) v2SnofsClip.value = clampImageV2Strength(settings.snofsClip, IMAGE_V2_SNOFS_CLIP)
|
|
||||||
} else {
|
|
||||||
v2SnofsModel.value = 0
|
|
||||||
v2SnofsClip.value = 0
|
|
||||||
}
|
|
||||||
if (mode !== 'generate' && v2Engine.value !== 'krea') {
|
|
||||||
if (settings.consistencyModel != null) v2ConsistencyModel.value = clampImageV2Strength(settings.consistencyModel, IMAGE_V2_CONSISTENCY_MODEL)
|
|
||||||
if (settings.consistencyClip != null) v2ConsistencyClip.value = clampImageV2Strength(settings.consistencyClip, IMAGE_V2_CONSISTENCY_CLIP)
|
|
||||||
}
|
|
||||||
if (settings.steps != null) v2Steps.value = clampImageSteps(settings.steps, IMAGE_V2_STEPS_DEFAULT)
|
if (settings.steps != null) v2Steps.value = clampImageSteps(settings.steps, IMAGE_V2_STEPS_DEFAULT)
|
||||||
if (settings.cfg != null) v2Cfg.value = clampImageCfg(settings.cfg, IMAGE_V2_CFG_DEFAULT)
|
if (settings.cfg != null) v2Cfg.value = clampImageCfg(settings.cfg, IMAGE_V2_CFG_DEFAULT)
|
||||||
if (settings.megapixels != null) v2Megapixels.value = clampImageScaleMegapixels(settings.megapixels, 1)
|
if (settings.megapixels != null) v2Megapixels.value = clampImageScaleMegapixels(settings.megapixels, 1)
|
||||||
@@ -5067,12 +5041,19 @@ function applyStillSettings(still: LibraryStill) {
|
|||||||
}
|
}
|
||||||
if (mode === 'compose' && settings.task) v2Task.value = settings.task
|
if (mode === 'compose' && settings.task) v2Task.value = settings.task
|
||||||
if (settings.seed != null) seedInput.value = String(Math.round(settings.seed))
|
if (settings.seed != null) seedInput.value = String(Math.round(settings.seed))
|
||||||
if (settings.loraStack?.length || settings.loraName) {
|
imageV2LoraStack.value = mergeLegacyImageV2Loras(
|
||||||
imageV2LoraStack.value = filterLoraStackForImageEngine(
|
settings.loraStack?.length || settings.loraName ? readLoraStack(settings) : imageV2LoraStack.value,
|
||||||
filterLoraStackForStudio(readLoraStack(settings), ltxEnabled.value),
|
{
|
||||||
v2Engine.value
|
engine: v2Engine.value,
|
||||||
)
|
mode,
|
||||||
|
xaigen: v2ConceptLoraEnabled.value,
|
||||||
|
snofsModel: settings.snofsModel,
|
||||||
|
snofsClip: settings.snofsClip,
|
||||||
|
consistencyModel: settings.consistencyModel,
|
||||||
|
consistencyClip: settings.consistencyClip,
|
||||||
|
kreaConcept: String(runtimeConfig.public.kreaConceptLora || IMAGE_V2_KREA_CONCEPT_LORA || '').trim()
|
||||||
}
|
}
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
studioMode.value = 'edit'
|
studioMode.value = 'edit'
|
||||||
@@ -5663,7 +5644,6 @@ async function editImage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setV2Mode(mode: ImageV2Mode) {
|
function setV2Mode(mode: ImageV2Mode) {
|
||||||
const previous = v2Mode.value
|
|
||||||
v2Mode.value = mode
|
v2Mode.value = mode
|
||||||
if (mode === 'edit') v2Task.value = 'scene'
|
if (mode === 'edit') v2Task.value = 'scene'
|
||||||
if (mode === 'refine') {
|
if (mode === 'refine') {
|
||||||
@@ -5672,11 +5652,6 @@ function setV2Mode(mode: ImageV2Mode) {
|
|||||||
}
|
}
|
||||||
if (mode === 'generate') {
|
if (mode === 'generate') {
|
||||||
v2Task.value = 't2i'
|
v2Task.value = 't2i'
|
||||||
v2ConsistencyModel.value = 0
|
|
||||||
v2ConsistencyClip.value = 0
|
|
||||||
} else if (previous === 'generate' && v2Engine.value === 'flux' && v2ConsistencyModel.value === 0 && v2ConsistencyClip.value === 0) {
|
|
||||||
v2ConsistencyModel.value = IMAGE_V2_CONSISTENCY_MODEL
|
|
||||||
v2ConsistencyClip.value = IMAGE_V2_CONSISTENCY_CLIP
|
|
||||||
}
|
}
|
||||||
if (v2Engine.value === 'krea' && mode === 'edit') v2Denoise.value = IMAGE_V2_KREA_EDIT_DENOISE
|
if (v2Engine.value === 'krea' && mode === 'edit') v2Denoise.value = IMAGE_V2_KREA_EDIT_DENOISE
|
||||||
if (v2Engine.value === 'krea' && mode === 'compose') v2Denoise.value = IMAGE_V2_KREA_COMPOSE_DENOISE
|
if (v2Engine.value === 'krea' && mode === 'compose') v2Denoise.value = IMAGE_V2_KREA_COMPOSE_DENOISE
|
||||||
@@ -5688,14 +5663,11 @@ function setV2Engine(engine: ImageV2Engine) {
|
|||||||
if (engine === 'krea') {
|
if (engine === 'krea') {
|
||||||
v2Steps.value = IMAGE_V2_KREA_STEPS
|
v2Steps.value = IMAGE_V2_KREA_STEPS
|
||||||
v2Cfg.value = IMAGE_V2_KREA_CFG
|
v2Cfg.value = IMAGE_V2_KREA_CFG
|
||||||
v2SnofsModel.value = 0
|
|
||||||
v2SnofsClip.value = 0
|
|
||||||
v2ConsistencyModel.value = 0
|
|
||||||
v2ConsistencyClip.value = 0
|
|
||||||
v2Turbo.value = false
|
v2Turbo.value = false
|
||||||
const dropped = imageV2LoraStack.value.filter(item => isKleinImageLora(item.name))
|
const dropped = imageV2LoraStack.value.filter(item => isKleinImageLora(item.name))
|
||||||
if (dropped.length) {
|
if (dropped.length) {
|
||||||
imageV2LoraStack.value = filterLoraStackForImageEngine(imageV2LoraStack.value, 'krea')
|
imageV2LoraStack.value = filterLoraStackForImageEngine(imageV2LoraStack.value, 'krea')
|
||||||
|
seedImageV2LorasIfEmpty()
|
||||||
toast(dropped.length === 1
|
toast(dropped.length === 1
|
||||||
? kleinLoraOnKreaMessage(dropped[0].name)
|
? kleinLoraOnKreaMessage(dropped[0].name)
|
||||||
: 'Flux LoRAs were removed. They cannot be used with Krea.')
|
: 'Flux LoRAs were removed. They cannot be used with Krea.')
|
||||||
@@ -5707,12 +5679,7 @@ function setV2Engine(engine: ImageV2Engine) {
|
|||||||
if (previous === 'krea') {
|
if (previous === 'krea') {
|
||||||
v2Steps.value = IMAGE_V2_STEPS_DEFAULT
|
v2Steps.value = IMAGE_V2_STEPS_DEFAULT
|
||||||
v2Cfg.value = IMAGE_V2_CFG_DEFAULT
|
v2Cfg.value = IMAGE_V2_CFG_DEFAULT
|
||||||
v2SnofsModel.value = v2ConceptLoraEnabled.value ? IMAGE_V2_SNOFS_MODEL : 0
|
seedImageV2LorasIfEmpty()
|
||||||
v2SnofsClip.value = v2ConceptLoraEnabled.value ? IMAGE_V2_SNOFS_CLIP : 0
|
|
||||||
if (v2Mode.value !== 'generate') {
|
|
||||||
v2ConsistencyModel.value = IMAGE_V2_CONSISTENCY_MODEL
|
|
||||||
v2ConsistencyClip.value = IMAGE_V2_CONSISTENCY_CLIP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5725,23 +5692,23 @@ function setGenerateSize(aspect: ImageV2GenerateAspect) {
|
|||||||
function applyRefinePreset(kind: 'face' | 'hand' | 'heavy') {
|
function applyRefinePreset(kind: 'face' | 'hand' | 'heavy') {
|
||||||
if (kind === 'face') {
|
if (kind === 'face') {
|
||||||
v2Denoise.value = IMAGE_V2_REFINE_FACE.strength
|
v2Denoise.value = IMAGE_V2_REFINE_FACE.strength
|
||||||
|
if (v2Engine.value === 'flux') {
|
||||||
if (v2ConceptLoraEnabled.value) {
|
if (v2ConceptLoraEnabled.value) {
|
||||||
v2SnofsModel.value = IMAGE_V2_REFINE_FACE.snofsModel
|
imageV2LoraStack.value = upsertImageV2Lora(imageV2LoraStack.value, IMAGE_V2_SNOFS_LORA, IMAGE_V2_REFINE_FACE.snofsModel, IMAGE_V2_REFINE_FACE.snofsClip)
|
||||||
v2SnofsClip.value = IMAGE_V2_REFINE_FACE.snofsClip
|
}
|
||||||
|
imageV2LoraStack.value = upsertImageV2Lora(imageV2LoraStack.value, IMAGE_V2_CONSISTENCY_LORA, IMAGE_V2_REFINE_FACE.consistencyModel, IMAGE_V2_REFINE_FACE.consistencyClip)
|
||||||
}
|
}
|
||||||
v2ConsistencyModel.value = IMAGE_V2_REFINE_FACE.consistencyModel
|
|
||||||
v2ConsistencyClip.value = IMAGE_V2_REFINE_FACE.consistencyClip
|
|
||||||
if (!prompt.value.trim()) prompt.value = IMAGE_V2_REFINE_FACE_PROMPT
|
if (!prompt.value.trim()) prompt.value = IMAGE_V2_REFINE_FACE_PROMPT
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (kind === 'hand') {
|
if (kind === 'hand') {
|
||||||
v2Denoise.value = IMAGE_V2_REFINE_HAND.strength
|
v2Denoise.value = IMAGE_V2_REFINE_HAND.strength
|
||||||
|
if (v2Engine.value === 'flux') {
|
||||||
if (v2ConceptLoraEnabled.value) {
|
if (v2ConceptLoraEnabled.value) {
|
||||||
v2SnofsModel.value = IMAGE_V2_REFINE_HAND.snofsModel
|
imageV2LoraStack.value = upsertImageV2Lora(imageV2LoraStack.value, IMAGE_V2_SNOFS_LORA, IMAGE_V2_REFINE_HAND.snofsModel, IMAGE_V2_REFINE_HAND.snofsClip)
|
||||||
v2SnofsClip.value = IMAGE_V2_REFINE_HAND.snofsClip
|
}
|
||||||
|
imageV2LoraStack.value = upsertImageV2Lora(imageV2LoraStack.value, IMAGE_V2_CONSISTENCY_LORA, IMAGE_V2_REFINE_HAND.consistencyModel, IMAGE_V2_REFINE_HAND.consistencyClip)
|
||||||
}
|
}
|
||||||
v2ConsistencyModel.value = IMAGE_V2_REFINE_HAND.consistencyModel
|
|
||||||
v2ConsistencyClip.value = IMAGE_V2_REFINE_HAND.consistencyClip
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v2Denoise.value = IMAGE_V2_REFINE_HEAVY.strength
|
v2Denoise.value = IMAGE_V2_REFINE_HEAVY.strength
|
||||||
@@ -5825,10 +5792,10 @@ async function editImageV2() {
|
|||||||
body.append('engine', v2Engine.value)
|
body.append('engine', v2Engine.value)
|
||||||
body.append('prompt', prompt.value.trim())
|
body.append('prompt', prompt.value.trim())
|
||||||
body.append('negative', v2Negative.value)
|
body.append('negative', v2Negative.value)
|
||||||
body.append('snofs_model', String(v2ConceptLoraEnabled.value ? clampImageV2Strength(v2SnofsModel.value, v2Engine.value === 'krea' ? 0 : IMAGE_V2_SNOFS_MODEL) : 0))
|
body.append('snofs_model', String(imageV2EngineLoras().find(item => isImageV2ConceptLora(item.name))?.strengthModel ?? 0))
|
||||||
body.append('snofs_clip', String(v2ConceptLoraEnabled.value ? clampImageV2Strength(v2SnofsClip.value, v2Engine.value === 'krea' ? 0 : IMAGE_V2_SNOFS_CLIP) : 0))
|
body.append('snofs_clip', String(imageV2EngineLoras().find(item => isImageV2ConceptLora(item.name))?.strengthClip ?? 0))
|
||||||
body.append('consistency_model', String(v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(v2ConsistencyModel.value, IMAGE_V2_CONSISTENCY_MODEL)))
|
body.append('consistency_model', String(imageV2EngineLoras().find(item => isImageV2ConsistencyLora(item.name))?.strengthModel ?? 0))
|
||||||
body.append('consistency_clip', String(v2Mode.value === 'generate' || v2Engine.value === 'krea' ? 0 : clampImageV2Strength(v2ConsistencyClip.value, IMAGE_V2_CONSISTENCY_CLIP)))
|
body.append('consistency_clip', String(imageV2EngineLoras().find(item => isImageV2ConsistencyLora(item.name))?.strengthClip ?? 0))
|
||||||
body.append('steps', String(clampImageSteps(v2Steps.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT)))
|
body.append('steps', String(clampImageSteps(v2Steps.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_STEPS : IMAGE_V2_STEPS_DEFAULT)))
|
||||||
body.append('cfg', String(clampImageCfg(v2Cfg.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT)))
|
body.append('cfg', String(clampImageCfg(v2Cfg.value, v2Engine.value === 'krea' ? IMAGE_V2_KREA_CFG : IMAGE_V2_CFG_DEFAULT)))
|
||||||
if (v2Mode.value !== 'generate') body.append('megapixels', String(clampImageScaleMegapixels(v2Megapixels.value, 1)))
|
if (v2Mode.value !== 'generate') body.append('megapixels', String(clampImageScaleMegapixels(v2Megapixels.value, 1)))
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import {
|
|||||||
clampImageV2Strength,
|
clampImageV2Strength,
|
||||||
composeImageV2Prompt,
|
composeImageV2Prompt,
|
||||||
imageV2WorkflowFile,
|
imageV2WorkflowFile,
|
||||||
|
mergeLegacyImageV2Loras,
|
||||||
parseImageV2Engine,
|
parseImageV2Engine,
|
||||||
type ImageV2Engine,
|
type ImageV2Engine,
|
||||||
type ImageV2Mode,
|
type ImageV2Mode,
|
||||||
@@ -401,7 +402,18 @@ function applyKreaConceptLora(graph: WorkflowGraph, loraName: string, model: num
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyKreaConceptIfNeeded(graph: WorkflowGraph, params: ImageV2BuildParams) {
|
function applyKreaConceptIfNeeded(graph: WorkflowGraph, params: ImageV2BuildParams) {
|
||||||
|
const merged = mergeLegacyImageV2Loras(params.loraStack, {
|
||||||
|
engine: 'krea',
|
||||||
|
mode: params.mode,
|
||||||
|
xaigen: isXaigenStudio(),
|
||||||
|
snofsModel: params.snofsModel,
|
||||||
|
snofsClip: params.snofsClip,
|
||||||
|
kreaConcept: params.kreaConceptLora
|
||||||
|
})
|
||||||
const conceptName = isXaigenStudio() ? String(params.kreaConceptLora || '').trim() : ''
|
const conceptName = isXaigenStudio() ? String(params.kreaConceptLora || '').trim() : ''
|
||||||
|
if (conceptName && merged.some(item => loraIdentityKey(item.name) === loraIdentityKey(conceptName))) {
|
||||||
|
return { snofsModel: 0, snofsClip: 0 }
|
||||||
|
}
|
||||||
const snofsModel = conceptName ? clampImageV2Strength(params.snofsModel, 0) : 0
|
const snofsModel = conceptName ? clampImageV2Strength(params.snofsModel, 0) : 0
|
||||||
const snofsClip = conceptName ? clampImageV2Strength(params.snofsClip, 0) : 0
|
const snofsClip = conceptName ? clampImageV2Strength(params.snofsClip, 0) : 0
|
||||||
if (!conceptName || (snofsModel <= 0 && snofsClip <= 0)) return { snofsModel: 0, snofsClip: 0 }
|
if (!conceptName || (snofsModel <= 0 && snofsClip <= 0)) return { snofsModel: 0, snofsClip: 0 }
|
||||||
@@ -413,6 +425,19 @@ function applyKreaConceptIfNeeded(graph: WorkflowGraph, params: ImageV2BuildPara
|
|||||||
return { snofsModel, snofsClip, name: resolved }
|
return { snofsModel, snofsClip, name: resolved }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function imageV2UserStack(params: ImageV2BuildParams, engine: ImageV2Engine) {
|
||||||
|
return mergeLegacyImageV2Loras(params.loraStack, {
|
||||||
|
engine,
|
||||||
|
mode: params.mode,
|
||||||
|
xaigen: isXaigenStudio(),
|
||||||
|
snofsModel: params.snofsModel,
|
||||||
|
snofsClip: params.snofsClip,
|
||||||
|
consistencyModel: params.consistencyModel,
|
||||||
|
consistencyClip: params.consistencyClip,
|
||||||
|
kreaConcept: params.kreaConceptLora
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function requireKreaModels(params: ImageV2BuildParams) {
|
function requireKreaModels(params: ImageV2BuildParams) {
|
||||||
if (!params.kreaUnetName || !params.kreaClipName || !params.kreaVaeName) {
|
if (!params.kreaUnetName || !params.kreaClipName || !params.kreaVaeName) {
|
||||||
throw createError({
|
throw createError({
|
||||||
@@ -463,7 +488,7 @@ function buildKreaItiWorkflow(params: ImageV2BuildParams) {
|
|||||||
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || `aigen-v2-krea-${params.mode}`)
|
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || `aigen-v2-krea-${params.mode}`)
|
||||||
patchScaleMegapixels(graph, params.megapixels ?? 1)
|
patchScaleMegapixels(graph, params.megapixels ?? 1)
|
||||||
const concept = applyKreaConceptIfNeeded(graph, params)
|
const concept = applyKreaConceptIfNeeded(graph, params)
|
||||||
const userLoras = applyImageV2UserLoras(graph, params.loraStack, 'krea')
|
const userLoras = applyImageV2UserLoras(graph, imageV2UserStack(params, 'krea'), 'krea')
|
||||||
|
|
||||||
assertImageV2Graph(graph, params.mode, compose ? params.imageBName : undefined, 'krea')
|
assertImageV2Graph(graph, params.mode, compose ? params.imageBName : undefined, 'krea')
|
||||||
const loaders = loadImageNames(graph)
|
const loaders = loadImageNames(graph)
|
||||||
@@ -514,7 +539,7 @@ function buildKreaGenerateWorkflow(params: ImageV2BuildParams) {
|
|||||||
setInput(graph, '15', 'scheduler', 'simple')
|
setInput(graph, '15', 'scheduler', 'simple')
|
||||||
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || 'aigen-v2-krea')
|
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || 'aigen-v2-krea')
|
||||||
const concept = applyKreaConceptIfNeeded(graph, params)
|
const concept = applyKreaConceptIfNeeded(graph, params)
|
||||||
const userLoras = applyImageV2UserLoras(graph, params.loraStack, 'krea')
|
const userLoras = applyImageV2UserLoras(graph, imageV2UserStack(params, 'krea'), 'krea')
|
||||||
|
|
||||||
assertImageV2Graph(graph, 'generate', undefined, 'krea')
|
assertImageV2Graph(graph, 'generate', undefined, 'krea')
|
||||||
const loaders = loadImageNames(graph)
|
const loaders = loadImageNames(graph)
|
||||||
@@ -596,22 +621,9 @@ export function buildImageV2Workflow(params: ImageV2BuildParams) {
|
|||||||
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || (generate ? 'aigen-v2-generate' : 'aigen-v2'))
|
setInput(graph, SAVE, 'filename_prefix', params.filenamePrefix || (generate ? 'aigen-v2-generate' : 'aigen-v2'))
|
||||||
if (!generate) patchScaleMegapixels(graph, params.megapixels ?? 1)
|
if (!generate) patchScaleMegapixels(graph, params.megapixels ?? 1)
|
||||||
|
|
||||||
if (conceptAllowed) {
|
if (graph[CONSISTENCY]) bypassLoraToBaseLoaders(graph, CONSISTENCY)
|
||||||
setInput(graph, SNOFS, 'lora_name', resolveRequiredLora(IMAGE_V2_SNOFS_LORA, 'SNOFS'))
|
if (graph[SNOFS]) bypassLoraToBaseLoaders(graph, SNOFS)
|
||||||
setInput(graph, SNOFS, 'strength_model', snofsModel)
|
const userLoras = applyImageV2UserLoras(graph, imageV2UserStack(params, 'flux'), 'flux')
|
||||||
setInput(graph, SNOFS, 'strength_clip', snofsClip)
|
|
||||||
} else {
|
|
||||||
bypassLoraToBaseLoaders(graph, SNOFS)
|
|
||||||
}
|
|
||||||
if (generate && consistencyModel <= 0 && consistencyClip <= 0) {
|
|
||||||
if (graph[SNOFS]) bypassLoraNode(graph, CONSISTENCY, SNOFS, SNOFS)
|
|
||||||
else bypassLoraToBaseLoaders(graph, CONSISTENCY)
|
|
||||||
} else {
|
|
||||||
setInput(graph, CONSISTENCY, 'lora_name', resolveRequiredLora(IMAGE_V2_CONSISTENCY_LORA, 'Consistency'))
|
|
||||||
setInput(graph, CONSISTENCY, 'strength_model', consistencyModel)
|
|
||||||
setInput(graph, CONSISTENCY, 'strength_clip', consistencyClip)
|
|
||||||
}
|
|
||||||
const userLoras = applyImageV2UserLoras(graph, params.loraStack, 'flux')
|
|
||||||
|
|
||||||
assertImageV2Graph(graph, params.mode, generate || refine ? undefined : params.imageBName, engine)
|
assertImageV2Graph(graph, params.mode, generate || refine ? undefined : params.imageBName, engine)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
import {
|
||||||
|
filterLoraStackForImageEngine,
|
||||||
|
loraIdentityKey,
|
||||||
|
makeLoraStackItem,
|
||||||
|
normalizeLoraStack,
|
||||||
|
type LoraStackItem
|
||||||
|
} from '~/utils/loras'
|
||||||
|
|
||||||
export const IMAGE_V2_MODES = ['edit', 'compose', 'refine', 'generate'] as const
|
export const IMAGE_V2_MODES = ['edit', 'compose', 'refine', 'generate'] as const
|
||||||
export const IMAGE_V2_TASKS = ['scene', 'identity', 'outfit', 'face_lock', 'refine', 't2i'] as const
|
export const IMAGE_V2_TASKS = ['scene', 'identity', 'outfit', 'face_lock', 'refine', 't2i'] as const
|
||||||
export const IMAGE_V2_ENGINES = ['flux', 'krea'] as const
|
export const IMAGE_V2_ENGINES = ['flux', 'krea'] as const
|
||||||
@@ -166,3 +174,88 @@ export type ImageV2PresetSettings = {
|
|||||||
width?: number
|
width?: number
|
||||||
height?: number
|
height?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isImageV2ConceptLora(name: string) {
|
||||||
|
const id = loraIdentityKey(name)
|
||||||
|
return id === loraIdentityKey(IMAGE_V2_SNOFS_LORA) || /klein_snofs/i.test(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isImageV2ConsistencyLora(name: string) {
|
||||||
|
const id = loraIdentityKey(name)
|
||||||
|
return id === loraIdentityKey(IMAGE_V2_CONSISTENCY_LORA) || /flux2-klein-9b-consistency/i.test(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function upsertImageV2Lora(stack: unknown, name: string, model: number, clip: number): LoraStackItem[] {
|
||||||
|
const item = makeLoraStackItem(name, model, clip)
|
||||||
|
const current = normalizeLoraStack(stack)
|
||||||
|
if (!item) return current
|
||||||
|
const key = loraIdentityKey(name)
|
||||||
|
const index = current.findIndex(entry => loraIdentityKey(entry.name) === key)
|
||||||
|
if (index >= 0) {
|
||||||
|
const next = [...current]
|
||||||
|
next[index] = { ...next[index], strengthModel: item.strengthModel, strengthClip: item.strengthClip }
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
if (isImageV2ConsistencyLora(name)) {
|
||||||
|
const conceptAt = current.findIndex(entry => isImageV2ConceptLora(entry.name))
|
||||||
|
if (conceptAt >= 0) return [...current.slice(0, conceptAt + 1), item, ...current.slice(conceptAt + 1)]
|
||||||
|
}
|
||||||
|
return [item, ...current]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defaultImageV2LoraStack(opts: {
|
||||||
|
engine: ImageV2Engine
|
||||||
|
mode: ImageV2Mode
|
||||||
|
xaigen: boolean
|
||||||
|
kreaConcept?: string
|
||||||
|
}): LoraStackItem[] {
|
||||||
|
if (opts.engine === 'krea') {
|
||||||
|
const name = String(opts.kreaConcept || '').trim()
|
||||||
|
if (!opts.xaigen || !name) return []
|
||||||
|
const item = makeLoraStackItem(name, IMAGE_V2_SNOFS_MODEL, IMAGE_V2_SNOFS_CLIP)
|
||||||
|
return item ? [item] : []
|
||||||
|
}
|
||||||
|
const out: LoraStackItem[] = []
|
||||||
|
if (opts.xaigen) {
|
||||||
|
const concept = makeLoraStackItem(IMAGE_V2_SNOFS_LORA, IMAGE_V2_SNOFS_MODEL, IMAGE_V2_SNOFS_CLIP)
|
||||||
|
if (concept) out.push(concept)
|
||||||
|
}
|
||||||
|
if (opts.mode !== 'generate') {
|
||||||
|
const consistency = makeLoraStackItem(IMAGE_V2_CONSISTENCY_LORA, IMAGE_V2_CONSISTENCY_MODEL, IMAGE_V2_CONSISTENCY_CLIP)
|
||||||
|
if (consistency) out.push(consistency)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mergeLegacyImageV2Loras(stack: unknown, opts: {
|
||||||
|
engine: ImageV2Engine
|
||||||
|
mode: ImageV2Mode
|
||||||
|
xaigen: boolean
|
||||||
|
snofsModel?: number
|
||||||
|
snofsClip?: number
|
||||||
|
consistencyModel?: number
|
||||||
|
consistencyClip?: number
|
||||||
|
kreaConcept?: string
|
||||||
|
}): LoraStackItem[] {
|
||||||
|
let items = filterLoraStackForImageEngine(stack, opts.engine)
|
||||||
|
if (opts.engine === 'krea') {
|
||||||
|
const name = String(opts.kreaConcept || '').trim()
|
||||||
|
const model = Number(opts.snofsModel) || 0
|
||||||
|
const clip = Number(opts.snofsClip) || 0
|
||||||
|
if (name && (model > 0 || clip > 0) && !items.some(item => loraIdentityKey(item.name) === loraIdentityKey(name))) {
|
||||||
|
return upsertImageV2Lora(items, name, model, clip)
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
const conceptModel = opts.xaigen ? Number(opts.snofsModel) || 0 : 0
|
||||||
|
const conceptClip = opts.xaigen ? Number(opts.snofsClip) || 0 : 0
|
||||||
|
if ((conceptModel > 0 || conceptClip > 0) && !items.some(item => isImageV2ConceptLora(item.name))) {
|
||||||
|
items = upsertImageV2Lora(items, IMAGE_V2_SNOFS_LORA, conceptModel, conceptClip)
|
||||||
|
}
|
||||||
|
const consistencyModel = opts.mode === 'generate' ? 0 : Number(opts.consistencyModel) || 0
|
||||||
|
const consistencyClip = opts.mode === 'generate' ? 0 : Number(opts.consistencyClip) || 0
|
||||||
|
if ((consistencyModel > 0 || consistencyClip > 0) && !items.some(item => isImageV2ConsistencyLora(item.name))) {
|
||||||
|
items = upsertImageV2Lora(items, IMAGE_V2_CONSISTENCY_LORA, consistencyModel, consistencyClip)
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user