Madras1 commited on
Commit
ad04d0f
Β·
verified Β·
1 Parent(s): af6e333

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +21 -0
  2. README.md +48 -10
  3. app.py +255 -0
  4. requirements.txt +28 -0
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system deps
6
+ RUN apt-get update && apt-get install -y \
7
+ git \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ # Copy requirements first for caching
11
+ COPY requirements.txt .
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ # Copy app
15
+ COPY app.py .
16
+
17
+ # Expose port
18
+ EXPOSE 7860
19
+
20
+ # Run
21
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -1,10 +1,48 @@
1
- ---
2
- title: Imagineai
3
- emoji: πŸ“‰
4
- colorFrom: purple
5
- colorTo: green
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Z-Image-Turbo API
3
+ emoji: 🎨
4
+ colorFrom: purple
5
+ colorTo: blue
6
+ sdk: docker
7
+ pinned: false
8
+ license: apache-2.0
9
+ ---
10
+
11
+ # 🎨 Z-Image-Turbo API
12
+
13
+ Generate high-quality images from text using Alibaba's **Z-Image-Turbo** model.
14
+
15
+ ## ⚠️ Performance Note
16
+
17
+ This Space runs on **CPU only**. Expect generation times of **2-5 minutes per image**.
18
+
19
+ ## πŸ“‘ API Usage
20
+
21
+ ### POST /generate
22
+
23
+ ```python
24
+ import requests
25
+
26
+ response = requests.post(
27
+ "https://YOUR_SPACE.hf.space/generate",
28
+ json={
29
+ "prompt": "a beautiful sunset over mountains",
30
+ "width": 512,
31
+ "height": 512,
32
+ "seed": -1,
33
+ "num_steps": 8
34
+ }
35
+ )
36
+
37
+ data = response.json()
38
+ # data["image_base64"] contains the PNG image as base64
39
+ # data["seed"] contains the seed used
40
+ ```
41
+
42
+ ### cURL
43
+
44
+ ```bash
45
+ curl -X POST "https://YOUR_SPACE.hf.space/generate" \
46
+ -H "Content-Type: application/json" \
47
+ -d '{"prompt": "a cat in space", "width": 512, "height": 512, "seed": -1, "num_steps": 8}'
48
+ ```
app.py ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Z-Image-Turbo API - FastAPI Implementation
3
+ Avoids Gradio/diffusers schema serialization bug
4
+ """
5
+ import os
6
+ import io
7
+ import base64
8
+ import random
9
+ import gc
10
+ from PIL import Image
11
+ from fastapi import FastAPI, HTTPException
12
+ from fastapi.responses import HTMLResponse, Response
13
+ from pydantic import BaseModel
14
+ import uvicorn
15
+
16
+ app = FastAPI(title="Z-Image-Turbo API")
17
+
18
+ # Global pipeline
19
+ pipe = None
20
+
21
+ class GenerateRequest(BaseModel):
22
+ prompt: str
23
+ width: int = 512
24
+ height: int = 512
25
+ seed: int = -1
26
+ num_steps: int = 8
27
+
28
+ class GenerateResponse(BaseModel):
29
+ image_base64: str
30
+ seed: int
31
+ status: str
32
+
33
+ def load_model():
34
+ """Lazy load the model"""
35
+ global pipe
36
+ if pipe is None:
37
+ print("Loading Z-Image-Turbo model...")
38
+ import torch
39
+ from diffusers import ZImagePipeline
40
+
41
+ pipe = ZImagePipeline.from_pretrained(
42
+ "Tongyi-MAI/Z-Image-Turbo",
43
+ torch_dtype=torch.float32,
44
+ low_cpu_mem_usage=True,
45
+ )
46
+ pipe.to("cpu")
47
+ print("Model loaded!")
48
+ return pipe
49
+
50
+ @app.get("/", response_class=HTMLResponse)
51
+ async def root():
52
+ """Simple HTML interface"""
53
+ return """
54
+ <!DOCTYPE html>
55
+ <html>
56
+ <head>
57
+ <title>Z-Image-Turbo API</title>
58
+ <style>
59
+ * { box-sizing: border-box; }
60
+ body {
61
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
62
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
63
+ color: white;
64
+ min-height: 100vh;
65
+ margin: 0;
66
+ padding: 20px;
67
+ }
68
+ .container { max-width: 800px; margin: 0 auto; }
69
+ h1 { text-align: center; font-size: 2.5em; margin-bottom: 10px; }
70
+ .subtitle { text-align: center; opacity: 0.7; margin-bottom: 30px; }
71
+ .form-group { margin-bottom: 20px; }
72
+ label { display: block; margin-bottom: 8px; font-weight: 500; }
73
+ input, textarea {
74
+ width: 100%;
75
+ padding: 12px;
76
+ border: none;
77
+ border-radius: 8px;
78
+ background: rgba(255,255,255,0.1);
79
+ color: white;
80
+ font-size: 16px;
81
+ }
82
+ textarea { min-height: 100px; resize: vertical; }
83
+ input:focus, textarea:focus { outline: 2px solid #667eea; }
84
+ button {
85
+ width: 100%;
86
+ padding: 15px;
87
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
88
+ border: none;
89
+ border-radius: 8px;
90
+ color: white;
91
+ font-size: 18px;
92
+ font-weight: 600;
93
+ cursor: pointer;
94
+ transition: transform 0.2s;
95
+ }
96
+ button:hover { transform: scale(1.02); }
97
+ button:disabled { opacity: 0.5; cursor: not-allowed; }
98
+ .result {
99
+ margin-top: 30px;
100
+ text-align: center;
101
+ padding: 20px;
102
+ background: rgba(255,255,255,0.05);
103
+ border-radius: 12px;
104
+ }
105
+ .result img { max-width: 100%; border-radius: 8px; }
106
+ .warning {
107
+ background: rgba(255,193,7,0.2);
108
+ padding: 15px;
109
+ border-radius: 8px;
110
+ margin-bottom: 20px;
111
+ border-left: 4px solid #ffc107;
112
+ }
113
+ .row { display: flex; gap: 15px; }
114
+ .row .form-group { flex: 1; }
115
+ #status { margin-top: 15px; font-style: italic; opacity: 0.8; }
116
+ </style>
117
+ </head>
118
+ <body>
119
+ <div class="container">
120
+ <h1>🎨 Z-Image-Turbo API</h1>
121
+ <p class="subtitle">Generate images from text using AI</p>
122
+
123
+ <div class="warning">
124
+ ⚠️ <strong>Running on CPU</strong> - Generation takes 2-5 minutes per image
125
+ </div>
126
+
127
+ <div class="form-group">
128
+ <label>Prompt</label>
129
+ <textarea id="prompt" placeholder="A majestic dragon flying over a crystal castle at sunset..."></textarea>
130
+ </div>
131
+
132
+ <div class="row">
133
+ <div class="form-group">
134
+ <label>Width</label>
135
+ <input type="number" id="width" value="512" min="256" max="768" step="64">
136
+ </div>
137
+ <div class="form-group">
138
+ <label>Height</label>
139
+ <input type="number" id="height" value="512" min="256" max="768" step="64">
140
+ </div>
141
+ <div class="form-group">
142
+ <label>Seed (-1 = random)</label>
143
+ <input type="number" id="seed" value="-1">
144
+ </div>
145
+ </div>
146
+
147
+ <button id="generateBtn" onclick="generate()">πŸš€ Generate Image</button>
148
+ <p id="status"></p>
149
+
150
+ <div class="result" id="result" style="display:none;">
151
+ <img id="resultImg" src="" alt="Generated image">
152
+ <p id="resultInfo"></p>
153
+ </div>
154
+ </div>
155
+
156
+ <script>
157
+ async function generate() {
158
+ const btn = document.getElementById('generateBtn');
159
+ const status = document.getElementById('status');
160
+ const result = document.getElementById('result');
161
+
162
+ btn.disabled = true;
163
+ status.textContent = 'Generating... This will take 2-5 minutes...';
164
+ result.style.display = 'none';
165
+
166
+ try {
167
+ const response = await fetch('/generate', {
168
+ method: 'POST',
169
+ headers: {'Content-Type': 'application/json'},
170
+ body: JSON.stringify({
171
+ prompt: document.getElementById('prompt').value,
172
+ width: parseInt(document.getElementById('width').value),
173
+ height: parseInt(document.getElementById('height').value),
174
+ seed: parseInt(document.getElementById('seed').value),
175
+ num_steps: 8
176
+ })
177
+ });
178
+
179
+ const data = await response.json();
180
+
181
+ if (response.ok) {
182
+ document.getElementById('resultImg').src = 'data:image/png;base64,' + data.image_base64;
183
+ document.getElementById('resultInfo').textContent = 'Seed: ' + data.seed;
184
+ result.style.display = 'block';
185
+ status.textContent = 'βœ… Done!';
186
+ } else {
187
+ status.textContent = '❌ Error: ' + (data.detail || 'Unknown error');
188
+ }
189
+ } catch (e) {
190
+ status.textContent = '❌ Error: ' + e.message;
191
+ }
192
+
193
+ btn.disabled = false;
194
+ }
195
+ </script>
196
+ </body>
197
+ </html>
198
+ """
199
+
200
+ @app.post("/generate", response_model=GenerateResponse)
201
+ async def generate(request: GenerateRequest):
202
+ """Generate an image from text prompt"""
203
+ import torch
204
+
205
+ try:
206
+ pipeline = load_model()
207
+
208
+ seed = request.seed
209
+ if seed == -1:
210
+ seed = random.randint(0, 2147483647)
211
+
212
+ generator = torch.Generator("cpu").manual_seed(seed)
213
+
214
+ width = min(max(request.width, 256), 768)
215
+ height = min(max(request.height, 256), 768)
216
+
217
+ print(f"Generating: '{request.prompt[:50]}...' at {width}x{height}, seed={seed}")
218
+
219
+ result = pipeline(
220
+ prompt=request.prompt,
221
+ width=width,
222
+ height=height,
223
+ num_inference_steps=request.num_steps,
224
+ guidance_scale=0.0,
225
+ generator=generator,
226
+ )
227
+
228
+ image = result.images[0]
229
+
230
+ # Convert to base64
231
+ buffer = io.BytesIO()
232
+ image.save(buffer, format="PNG")
233
+ image_base64 = base64.b64encode(buffer.getvalue()).decode()
234
+
235
+ gc.collect()
236
+
237
+ return GenerateResponse(
238
+ image_base64=image_base64,
239
+ seed=seed,
240
+ status="success"
241
+ )
242
+
243
+ except Exception as e:
244
+ print(f"Error: {e}")
245
+ import traceback
246
+ traceback.print_exc()
247
+ raise HTTPException(status_code=500, detail=str(e))
248
+
249
+ @app.get("/health")
250
+ async def health():
251
+ return {"status": "ok"}
252
+
253
+ if __name__ == "__main__":
254
+ port = int(os.environ.get("PORT", 7860))
255
+ uvicorn.run(app, host="0.0.0.0", port=port)
requirements.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Z-Image-Turbo API Requirements
2
+
3
+ # Fix numpy first (torch needs numpy<2)
4
+ numpy<2
5
+
6
+ # PyTorch
7
+ --extra-index-url https://download.pytorch.org/whl/cpu
8
+ torch>=2.5.0
9
+
10
+ # Diffusers from source (has Z-Image support)
11
+ git+https://github.com/huggingface/diffusers
12
+
13
+ # Other deps
14
+ transformers>=4.40.0
15
+ accelerate>=0.30.0
16
+ safetensors
17
+ sentencepiece
18
+
19
+ # FastAPI (no Gradio!)
20
+ fastapi
21
+ uvicorn[standard]
22
+ python-multipart
23
+
24
+ # Image processing
25
+ Pillow
26
+
27
+ # Utils
28
+ huggingface_hub