Spaces:
Configuration error
Configuration error
Z-Image-Turbo API Wrapper - Complete Setup Guide
Overview
This wrapper provides a simple REST API endpoint that handles:
- Calling the Gradio Z-Image-Turbo API
- Polling for results (async handling)
- Returning the direct image URL
Two implementations provided:
- Python (Flask)
- Node.js (Express)
Python Setup (Recommended)
Prerequisites
- Python 3.8+
- pip
Installation
- Clone/Download files
# Get app.py, requirements.txt, USAGE_EXAMPLES.md
ls -la
# Should see: app.py, requirements.txt, USAGE_EXAMPLES.md
- Install dependencies
pip install -r requirements.txt
- Run the server
python app.py
Expected output: ```
Z-Image-Turbo API Wrapper
Gradio API URL: https://mohamedislegend4-z-image-turbo-api.hf.space Starting Flask server...
- Running on http://0.0.0.0:5000
4. **Test the API**
```bash
# Health check
curl http://localhost:5000/health
# Generate image
curl -X POST http://localhost:5000/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "A beautiful sunset"}'
Production Deployment (Python)
Using Gunicorn:
pip install gunicorn
# Run with 4 workers
gunicorn -w 4 -b 0.0.0.0:5000 --timeout 300 app:app
Using systemd service:
sudo cat > /etc/systemd/system/z-image-api.service << EOF
[Unit]
Description=Z-Image-Turbo API Wrapper
After=network.target
[Service]
Type=notify
User=www-data
WorkingDirectory=/home/www-data/z-image-api
ExecStart=/usr/bin/gunicorn -w 4 -b 0.0.0.0:5000 --timeout 300 app:app
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable z-image-api
sudo systemctl start z-image-api
Node.js Setup
Prerequisites
- Node.js 14+
- npm
Installation
- Download files
# Get server.js and package.json
ls -la
# Should see: server.js, package.json
- Install dependencies
npm install
- Run the server
npm start
Or with auto-reload during development:
npm install --save-dev nodemon
npm run dev
Expected output:
[2024-01-15T10:30:45.123Z] INFO: ============================================================
[2024-01-15T10:30:45.124Z] INFO: Z-Image-Turbo API Wrapper (Node.js)
[2024-01-15T10:30:45.125Z] INFO: ============================================================
[2024-01-15T10:30:45.126Z] INFO: Gradio API URL: https://...
[2024-01-15T10:30:45.127Z] INFO: Server running on: http://localhost:5000
- Test the API
# Health check
curl http://localhost:5000/health
# Generate image
curl -X POST http://localhost:5000/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "A beautiful sunset"}'
Production Deployment (Node.js)
Using PM2:
npm install -g pm2
# Start
pm2 start server.js --name "z-image-api" -i 4
# Make it restart on boot
pm2 startup
pm2 save
Using Docker:
cat > Dockerfile << 'EOF'
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY server.js .
EXPOSE 5000
CMD ["node", "server.js"]
EOF
docker build -t z-image-api .
docker run -d -p 5000:5000 --name z-image-api z-image-api
Docker Deployment (Both)
Python Version
cat > Dockerfile << 'EOF'
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "--timeout", "300", "app:app"]
EOF
# Build
docker build -t z-image-api-python .
# Run
docker run -d -p 5000:5000 --name z-image-api z-image-api-python
Docker Compose (Both)
version: '3.8'
services:
# Python version
z-image-python:
image: z-image-api-python
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
restart: unless-stopped
# Node.js version (use one or the other)
z-image-node:
image: z-image-api-node
ports:
- "5001:5000"
environment:
- NODE_ENV=production
restart: unless-stopped
# Nginx reverse proxy
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- z-image-python
- z-image-node
restart: unless-stopped
API Usage Quick Start
Basic Request
curl -X POST http://localhost:5000/api/generate \
-H "Content-Type: application/json" \
-d '{
"prompt": "A serene forest landscape at dawn",
"steps": 20,
"height": 512,
"width": 512
}'
Response Format
{
"success": true,
"prompt": "A serene forest landscape at dawn",
"steps": 20,
"height": 512,
"width": 512,
"image_url": "https://example.com/path/to/image.png",
"image_path": "/tmp/path/to/image",
"size": 234567,
"mime_type": "image/png",
"filename": "image.png"
}
Download Generated Image
RESPONSE=$(curl -s -X POST http://localhost:5000/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "A beautiful sunset"}')
IMAGE_URL=$(echo $RESPONSE | jq -r '.image_url')
if [ "$IMAGE_URL" != "null" ]; then
curl -o my_image.png "$IMAGE_URL"
echo "Downloaded to my_image.png"
fi
Configuration
Environment Variables
Create a .env file:
# API Configuration
GRADIO_API_URL=https://mohamedislegend4-z-image-turbo-api.hf.space
PORT=5000
# Server Configuration
WORKERS=4
TIMEOUT=300
DEBUG=False
# Polling Configuration
MAX_POLL_ATTEMPTS=120
POLL_INTERVAL=1
Python: Load Environment Variables
Modify app.py:
from dotenv import load_dotenv
import os
load_dotenv()
GRADIO_API_URL = os.getenv("GRADIO_API_URL", "https://...")
MAX_POLL_ATTEMPTS = int(os.getenv("MAX_POLL_ATTEMPTS", 120))
Node.js: Load Environment Variables
Modify server.js:
require('dotenv').config();
const PORT = process.env.PORT || 5000;
const GRADIO_API_URL = process.env.GRADIO_API_URL || 'https://...';
const MAX_POLL_ATTEMPTS = parseInt(process.env.MAX_POLL_ATTEMPTS) || 120;
Troubleshooting
Issue: "Connection refused"
Solution: Make sure the server is running
# Python
python app.py
# Node.js
npm start
Issue: "Timeout waiting for image"
Cause: The Gradio API is slow or overloaded Solutions:
- Reduce
stepsparameter (default 20, try 8-15) - Use smaller image dimensions (try 256x256 or 512x512)
- Try again later
Issue: "Empty image_url in response"
Cause: The Gradio API didn't return image data Debug: Check server logs for error messages
Issue: High latency/slow responses
Cause:
- First request needs model initialization
- Network latency to Gradio API Solutions:
- Use a server closer to the Gradio API
- Consider running Z-Image-Turbo locally
Issue: "Port already in use"
Solution: Change port or kill existing process
# Find process on port 5000
lsof -i :5000
# Kill it
kill -9 <PID>
# Or use different port
python app.py --port 5001
Performance Tuning
For Python (Gunicorn)
# Adjust workers based on CPU cores
# Rule: workers = (2 × cores) + 1
gunicorn -w 8 -b 0.0.0.0:5000 \
--timeout 300 \
--max-requests 1000 \
--max-requests-jitter 100 \
app:app
For Node.js (Cluster)
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
const numWorkers = os.cpus().length;
for (let i = 0; i < numWorkers; i++) {
cluster.fork();
}
} else {
app.listen(PORT);
}
Caching Responses
from functools import lru_cache
@app.route('/api/generate', methods=['POST'])
@lru_cache(maxsize=100)
def generate():
# ... implementation
Reverse Proxy Setup (Nginx)
upstream z_image_api {
server localhost:5000 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name api.example.com;
location /api/ {
proxy_pass http://z_image_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Increase timeout for image generation
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
# Buffering
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
location /health {
proxy_pass http://z_image_api;
}
}
Monitoring & Logging
Python Logs
# Real-time
tail -f app.log
# With Flask's built-in logging
# Logs appear in console by default
Node.js Logs
# PM2 logs
pm2 logs z-image-api
# Docker logs
docker logs -f z-image-api
Health Check Script
#!/bin/bash
while true; do
HEALTH=$(curl -s http://localhost:5000/health | jq -r '.status')
if [ "$HEALTH" == "ok" ]; then
echo "✓ API is healthy"
else
echo "✗ API is down!"
# Restart if needed
fi
sleep 60
done
API Rate Limiting
Python with Flask-Limiter
pip install Flask-Limiter
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app=app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/api/generate', methods=['POST'])
@limiter.limit("5 per minute")
def generate():
# ... implementation
Node.js with express-rate-limit
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 5 // 5 requests per minute
});
app.post('/api/generate', limiter, (req, res) => {
// ... implementation
});
Next Steps
- Start the server (Python or Node.js)
- Test with curl (see examples above)
- Integrate into your application
- Deploy to production (Docker, systemd, PM2, etc.)
- Monitor performance (logs, metrics, health checks)
See USAGE_EXAMPLES.md for more detailed code examples!