1
0
Fork 0

wire up basic API client

This commit is contained in:
Sean Sube 2023-01-04 22:54:31 -06:00
parent c4e542bc40
commit 85f117823c
5 changed files with 117 additions and 7 deletions

28
gui/src/api/client.ts Normal file
View File

@ -0,0 +1,28 @@
export interface Txt2ImgParams {
prompt: string;
cfg: number;
steps: number;
}
export interface ApiClient {
txt2img(params: Txt2ImgParams): Promise<string>;
}
export function makeClient(root: string, f = fetch): ApiClient {
return {
async txt2img(params: Txt2ImgParams): Promise<string> {
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);
if (res.status === 200) {
const imageBlob = await res.blob();
return URL.createObjectURL(imageBlob);
} else {
throw new Error('request error');
}
},
}
}

View File

@ -1,9 +1,19 @@
import { TabContext, TabList, TabPanel } from '@mui/lab'; import { TabContext, TabList, TabPanel } from '@mui/lab';
import { Box, Container, Tab, Typography } from '@mui/material'; import { Box, Container, MenuItem, Select, Tab, Typography } from '@mui/material';
import * as React from 'react'; import * as React from 'react';
export function OnnxWeb() { import { ApiClient } from '../api/client.js';
const [tab, setTab] = React.useState('1'); import { Txt2Img } from './Txt2Img.js';
const { useState } = React;
export interface OnnxWebProps {
client: ApiClient;
}
export function OnnxWeb(props: OnnxWebProps) {
const [tab, setTab] = useState('1');
const [model, setModel] = useState('v1.5');
return ( return (
<div> <div>
@ -13,6 +23,14 @@ export function OnnxWeb() {
ONNX Web GUI ONNX Web GUI
</Typography> </Typography>
</Box> </Box>
<Box sx={{ my: 4 }}>
<Select value={model} onChange={(e) => {
setModel(e.target.value);
}}>
<MenuItem value='v1.4'>Stable Diffusion v1.4</MenuItem>
<MenuItem value='v1.5'>Stable Diffusion v1.5</MenuItem>
</Select>
</Box>
<TabContext value={tab}> <TabContext value={tab}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}> <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={(_e, idx) => { <TabList onChange={(_e, idx) => {
@ -23,9 +41,18 @@ export function OnnxWeb() {
<Tab label="settings" value="3" /> <Tab label="settings" value="3" />
</TabList> </TabList>
</Box> </Box>
<TabPanel value="1">txt2img</TabPanel> <TabPanel value="1">
<TabPanel value="2">img2img</TabPanel> <Box>
<TabPanel value="3">settings</TabPanel> txt2img using {model}
</Box>
<Txt2Img {...props} />
</TabPanel>
<TabPanel value="2">
<Box>
img2img using {model}
</Box>
</TabPanel>
<TabPanel value="3">settings for onnx-web</TabPanel>
</TabContext> </TabContext>
</Container> </Container>
</div> </div>

View File

@ -0,0 +1,47 @@
import { Box, Button, TextField } from "@mui/material";
import * as React from 'react';
import { ApiClient } from "../api/client";
const { useEffect, useState } = React;
export interface Txt2ImgProps {
client: ApiClient;
}
export function Txt2Img(props: Txt2ImgProps) {
const { client } = props;
const [image, setImage] = useState('');
const [cfg, setCfg] = useState(5);
const [prompt, setPrompt] = useState('an astronaut eating a hamburger');
const [steps, setSteps] = useState(20);
async function getImage() {
const image = await client.txt2img({ prompt, cfg, steps });
console.log(prompt, image);
setImage(image);
}
function renderImage() {
if (image === '') {
return <div>No image</div>;
} else {
return <img src={image} />;
}
}
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()}
</Box>;
}

5
gui/src/config.ts Normal file
View File

@ -0,0 +1,5 @@
export const CONFIG = {
api: {
root: 'http://ssube-desktop.home.holdmyran.ch:5000',
},
};

View File

@ -1,12 +1,15 @@
import { mustExist } from '@apextoaster/js-utils'; import { mustExist } from '@apextoaster/js-utils';
import * as React from 'react'; import * as React from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import { makeClient } from './api/client';
import { OnnxWeb } from './components/OnnxWeb'; import { OnnxWeb } from './components/OnnxWeb';
import { CONFIG } from './config';
export function main() { export function main() {
const appElement = mustExist(document.getElementById('app')); const appElement = mustExist(document.getElementById('app'));
const app = ReactDOM.createRoot(appElement); const app = ReactDOM.createRoot(appElement);
app.render(<OnnxWeb />); const client = makeClient(CONFIG.api.root);
app.render(<OnnxWeb client={client} />);
} }
main(); main();