Show the Qwen LoRA card with qwen-stem picks and apply them on generate.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -171,9 +171,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="form.engine!=='qwen21'">
|
||||
<div v-if="['flux','krea','qwen21'].includes(form.engine)">
|
||||
<span class="field-label">LoRA</span>
|
||||
<LoraSelect v-model="form.settings.loraStack" compact :names="pickerLoras" :use="currentLoraUse" :clip-strength="!video" filename-subtitle :aliases="{...loraNames.aliases,...library.loraAliases}" :triggers="{...loraNames.triggers,...library.loraTriggers}" missing-label="None" @insert-trigger="form.promptSections.action += ' '+$event" />
|
||||
<LoraSelect
|
||||
v-model="form.settings.loraStack"
|
||||
compact
|
||||
:names="pickerLoras"
|
||||
:use="currentLoraUse"
|
||||
:clip-strength="form.engine!=='qwen21' && !video"
|
||||
filename-subtitle
|
||||
:aliases="{...loraNames.aliases,...library.loraAliases}"
|
||||
:triggers="{...loraNames.triggers,...library.loraTriggers}"
|
||||
missing-label="None"
|
||||
@insert-trigger="form.promptSections.action += ' '+$event"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -532,7 +543,6 @@ watch(()=>form.engine,(engine,prev)=>{
|
||||
form.settings.cfg=1
|
||||
form.lockFace=false
|
||||
form.lockOutfit=false
|
||||
form.settings.loraStack=[]
|
||||
}
|
||||
})
|
||||
watch(()=>form.enhancePrompt,on=>writeStoredEnhancePrompt(!!on))
|
||||
@@ -548,7 +558,6 @@ watch(()=>[form.mode,form.engine],([mode,engine])=>{
|
||||
form.settings.cfg=1
|
||||
form.lockFace=false
|
||||
form.lockOutfit=false
|
||||
form.settings.loraStack=[]
|
||||
}
|
||||
const plan=photosPlan({mode,engine})
|
||||
if(!plan.show){form.photos=[];form.imageAId='';form.imageBId='';if(engine==='qwen21')form.identityStillId='';return}
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
<template v-else>
|
||||
<div>
|
||||
<span class="m-label">LoRA</span>
|
||||
<LoraSelect v-model="ctx.form.settings.loraStack" compact :names="ctx.pickerLoras" :use="ctx.currentLoraUse" :clip-strength="!ctx.video" filename-subtitle :aliases="ctx.loraAliases" :triggers="ctx.loraTriggers" missing-label="None" @insert-trigger="ctx.form.promptSections.action += ' '+$event" />
|
||||
<LoraSelect v-model="ctx.form.settings.loraStack" compact :names="ctx.pickerLoras" :use="ctx.currentLoraUse" :clip-strength="ctx.form.engine!=='qwen21' && !ctx.video" filename-subtitle :aliases="ctx.loraAliases" :triggers="ctx.loraTriggers" missing-label="None" @insert-trigger="ctx.form.promptSections.action += ' '+$event" />
|
||||
</div>
|
||||
<label class="m-label">Seed
|
||||
<div class="m-seed">
|
||||
|
||||
@@ -406,6 +406,8 @@ async function prepareGraph(r: any) {
|
||||
r.sampleDenoise = null
|
||||
r.heroReferenceAttached = false
|
||||
}
|
||||
await ensureComfyLoraNames('image')
|
||||
applyUserLoraToGraph(graph, s.loraStack)
|
||||
}
|
||||
else {
|
||||
const mode = identityPlan?.mode ?? (q.mode === 'iterate' ? (a ? 'edit' : 'generate') : q.mode);
|
||||
|
||||
@@ -79,7 +79,7 @@ export function validateRequest(raw, xaigen = false) {
|
||||
photos: Array.isArray(raw.photos) ? raw.photos : [],
|
||||
startFrameSource: raw.startClipId ? {kind:'previous-last-frame',clipId:raw.startClipId} : {kind:'still',stillId:raw.imageAId || ''},
|
||||
promptSections, compiledPrompt:compilePrompt(promptSections,video,{...raw,engine,lockFace:qwen?false:raw.lockFace,lockOutfit:qwen?false:raw.lockOutfit}),
|
||||
settings: { aspect, fps:number('fps',24,1,60), width, height, steps, cfg, seedMode:raw.settings?.seedMode==='locked'?'locked':'random',seed:shotSeeds[0],duration:number('duration',5,1,15),turbo:raw.settings?.turbo !== false, loraStack:qwen?[]:(Array.isArray(raw.settings?.loraStack)?raw.settings.loraStack:[]) },
|
||||
settings: { aspect, fps:number('fps',24,1,60), width, height, steps, cfg, seedMode:raw.settings?.seedMode==='locked'?'locked':'random',seed:shotSeeds[0],duration:number('duration',5,1,15),turbo:raw.settings?.turbo !== false, loraStack:Array.isArray(raw.settings?.loraStack)?raw.settings.loraStack:[] },
|
||||
guides: (Array.isArray(raw.guides)?raw.guides:[]).slice(0,8).map(g=>{ if (!g.stillId || !Number.isInteger(g.frame) || g.frame<1 || g.frame>=frames) fail('Each guide requires a still and positive frame index.'); return {stillId:String(g.stillId),frame:g.frame} }),
|
||||
batch: (Array.isArray(raw.batch)?raw.batch:[]).slice(0,30).map(s=>{const next=sectionsFrom({...promptSections,...(typeof s==='string'?{action:s}:s)});if(!next.action.trim())fail('Every shot needs an action prompt.');return video?next:{action:next.action}}) }
|
||||
}
|
||||
|
||||
+12
-5
@@ -305,23 +305,30 @@ export function inferLoraUse(name: string): LoraUse[] | null {
|
||||
return uses.length ? uses : null
|
||||
}
|
||||
|
||||
/** Qwen 2.1 user adapters: basename stem starts with qwen or qwen2 (not klein). */
|
||||
export function isQwenImageLora(name: string) {
|
||||
const stem = loraIdentityKey(name).replace(/\.(safetensors|sft|ckpt|pt|bin)$/i, '')
|
||||
return /^(qwen2|qwen)/i.test(stem)
|
||||
}
|
||||
|
||||
export function loraMatchesUse(name: string, use: LoraUse) {
|
||||
if (use === 'qwen21') return false
|
||||
return !isSystemGraphLora(name) && !!inferLoraUse(name)?.includes(use)
|
||||
if (isSystemGraphLora(name)) return false
|
||||
if (use === 'qwen21') return isQwenImageLora(name)
|
||||
return !!inferLoraUse(name)?.includes(use)
|
||||
}
|
||||
|
||||
/** Saved stacks may contain unlabelled adapters; never carry a known wrong engine. */
|
||||
export function filterLoraStackForUse(stack: unknown, use: LoraUse, xaigen: boolean) {
|
||||
if (use === 'ltx' && !xaigen) return []
|
||||
if (use === 'qwen21') return []
|
||||
return filterLoraStackForStudio(stack, xaigen).filter(item => {
|
||||
if (isSystemGraphLora(item.name)) return false
|
||||
if (use === 'qwen21') return isQwenImageLora(item.name)
|
||||
const uses = inferLoraUse(item.name)
|
||||
return !isSystemGraphLora(item.name) && (!uses || uses.includes(use))
|
||||
return !uses || uses.includes(use)
|
||||
})
|
||||
}
|
||||
|
||||
export function filterLorasForUse(names: string[], use: LoraUse) {
|
||||
if (use === 'qwen21') return []
|
||||
return names.filter(name => loraMatchesUse(name, use))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user