1
0
Fork 0

stack txt2img inputs, read host/port for dev server

This commit is contained in:
Sean Sube 2023-01-04 23:25:27 -06:00
parent 85f117823c
commit 8bbcdc175b
5 changed files with 60 additions and 31 deletions

3
README.md Normal file
View File

@ -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.

View File

@ -1,11 +1,16 @@
import { mustDefault } from '@apextoaster/js-utils';
import { readFile } from 'fs'; import { readFile } from 'fs';
import { createServer } from 'http'; import { createServer } from 'http';
import { join } from 'path'; import { join } from 'path';
const hostname = '127.0.0.1'; const { env } = process;
const port = 3000;
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 root = process.cwd();
const portNum = parseInt(port, 10);
const server = createServer((req, res) => { const server = createServer((req, res) => {
readFile(join(root, 'out', req.url || 'index.html'), function (err, data) { readFile(join(root, 'out', req.url || 'index.html'), function (err, data) {
if (err) { if (err) {
@ -18,6 +23,6 @@ const server = createServer((req, res) => {
}); });
}); });
server.listen(port, hostname, () => { server.listen(portNum, host, () => {
console.log(`Server running at http://${hostname}:${port}/`); console.log(`Dev server running at http://${host}:${port}/index.html`);
}); });

View File

@ -1,3 +1,5 @@
import { doesExist } from '@apextoaster/js-utils';
export interface Txt2ImgParams { export interface Txt2ImgParams {
prompt: string; prompt: string;
cfg: number; cfg: number;
@ -8,21 +10,38 @@ export interface ApiClient {
txt2img(params: Txt2ImgParams): Promise<string>; 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 { export function makeClient(root: string, f = fetch): ApiClient {
let pending: Promise<string> | undefined;
return { return {
async txt2img(params: Txt2ImgParams): Promise<string> { 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 { prompt, cfg, steps } = params;
const safePrompt = encodeURIComponent(prompt); const url = new URL('/txt2img', root);
const url = `${root}/txt2img?prompt=${safePrompt}&steps=${steps.toFixed(0)}&cfg=${cfg.toFixed(0)}`; url.searchParams.append('cfg', cfg.toFixed(0));
const res = await f(url); url.searchParams.append('prompt', prompt);
url.searchParams.append('steps', steps.toFixed(0));
if (res.status === 200) { pending = f(url).then((res) => {
const imageBlob = await res.blob(); pending = undefined;
return URL.createObjectURL(imageBlob); return imageFromResponse(res);
} else { });
throw new Error('request error');
} return await pending;
}, },
} }
} }

View File

@ -42,9 +42,6 @@ export function OnnxWeb(props: OnnxWebProps) {
</TabList> </TabList>
</Box> </Box>
<TabPanel value="1"> <TabPanel value="1">
<Box>
txt2img using {model}
</Box>
<Txt2Img {...props} /> <Txt2Img {...props} />
</TabPanel> </TabPanel>
<TabPanel value="2"> <TabPanel value="2">

View File

@ -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 * 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 { export interface Txt2ImgProps {
client: ApiClient; client: ApiClient;
@ -31,17 +32,21 @@ export function Txt2Img(props: Txt2ImgProps) {
} }
return <Box> return <Box>
<TextField label="CFG" variant="outlined" type="number" inputProps={{ min: 5, max: 30 }} value={cfg} onChange={(event) => { <Stack spacing={2}>
setCfg(parseInt(event.target.value, 10)); <Box>
}} /> txt2img mode
<TextField label="Steps" variant="outlined" type="number" inputProps={{ min: 15, max: 150 }} value={steps} onChange={(event) => { </Box>
setSteps(parseInt(event.target.value, 10)); <TextField label="CFG" variant="outlined" type="number" inputProps={{ min: 5, max: 30 }} value={cfg} onChange={(event) => {
}} /> setCfg(parseInt(event.target.value, 10));
<TextField label="Prompt" variant="outlined" value={prompt} onChange={(event) => { }} />
console.log('changing prompt', event.target.value); <TextField label="Steps" variant="outlined" type="number" inputProps={{ min: 15, max: 150 }} value={steps} onChange={(event) => {
setPrompt(event.target.value); setSteps(parseInt(event.target.value, 10));
}} /> }} />
<Button onClick={getImage}>Generate</Button> <TextField label="Prompt" variant="outlined" value={prompt} onChange={(event) => {
{renderImage()} setPrompt(event.target.value);
}} />
<Button onClick={getImage}>Generate</Button>
{renderImage()}
</Stack>
</Box>; </Box>;
} }