Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Image Generation API
# Imogen Image Generation API

FastAPI wrapper that exposes OpenAI-style image generation endpoints backed by
Diffusers.
Expand All @@ -24,6 +24,15 @@ curl -X POST http://localhost:8001/v1/images/generations \
}'
```

## Olares Packaging

The Olares chart packages Imogen as a shared application:

- Admin install: one shared GPU-backed backend for the cluster.
- User install: a lightweight user-space API entrance that proxies to the shared backend.
- Shared endpoint: `http://imagegenapi.shared.olares.com`
- User endpoint: `https://imagegenapi.{OlaresID}.olares.com`

## Environment Variables

- `HOST` (default: `0.0.0.0`)
Expand All @@ -38,4 +47,3 @@ curl -X POST http://localhost:8001/v1/images/generations \
- `IMAGE_MAX_HEIGHT` (default: `1536`)
- `IMAGE_OUTPUT_DIR` (default: `/data/outputs`)
- `IMAGE_OUTPUT_FORMAT` (`png|jpeg|jpg`, default: `png`)

4 changes: 2 additions & 2 deletions olares/imagegenapi/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: imagegenapi
description: Olares app for OpenAI-style image generation API
description: Olares shared app for Imogen OpenAI-style image generation API
type: application
version: 1.2.0
appVersion: "1.2.0"
appVersion: "1.2.0"
77 changes: 62 additions & 15 deletions olares/imagegenapi/OlaresManifest.yaml
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
olaresManifest.version: "0.11.0"
olaresManifest.type: app
apiVersion: "v2"
metadata:
name: imagegenapi
description: Private image generation API powered by Stable Diffusion XL.
description: Shared Imogen image generation API powered by Stable Diffusion XL.
icon: https://avatars.githubusercontent.com/u/139895814?s=200&v=4
appid: imagegenapi
title: Image Generation API
title: Imogen Image Generation API
version: "1.2.0"
categories:
- AI
- Utilities
- Developer Tools
sharedEntrances:
- name: imagegenapi
title: Imogen API
host: sharedentrances-imogen
icon: https://avatars.githubusercontent.com/u/139895814?s=200&v=4
port: 0
invisible: true
authLevel: internal
entrances:
- name: imagegenapi
port: 8080
host: imagegenapi-web-svc
title: Imogen API
icon: https://avatars.githubusercontent.com/u/139895814?s=200&v=4
authLevel: internal
openMethod: window
permission:
appData: true
appCache: true
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
userData:
- Home
{{- end }}
spec:
versionName: "gpu-cu128"
fullDescription: |
Image Generation API exposes OpenAI-style image generation endpoints on Olares.
Imogen Image Generation API exposes OpenAI-style image generation endpoints on Olares.

This is the shared Olares package. The administrator installs one shared Imogen backend for the cluster, while each user installs a lightweight user-space API entrance that proxies to that shared backend.

Endpoints
- `GET /`
Expand All @@ -42,13 +63,17 @@ spec:
- `GET /v1/images/{image_id}`
- Serves generated images when `response_format=url`.

Olares endpoints
- Shared app-to-app endpoint: `http://imagegenapi.shared.olares.com`
- User-space endpoint: `https://imagegenapi.{OlaresID}.olares.com`

Example request
- `curl -X POST http://imagegenapi-svc:8001/v1/images/generations -H "Content-Type: application/json" -d '{"model":"stabilityai/stable-diffusion-xl-base-1.0","prompt":"a cinematic mountain landscape at sunrise","size":"1024x1024","response_format":"url"}'`
- `curl -X POST http://imagegenapi.shared.olares.com/v1/images/generations -H "Content-Type: application/json" -d '{"model":"stabilityai/stable-diffusion-xl-base-1.0","prompt":"a cinematic mountain landscape at sunrise","size":"1024x1024","response_format":"url"}'`

Notes
- First request may be slow while model weights are pulled into app data.
- Hugging Face and torch caches are persisted under `userspace.appData`.
- Generated image files are persisted under `userspace.appData/outputs`.
- Hugging Face and torch caches are persisted by the shared backend installation.
- Generated image files are persisted by the shared backend under `outputs`.
- This package targets `amd64` Olares nodes with NVIDIA GPU support.
developer: progress44
website: https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0
Expand All @@ -60,6 +85,7 @@ spec:
url: https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0
locale:
- en-US
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
requiredMemory: 12Gi
limitedMemory: 12Gi
requiredDisk: 5Gi
Expand All @@ -68,14 +94,42 @@ spec:
limitedCpu: 4
requiredGpu: 12Gi
limitedGpu: 16Gi
{{- else }}
requiredMemory: 64Mi
limitedMemory: 256Mi
requiredDisk: 1Mi
limitedDisk: 100Mi
requiredCpu: 10m
limitedCpu: 100m
{{- end }}
supportArch:
- amd64
subCharts:
- name: imagegenapiserver
shared: true
- name: imagegenapi
options:
apiTimeout: 0
dependencies:
- name: olares
type: system
version: ">=1.12.1-0"
version: ">=1.12.3-0"
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
{{- else }}
- name: imagegenapi
type: application
version: ">=1.2.0"
mandatory: true
{{- end }}
appScope:
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
clusterScoped: true
appRef:
- imagegenapi
{{- else }}
clusterScoped: false
{{- end }}
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
envs:
- envName: OLARES_USER_HUGGINGFACE_TOKEN
required: false
Expand All @@ -87,11 +141,4 @@ envs:
applyOnChange: true
valueFrom:
envName: OLARES_USER_HUGGINGFACE_SERVICE
entrances:
- name: imagegenapi
port: 8001
host: imagegenapi-svc
title: Image Generation API
icon: https://avatars.githubusercontent.com/u/139895814?s=200&v=4
authLevel: internal
openMethod: window
{{- end }}
28 changes: 20 additions & 8 deletions olares/imagegenapi/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
# Image Generation API for Olares
# Imogen Image Generation API for Olares

This package deploys the published image:
This package deploys Imogen as an Olares shared application using the published image:

- `ghcr.io/progress44/rpi-system-image-gen-api:latest`

The app exposes OpenAI-style image generation endpoints at:
The administrator installs one shared GPU-backed backend for the Olares cluster.
Each user gets a lightweight user-space API entrance that proxies to that shared backend.

- `http://imagegenapi-svc:8001`
## Olares Endpoints

- Shared app-to-app endpoint: `http://imagegenapi.shared.olares.com`
- User-space endpoint: `https://imagegenapi.{OlaresID}.olares.com`

Use the shared endpoint for backend-to-backend calls from other Olares apps. Use the
user-space endpoint when a browser or user-installed app needs the normal Olares route.

## Chart Structure

- `imagegenapiserver`: shared backend chart deployed once for the cluster by the admin.
- `imagegenapi`: per-user OpenResty proxy chart that exposes the normal user-space API entrance.

## Endpoints

Expand All @@ -19,7 +31,7 @@ The app exposes OpenAI-style image generation endpoints at:
## Request example

```bash
curl -X POST http://imagegenapi-svc:8001/v1/images/generations \
curl -X POST http://imagegenapi.shared.olares.com/v1/images/generations \
-H "Content-Type: application/json" \
-d '{
"model": "stabilityai/stable-diffusion-xl-base-1.0",
Expand All @@ -32,7 +44,7 @@ curl -X POST http://imagegenapi-svc:8001/v1/images/generations \
## Notes

- The first request may be slower while model files are downloaded.
- Hugging Face and torch caches persist under `userspace.appData`.
- Generated outputs persist under `userspace.appData/outputs`.
- Hugging Face and torch caches persist with the shared backend installation.
- Generated outputs persist with the shared backend under `outputs`.
- Use Olares env variables `OLARES_USER_HUGGINGFACE_TOKEN` and
`OLARES_USER_HUGGINGFACE_SERVICE` if needed.
`OLARES_USER_HUGGINGFACE_SERVICE` on the admin install if needed.
6 changes: 6 additions & 0 deletions olares/imagegenapi/imagegenapi/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: imagegenapi
description: User-space API entrance for shared Imogen image generation API
type: application
version: 1.2.0
appVersion: "1.25.3-2"
122 changes: 122 additions & 0 deletions olares/imagegenapi/imagegenapi/templates/clientproxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: imagegenapi-nginx-config
namespace: {{ .Release.Namespace }}
data:
nginx.conf: |
server {
listen {{ .Values.proxy.port }};
access_log /opt/bitnami/openresty/nginx/logs/access.log;
error_log /opt/bitnami/openresty/nginx/logs/error.log;

proxy_connect_timeout 60s;
proxy_send_timeout 900s;
proxy_read_timeout 900s;
proxy_http_version 1.1;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization $http_authorization;
proxy_set_header Cookie $http_cookie;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

location / {
resolver coredns.kube-system.svc.cluster.local valid=10s;
proxy_pass http://{{ .Values.proxy.backendHost }}:{{ .Values.proxy.backendPort }};
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;

proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD" always;
add_header Access-Control-Allow-Headers "authorization,content-type,x-csrftoken,deviceType,token" always;

if ($request_method = 'OPTIONS') {
return 204;
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: imagegenapi-web
spec:
replicas: 1
selector:
matchLabels:
app: imagegenapi-web
strategy:
type: Recreate
template:
metadata:
labels:
app: imagegenapi-web
spec:
volumes:
- name: imagegenapi-nginx-config
configMap:
name: imagegenapi-nginx-config
items:
- key: nginx.conf
path: nginx.conf
containers:
- name: nginx
image: {{ .Values.proxy.image | quote }}
ports:
- containerPort: {{ .Values.proxy.port }}
protocol: TCP
env:
- name: OPENRESTY_CONF_FILE
value: /etc/nginx/nginx.conf
readinessProbe:
exec:
command:
- /bin/sh
- -c
- |
http_code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:{{ .Values.proxy.port }}/health)
[ $http_code -ge 200 ] && [ $http_code -lt 500 ]
initialDelaySeconds: 2
timeoutSeconds: 3
periodSeconds: 3
successThreshold: 1
failureThreshold: 60
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 10m
memory: 64Mi
volumeMounts:
- name: imagegenapi-nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: imagegenapi-nginx-config
mountPath: /opt/bitnami/openresty/nginx/conf/server_blocks/nginx.conf
subPath: nginx.conf
---
apiVersion: v1
kind: Service
metadata:
name: imagegenapi-web-svc
namespace: {{ .Release.Namespace }}
spec:
type: ClusterIP
selector:
app: imagegenapi-web
ports:
- name: http
protocol: TCP
port: {{ .Values.proxy.port }}
targetPort: {{ .Values.proxy.port }}
5 changes: 5 additions & 0 deletions olares/imagegenapi/imagegenapi/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
proxy:
image: docker.io/beclab/aboveos-bitnami-openresty:1.25.3-2
backendHost: imagegenapi-svc.imagegenapiserver-shared
backendPort: 8001
port: 8080
6 changes: 6 additions & 0 deletions olares/imagegenapi/imagegenapiserver/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: imagegenapiserver
description: Shared backend for Imogen image generation API
type: application
version: 1.2.0
appVersion: "1.2.0"
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
{{- $olaresEnv := .Values.olaresEnv | default dict }}
---
apiVersion: v1
kind: ConfigMap
Expand All @@ -18,11 +20,12 @@ data:
IMAGE_OUTPUT_FORMAT: {{ .Values.imagegen.outputFormat | quote }}
IMAGE_OUTPUT_DIR: /data/outputs
HF_HOME: /data/huggingface
HF_ENDPOINT: {{ .Values.olaresEnv.OLARES_USER_HUGGINGFACE_SERVICE | default "https://huggingface.co/" | quote }}
HF_TOKEN: {{ .Values.olaresEnv.OLARES_USER_HUGGINGFACE_TOKEN | default "" | quote }}
HUGGING_FACE_HUB_TOKEN: {{ .Values.olaresEnv.OLARES_USER_HUGGINGFACE_TOKEN | default "" | quote }}
HF_ENDPOINT: {{ get $olaresEnv "OLARES_USER_HUGGINGFACE_SERVICE" | default "https://huggingface.co/" | quote }}
HF_TOKEN: {{ get $olaresEnv "OLARES_USER_HUGGINGFACE_TOKEN" | default "" | quote }}
HUGGING_FACE_HUB_TOKEN: {{ get $olaresEnv "OLARES_USER_HUGGINGFACE_TOKEN" | default "" | quote }}
HF_HUB_CACHE: /data/huggingface/hub
TRANSFORMERS_CACHE: /data/huggingface/transformers
TORCH_HOME: /data/torch
NVIDIA_VISIBLE_DEVICES: {{ .Values.imagegen.nvidiaVisibleDevices | quote }}
NVIDIA_DRIVER_CAPABILITIES: {{ .Values.imagegen.nvidiaDriverCapabilities | quote }}
{{- end }}
Loading
Loading