FastAPI Foundation
Let's build a robust FastAPI application that serves ImageBind embeddings through clean REST endpoints.
🏗️ API Architecture Overview
Client Upload
→
FastAPI
→
ImageBind
→
Response
Step 1: Install Dependencies
bash
# Add to your existing Dockerfile or install in container
pip install fastapi uvicorn python-multipart aiofiles pydantic
Step 2: Create Project Structure
bash
# In your workspace directory
mkdir api
cd api
# Create the main files
touch main.py
touch models.py
touch services.py
touch config.py
# Create directories
mkdir uploads
mkdir static
Step 3: Basic FastAPI Setup (main.py)
python
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
import uvicorn
import os
from contextlib import asynccontextmanager
from services import ImageBindService
from models import EmbeddingResponse, ErrorResponse
from config import settings
# Global variable to hold our ImageBind service
imagebind_service = None
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: Initialize ImageBind model
global imagebind_service
print("🚀 Initializing ImageBind service...")
imagebind_service = ImageBindService()
await imagebind_service.initialize()
print("✅ ImageBind service ready!")
yield
# Shutdown: Clean up resources
print("🔄 Shutting down ImageBind service...")
if imagebind_service:
imagebind_service.cleanup()
print("✅ Cleanup complete!")
# Create FastAPI app with lifespan management
app = FastAPI(
title="ImageBind Multimodal API",
description="Generate embeddings from images, text, and audio using Meta's ImageBind",
version="1.0.0",
lifespan=lifespan
)
# Enable CORS for web applications
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Configure appropriately for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Serve static files
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
async def root():
"""Welcome endpoint with API information"""
return {
"message": "ImageBind Multimodal API",
"version": "1.0.0",
"docs": "/docs",
"endpoints": {
"text_embedding": "/embed/text",
"image_embedding": "/embed/image",
"audio_embedding": "/embed/audio",
"health": "/health"
}
}
@app.get("/health")
async def health_check():
"""Health check endpoint"""
global imagebind_service
if imagebind_service and imagebind_service.is_ready():
return {"status": "healthy", "model": "loaded"}
return JSONResponse(
status_code=503,
content={"status": "unhealthy", "model": "not_loaded"}
)
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info"
)
Step 4: Configuration (config.py)
python
import os
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# API Configuration
api_title: str = "ImageBind Multimodal API"
api_version: str = "1.0.0"
debug: bool = True
# Model Configuration
device: str = "cuda" if os.environ.get("CUDA_AVAILABLE") else "cpu"
model_name: str = "imagebind_huge"
# File Upload Configuration
max_file_size: int = 50 * 1024 * 1024 # 50MB
allowed_image_types: list = ["image/jpeg", "image/png", "image/gif", "image/webp"]
allowed_audio_types: list = ["audio/wav", "audio/mp3", "audio/ogg", "audio/flac"]
# Processing Configuration
batch_size: int = 1
max_text_length: int = 1000
# Directory Configuration
upload_dir: str = "uploads"
static_dir: str = "static"
class Config:
env_file = ".env"
# Create global settings instance
settings = Settings()