wire up basic API client
This commit is contained in:
parent
c4e542bc40
commit
85f117823c
|
@ -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');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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>;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const CONFIG = {
|
||||||
|
api: {
|
||||||
|
root: 'http://ssube-desktop.home.holdmyran.ch:5000',
|
||||||
|
},
|
||||||
|
};
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue