stack txt2img inputs, read host/port for dev server
This commit is contained in:
parent
85f117823c
commit
8bbcdc175b
|
@ -0,0 +1,3 @@
|
|||
# ONNX Web
|
||||
|
||||
This is a web GUI for ONNX models, providing a way to run AMD GPU-accelerated models on Windows with a remote web UI.
|
13
gui/serve.js
13
gui/serve.js
|
@ -1,11 +1,16 @@
|
|||
import { mustDefault } from '@apextoaster/js-utils';
|
||||
import { readFile } from 'fs';
|
||||
import { createServer } from 'http';
|
||||
import { join } from 'path';
|
||||
|
||||
const hostname = '127.0.0.1';
|
||||
const port = 3000;
|
||||
const { env } = process;
|
||||
|
||||
const host = mustDefault(env.ONNX_WEB_DEV_HOST, '0.0.0.0');
|
||||
const port = mustDefault(env.ONNX_WEB_DEV_PORT, '3000');
|
||||
const root = process.cwd();
|
||||
|
||||
const portNum = parseInt(port, 10);
|
||||
|
||||
const server = createServer((req, res) => {
|
||||
readFile(join(root, 'out', req.url || 'index.html'), function (err, data) {
|
||||
if (err) {
|
||||
|
@ -18,6 +23,6 @@ const server = createServer((req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
server.listen(port, hostname, () => {
|
||||
console.log(`Server running at http://${hostname}:${port}/`);
|
||||
server.listen(portNum, host, () => {
|
||||
console.log(`Dev server running at http://${host}:${port}/index.html`);
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { doesExist } from '@apextoaster/js-utils';
|
||||
|
||||
export interface Txt2ImgParams {
|
||||
prompt: string;
|
||||
cfg: number;
|
||||
|
@ -8,21 +10,38 @@ export interface ApiClient {
|
|||
txt2img(params: Txt2ImgParams): Promise<string>;
|
||||
}
|
||||
|
||||
export async function imageFromResponse(res: Response) {
|
||||
if (res.status === 200) {
|
||||
const imageBlob = await res.blob();
|
||||
return URL.createObjectURL(imageBlob);
|
||||
} else {
|
||||
throw new Error('request error');
|
||||
}
|
||||
}
|
||||
|
||||
export function makeClient(root: string, f = fetch): ApiClient {
|
||||
let pending: Promise<string> | undefined;
|
||||
|
||||
return {
|
||||
async txt2img(params: Txt2ImgParams): Promise<string> {
|
||||
if (doesExist(pending)) {
|
||||
console.log('skipping duplicate request, one is already pending');
|
||||
return pending;
|
||||
}
|
||||
|
||||
const { prompt, cfg, steps } = params;
|
||||
|
||||
const safePrompt = encodeURIComponent(prompt);
|
||||
const url = `${root}/txt2img?prompt=${safePrompt}&steps=${steps.toFixed(0)}&cfg=${cfg.toFixed(0)}`;
|
||||
const res = await f(url);
|
||||
const url = new URL('/txt2img', root);
|
||||
url.searchParams.append('cfg', cfg.toFixed(0));
|
||||
url.searchParams.append('prompt', prompt);
|
||||
url.searchParams.append('steps', steps.toFixed(0));
|
||||
|
||||
if (res.status === 200) {
|
||||
const imageBlob = await res.blob();
|
||||
return URL.createObjectURL(imageBlob);
|
||||
} else {
|
||||
throw new Error('request error');
|
||||
}
|
||||
pending = f(url).then((res) => {
|
||||
pending = undefined;
|
||||
return imageFromResponse(res);
|
||||
});
|
||||
|
||||
return await pending;
|
||||
},
|
||||
}
|
||||
}
|
|
@ -42,9 +42,6 @@ export function OnnxWeb(props: OnnxWebProps) {
|
|||
</TabList>
|
||||
</Box>
|
||||
<TabPanel value="1">
|
||||
<Box>
|
||||
txt2img using {model}
|
||||
</Box>
|
||||
<Txt2Img {...props} />
|
||||
</TabPanel>
|
||||
<TabPanel value="2">
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { Box, Button, TextField } from "@mui/material";
|
||||
import { Box, Button, Stack, TextField } from '@mui/material';
|
||||
import * as React from 'react';
|
||||
import { ApiClient } from "../api/client";
|
||||
|
||||
const { useEffect, useState } = React;
|
||||
import { ApiClient } from '../api/client.js';
|
||||
|
||||
const { useState } = React;
|
||||
|
||||
export interface Txt2ImgProps {
|
||||
client: ApiClient;
|
||||
|
@ -31,17 +32,21 @@ export function Txt2Img(props: Txt2ImgProps) {
|
|||
}
|
||||
|
||||
return <Box>
|
||||
<TextField label="CFG" variant="outlined" type="number" inputProps={{ min: 5, max: 30 }} value={cfg} onChange={(event) => {
|
||||
setCfg(parseInt(event.target.value, 10));
|
||||
}} />
|
||||
<TextField label="Steps" variant="outlined" type="number" inputProps={{ min: 15, max: 150 }} value={steps} onChange={(event) => {
|
||||
setSteps(parseInt(event.target.value, 10));
|
||||
}} />
|
||||
<TextField label="Prompt" variant="outlined" value={prompt} onChange={(event) => {
|
||||
console.log('changing prompt', event.target.value);
|
||||
setPrompt(event.target.value);
|
||||
}} />
|
||||
<Button onClick={getImage}>Generate</Button>
|
||||
{renderImage()}
|
||||
<Stack spacing={2}>
|
||||
<Box>
|
||||
txt2img mode
|
||||
</Box>
|
||||
<TextField label="CFG" variant="outlined" type="number" inputProps={{ min: 5, max: 30 }} value={cfg} onChange={(event) => {
|
||||
setCfg(parseInt(event.target.value, 10));
|
||||
}} />
|
||||
<TextField label="Steps" variant="outlined" type="number" inputProps={{ min: 15, max: 150 }} value={steps} onChange={(event) => {
|
||||
setSteps(parseInt(event.target.value, 10));
|
||||
}} />
|
||||
<TextField label="Prompt" variant="outlined" value={prompt} onChange={(event) => {
|
||||
setPrompt(event.target.value);
|
||||
}} />
|
||||
<Button onClick={getImage}>Generate</Button>
|
||||
{renderImage()}
|
||||
</Stack>
|
||||
</Box>;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue