Add support for NovelAI V4 model and configuration settings

This commit is contained in:
YH_KIM
2025-04-12 23:29:45 +09:00
parent 4c47480b7e
commit 668b8d171c
3 changed files with 198 additions and 149 deletions

View File

@@ -35,7 +35,25 @@
image: '', image: '',
InfoExtracted: 0.5, InfoExtracted: 0.5,
RefStrength: 0.5, RefStrength: 0.5,
refimage: '' refimage: '',
autoSmea:false,
legacy_uc:false,
use_coords:false,
v4_prompt:{
caption:{
base_caption:'',
char_captions:[]
},
use_coords:false,
use_order:true
},
v4_negative_prompt:{
caption:{
base_caption:'',
char_captions:[]
},
legacy_uc:false,
}
} }
if (DBState.db.NAIImgConfig.sampler === 'ddim_v3'){ if (DBState.db.NAIImgConfig.sampler === 'ddim_v3'){
DBState.db.NAIImgConfig.sm = false DBState.db.NAIImgConfig.sm = false
@@ -43,7 +61,7 @@
} }
}); });
let submenu = $state(DBState.db.useLegacyGUI ? -1 : 0) let submenu = $state(DBState.db.useLegacyGUI ? -1 : 0);
// HypaV3 // HypaV3
$effect(() => { $effect(() => {
@@ -88,6 +106,14 @@
return parseFloat(maxMemoryRatio.toFixed(2)); return parseFloat(maxMemoryRatio.toFixed(2));
} }
// End HypaV3 // End HypaV3
// add init NAI V4
// if(DBState.db.NAIImgConfig.autoSmea === undefined) DBState.db.NAIImgConfig.autoSmea = false;
// if(DBState.db.NAIImgConfig.use_coords === undefined) DBState.db.NAIImgConfig.use_coords = false;
// if(DBState.db.NAIImgConfig.v4_prompt.use_coords === undefined) DBState.db.NAIImgConfig.v4_prompt.use_coords = false;
// if(DBState.db.NAIImgConfig.v4_prompt.use_order === undefined) DBState.db.NAIImgConfig.v4_prompt.use_order = false;
// if(DBState.db.NAIImgConfig.v4_negative_prompt.legacy_uc === undefined) DBState.db.NAIImgConfig.v4_negative_prompt.legacy_uc = false;
</script> </script>
<h2 class="mb-2 text-2xl font-bold mt-2">{language.otherBots}</h2> <h2 class="mb-2 text-2xl font-bold mt-2">{language.otherBots}</h2>
@@ -168,50 +194,75 @@
<TextInput size="sm" marginBottom bind:value={DBState.db.sdConfig.hr_upscaler}/> <TextInput size="sm" marginBottom bind:value={DBState.db.sdConfig.hr_upscaler}/>
{/if} {/if}
{/if} {/if}
{#if DBState.db.sdProvider === 'novelai'} {#if DBState.db.sdProvider === 'novelai'}
<span class="text-textcolor mt-2">Novel AI {language.providerURL}</span> <span class="text-textcolor mt-2">Novel AI {language.providerURL}</span>
<TextInput size="sm" marginBottom placeholder="https://image.novelai.net" bind:value={DBState.db.NAIImgUrl}/> <TextInput size="sm" marginBottom placeholder="https://image.novelai.net" bind:value={DBState.db.NAIImgUrl}/>
<span class="text-textcolor">API Key</span> <span class="text-textcolor">API Key</span>
<TextInput size="sm" marginBottom placeholder="pst-..." bind:value={DBState.db.NAIApiKey}/> <TextInput size="sm" marginBottom placeholder="pst-..." bind:value={DBState.db.NAIApiKey}/>
<span class="text-textcolor">Model</span> <span class="text-textcolor">Model</span>
<TextInput size="sm" marginBottom placeholder="nai-diffusion-3" bind:value={DBState.db.NAIImgModel}/> <TextInput size="sm" marginBottom placeholder="nai-diffusion-4-full" bind:value={DBState.db.NAIImgModel}/>
<span class="text-textcolor">Width</span> <span class="text-textcolor">Width</span>
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.width}/> <NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.width}/>
<span class="text-textcolor">Height</span> <span class="text-textcolor">Height</span>
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.height}/> <NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.height}/>
<span class="text-textcolor">Sampler</span> <span class="text-textcolor">Sampler</span>
<SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}>
<OptionInput value="k_euler" >Euler</OptionInput> {#if DBState.db.NAIImgModel === 'nai-diffusion-4-full'}
<OptionInput value="k_euler_ancestral" >Euler Ancestral</OptionInput> <SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}>
<OptionInput value="k_dpmpp_2s_ancestral" >DPM++ 2S Ancestral</OptionInput> <OptionInput value="k_euler_ancestral" >(Recommended)Euler Ancestral</OptionInput>
<OptionInput value="k_dpmpp_2m" >DPM++ 2M</OptionInput> <OptionInput value="k_dpmpp_2s_ancestral" >(Recommended)DPM++ 2S Ancestral</OptionInput>
<OptionInput value="k_dpmpp_sde" >DPM++ SDE</OptionInput> <OptionInput value="k_dpmpp_2m_sde" >(Recommended)DPM++ 2M SDE</OptionInput>
<OptionInput value="k_dpmpp_2s" >DPM++ 2S</OptionInput> <OptionInput value="k_euler" >(Other)Euler</OptionInput>
<OptionInput value="ddim_v3" >DDIM</OptionInput> <OptionInput value="k_dpmpp_2m" >(Other)DPM++ 2M</OptionInput>
</SelectInput> <OptionInput value="k_dpmpp_sde" >(Other)DPM++ SDE</OptionInput>
</SelectInput>
{:else}
<SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}>
<OptionInput value="k_euler" >Euler</OptionInput>
<OptionInput value="k_euler_ancestral" >Euler Ancestral</OptionInput>
<OptionInput value="k_dpmpp_2s_ancestral" >DPM++ 2S Ancestral</OptionInput>
<OptionInput value="k_dpmpp_2m" >DPM++ 2M</OptionInput>
<OptionInput value="k_dpmpp_sde" >DPM++ SDE</OptionInput>
<OptionInput value="k_dpmpp_2s" >DPM++ 2S</OptionInput>
<OptionInput value="ddim_v3" >DDIM</OptionInput>
</SelectInput>
{/if}
<span class="text-textcolor">steps</span> <span class="text-textcolor">steps</span>
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.steps}/> <NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.steps}/>
<span class="text-textcolor">CFG scale</span> <span class="text-textcolor">CFG scale</span>
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.scale}/> <NumberInput size="sm" marginBottom min={0} max={2048} bind:value={DBState.db.NAIImgConfig.scale}/>
{#if !DBState.db.NAII2I || DBState.db.NAIImgConfig.sampler !== 'ddim_v3'} {#if !DBState.db.NAII2I || DBState.db.NAIImgConfig.sampler !== 'ddim_v3'}
<Check bind:check={DBState.db.NAIImgConfig.sm} name="Use SMEA"/> <Check bind:check={DBState.db.NAIImgConfig.sm} name="Use SMEA"/>
{:else if DBState.db.NAIImgModel !== 'nai-diffusion-4-full'}
<Check bind:check={DBState.db.NAIImgConfig.sm_dyn} name='Use DYN'/> <Check bind:check={DBState.db.NAIImgConfig.sm_dyn} name='Use DYN'/>
{/if} {/if}
<Check bind:check={DBState.db.NAII2I} name="Enable I2I"/> <Check bind:check={DBState.db.NAII2I} name="Enable I2I"/>
{#if DBState.db.NAIImgModel === 'nai-diffusion-4-full'}
<Check bind:check={DBState.db.NAIImgConfig.autoSmea} name='Auto Smea'/>
<Check bind:check={DBState.db.NAIImgConfig.use_coords} name='Use coords'/>
<Check bind:check={DBState.db.NAIImgConfig.legacy_uc} name='Use legacy uc'/>
<!-- <Check bind:check={DBState.db.NAIImgConfig.v4_prompt.use_coords} name='Use v4 prompt coords'/>-->
<!-- <Check bind:check={DBState.db.NAIImgConfig.v4_prompt.use_order} name='Use v4 prompt order'/>-->
<!-- <Check bind:check={DBState.db.NAIImgConfig.v4_negative_prompt.legacy_uc} name='Use v4 negative prompt legacy uc'/>-->
{/if}
{#if DBState.db.NAII2I} {#if DBState.db.NAII2I}
<span class="text-textcolor mt-4">Strength</span> <span class="text-textcolor mt-4">Strength</span>
<SliderInput min={0} max={0.99} step={0.01} bind:value={DBState.db.NAIImgConfig.strength}/> <SliderInput min={0} max={0.99} step={0.01} bind:value={DBState.db.NAIImgConfig.strength}/>
<span class="text-textcolor2 mb-6 text-sm">{DBState.db.NAIImgConfig.strength}</span> <span class="text-textcolor2 mb-6 text-sm">{DBState.db.NAIImgConfig.strength}</span>
<span class="text-textcolor">Noise</span> <span class="text-textcolor">Noise</span>
<SliderInput min={0} max={0.99} step={0.01} bind:value={DBState.db.NAIImgConfig.noise}/> <SliderInput min={0} max={0.99} step={0.01} bind:value={DBState.db.NAIImgConfig.noise}/>
<span class="text-textcolor2 mb-6 text-sm">{DBState.db.NAIImgConfig.noise}</span> <span class="text-textcolor2 mb-6 text-sm">{DBState.db.NAIImgConfig.noise}</span>
<span class="text-textcolor">Base image</span> <span class="text-textcolor">Base image</span>
<button onclick={async () => { <button onclick={async () => {
const img = await selectSingleFile([ const img = await selectSingleFile([
@@ -231,12 +282,12 @@
{:else} {:else}
{#await getCharImage(DBState.db.NAIImgConfig.image, 'css')} {#await getCharImage(DBState.db.NAIImgConfig.image, 'css')}
<div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500"></div> <div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500"></div>
{:then im} {:then im}
<div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500" style={im}></div> <div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500" style={im}></div>
{/await} {/await}
{/if} {/if}
</button> </button>
{/if} {/if}
<Check bind:check={DBState.db.NAIREF} name="Enable Reference" className="mt-4"/> <Check bind:check={DBState.db.NAIREF} name="Enable Reference" className="mt-4"/>
@@ -273,8 +324,8 @@
{:else} {:else}
{#await getCharImage(DBState.db.NAIImgConfig.refimage, 'css')} {#await getCharImage(DBState.db.NAIImgConfig.refimage, 'css')}
<div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500"></div> <div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500"></div>
{:then im} {:then im}
<div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500" style={im}></div> <div class="rounded-md h-20 w-20 shadow-lg bg-textcolor2 cursor-pointer hover:text-green-500" style={im}></div>
{/await} {/await}
{/if} {/if}
</button> </button>

View File

@@ -1,5 +1,5 @@
import { get } from "svelte/store" import { get } from "svelte/store"
import { getDatabase, type character } from "../storage/database.svelte" import { getDatabase, type character, type NAIImgConfig } from "../storage/database.svelte"
import { requestChatData } from "./request" import { requestChatData } from "./request"
import { alertError } from "../alert" import { alertError } from "../alert"
import { fetchNative, globalFetch, readImage } from "../globalApi.svelte" import { fetchNative, globalFetch, readImage } from "../globalApi.svelte"
@@ -125,6 +125,62 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
let reqlist:any = {} let reqlist:any = {}
const commonReq = {
body: {
"input": genPrompt,
"model": db.NAIImgModel,
"parameters": {
"params_version": 3,
"add_original_image": true,
"cfg_rescale": 0,
"controlnet_strength": 1,
"dynamic_thresholding": false,
"n_samples": 1,
"width": db.NAIImgConfig.width,
"height": db.NAIImgConfig.height,
"sampler": db.NAIImgConfig.sampler,
"steps": db.NAIImgConfig.steps,
"scale": db.NAIImgConfig.scale,
"negative_prompt": neg,
"sm": false,
"sm_dyn": false,
"noise": db.NAIImgConfig.noise,
"noise_schedule": "native",
"strength": db.NAIImgConfig.strength,
"ucPreset": 3,
"uncond_scale": 1,
"qualityToggle": false,
"lagacy_v3_extend": false,
"lagacy": false,
"reference_information_extracted": db.NAIImgConfig.InfoExtracted,
"reference_strength": db.NAIImgConfig.RefStrength,
//add v4
"autoSmea": db.NAIImgConfig.autoSmea || false,
use_coords: db.NAIImgConfig.use_coords || false,
legacy_uc: db.NAIImgConfig.legacy_uc || false,
v4_prompt:{
caption:{
base_caption:genPrompt,
char_captions: []
},
use_coords: false,//db.NAIImgConfig.v4_prompt.use_coords || false,
use_order: true//db.NAIImgConfig.v4_prompt.use_order || true
},
"v4_negative_prompt":{
caption:{
base_caption:neg,
char_captions: []
},
legacy_uc: false//db.NAIImgConfig.v4_negative_prompt.legacy_uc || false,
}
}
},
headers:{
"Authorization": "Bearer " + db.NAIApiKey
},
rawResponse: true
}
if(db.NAII2I){ if(db.NAII2I){
let seed = Math.floor(Math.random() * 10000000000) let seed = Math.floor(Math.random() * 10000000000)
@@ -139,9 +195,6 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
} }
let refimgbase64 = undefined let refimgbase64 = undefined
if(db.NAIREF){ if(db.NAIREF){
if(db.NAIImgConfig.refimage !== ''){ if(db.NAIImgConfig.refimage !== ''){
@@ -149,56 +202,19 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
} }
} }
reqlist = { reqlist = commonReq;
body: { reqlist.body.action = "img2img";
"action": "img2img", reqlist.body.parameters.image = base64img;
"input": genPrompt, reqlist.body.parameters.extra_noise_seed = seed;
"model": db.NAIImgModel, reqlist.body.parameters.seed = seed;
"parameters": {
"params_version": 1,
"add_original_image": true,
"cfg_rescale": 0,
"controlnet_strength": 1,
"dynamic_thresholding": false,
"extra_noise_seed": seed,
"n_samples": 1,
"width": db.NAIImgConfig.width,
"height": db.NAIImgConfig.height,
"sampler": db.NAIImgConfig.sampler,
"steps": db.NAIImgConfig.steps,
"scale": db.NAIImgConfig.scale,
"seed": seed,
"negative_prompt": neg,
"sm": false,
"sm_dyn": false,
"noise": db.NAIImgConfig.noise,
"noise_schedule": "native",
"strength": db.NAIImgConfig.strength,
"image": base64img,
"ucPreset": 3,
"uncond_scale": 1,
"qualityToggle": false,
"lagacy_v3_extend": false,
"lagacy": false,
"reference_information_extracted": db.NAIImgConfig.InfoExtracted,
"reference_strength": db.NAIImgConfig.RefStrength
}
},
headers:{
"Authorization": "Bearer " + db.NAIApiKey
},
rawResponse: true
}
if(refimgbase64 !== undefined){ if(refimgbase64 !== undefined){
reqlist.body.parameters.reference_image = refimgbase64 reqlist.body.parameters.reference_image = refimgbase64
} }
}else{ }else{
if (db.NAIREF) { if (db.NAIREF) {
let base64img = '' let base64img = ''
if(db.NAIImgConfig.image === ''){ if(db.NAIImgConfig.image === ''){
const charimg = currentChar.image; const charimg = currentChar.image;
@@ -208,84 +224,12 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
} else{ } else{
base64img = Buffer.from(await readImage(db.NAIImgConfig.refimage)).toString('base64'); base64img = Buffer.from(await readImage(db.NAIImgConfig.refimage)).toString('base64');
} }
reqlist = { reqlist = commonReq;
body: { reqlist.body.action = 'generate';
"action": "generate", reqlist.body.parameters.reference_image = base64img;
"input": genPrompt,
"model": db.NAIImgModel,
"parameters": {
"params_version": 1,
"add_original_image": true,
"cfg_rescale": 0,
"controlnet_strength": 1,
"dynamic_thresholding": false,
"n_samples": 1,
"width": db.NAIImgConfig.width,
"height": db.NAIImgConfig.height,
"sampler": db.NAIImgConfig.sampler,
"steps": db.NAIImgConfig.steps,
"scale": db.NAIImgConfig.scale,
"negative_prompt": neg,
"sm": db.NAIImgConfig.sm,
"sm_dyn": db.NAIImgConfig.sm_dyn,
"noise_schedule": "native",
"ucPreset": 3,
"uncond_scale": 1,
"qualityToggle": false,
"legacy": false,
"lagacy_v3_extend": false,
"reference_image": base64img,
"reference_strength": db.NAIImgConfig.RefStrength,
"reference_information_extracted": db.NAIImgConfig.InfoExtracted
}
},
headers:{
"Authorization": "Bearer " + db.NAIApiKey
},
rawResponse: true
}
} else { } else {
reqlist = { reqlist = commonReq;
body: {
"input": genPrompt,
"model": db.NAIImgModel,
"parameters": {
"params_version": 1,
"width": db.NAIImgConfig.width,
"height": db.NAIImgConfig.height,
"scale": db.NAIImgConfig.scale,
"sampler": db.NAIImgConfig.sampler,
"steps": db.NAIImgConfig.steps,
"n_samples": 1,
"ucPreset": 3,
"qualityToggle": false,
"sm": db.NAIImgConfig.sm,
"sm_dyn": db.NAIImgConfig.sm_dyn,
"dynamic_thresholding": false,
"controlnet_strength": 1,
"legacy": false,
"add_original_image": true,
"uncond_scale": 1,
"cfg_rescale": 0,
"noise_schedule": "native",
"legacy_v3_extend": false,
"reference_information_extracted": db.NAIImgConfig.InfoExtracted,
"reference_strength": db.NAIImgConfig.RefStrength,
"negative_prompt": neg,
}
},
headers:{
"Authorization": "Bearer " + db.NAIApiKey
},
rawResponse: true
}
} }
} }
try { try {
const da = await globalFetch(db.NAIImgUrl, reqlist) const da = await globalFetch(db.NAIImgUrl, reqlist)

View File

@@ -264,7 +264,26 @@ export function setDatabase(data:Database){
image:"", image:"",
refimage:"", refimage:"",
InfoExtracted:1, InfoExtracted:1,
RefStrength:0.4 RefStrength:0.4,
//add 4
autoSmea:false,
legacy_uc:false,
use_coords:false,
v4_prompt:{
caption:{
base_caption:'',
char_captions:[]
},
use_coords:false,
use_order:true
},
v4_negative_prompt:{
caption:{
base_caption:'',
char_captions:[]
},
legacy_uc:false,
}
} }
} }
if(checkNullish(data.customTextTheme)){ if(checkNullish(data.customTextTheme)){
@@ -1363,7 +1382,7 @@ interface sdConfig{
hr_upscaler:string hr_upscaler:string
} }
interface NAIImgConfig{ export interface NAIImgConfig{
width:number, width:number,
height:number, height:number,
sampler:string, sampler:string,
@@ -1377,8 +1396,43 @@ interface NAIImgConfig{
refimage:string, refimage:string,
InfoExtracted:number, InfoExtracted:number,
RefStrength:number RefStrength:number
//add 4
autoSmea:boolean,
use_coords:boolean,
legacy_uc: boolean,
v4_prompt:NAIImgConfigV4Prompt,
v4_negative_prompt:NAIImgConfigV4NegativePrompt,
} }
//add 4
interface NAIImgConfigV4Prompt{
caption: NAIImgConfigV4Caption,
use_coords: boolean,
use_order: boolean
}
//add 4
interface NAIImgConfigV4NegativePrompt{
caption: NAIImgConfigV4Caption,
legacy_uc: boolean
}
//add 4
interface NAIImgConfigV4Caption{
base_caption: string,
char_captions: NAIImgConfigV4CharCaption[]
}
//add 4
interface NAIImgConfigV4CharCaption{
char_caption: string,
centers:
{
x: number,
y: number
}[]
}
interface ComfyConfig{ interface ComfyConfig{
workflow:string, workflow:string,
posNodeID: string, posNodeID: string,