1
0
Fork 0

Add sampler to image generation settings.

This commit is contained in:
Pabloader 2026-04-15 08:14:47 +00:00
parent a2684eda63
commit f4a8595dac
4 changed files with 59 additions and 5 deletions

View File

@ -3,11 +3,12 @@ import { useInputCallback } from "@common/hooks/useInputCallback";
import { useInputState } from "@common/hooks/useInputState";
import clsx from "clsx";
import styles from "../../assets/settings-modal.module.css";
import LLM from "../../utils/llm";
import { DEFAULT_IMAGE_GENERATION_SETTINGS, useAppState } from "../../contexts/state";
export const ImageSettings = () => {
const { imageGenerationSettings, dispatch } = useAppState();
const { width, height, negative_prompt } = imageGenerationSettings;
const { width, height, negative_prompt, sampler_name } = imageGenerationSettings;
const [widthDraft, setWidthDraft] = useInputState(String(width));
const [heightDraft, setHeightDraft] = useInputState(String(height));
@ -15,14 +16,24 @@ export const ImageSettings = () => {
const commitWidth = () => {
const parsed = parseInt(widthDraft, 10);
if (!isNaN(parsed) && parsed > 0) {
dispatch({ type: 'SET_IMAGE_GENERATION_SETTINGS', settings: { width: parsed } });
const snapped = Math.max(64, Math.round(parsed / 64) * 64);
dispatch({
type: 'SET_IMAGE_GENERATION_SETTINGS',
settings: { width: snapped }
});
setWidthDraft(String(snapped));
}
};
const commitHeight = () => {
const parsed = parseInt(heightDraft, 10);
if (!isNaN(parsed) && parsed > 0) {
dispatch({ type: 'SET_IMAGE_GENERATION_SETTINGS', settings: { height: parsed } });
const snapped = Math.max(64, Math.round(parsed / 64) * 64);
dispatch({
type: 'SET_IMAGE_GENERATION_SETTINGS',
settings: { height: snapped }
});
setHeightDraft(String(snapped));
}
};
@ -30,8 +41,18 @@ export const ImageSettings = () => {
dispatch({ type: 'SET_IMAGE_GENERATION_SETTINGS', settings: { negative_prompt: value } });
}, []);
const handleSamplerChange = useInputCallback((value) => {
dispatch({
type: 'SET_IMAGE_GENERATION_SETTINGS',
settings: { sampler_name: value as LLM.ImageSamplerName },
});
}, []);
const handleReset = () => {
dispatch({ type: 'SET_IMAGE_GENERATION_SETTINGS', settings: DEFAULT_IMAGE_GENERATION_SETTINGS });
dispatch({
type: 'SET_IMAGE_GENERATION_SETTINGS',
settings: DEFAULT_IMAGE_GENERATION_SETTINGS,
});
setWidthDraft(String(DEFAULT_IMAGE_GENERATION_SETTINGS.width));
setHeightDraft(String(DEFAULT_IMAGE_GENERATION_SETTINGS.height));
};
@ -70,6 +91,18 @@ export const ImageSettings = () => {
onKeyDown={(e) => e.key === 'Enter' && commitHeight()}
/>
</div>
<div class={styles.formGroup}>
<label class={styles.label}>Sampler</label>
<select
value={sampler_name}
onChange={handleSamplerChange}
class={styles.select}
>
{Object.values(LLM.ImageSamplerName).map(s => (
<option key={s} value={s}>{s}</option>
))}
</select>
</div>
<div class={clsx(styles.formGroup, styles.formGroupFill)}>
<label class={styles.label}>Negative Prompt</label>
<ContentEditable

View File

@ -76,12 +76,14 @@ export interface ImageGenerationSettings {
width: number;
height: number;
negative_prompt: string;
sampler_name: LLM.ImageSamplerName;
}
export const DEFAULT_IMAGE_GENERATION_SETTINGS: ImageGenerationSettings = {
width: 768,
height: 768,
negative_prompt: 'ugly face, bad face, no face, poorly drawn face, greyscale, depth of field, mutated fingers, mutated hands, extra fingers, deformed, ugly, bad anatomy, bad proportions, extra limbs, signature, text, lowres, error, missing fingers, missing limbs, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, watermark, username, blurry, artist name',
sampler_name: LLM.ImageSamplerName.KEulerA,
};
export const DEFAULT_GENERATION_SETTINGS: GenerationSettings = {

View File

@ -118,10 +118,28 @@ namespace LLM {
error: string;
}
export enum ImageSamplerName {
DDIM = 'DDIM',
LCM = 'lcm',
DPMSolver = 'dpmsolver',
KHeun = 'k_heun',
KLMS = 'k_lms',
KDpmpp2M = 'k_dpmpp_2m',
KDpmppSDE = 'k_dpmpp_sde',
KDpm2 = 'k_dpm_2',
KDpmFast = 'k_dpm_fast',
KDpmAdaptive = 'k_dpm_adaptive',
KEuler = 'k_euler',
KDpmpp2sA = 'k_dpmpp_2s_a',
KEulerA = 'k_euler_a',
KDpm2A = 'k_dpm_2_a',
}
export interface ImageGenerationSettings {
width?: number;
height?: number;
negative_prompt?: string;
sampler_name?: ImageSamplerName;
}
export interface ImageGenerationRequest {

View File

@ -478,7 +478,7 @@ export namespace Tools {
if (!appState.imageModel) {
return 'Error: No image model configured';
}
const { width: defaultWidth, height: defaultHeight, negative_prompt } = appState.imageGenerationSettings;
const { width: defaultWidth, height: defaultHeight, negative_prompt, sampler_name } = appState.imageGenerationSettings;
const response = await LLM.generateImage(appState.connection, {
model: appState.imageModel.id,
prompt: args.prompt,
@ -487,6 +487,7 @@ export namespace Tools {
width: args.width ?? defaultWidth,
height: args.height ?? defaultHeight,
negative_prompt: negative_prompt || undefined,
sampler_name: sampler_name || undefined,
},
});
if ('error' in response) {