Add support for NovelAI V4 model and configuration settings (#816)

# PR Checklist
- [ ] Have you checked if it works normally in all models? *Ignore this
if it doesn't use models.*
- [ ] Have you checked if it works normally in all web, local, and node
hosted versions? If it doesn't, have you blocked it in those versions?
- [ ] Have you added type definitions?

# Description
Add and enable temporary settings for NovelAI V4 models.
Character-specific prompt settings have been temporarily forcibly added,
so modifications are needed to allow custom prompt values to be input
later.
NovelAI V4 모델 추가.
캐릭터별 프롬프트는 임시추가 했기때문에 추후 커스텀 설정 할 수 있도록 변경해야함.
This commit is contained in:
kwaroran
2025-04-14 14:05:56 +09:00
committed by GitHub
3 changed files with 237 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,16 @@
return parseFloat(maxMemoryRatio.toFixed(2)); return parseFloat(maxMemoryRatio.toFixed(2));
} }
// End HypaV3 // End HypaV3
let imageModel = '';
// 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>
@@ -176,13 +204,36 @@
<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}/>
<SelectInput className="mt-2 mb-4" bind:value={imageModel} onchange={(e)=>{
DBState.db.NAIImgModel = imageModel;
}}>
<OptionInput value="" >Choose...</OptionInput>
<OptionInput value="nai-diffusion-4-full" >nai-diffusion-4-full</OptionInput>
<OptionInput value="nai-diffusion-4-curated-preview" >nai-diffusion-4-curated-preview</OptionInput>
<OptionInput value="nai-diffusion-3" >nai-diffusion-3</OptionInput>
<OptionInput value="nai-diffusion-furry-3" >nai-diffusion-furry-3</OptionInput>
<OptionInput value="nai-diffusion-2" >nai-diffusion-2</OptionInput>
</SelectInput>
<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>
{#if DBState.db.NAIImgModel === 'nai-diffusion-4-full'
|| DBState.db.NAIImgModel === 'nai-diffusion-4-curated-preview'}
<SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}>
<OptionInput value="k_euler_ancestral" >(Recommended)Euler Ancestral</OptionInput>
<OptionInput value="k_dpmpp_2s_ancestral" >(Recommended)DPM++ 2S Ancestral</OptionInput>
<OptionInput value="k_dpmpp_2m_sde" >(Recommended)DPM++ 2M SDE</OptionInput>
<OptionInput value="k_euler" >(Other)Euler</OptionInput>
<OptionInput value="k_dpmpp_2m" >(Other)DPM++ 2M</OptionInput>
<OptionInput value="k_dpmpp_sde" >(Other)DPM++ SDE</OptionInput>
</SelectInput>
{:else}
<SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}> <SelectInput className="mt-2 mb-4" bind:value={DBState.db.NAIImgConfig.sampler}>
<OptionInput value="k_euler" >Euler</OptionInput> <OptionInput value="k_euler" >Euler</OptionInput>
<OptionInput value="k_euler_ancestral" >Euler Ancestral</OptionInput> <OptionInput value="k_euler_ancestral" >Euler Ancestral</OptionInput>
@@ -192,6 +243,8 @@
<OptionInput value="k_dpmpp_2s" >DPM++ 2S</OptionInput> <OptionInput value="k_dpmpp_2s" >DPM++ 2S</OptionInput>
<OptionInput value="ddim_v3" >DDIM</OptionInput> <OptionInput value="ddim_v3" >DDIM</OptionInput>
</SelectInput> </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>
@@ -199,10 +252,24 @@
{#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'
|| DBState.db.NAIImgModel === 'nai-diffusion-4-curated-preview'}
<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'
|| DBState.db.NAIImgModel === 'nai-diffusion-4-curated-preview'}
<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>

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,
use_coords: db.NAIImgConfig.use_coords,
legacy_uc: db.NAIImgConfig.legacy_uc,
v4_prompt:{
caption:{
base_caption:genPrompt,
char_captions: []
},
use_coords: db.NAIImgConfig.v4_prompt.use_coords,
use_order: db.NAIImgConfig.v4_prompt.use_order
},
"v4_negative_prompt":{
caption:{
base_caption:neg,
char_captions: []
},
legacy_uc: db.NAIImgConfig.v4_negative_prompt.legacy_uc,
}
}
},
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)
@@ -140,65 +196,26 @@ 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 !== ''){
refimgbase64 = Buffer.from(await readImage(db.NAIImgConfig.refimage)).toString('base64'); refimgbase64 = Buffer.from(await readImage(db.NAIImgConfig.refimage)).toString('base64');
} }
} }
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
} }
console.log({img2img:reqlist});
}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 +225,15 @@ 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, console.log({generate:reqlist});
"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: { reqlist.body.action = 'generate';
"input": genPrompt, console.log({nothing:reqlist});
"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,9 +264,49 @@ 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,
} }
} }
}
//add NAI v4 (사용중인 사람용 추가 DB Init)
if(checkNullish(data.NAIImgConfig.v4_prompt)){
data.NAIImgConfig.autoSmea = false;
data.NAIImgConfig.use_coords = false;
data.NAIImgConfig.legacy_uc = false;
data.NAIImgConfig.v4_prompt = {
caption:{
base_caption:"",
char_captions:[]
},
use_coords:false,
use_order:true
};
data.NAIImgConfig.v4_negative_prompt = {
caption:{
base_caption:"",
char_captions:[]
},
legacy_uc:false,
};
}
if(checkNullish(data.customTextTheme)){ if(checkNullish(data.customTextTheme)){
data.customTextTheme = { data.customTextTheme = {
FontColorStandard: "#f8f8f2", FontColorStandard: "#f8f8f2",
@@ -1363,7 +1403,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,6 +1417,39 @@ 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{