Neural Style Transfer API
VGG19-based style transfer with a production FastAPI deployment
A minimal FastAPI web application to perform neural style transfer using a VGG19‑based optimization loop. Suitable for a demo deployment on a small VPS (with CPU it will be slow; GPU recommended for faster results).
Features
- Upload content + style images via web form.
- Adjustable steps and style weight.
- Returns stylized image directly.
- Simple, dependency‑light (no database).
Tech Stack
- Python, FastAPI, Uvicorn
- PyTorch + TorchVision (VGG19 features)
- Frontend: vanilla HTML/CSS/JS
Setup
python -m venv .venv
source .venv/bin/activate # (macOS/Linux)
python -m pip install --upgrade pip
pip install -r requirements.txt
If running on a CPU‑only VPS you may want to install the CPU wheels for torch explicitly (see https://pytorch.org for the right command). The pinned versions here target recent PyTorch.
Run (Dev)
uvicorn src.server:app --reload --host 0.0.0.0 --port 8000
Open: http://localhost:8000
Production Suggestions
Use gunicorn with Uvicorn workers behind Nginx:
pip install gunicorn
GUNICORN_CMD_ARGS="--timeout 180" gunicorn -k uvicorn.workers.UvicornWorker -w 1 -b 0.0.0.0:8000 src.server:app
Add Nginx reverse proxy for TLS and static caching.
Caddy Reverse Proxy Under a Subpath (/ml)
If you serve multiple apps on one domain and want this app at https://apps.example.com/ml/:
- Run the app on an internal port (e.g. 8006):
BASE_PATH=/ml GUNICORN_CMD_ARGS="--timeout 300" gunicorn -k uvicorn.workers.UvicornWorker -w 1 -b 127.0.0.1:8006 src.server:app
- In your Caddyfile:
apps.example.com {
handle /ml/* {
uri strip_prefix /ml
reverse_proxy 127.0.0.1:8006 {
header_up X-Forwarded-Prefix /ml
}
}
}
- All internal links/scripts are generated using BASE_PATH so the form posts to
/ml/stylizeand static assets load from/ml/static/style.css.
Note: If you use systemd, set Environment=BASE_PATH=/ml in the service file.
Docker
Build:
docker build -t style-transfer-app:latest .
Run (root path):
docker run --rm -p 8000:8000 style-transfer-app:latest
Run under a base path (/ml):
docker run --rm -e BASE_PATH=/ml -p 8000:8000 style-transfer-app:latest
Bind a host volume for uploads (optional temporary files):
docker run --rm -p 8000:8000 -v "$PWD/uploads":/app/uploads style-transfer-app:latest
Pre‑pulling VGG19 weights occurs at build; to disable remove the corresponding RUN line in Dockerfile.
For heavier traffic or faster inference, replace the iterative optimization with a pre‑trained fast style transfer network (e.g., Johnson et al. 2016) and precompute multiple style models.
Environment Variables
None required currently.
Notes
- Iterative optimization (default 200 steps) on CPU may take several minutes. Reduce steps or deploy a GPU instance.
- The current implementation processes one request fully in memory. For concurrency, you could queue jobs (e.g., with Celery or an asyncio task queue) and stream progress via Server‑Sent Events or WebSockets.
License
MIT (add a LICENSE file if you want explicit licensing).