Image captioning using BLIP (Transformers-based)
Project description
🖼️ Image Captioning API
A high-performance, production-ready REST API for ML-based image captioning — built with FastAPI, async concurrency, and GPU-optimized inference.
🚀 Features
- Zero-Disk I/O — In-memory
BytesIObuffers eliminate file system overhead (~200–500ms saved per request) - Singleton Model Loading — Model weights loaded once at startup via FastAPI
lifespanevents (sub-second latency vs. 8+ seconds with per-request loading) - Managed GPU Concurrency —
asyncio.Semaphoreprevents CUDA OOM crashes;asyncio.to_threadkeeps the API responsive during heavy inference - FP16 +
torch.compile— 50% VRAM reduction and ~25% faster execution via Tensor Core acceleration - Security Validation —
python-magicbinary header inspection +MAX_FILE_SIZEenforcement at the gate, before GPU resources are touched
📈 Performance
| Metric | Original Script | Optimized API |
|---|---|---|
| Average Latency | ~7.5s (model reloads) | ~0.6s (warm model) |
| Concurrency | Sequential (1 at a time) | Concurrent (queue-based) |
| Disk Usage | Temp file per request | 0 bytes (in-memory) |
| VRAM Stability | High OOM risk | Safe (semaphore-limited) |
🏗️ Architecture
Incoming Request
│
▼
[Security Shield] ← python-magic + MAX_FILE_SIZE check
│
▼
[In-Memory Buffer] ← io.BytesIO (no disk I/O)
│
▼
[Async Queue] ← asyncio.Semaphore (concurrency gate)
│
▼
[Background Thread] ← asyncio.to_thread (non-blocking)
│
▼
[GPU Inference] ← Singleton CaptioningModel (FP16 + torch.compile)
│
▼
Response
⚙️ Installation
# Clone the repository
git clone https://github.com/your-org/image-captioning-api.git
cd image-captioning-api
# Install dependencies
pip install -r requirements.txt
Requirements: Python 3.10+, CUDA-capable GPU, PyTorch with CUDA support.
🔧 Running the API
Development
uvicorn app:app --reload --host 0.0.0.0 --port 8000
Production (recommended)
Use Gunicorn with Uvicorn workers for maximum performance on multi-core systems:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker app:app --bind 0.0.0.0:8000
Tip: Set
-w(workers) to(2 × CPU cores) + 1as a starting point.
📡 API Reference
POST /caption
Submit an image and receive a generated caption.
Request
Content-Type: multipart/form-data
Body: file=<image>
Response
{
"caption": "A dog running through a field of sunflowers."
}
Error Responses
| Code | Reason |
|---|---|
400 |
Invalid file type or binary header mismatch |
413 |
File exceeds MAX_FILE_SIZE limit |
503 |
GPU queue at capacity |
GET /health
Returns 200 OK when the model is loaded and the API is ready.
🔐 Configuration
Set the following environment variables:
| Variable | Default | Description |
|---|---|---|
MAX_FILE_SIZE |
10485760 |
Max upload size in bytes (default: 10MB) |
GPU_CONCURRENCY |
4 |
Max simultaneous GPU inference tasks |
MODEL_PATH |
./models/captioner |
Path to model weights |
🛡️ Security
All uploads are validated before reaching GPU resources:
- Binary header inspection via
python-magic— rejects files that aren't valid images regardless of extension - Size enforcement — files exceeding
MAX_FILE_SIZEare rejected at ingestion - No disk writes — uploaded data never touches the filesystem
🧠 Key Implementation Details
Singleton Model (Lifespan)
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.model = CaptioningModel() # loaded once at startup
yield
del app.state.model # cleanup on shutdown
Managed GPU Concurrency
semaphore = asyncio.Semaphore(GPU_CONCURRENCY)
async def caption_image(file_bytes: bytes) -> str:
async with semaphore:
return await asyncio.to_thread(_run_inference, file_bytes)
FP16 Inference
model = model.half() # FP16: 50% VRAM reduction
model = torch.compile(model) # JIT-optimized kernels
📄 License
MIT License — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file image_captioning-1.0.0.tar.gz.
File metadata
- Download URL: image_captioning-1.0.0.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f779195193bb8c564075cb2f22cb34b4d19cb5df3f3224a5ae90b78920ac819b
|
|
| MD5 |
ff4e2f3d7c085d94fc77f1a50a24d83f
|
|
| BLAKE2b-256 |
b702ce672f95404ab012296c49fb1cff54a8e9da35f24d64068b3866c97d62d4
|
File details
Details for the file image_captioning-1.0.0-py3-none-any.whl.
File metadata
- Download URL: image_captioning-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f4699ed9f5d0cb840ae4e7a453b0d03bff337bf5f2ae4c2290d260e3bf49139
|
|
| MD5 |
42f9791b9ec05c52cb63b93d0bad641c
|
|
| BLAKE2b-256 |
e2c30ff94900a8161a0b9900722b8665a33b1321b5a563e8abb4a1bbdf250c63
|