API Development

Tutorial 2 of 8

Building Your First API Endpoint

Transform your ImageBind setup into a production-ready FastAPI service with file uploads, embedding generation, and proper error handling. Build REST endpoints that can process multimodal data at scale.

FastAPI Framework

Modern, fast web framework with automatic API documentation

File Processing

Handle image, audio, and text uploads with validation

Production Ready

Scalable architecture with proper error handling

Tutorial Progress

FastAPI Foundation

Set up FastAPI structure and basic configuration

ImageBind Integration

Connect ImageBind model to API endpoints

File Upload Handling

Process image, audio, and text inputs

Response Formatting

Structure API responses and error handling

Testing & Deployment

Test endpoints and prepare for production

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()