From 8bbcdc175b191874114e70777b3cbc3716a07756 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Wed, 4 Jan 2023 23:25:27 -0600 Subject: [PATCH] stack txt2img inputs, read host/port for dev server --- README.md | 3 +++ gui/serve.js | 13 ++++++++---- gui/src/api/client.ts | 37 +++++++++++++++++++++++++--------- gui/src/components/OnnxWeb.tsx | 3 --- gui/src/components/Txt2Img.tsx | 35 ++++++++++++++++++-------------- 5 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..0b163599 --- /dev/null +++ b/README.md @@ -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. diff --git a/gui/serve.js b/gui/serve.js index 23596dc7..050406b5 100644 --- a/gui/serve.js +++ b/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`); }); diff --git a/gui/src/api/client.ts b/gui/src/api/client.ts index 1ca245ec..f72feefd 100644 --- a/gui/src/api/client.ts +++ b/gui/src/api/client.ts @@ -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; } +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 | undefined; + return { async txt2img(params: Txt2ImgParams): Promise { + 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; }, } } \ No newline at end of file diff --git a/gui/src/components/OnnxWeb.tsx b/gui/src/components/OnnxWeb.tsx index 124fe84d..47423ccd 100644 --- a/gui/src/components/OnnxWeb.tsx +++ b/gui/src/components/OnnxWeb.tsx @@ -42,9 +42,6 @@ export function OnnxWeb(props: OnnxWebProps) { - - txt2img using {model} - diff --git a/gui/src/components/Txt2Img.tsx b/gui/src/components/Txt2Img.tsx index b703017b..444571bf 100644 --- a/gui/src/components/Txt2Img.tsx +++ b/gui/src/components/Txt2Img.tsx @@ -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 - { - setCfg(parseInt(event.target.value, 10)); - }} /> - { - setSteps(parseInt(event.target.value, 10)); - }} /> - { - console.log('changing prompt', event.target.value); - setPrompt(event.target.value); - }} /> - - {renderImage()} + + + txt2img mode + + { + setCfg(parseInt(event.target.value, 10)); + }} /> + { + setSteps(parseInt(event.target.value, 10)); + }} /> + { + setPrompt(event.target.value); + }} /> + + {renderImage()} + ; }