Z-Image-Turbo-API / SETUP_GUIDE.md
mohamedislegend4's picture
Upload 9 files
d6e90da verified
|
Raw
History Blame Contribute Delete
10.4 kB
# Z-Image-Turbo API Wrapper - Complete Setup Guide
## Overview
This wrapper provides a simple REST API endpoint that handles:
1. Calling the Gradio Z-Image-Turbo API
2. Polling for results (async handling)
3. Returning the direct image URL
**Two implementations provided:**
- Python (Flask)
- Node.js (Express)
---
## Python Setup (Recommended)
### Prerequisites
- Python 3.8+
- pip
### Installation
1. **Clone/Download files**
```bash
# Get app.py, requirements.txt, USAGE_EXAMPLES.md
ls -la
# Should see: app.py, requirements.txt, USAGE_EXAMPLES.md
```
2. **Install dependencies**
```bash
pip install -r requirements.txt
```
3. **Run the server**
```bash
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:
```bash
pip install gunicorn
# Run with 4 workers
gunicorn -w 4 -b 0.0.0.0:5000 --timeout 300 app:app
```
Using systemd service:
```bash
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
1. **Download files**
```bash
# Get server.js and package.json
ls -la
# Should see: server.js, package.json
```
2. **Install dependencies**
```bash
npm install
```
3. **Run the server**
```bash
npm start
```
Or with auto-reload during development:
```bash
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
```
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 (Node.js)
Using PM2:
```bash
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:
```bash
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
```bash
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)
```yaml
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
```bash
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
```json
{
"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
```bash
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:
```bash
# 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`:
```python
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`:
```javascript
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
```bash
# Python
python app.py
# Node.js
npm start
```
### Issue: "Timeout waiting for image"
**Cause:** The Gradio API is slow or overloaded
**Solutions:**
- Reduce `steps` parameter (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
```bash
# 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)
```bash
# 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)
```javascript
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
```python
from functools import lru_cache
@app.route('/api/generate', methods=['POST'])
@lru_cache(maxsize=100)
def generate():
# ... implementation
```
---
## Reverse Proxy Setup (Nginx)
```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
```bash
# Real-time
tail -f app.log
# With Flask's built-in logging
# Logs appear in console by default
```
### Node.js Logs
```bash
# PM2 logs
pm2 logs z-image-api
# Docker logs
docker logs -f z-image-api
```
### Health Check Script
```bash
#!/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
```bash
pip install Flask-Limiter
```
```python
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
```bash
npm install express-rate-limit
```
```javascript
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
1. **Start the server** (Python or Node.js)
2. **Test with curl** (see examples above)
3. **Integrate into your application**
4. **Deploy to production** (Docker, systemd, PM2, etc.)
5. **Monitor performance** (logs, metrics, health checks)
See `USAGE_EXAMPLES.md` for more detailed code examples!