content-understanding/docs/api.md

5.7 KiB

REST API

The package includes a FastAPI service for HTTP-based content analysis.

Running the Service

# Production
uvicorn lilith_content_understanding.api:app --host 0.0.0.0 --port 8002

# Development with auto-reload
uvicorn lilith_content_understanding.api:app --reload --port 8002

# With workers
uvicorn lilith_content_understanding.api:app --workers 4 --port 8002

API Documentation

Once running, visit:


Endpoints

Health Check

GET /health

Response:

{
  "status": "healthy",
  "version": "0.1.0",
  "detectors": {
    "nsfw": true,
    "body_parts": false
  },
  "analyzers": {
    "depth": true,
    "color": true,
    "composition": true,
    "scene": true
  }
}

NSFW Detection

POST /detect/nsfw
Content-Type: multipart/form-data

file: <image file>
threshold: 0.7  (optional)

Response:

{
  "is_nsfw": false,
  "confidence": 0.95,
  "category": "safe",
  "all_scores": {
    "nsfw": 0.05,
    "safe": 0.95
  }
}

Body Part Detection

POST /detect/body-parts
Content-Type: multipart/form-data

file: <image file>
threshold: 0.4  (optional)

Response:

{
  "has_nudity": true,
  "has_male_genitalia": false,
  "has_female_genitalia": false,
  "has_breasts": true,
  "has_buttocks": false,
  "gender_presentation": "female",
  "gender_confidence": 0.85,
  "body_parts": ["BREASTS", "FACE_FEMALE"],
  "detections": [
    {
      "label": "FEMALE_BREAST_EXPOSED",
      "confidence": 0.92,
      "bbox": [0.3, 0.4, 0.7, 0.8],
      "category": "BREASTS"
    }
  ]
}

Depth Analysis

POST /analyze/depth
Content-Type: multipart/form-data

file: <image file>
include_map: false  (optional, include base64 depth map)
model: "depth-anything-v2-small"  (optional)

Response:

{
  "width": 512,
  "height": 512,
  "min_depth": 0.0,
  "max_depth": 1.0,
  "depth_map_base64": null
}

Get depth as image:

GET /analyze/depth/image
Content-Type: multipart/form-data

file: <image file>
colormap: "magma"  (optional)

Returns: image/png


Color Analysis

POST /analyze/colors
Content-Type: multipart/form-data

file: <image file>
num_colors: 5  (optional, 2-10)

Response:

{
  "colors": [
    {
      "rgb": [45, 52, 89],
      "hex": "#2d3459",
      "hsl": [230.5, 32.8, 26.3],
      "percentage": 35.2,
      "name": "blue"
    }
  ],
  "hex_colors": ["#2d3459", "#f5a623", ...],
  "harmony_type": "complementary",
  "mood": "cool",
  "average_saturation": 45.2,
  "average_lightness": 52.1
}

Get color swatch as image:

GET /analyze/colors/swatch
Content-Type: multipart/form-data

file: <image file>
num_colors: 5  (optional)
width: 500  (optional)
height: 100  (optional)

Returns: image/png


Composition Analysis

POST /analyze/composition
Content-Type: multipart/form-data

file: <image file>

Response:

{
  "rule_of_thirds_score": 0.72,
  "symmetry_score": 0.45,
  "balance_score": 0.68,
  "balance_type": "asymmetric",
  "negative_space_ratio": 0.35,
  "complexity_score": 0.52,
  "focal_points": [
    {
      "x": 0.33,
      "y": 0.33,
      "strength": 0.85,
      "quadrant": 1,
      "on_thirds_intersection": true
    }
  ],
  "suggestions": [
    "Consider adding more negative space for breathing room"
  ]
}

Scene Classification

POST /analyze/scene
Content-Type: multipart/form-data

file: <image file>

Response:

{
  "scene_type": "landscape",
  "scene_confidence": 0.87,
  "environment": "outdoor",
  "time_of_day": "sunset",
  "weather": "sunny",
  "tags": ["landscape", "outdoor", "nature", "mountain"],
  "suggested_styles": ["golden hour", "hdr", "dramatic"]
}

Full Analysis

Perform all analyses in one request:

POST /analyze/full
Content-Type: multipart/form-data

file: <image file>
include_nsfw: true  (optional)
include_body_parts: false  (optional)
include_depth: true  (optional)
include_colors: true  (optional)
include_composition: true  (optional)
include_scene: true  (optional)

Response includes all enabled analyses:

{
  "nsfw": { ... },
  "body_parts": null,
  "depth": { ... },
  "colors": { ... },
  "composition": { ... },
  "scene": { ... }
}

Python Client Example

import httpx

# Upload image and get NSFW result
with open("image.jpg", "rb") as f:
    response = httpx.post(
        "http://localhost:8002/detect/nsfw",
        files={"file": f},
        params={"threshold": 0.7}
    )
    result = response.json()
    print(f"NSFW: {result['is_nsfw']}")

# Full analysis
with open("image.jpg", "rb") as f:
    response = httpx.post(
        "http://localhost:8002/analyze/full",
        files={"file": f},
        params={
            "include_body_parts": False,
            "include_depth": True
        }
    )
    result = response.json()
    print(f"Scene: {result['scene']['scene_type']}")

Error Responses

400 Bad Request

Invalid image file:

{
  "detail": "Invalid image: cannot identify image file"
}

501 Not Implemented

Missing optional dependency:

{
  "detail": "Body part detection requires nudenet. Install with: pip install lilith-content-understanding[nudenet]"
}

CORS Configuration

from lilith_content_understanding.api import create_app

app = create_app(
    cors_origins=["http://localhost:3000", "https://myapp.com"]
)

Custom Configuration

from lilith_content_understanding.api import create_app

app = create_app(
    title="My Content API",
    version="1.0.0",
    cors_origins=["*"],
)