feature: StableStudio web interface

run `aimg server` and visit http://127.0.0.1:8000/
pull/339/head
Bryce 1 year ago committed by Bryce Drennan
parent 8e28a2ed02
commit 7b032c8e9a

@ -79,6 +79,19 @@ require_pyenv:
echo -e "\033[0;32m ✔️ pyenv-virtualenv installed\033[0m";\
fi
update-stablestudio:
@echo "Updating stablestudio"
cd ../imaginAIry-StableStudio && \
yarn build && \
yarn build:production
rm -rf imaginairy/http/stablestudio/dist
cp -R ../imaginAIry-StableStudio/packages/stablestudio-ui/dist imaginairy/http/stablestudio/dist
rm -rf imaginairy/http/stablestudio/dist/examples
rm -rf imaginairy/http/stablestudio/dist/media
rm -rf imaginairy/http/stablestudio/dist/presets
cp ../imaginAIry-StableStudio/LICENSE imaginairy/http/stablestudio/dist/LICENSE
@echo "Updated stablestudio"
vendor_openai_clip:
mkdir -p ./downloads
-cd ./downloads && git clone git@github.com:openai/CLIP.git

@ -28,6 +28,14 @@ AI imagined images. Pythonic generation of stable diffusion images.
<img src="assets/009719_942389026_kdpmpp2m15_PS7.5_a_flower.gif" height="256">
</p>
### Run API server and StableStudio web interface (alpha)
Generate images via API or web interface. Much smaller featureset compared to the command line tool.
```bash
>> aimg server
```
Visit http://localhost:8000/ and http://localhost:8000/docs
<img src="https://github.com/Stability-AI/StableStudio/blob/a65d4877ad7d309627808a169818f1add8c278ae/misc/GenerateScreenshot.png?raw=true">
### Image Structure Control [by ControlNet](https://github.com/lllyasviel/ControlNet)
Generate images guided by body poses, depth maps, canny edges, hed boundaries, or normal maps.
@ -486,6 +494,7 @@ A: The AI models are cached in `~/.cache/` (or `HUGGINGFACE_HUB_CACHE`). To dele
**13.0.0**
- 🎉 feature: multi-controlnet support. pass in multiple `--control-mode`, `--control-image`, and `--control-image-raw` arguments.
- 🎉 feature: add colorization controlnet. improve `aimg colorize` command
- 🎉🧪 feature: Graphical Web Interface [StableStudio](https://github.com/Stability-AI/StableStudio). run `aimg server` and visit http://127.0.0.1:8000/
- 🎉🧪 feature: API server `aimg server` command. Runs a http webserver (not finished). After running, visit http://127.0.0.1:8000/docs for api.
- 🎉🧪 feature: API support for [Stablity AI's new open-source Generative AI interface, StableStudio](https://github.com/Stability-AI/StableStudio).
- 🎉🧪 feature: "better" memory management. If GPU is full, least-recently-used model is moved to RAM. I'm not confident this works well.

@ -1,9 +1,11 @@
import os.path
from asyncio import Lock
from fastapi import FastAPI, Query
from fastapi.concurrency import run_in_threadpool
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from fastapi.staticfiles import StaticFiles
from imaginairy.http.models import ImagineWebPrompt
from imaginairy.http.stablestudio import routes
@ -40,3 +42,9 @@ async def imagine_get_endpoint(text: str = Query(...)):
async with gpu_lock:
img_io = await run_in_threadpool(generate_image, ImagineWebPrompt(prompt=text))
return StreamingResponse(img_io, media_type="image/jpg")
static_folder = os.path.dirname(os.path.abspath(__file__)) + "/stablestudio/dist"
print(f"static_folder: {static_folder}")
app.mount("/", StaticFiles(directory=static_folder, html=True), name="static")

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Stability AI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,52 @@
var l = (t) => {
let e,
i = new Set(),
r = (o, u) => {
let s = typeof o == "function" ? o(e) : o;
if (!Object.is(s, e)) {
let g = e;
(e = u ?? typeof s != "object" ? s : Object.assign({}, e, s)),
i.forEach((p) => p(e, g));
}
},
a = () => e,
n = {
setState: r,
getState: a,
subscribe: (o) => (i.add(o), () => i.delete(o)),
destroy: () => {
(import.meta.env && import.meta.env.MODE) !== "production" &&
console.warn(
"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
),
i.clear();
},
};
return (e = t(r, a, n)), n;
},
d = (t) => (t ? l(t) : l),
c = (t) => (e) => d((i, r) => t({ set: i, get: r, context: e }));
var m = c(() => ({
manifest: {
name: "Example Plugin",
description: "An example plugin for StableStudio",
version: "1.2.3",
author: "Bobby Joe",
license: "MIT",
link: "https://github.com",
icon: "https://place.dog/100/100",
},
getStatus: () => ({
indicator: "success",
message: "This plugin is working",
}),
settings: {
exampleSetting: {
type: "string",
default: "Hello, World!",
placeholder: "Example setting",
},
},
}));
export { m as createPlugin };
//# sourceMappingURL=index.js.map

@ -0,0 +1,52 @@
var l = (t) => {
let e,
i = new Set(),
r = (o, u) => {
let s = typeof o == "function" ? o(e) : o;
if (!Object.is(s, e)) {
let g = e;
(e = u ?? typeof s != "object" ? s : Object.assign({}, e, s)),
i.forEach((p) => p(e, g));
}
},
a = () => e,
n = {
setState: r,
getState: a,
subscribe: (o) => (i.add(o), () => i.delete(o)),
destroy: () => {
(import.meta.env && import.meta.env.MODE) !== "production" &&
console.warn(
"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
),
i.clear();
},
};
return (e = t(r, a, n)), n;
},
d = (t) => (t ? l(t) : l),
c = (t) => (e) => d((i, r) => t({ set: i, get: r, context: e }));
var m = c(() => ({
// manifest: {
// name: "Example Plugin",
// description: "An example plugin for StableStudio",
// version: "1.2.3",
// author: "Bobby Joe",
// license: "MIT",
// link: "https://github.com",
// icon: "place.dog/100/100",
// },
getStatus: () => ({
indicator: "success",
message: "This plugin is working",
}),
settings: {
exampleSetting: {
type: "string",
default: "Hello, World!",
placeholder: "Example setting",
},
},
}));
export { m as createPlugin };
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,8 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_201_2" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="1" width="30" height="30">
<path d="M20.342 1.56128L30.6364 12.5235L26.4184 26.9581L11.906 30.4303L1.61151 19.4681L5.82952 5.03354L20.342 1.56128Z" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_201_2)">
<path d="M44.6902 -40.8057L-40.8056 -12.6903L-12.6902 72.8055L72.8055 44.6901L44.6902 -40.8057Z" fill="#D3D3D3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 507 B

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>StableStudio</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link
rel="preload"
href="Inter.ttf"
as="font"
type="font/ttf"
crossorigin
/>
<script type="module" crossorigin src="/assets/index-80230e31.js"></script>
<link rel="stylesheet" href="/assets/index-03379660.css">
</head>
<body>
<div
id="tooltip-root"
class="dark h-[100vh] w-[100vw] overflow-hidden text-white"
></div>
<div id="modal-root" class="dark overflow-hidden text-white"></div>
<div id="app" class="dark"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

@ -54,6 +54,8 @@ async def list_models():
model_objs = []
for model_config in MODEL_CONFIGS:
if "inpaint" in model_config.description.lower():
continue
model_obj = StableStudioModel(
id=model_config.short_name,
name=model_config.description,

@ -5,7 +5,7 @@ from imaginairy import imagine
def generate_image(prompt):
"""ImagineWebPrompt to generated image"""
"""ImagineWebPrompt to generated image."""
prompt = prompt.to_imagine_prompt()
result = next(imagine([prompt]))
img = result.images["generated"]
@ -16,7 +16,7 @@ def generate_image(prompt):
def generate_image_b64(prompt):
"""ImagineWebPrompt to generated base64 encoded image"""
"""ImagineWebPrompt to generated base64 encoded image."""
img_io = generate_image(prompt)
img_base64 = base64.b64encode(img_io.getvalue())
return img_base64

@ -60,6 +60,9 @@ setup(
"configs/*.yaml",
"data/*.*",
"bin/*.*",
"http/stablestudio/dist/*.*",
"http/stablestudio/dist/assets/*.*",
"http/stablestudio/dist/LICENSE",
"enhancers/phraselists/*.txt",
"vendored/clip/*.txt.gz",
"vendored/clipseg/*.pth",

Loading…
Cancel
Save