feat(gui): add wildcard menu to web UI
This commit is contained in:
parent
90bc28d06e
commit
cdbdd9b4e2
|
@ -161,6 +161,10 @@ def list_schedulers(server: ServerContext):
|
||||||
return jsonify(get_pipeline_schedulers())
|
return jsonify(get_pipeline_schedulers())
|
||||||
|
|
||||||
|
|
||||||
|
def list_wildcards(server: ServerContext):
|
||||||
|
return jsonify(list(get_wildcard_data().keys()))
|
||||||
|
|
||||||
|
|
||||||
def img2img(server: ServerContext, pool: DevicePoolExecutor):
|
def img2img(server: ServerContext, pool: DevicePoolExecutor):
|
||||||
source_file = request.files.get("source")
|
source_file = request.files.get("source")
|
||||||
if source_file is None:
|
if source_file is None:
|
||||||
|
@ -597,6 +601,7 @@ def register_api_routes(app: Flask, server: ServerContext, pool: DevicePoolExecu
|
||||||
app.route("/api/settings/platforms")(wrap_route(list_platforms, server)),
|
app.route("/api/settings/platforms")(wrap_route(list_platforms, server)),
|
||||||
app.route("/api/settings/schedulers")(wrap_route(list_schedulers, server)),
|
app.route("/api/settings/schedulers")(wrap_route(list_schedulers, server)),
|
||||||
app.route("/api/settings/strings")(wrap_route(list_extra_strings, server)),
|
app.route("/api/settings/strings")(wrap_route(list_extra_strings, server)),
|
||||||
|
app.route("/api/settings/wildcards")(wrap_route(list_wildcards, server)),
|
||||||
app.route("/api/img2img", methods=["POST"])(
|
app.route("/api/img2img", methods=["POST"])(
|
||||||
wrap_route(img2img, server, pool=pool)
|
wrap_route(img2img, server, pool=pool)
|
||||||
),
|
),
|
||||||
|
|
|
@ -212,6 +212,11 @@ export function makeClient(root: string, token: Maybe<string> = undefined, f = f
|
||||||
translation: Record<string, string>;
|
translation: Record<string, string>;
|
||||||
}>;
|
}>;
|
||||||
},
|
},
|
||||||
|
async wildcards(): Promise<Array<string>> {
|
||||||
|
const path = makeApiUrl(root, 'settings', 'wildcards');
|
||||||
|
const res = await f(path);
|
||||||
|
return await res.json() as Array<string>;
|
||||||
|
},
|
||||||
async img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams, highres?: HighresParams): Promise<ImageResponseWithRetry> {
|
async img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams, highres?: HighresParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeImageURL(root, 'img2img', params);
|
const url = makeImageURL(root, 'img2img', params);
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
|
@ -51,6 +51,8 @@ export interface ApiClient {
|
||||||
translation: Record<string, string>;
|
translation: Record<string, string>;
|
||||||
}>>;
|
}>>;
|
||||||
|
|
||||||
|
wildcards(): Promise<Array<string>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a txt2img pipeline.
|
* Start a txt2img pipeline.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -72,6 +72,9 @@ export const LOCAL_CLIENT = {
|
||||||
async strings() {
|
async strings() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
async wildcards() {
|
||||||
|
throw new NoServerError();
|
||||||
|
},
|
||||||
async restart() {
|
async restart() {
|
||||||
throw new NoServerError();
|
throw new NoServerError();
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,14 +29,6 @@ export interface PromptInputProps {
|
||||||
|
|
||||||
export const PROMPT_GROUP = 75;
|
export const PROMPT_GROUP = 75;
|
||||||
|
|
||||||
function splitPrompt(prompt: string): Array<string> {
|
|
||||||
return prompt
|
|
||||||
.split(',')
|
|
||||||
.flatMap((phrase) => phrase.split(' '))
|
|
||||||
.map((word) => word.trim())
|
|
||||||
.filter((word) => word.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PromptInput(props: PromptInputProps) {
|
export function PromptInput(props: PromptInputProps) {
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const { selector, onChange } = props;
|
const { selector, onChange } = props;
|
||||||
|
@ -48,12 +40,15 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
const models = useQuery(['models'], async () => client.models(), {
|
const models = useQuery(['models'], async () => client.models(), {
|
||||||
staleTime: STALE_TIME,
|
staleTime: STALE_TIME,
|
||||||
});
|
});
|
||||||
|
const wildcards = useQuery(['wildcards'], async () => client.wildcards(), {
|
||||||
|
staleTime: STALE_TIME,
|
||||||
|
});
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
function addNetwork(type: string, name: string, weight = 1.0) {
|
function addNetwork(type: string, name: string, weight = 1.0) {
|
||||||
onChange({
|
onChange({
|
||||||
prompt: `<${type}:${name}:1.0> ${prompt}`,
|
prompt: `<${type}:${name}:${weight.toFixed(2)}> ${prompt}`,
|
||||||
negativePrompt,
|
negativePrompt,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -64,6 +59,12 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addWildcard(name: string) {
|
||||||
|
onChange({
|
||||||
|
prompt: `${prompt}, __${name}__`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const tokens = useMemo(() => {
|
const tokens = useMemo(() => {
|
||||||
const networks = extractNetworks(prompt);
|
const networks = extractNetworks(prompt);
|
||||||
return getNetworkTokens(models.data, networks);
|
return getNetworkTokens(models.data, networks);
|
||||||
|
@ -124,6 +125,18 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
addNetwork('lora', name);
|
addNetwork('lora', name);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<QueryMenu
|
||||||
|
id='wildcard'
|
||||||
|
labelKey='wildcard'
|
||||||
|
name={t('wildcard')}
|
||||||
|
query={{
|
||||||
|
result: wildcards,
|
||||||
|
selector: (result) => result,
|
||||||
|
}}
|
||||||
|
onSelect={(name) => {
|
||||||
|
addWildcard(name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,6 +257,7 @@ export const I18N_STRINGS_DE = {
|
||||||
'correction-first': 'Korrektur zuerst',
|
'correction-first': 'Korrektur zuerst',
|
||||||
'correction-last': 'Korrektur zuletzt',
|
'correction-last': 'Korrektur zuletzt',
|
||||||
},
|
},
|
||||||
|
wildcard: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -339,6 +339,7 @@ export const I18N_STRINGS_EN = {
|
||||||
'correction-first': 'Correction First',
|
'correction-first': 'Correction First',
|
||||||
'correction-last': 'Correction Last',
|
'correction-last': 'Correction Last',
|
||||||
},
|
},
|
||||||
|
wildcard: 'Wildcard',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,6 +257,7 @@ export const I18N_STRINGS_ES = {
|
||||||
'correction-first': 'corrección primero',
|
'correction-first': 'corrección primero',
|
||||||
'correction-last': 'última corrección',
|
'correction-last': 'última corrección',
|
||||||
},
|
},
|
||||||
|
wildcard: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,6 +257,7 @@ export const I18N_STRINGS_FR = {
|
||||||
'correction-first': '',
|
'correction-first': '',
|
||||||
'correction-last': '',
|
'correction-last': '',
|
||||||
},
|
},
|
||||||
|
wildcard: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue