tiny-army / web /imagenServer.js
polats's picture
Add Klein ZeroGPU portrait option
f77d660
// Image engines backed by our /portrait route (server-side, so keys stay off the client):
// • zimage-local — Z-Image-Turbo on YOUR GPU (TINY_IMAGE_MODE=local). Localhost only.
// • flux / flux-dev — FLUX via NVIDIA NIM (or HF Inference) in the cloud.
// Mirrors ttsQwen3.js (engine + engineLocal). generate() returns a PNG Blob.
export const isLocalhost = () => {
try { return /^(localhost|127\.0\.0\.1|\[?::1\]?|0\.0\.0\.0)$/i.test(location.hostname) } catch { return false }
}
async function postPortrait(body) {
const resp = await fetch('/portrait', {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
})
if (!resp.ok) throw new Error(`portrait ${resp.status}: ${(await resp.text()).slice(0, 160)}`)
return resp.blob() // image/png
}
const common = { needsDownload: false, networked: true, ensure: async () => {} }
// LOCAL: same-origin /portrait on a locally-run app.py (TINY_IMAGE_MODE=local → Z-Image
// on your GPU). Only offered on localhost; shown disabled with a note in prod.
export const engineLocal = {
...common,
id: 'zimage-local',
label: 'Z-Image-Turbo · local (your GPU)',
available: () => isLocalhost(),
note: 'run the project locally',
generate: (prompt, { seed } = {}) => postPortrait({ prompt, seed, engine: 'local' }),
backendLabel: () => '🖥 local model',
}
export const engineKleinZeroGpu = {
...common,
id: 'klein-zerogpu',
label: 'FLUX.2 klein 4B · ZeroGPU',
available: () => true,
generate: (prompt, { seed } = {}) => postPortrait({ prompt, seed, engine: 'klein', provider: 'flux-klein-4b' }),
backendLabel: () => 'ZeroGPU FLUX.2 klein 4B',
}
// CLOUD: FLUX via the backend proxy (NVIDIA NIM, else HF Inference). `provider` picks the
// NIM sub-model. schnell = fast (4 steps), dev = higher quality (28 steps).
export const engineCloud = {
...common,
id: 'flux',
label: 'FLUX schnell · cloud (fast)',
available: () => true,
generate: (prompt, { seed } = {}) => postPortrait({ prompt, seed, engine: 'cloud', provider: 'flux-schnell' }),
backendLabel: () => '☁ FLUX (NIM)',
}
export const engineCloudDev = {
...common,
id: 'flux-dev',
label: 'FLUX dev · cloud (higher quality)',
available: () => true,
generate: (prompt, { seed } = {}) => postPortrait({ prompt, seed, engine: 'cloud', provider: 'flux-dev' }),
backendLabel: () => '☁ FLUX dev (NIM)',
}