Spaces:
Configuration error
Configuration error
| # Z-Image-Turbo API Wrapper | |
| **Simple REST API wrapper for the Z-Image-Turbo Gradio space that returns direct image URLs** | |
| ## What is this? | |
| This project wraps the Gradio-based Z-Image-Turbo API and provides: | |
| - β Simple REST endpoints | |
| - β Automatic polling for async results | |
| - β Direct image URL response | |
| - β Both Python (Flask) and Node.js (Express) implementations | |
| - β Production-ready with Docker support | |
| - β Easy deployment (systemd, PM2, Docker Compose, etc.) | |
| ## Features | |
| - **Simple API**: Single endpoint - POST `/api/generate` with a prompt | |
| - **Direct URLs**: Returns the image URL directly (no base64, no polling needed from client) | |
| - **Async Handling**: Handles the Gradio async polling internally | |
| - **Error Handling**: Graceful error responses with helpful messages | |
| - **CORS Support**: Ready for web frontend integration | |
| - **Configurable**: Adjustable timeout, polling intervals, parameters | |
| - **Logging**: Detailed logging for debugging | |
| - **Health Checks**: Built-in health endpoint | |
| - **Scalable**: Multi-worker support (Gunicorn, PM2, Docker) | |
| ## Quick Start | |
| ### Option 1: Python (Recommended) | |
| ```bash | |
| # Setup | |
| bash setup.sh | |
| # Run | |
| source venv/bin/activate | |
| python app.py | |
| # Test | |
| curl -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"prompt": "A beautiful sunset"}' | |
| ``` | |
| ### Option 2: Node.js | |
| ```bash | |
| # Setup | |
| bash setup-node.sh | |
| # Run | |
| npm start | |
| # Test | |
| curl -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"prompt": "A beautiful sunset"}' | |
| ``` | |
| ### Option 3: Docker | |
| ```bash | |
| # Python | |
| docker build -t z-image-api -f Dockerfile.python . | |
| docker run -p 5000:5000 z-image-api | |
| # Node.js | |
| docker build -t z-image-api -f Dockerfile.nodejs . | |
| docker run -p 5000:5000 z-image-api | |
| ``` | |
| ## API Endpoints | |
| ### GET `/health` | |
| Health check endpoint | |
| ```bash | |
| curl http://localhost:5000/health | |
| ``` | |
| Response: | |
| ```json | |
| {"status": "ok"} | |
| ``` | |
| ### GET `/api/info` | |
| Get API information and available parameters | |
| ```bash | |
| curl http://localhost:5000/api/info | |
| ``` | |
| ### POST `/api/generate` | |
| Generate an image | |
| **Request:** | |
| ```bash | |
| curl -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "prompt": "A beautiful sunset over mountains", | |
| "steps": 20, | |
| "height": 512, | |
| "width": 512 | |
| }' | |
| ``` | |
| **Parameters:** | |
| | Parameter | Type | Default | Required | Description | | |
| |-----------|------|---------|----------|-------------| | |
| | prompt | string | - | β Yes | Text description of the image | | |
| | steps | integer | 20 | No | Inference steps (1-50) | | |
| | height | integer | 512 | No | Image height in pixels | | |
| | width | integer | 512 | No | Image width in pixels | | |
| **Response:** | |
| ```json | |
| { | |
| "success": true, | |
| "prompt": "A beautiful sunset over mountains", | |
| "steps": 20, | |
| "height": 512, | |
| "width": 512, | |
| "image_url": "https://example.com/path/to/image.png", | |
| "image_path": "/path/to/local/image", | |
| "size": 123456, | |
| "mime_type": "image/png", | |
| "filename": "image.png" | |
| } | |
| ``` | |
| **Error Response:** | |
| ```json | |
| { | |
| "success": false, | |
| "error": "Error message describing what went wrong" | |
| } | |
| ``` | |
| ## Usage Examples | |
| ### Curl | |
| **Simple generation:** | |
| ```bash | |
| curl -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"prompt": "A cat sitting on a window sill"}' | |
| ``` | |
| **Extract and download image:** | |
| ```bash | |
| RESPONSE=$(curl -s -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"prompt": "A sunset over the ocean"}') | |
| IMAGE_URL=$(echo $RESPONSE | jq -r '.image_url') | |
| curl -o my_image.png "$IMAGE_URL" | |
| ``` | |
| ### Python | |
| ```python | |
| import requests | |
| response = requests.post( | |
| 'http://localhost:5000/api/generate', | |
| json={ | |
| 'prompt': 'A magical forest', | |
| 'steps': 25, | |
| 'height': 768, | |
| 'width': 768 | |
| } | |
| ) | |
| result = response.json() | |
| if result['success']: | |
| print(f"Image URL: {result['image_url']}") | |
| # Download it | |
| img = requests.get(result['image_url']) | |
| with open('image.png', 'wb') as f: | |
| f.write(img.content) | |
| ``` | |
| ### JavaScript | |
| ```javascript | |
| async function generateImage(prompt) { | |
| const response = await fetch('http://localhost:5000/api/generate', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| prompt: prompt, | |
| steps: 20, | |
| height: 512, | |
| width: 512 | |
| }) | |
| }); | |
| const result = await response.json(); | |
| if (result.success) { | |
| console.log('Image URL:', result.image_url); | |
| // Use the image URL | |
| document.getElementById('image').src = result.image_url; | |
| } | |
| } | |
| generateImage('A beautiful landscape'); | |
| ``` | |
| ### cURL with timeout handling | |
| ```bash | |
| #!/bin/bash | |
| TIMEOUT=600 # 10 minutes | |
| PROMPT="A futuristic city with neon lights" | |
| echo "Generating image..." | |
| RESPONSE=$(curl -s -X POST http://localhost:5000/api/generate \ | |
| --max-time $TIMEOUT \ | |
| -H "Content-Type: application/json" \ | |
| -d "{\"prompt\": \"$PROMPT\", \"steps\": 25}") | |
| if [ $? -eq 0 ]; then | |
| SUCCESS=$(echo $RESPONSE | jq -r '.success') | |
| if [ "$SUCCESS" == "true" ]; then | |
| IMAGE_URL=$(echo $RESPONSE | jq -r '.image_url') | |
| echo "β Generated: $IMAGE_URL" | |
| else | |
| ERROR=$(echo $RESPONSE | jq -r '.error') | |
| echo "β Error: $ERROR" | |
| fi | |
| else | |
| echo "β Request failed or timed out" | |
| fi | |
| ``` | |
| ## Files Included | |
| ``` | |
| βββ app.py # Flask implementation (Python) | |
| βββ server.js # Express implementation (Node.js) | |
| βββ requirements.txt # Python dependencies | |
| βββ package.json # Node.js dependencies | |
| βββ setup.sh # Python quick setup script | |
| βββ setup-node.sh # Node.js quick setup script | |
| βββ README.md # This file | |
| βββ SETUP_GUIDE.md # Detailed setup and deployment guide | |
| βββ USAGE_EXAMPLES.md # More detailed usage examples | |
| βββ Dockerfile # Docker build file | |
| ``` | |
| ## Configuration | |
| ### Environment Variables | |
| Create a `.env` file: | |
| ```bash | |
| # API Settings | |
| GRADIO_API_URL=https://mohamedislegend4-z-image-turbo-api.hf.space | |
| PORT=5000 | |
| # Server Settings | |
| WORKERS=4 | |
| TIMEOUT=300 | |
| DEBUG=False | |
| # Polling Settings | |
| MAX_POLL_ATTEMPTS=120 | |
| POLL_INTERVAL=1 | |
| ``` | |
| ### Python Configuration | |
| Edit the constants in `app.py`: | |
| ```python | |
| GRADIO_API_URL = "https://mohamedislegend4-z-image-turbo-api.hf.space" | |
| MAX_POLL_ATTEMPTS = 120 # 2 minutes | |
| POLL_INTERVAL = 1 # seconds | |
| ``` | |
| ### Node.js Configuration | |
| Edit the constants in `server.js`: | |
| ```javascript | |
| const PORT = process.env.PORT || 5000; | |
| const GRADIO_API_URL = 'https://mohamedislegend4-z-image-turbo-api.hf.space'; | |
| const MAX_POLL_ATTEMPTS = 120; | |
| const POLL_INTERVAL = 1000; // ms | |
| ``` | |
| ## Performance Tips | |
| ### Image Generation Parameters | |
| | Parameter | Fast | Balanced | High Quality | | |
| |-----------|------|----------|--------------| | |
| | steps | 8-12 | 20-25 | 40-50 | | |
| | height | 256 | 512 | 768-1024 | | |
| | width | 256 | 512 | 768-1024 | | |
| | time | 10-20s | 30-60s | 60-120s | | |
| ### Server Optimization | |
| **Python (Gunicorn):** | |
| ```bash | |
| gunicorn -w 8 -b 0.0.0.0:5000 \ | |
| --timeout 300 \ | |
| --max-requests 1000 \ | |
| --worker-class sync \ | |
| app:app | |
| ``` | |
| **Node.js (PM2):** | |
| ```bash | |
| pm2 start server.js -i 4 --name z-image-api | |
| pm2 save | |
| ``` | |
| ## Deployment | |
| ### Systemd (Python) | |
| ```bash | |
| sudo cat > /etc/systemd/system/z-image-api.service << EOF | |
| [Unit] | |
| Description=Z-Image-Turbo API | |
| After=network.target | |
| [Service] | |
| Type=simple | |
| User=www-data | |
| WorkingDirectory=/opt/z-image-api | |
| ExecStart=/opt/z-image-api/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 --timeout 300 app:app | |
| Restart=always | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| sudo systemctl daemon-reload | |
| sudo systemctl enable z-image-api | |
| sudo systemctl start z-image-api | |
| ``` | |
| ### Docker Compose | |
| See `SETUP_GUIDE.md` for complete Docker Compose configuration. | |
| ## Troubleshooting | |
| ### "Connection refused" | |
| - Ensure the server is running | |
| - Check if port 5000 is in use: `lsof -i :5000` | |
| ### "Timeout waiting for result" | |
| - The Gradio API is slow or overloaded | |
| - Try reducing `steps` or image size | |
| - Check if `mohamedislegend4-z-image-turbo-api.hf.space` is accessible | |
| ### "Empty image_url" | |
| - The Gradio API didn't return image data | |
| - Check server logs for details | |
| - Try again with simpler parameters | |
| ### Slow responses | |
| - First request initializes the model (slow) | |
| - Subsequent requests are faster | |
| - Network latency to Gradio API affects speed | |
| See `SETUP_GUIDE.md` for more troubleshooting tips. | |
| ## How It Works | |
| ``` | |
| Client Request | |
| β | |
| Flask/Express Server (this wrapper) | |
| β | |
| Call Gradio Endpoint: /gradio_api/call/v2/generate | |
| β | |
| Get event_id | |
| β | |
| Poll Result: /gradio_api/call/generate/{event_id} (every 1 second) | |
| β | |
| Wait for result (up to 2 minutes) | |
| β | |
| Extract image data | |
| β | |
| Return image_url to client | |
| β | |
| Client Response with image_url | |
| ``` | |
| ## What's Next? | |
| 1. **Start the server** (see Quick Start) | |
| 2. **Test with curl** (see API Endpoints) | |
| 3. **Integrate into your app** (see Usage Examples) | |
| 4. **Deploy to production** (see SETUP_GUIDE.md) | |
| 5. **Monitor and optimize** (see SETUP_GUIDE.md) | |
| ## Requirements | |
| **Python:** | |
| - Python 3.8+ | |
| - Flask 3.0+ | |
| - Requests 2.31+ | |
| **Node.js:** | |
| - Node.js 14+ | |
| - Express 4.18+ | |
| - Axios 1.6+ | |
| **Both:** | |
| - Internet connection (to reach Gradio API) | |
| - Reasonable timeout (images can take 30-120 seconds) | |
| ## License | |
| MIT | |
| ## Support | |
| For issues or questions: | |
| 1. Check `SETUP_GUIDE.md` troubleshooting section | |
| 2. Check server logs | |
| 3. Ensure Gradio API is accessible | |
| 4. Review `USAGE_EXAMPLES.md` for code samples | |
| ## Credits | |
| - Built for: Z-Image-Turbo by Tongyi-MAI | |
| - Gradio Space: mohamedislegend4/Z-Image-Turbo-API | |
| - Wrapper created: 2024 | |
| --- | |
| **Ready to generate images? Start with:** | |
| ```bash | |
| # Python | |
| bash setup.sh && source venv/bin/activate && python app.py | |
| # Node.js | |
| bash setup-node.sh && npm start | |
| ``` | |
| Then test with: | |
| ```bash | |
| curl -X POST http://localhost:5000/api/generate \ | |
| -H "Content-Type: application/json" \ | |
| -d '{"prompt": "Your image description here"}' | |
| ``` | |