feat(maturity): add dedicated NSFW/maturity analysis service
- Add maturity/ service (FastAPI + Falconsai/nsfw_image_detection ViT classifier)
- /analyze (URL) and /analyze/file (multipart upload) endpoints
- Normalized response: maturity_label, confidence, score, labels,
action_hint (safe/review/flag_high), advisory, threshold_used,
analysis_time_ms, model, source
- Configurable thresholds via MATURITY_THRESHOLD_MATURE / MATURITY_THRESHOLD_REVIEW
- Reuses common/image_io for URL validation and file-size enforcement
- Explicit 502/503 errors on failure — no silent safe fallback
- Per-request structured logging (score, label, threshold path, elapsed ms)
- Update gateway/main.py
- MATURITY_URL + MATURITY_ENABLED env vars
- POST /analyze/maturity and POST /analyze/maturity/file endpoints
- /health includes maturity service status
- _assert_maturity_enabled() guard for clean 503 when disabled
- All existing endpoints untouched (additive change)
- Update docker-compose.yml
- Add maturity service with healthcheck (start_period: 90s)
- Gateway environment: MATURITY_URL, MATURITY_ENABLED
- Gateway depends_on: maturity (service_healthy)
- Update README.md and USAGE.md
- Document maturity service, env vars, curl examples,
full response schema table, action_hint logic, failure guidance
This commit is contained in:
84
USAGE.md
84
USAGE.md
@@ -1,10 +1,10 @@
|
||||
# Skinbase Vision Stack — Usage Guide
|
||||
|
||||
This document explains how to run and use the Skinbase Vision Stack (Gateway + CLIP, BLIP, YOLO, Qdrant services).
|
||||
This document explains how to run and use the Skinbase Vision Stack (Gateway + CLIP, BLIP, YOLO, Qdrant, Card Renderer, Maturity services).
|
||||
|
||||
## Overview
|
||||
|
||||
- Services: `gateway`, `clip`, `blip`, `yolo`, `qdrant`, `qdrant-svc`, `card-renderer` (FastAPI each, except `qdrant` which is the official Qdrant DB).
|
||||
- Services: `gateway`, `clip`, `blip`, `yolo`, `qdrant`, `qdrant-svc`, `card-renderer`, `maturity` (FastAPI each, except `qdrant` which is the official Qdrant DB).
|
||||
- Gateway is the public API endpoint; the other services are internal.
|
||||
|
||||
## Model overview
|
||||
@@ -19,6 +19,8 @@ This document explains how to run and use the Skinbase Vision Stack (Gateway + C
|
||||
|
||||
- **Card Renderer**: Generates branded social-card images (e.g. Open Graph previews) from artwork images. Applies smart center-weighted cropping, gradient overlays, title/username/tag text, and an optional logo. Returns binary image bytes (WebP by default). Template: `nova-artwork-v1`.
|
||||
|
||||
- **Maturity**: Dedicated NSFW/maturity classifier. Accepts an image and returns a normalized safety signal including `maturity_label` (`safe`/`mature`), `confidence`, raw `score`, optional sublabels (e.g. `nsfw`), and an `action_hint` (`safe`, `review`, `flag_high`) designed for Nova moderation workflows. Powered by `Falconsai/nsfw_image_detection` (ViT-based, HuggingFace). Thresholds are configurable via environment variables.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Desktop (with `docker compose`) or a Docker environment.
|
||||
@@ -40,6 +42,19 @@ Notes:
|
||||
- `HUGGINGFACE_TOKEN` is required if the configured BLIP model requires Hugging Face authentication.
|
||||
- Startup uses container healthchecks, so initial boot can take longer while models download and warm up.
|
||||
|
||||
Optional maturity configuration (can be added to `.env` to override defaults):
|
||||
|
||||
```bash
|
||||
MATURITY_MODEL=Falconsai/nsfw_image_detection
|
||||
MATURITY_THRESHOLD_MATURE=0.80
|
||||
MATURITY_THRESHOLD_REVIEW=0.60
|
||||
MATURITY_ENABLED=true
|
||||
```
|
||||
|
||||
- `MATURITY_THRESHOLD_MATURE`: score above this → `mature` + `flag_high` (default `0.80`).
|
||||
- `MATURITY_THRESHOLD_REVIEW`: score above this but below mature threshold → `mature` + `review` (default `0.60`).
|
||||
- `MATURITY_ENABLED`: set to `false` to disable maturity endpoints at the gateway without removing the service.
|
||||
|
||||
Run from repository root:
|
||||
|
||||
```bash
|
||||
@@ -168,9 +183,65 @@ Parameters:
|
||||
|
||||
Return: detected objects with `class`, `confidence`, and `bbox` (bounding box coordinates).
|
||||
|
||||
### Qdrant — vector storage & similarity search
|
||||
### Maturity — NSFW / maturity analysis
|
||||
|
||||
The Qdrant integration lets you store image embeddings and find visually similar images. Embeddings are generated automatically by the CLIP service.
|
||||
Analyzes an image for mature or NSFW content and returns a structured signal intended for Nova moderation workflows.
|
||||
|
||||
URL request:
|
||||
|
||||
```bash
|
||||
curl -X POST https://vision.klevze.net/analyze/maturity \
|
||||
-H "X-API-Key: <your-api-key>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"url":"https://files.skinbase.org/img/aa/bb/cc/md.webp"}'
|
||||
```
|
||||
|
||||
File upload:
|
||||
|
||||
```bash
|
||||
curl -X POST https://vision.klevze.net/analyze/maturity/file \
|
||||
-H "X-API-Key: <your-api-key>" \
|
||||
-F "file=@/path/to/image.webp"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"maturity_label": "mature",
|
||||
"confidence": 0.94,
|
||||
"score": 0.94,
|
||||
"labels": ["nsfw"],
|
||||
"model": "Falconsai/nsfw_image_detection",
|
||||
"threshold_used": 0.80,
|
||||
"analysis_time_ms": 183.0,
|
||||
"source": "maturity-service",
|
||||
"action_hint": "flag_high",
|
||||
"advisory": "High-confidence mature content detected"
|
||||
}
|
||||
```
|
||||
|
||||
Response fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `maturity_label` | string | `safe` or `mature` |
|
||||
| `confidence` | float | Confidence in the label decision (0–1). For `safe`, this is `1 - score`. |
|
||||
| `score` | float | Raw NSFW probability from the model (0–1). |
|
||||
| `labels` | array | Sublabels when mature: currently `["nsfw"]`. Empty for safe results. |
|
||||
| `model` | string | Model identifier / HuggingFace model ID. |
|
||||
| `threshold_used` | float | The threshold value that determined the label. |
|
||||
| `analysis_time_ms` | float | Inference time in milliseconds. |
|
||||
| `source` | string | Always `maturity-service`. |
|
||||
| `action_hint` | string | `safe`, `review`, or `flag_high`. Use this in Nova to drive blur/queue/flag decisions. |
|
||||
| `advisory` | string | Short human-readable explanation. |
|
||||
|
||||
`action_hint` decision logic:
|
||||
- `flag_high`: score ≥ `MATURITY_THRESHOLD_MATURE` (default 0.80) — high-confidence mature, flag for moderation.
|
||||
- `review`: score ≥ `MATURITY_THRESHOLD_REVIEW` (default 0.60) but below mature threshold — possible mature, queue for human review.
|
||||
- `safe`: score below both thresholds — content appears safe.
|
||||
|
||||
If the maturity service is unavailable the gateway returns a `502` or `503` error. **Nova must not treat a gateway failure as a `safe` result** — retry or queue for later processing. store image embeddings and find visually similar images. Embeddings are generated automatically by the CLIP service.
|
||||
|
||||
Qdrant point IDs must be either an unsigned integer or a UUID string. If you send another string value, the wrapper may replace it with a generated UUID and store the original value in metadata as `_original_id`.
|
||||
|
||||
@@ -457,7 +528,9 @@ uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
- Qdrant upsert error about invalid point ID: use a UUID or unsigned integer for `id`, or omit it and use the returned generated `id`.
|
||||
- Image URL rejected before download: the URL may point to localhost, a private IP, a non-`http/https` scheme, or a non-image content type.
|
||||
- High memory / OOM: increase host memory or reduce model footprint; consider GPUs.
|
||||
- Slow startup: model weights load on service startup — expect extra time.
|
||||
- Slow startup: model weights load on service startup — expect extra time. The maturity service (`start_period: 90s`) may take longer on first boot as it downloads the classifier weights (~330 MB). Mount `~/.cache/huggingface` as a volume to persist across rebuilds.
|
||||
- Maturity endpoint returns `503`: `MATURITY_ENABLED` is set to `false` in environment configuration.
|
||||
- Maturity endpoint returns `502`: the maturity container is unhealthy or still starting up; wait and retry.
|
||||
|
||||
## Extending
|
||||
|
||||
@@ -469,6 +542,7 @@ uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
- `docker-compose.yml` — composition and service definitions.
|
||||
- `gateway/` — gateway FastAPI server.
|
||||
- `clip/`, `blip/`, `yolo/` — service implementations and Dockerfiles.
|
||||
- `maturity/` — NSFW/maturity classifier service (ViT-based, HuggingFace `Falconsai/nsfw_image_detection`).
|
||||
- `qdrant/` — Qdrant API wrapper service (FastAPI).
|
||||
- `card-renderer/` — card rendering service (FastAPI).
|
||||
- `common/` — shared helpers (e.g., image I/O).
|
||||
|
||||
Reference in New Issue
Block a user