Skip to content

API reference

Generated from the docstrings. Everything on this page is public API.

Moderator

Detect policy-violating content in images.

For example:

from openmoderate import Moderator

mod = Moderator()
result = mod.analyze("upload.jpg")
if not result.is_safe:
    print(result.violations)

Parameters:

Name Type Description Default
config ModerationConfig | Mapping | str | Path | None

A ModerationConfig, a dict, or a path to a YAML file.

None
preset str | None

"fast" (default), "balanced" or "accurate": which CLIP model to use, with its calibration. See openmoderate.config.PRESETS.

None
thresholds Mapping[str, float] | None

Per-category threshold overrides, e.g. {"weapons": 0.4}.

None
categories list[str] | None

Only check these categories.

None
exclude list[str] | None

Skip these categories.

None
head LinearHead | str | Path | None

A trained head (.omh path or LinearHead) from openmoderate train. Its labels are added to the result; labels that also exist as zero-shot categories are blended according to head_weight.

None
head_weight float

For labels known to both, 1.0 uses only the trained head, 0.0 only the zero-shot score, values in between blend them.

1.0
engine Engine | None

Custom embedding engine (defaults to OpenCLIP, loaded lazily).

None
device str

"auto", "cpu", "cuda" or "mps".

'auto'

label_specs property

label_specs: list[LabelSpec]

Every label this moderator reports, with its parent and threshold.

score_embeddings

score_embeddings(image_embeddings: ndarray) -> np.ndarray

Zero-shot category scores in [0, 1), shape (n_images, n_categories).

For each category we take the margin between the image's best-matching category prompt and its best-matching safe prompt (in CLIP logit units), then map it through a calibrated sigmoid. Categories are scored independently, so an image can be both weapons and violence.

score_all

score_all(image_embeddings: ndarray) -> np.ndarray

Final scores for every label in category_names (zero-shot + head).

score_images

score_images(images: list[Image]) -> np.ndarray

Scores for already-loaded RGB PIL images (after border trimming, if enabled).

analyze

analyze(image: ImageInput) -> ModerationResult

Analyse a single image (path, URL, bytes, file object or PIL image).

analyze_video

analyze_video(video: VideoInput, *, fps: float = 1.0, max_frames: int | None = None, max_duration: float | None = None, min_frames: int = 1, stop_on_violation: bool = False, batch_size: int = 16, keep_frame_scores: bool = False) -> VideoModerationResult

Moderate a video by sampling frames (needs pip install "openmoderate[video]").

Parameters:

Name Type Description Default
video VideoInput

Path, bytes or file object.

required
fps float

Frames sampled per second of video.

1.0
max_frames int | None

Stop after this many sampled frames.

None
max_duration float | None

Stop decoding after this many seconds (result.truncated).

None
min_frames int

Ignore segments shorter than this many flagged frames, to suppress one-frame false positives.

1
stop_on_violation bool

Stop at the first violating segment, for fast rejection.

False
keep_frame_scores bool

Include every sampled frame's scores in the result.

False

Returns:

Type Description
VideoModerationResult

A openmoderate.video.VideoModerationResult with timestamped

VideoModerationResult

segments per violated label.

Results

ModerationResult dataclass

Outcome of analysing one image.

labels holds a score for every configured category (sorted by confidence), violations holds only the labels whose score crossed their threshold.

Label dataclass

A single moderation label with its confidence score in [0, 1].

LabelSpec

Bases: NamedTuple

Videos

VideoModerationResult dataclass

VideoSegment dataclass

A stretch of video where one label stayed above its threshold.

Configuration

ModerationConfig dataclass

from_preset classmethod

from_preset(name: str) -> ModerationConfig

A default configuration using one of the PRESETS ("fast", "balanced", "accurate").

default classmethod

default() -> ModerationConfig

The default configuration, honouring the OPENMODERATE_PRESET environment variable.

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> ModerationConfig

Build a config from a dict (e.g. parsed YAML).

Supported keys: preset ("fast", "balanced" or "accurate"), model, pretrained, cache_dir, safe_prompts, thresholds (name -> float), enabled/disabled (lists of names) and custom_categories (list of {name, prompts, threshold, parent}). model/pretrained override the preset.

Category dataclass

Trained heads

LinearHead dataclass

One-vs-rest logistic regression: sigmoid(embeddings @ weights.T + bias).

predict

predict(embeddings: ndarray) -> np.ndarray

Probabilities of shape (n_images, n_labels).

Errors

ImageLoadError

Bases: ValueError

VideoLoadError

Bases: ValueError

Framework integrations

integrations

Drop-in upload moderation for web frameworks.

  • FastAPI: openmoderate.integrations.fastapi
  • Flask: openmoderate.integrations.flask
  • Django: openmoderate.integrations.django

ImageRejected

Bases: ModerationError

The upload is an image that violates the moderation policy.

ModerationError

Bases: Exception

Base class for upload moderation failures.

UnreadableUpload

Bases: ModerationError

The upload could not be decoded as an image.

UploadTooLarge

Bases: ModerationError

The upload exceeds the size limit.

check_image

check_image(data: bytes, *, field: str | None = None, moderator: Moderator | None = None, on_unreadable: OnUnreadable = 'reject') -> ModerationResult | None

Moderate raw image bytes.

Returns the result for a safe image, None for an unreadable file that is allowed through, and raises ImageRejected / UnreadableUpload otherwise.

configure

configure(moderator: Moderator | None = None, /, **kwargs: Any) -> None

Set the moderator the integrations use.

Pass a ready Moderator, or keyword arguments for one (config, head, thresholds, device, ...), which is then created lazily on first use. Call this once at startup; calling it again replaces the shared moderator.

get_moderator

get_moderator(thresholds: Mapping[str, float] | None = None, categories: list[str] | None = None, exclude: list[str] | None = None) -> Moderator

Return the shared moderator, or a variant with a different policy.

Variants reuse the shared moderator's engine, so they cost no extra model memory.

fastapi

FastAPI integration: reject violating image uploads before your endpoint runs.

from fastapi import FastAPI, UploadFile
from openmoderate.integrations.fastapi import ModeratedFile, moderated

app = FastAPI()

@app.post("/avatar")
async def avatar(file: ModeratedFile):          # form field "file"
    ...                                          # only safe images get here

@app.post("/photos")
async def photos(photo: UploadFile = moderated("photo", thresholds={"weapons": 0.3})):
    ...

Violating images get a 422 response (413 if too large) and the endpoint never runs. Moderation runs in a worker thread, so it does not block the event loop.

moderated

moderated(field: str = 'file', *, moderator: Moderator | None = None, thresholds: Mapping[str, float] | None = None, categories: list[str] | None = None, exclude: list[str] | None = None, on_unreadable: OnUnreadable = 'reject', status_code: int = 422, include_scores: bool = False, max_bytes: int = MAX_BYTES) -> Any

A Depends(...) that parses form field field and moderates it.

Use as a default value: file: UploadFile = moderated("file").

moderated_files

moderated_files(field: str = 'files', *, moderator: Moderator | None = None, thresholds: Mapping[str, float] | None = None, categories: list[str] | None = None, exclude: list[str] | None = None, on_unreadable: OnUnreadable = 'reject', status_code: int = 422, include_scores: bool = False, max_bytes: int = MAX_BYTES) -> Any

Like moderated for a repeated field (list[UploadFile]); every file must pass.

flask

Flask integration: reject violating image uploads.

Per view, with a decorator:

from openmoderate.integrations.flask import moderate_uploads

@app.post("/avatar")
@moderate_uploads("avatar")              # or no args: every file in the request
def avatar():
    request.files["avatar"].save(...)    # only safe images get here

Or for every request, with the extension:

from openmoderate.integrations.flask import OpenModerate

OpenModerate(app, check_all_requests=True)

Violating images get a JSON 422 response (413 if too large).

OpenModerate

Flask extension.

Parameters:

Name Type Description Default
app Flask | None

The Flask app (or call init_app later).

None
moderator Moderator | None

A ready Moderator; otherwise one is built lazily from the OPENMODERATE_CONFIG / OPENMODERATE_HEAD / OPENMODERATE_PRESET app config keys.

None
check_all_requests bool

Moderate every uploaded file on every request.

False
on_unreadable OnUnreadable

What to do with uploads that are not images. Defaults to "allow" here, since a blanket check also sees PDFs, CSVs and so on.

'allow'

moderate_uploads

moderate_uploads(*fields: str, moderator: Moderator | None = None, thresholds: Mapping[str, float] | None = None, categories: list[str] | None = None, exclude: list[str] | None = None, on_unreadable: OnUnreadable = 'reject', status_code: int = 422, include_scores: bool = False, max_bytes: int = MAX_BYTES) -> Callable

Decorate a view so the named file fields (default: all of them) are moderated first.

django

Django integration: a field validator and a middleware.

Validator (works in model fields, forms, the admin and Django REST Framework serializers):

from openmoderate.integrations.django import ModerationValidator

class Profile(models.Model):
    avatar = models.ImageField(validators=[ModerationValidator()])
    banner = models.ImageField(validators=[ModerationValidator(thresholds={"suggestive": 0.4})])

Middleware (moderates every uploaded file under the configured URL prefixes):

MIDDLEWARE = [..., "openmoderate.integrations.django.ModerationMiddleware"]

Settings, all optional:

OPENMODERATE = {
    "CONFIG": BASE_DIR / "policy.yaml",   # policy YAML
    "HEAD": BASE_DIR / "my_head.omh",     # trained head
    "PRESET": "accurate",                 # fast (default), balanced or accurate
    "DEVICE": "auto",
    "PATHS": ["/uploads/", "/api/"],      # middleware only; default: every path
    "ON_UNREADABLE": "allow",            # middleware: non-image files pass through
    "STATUS_CODE": 422,
    "INCLUDE_SCORES": False,
}

ModerationValidator

Reject images that violate the moderation policy.

Policy overrides apply to this field only and reuse the shared model, so they cost no extra memory.

Parameters:

Name Type Description Default
thresholds Mapping[str, float] | None

Per-category threshold overrides, e.g. {"suggestive": 0.4}.

None
categories list[str] | None

Only check these categories.

None
exclude list[str] | None

Skip these categories.

None
on_unreadable OnUnreadable

"reject" (default) or "allow" files that are not images.

'reject'
message str | None

Error shown to the user; %(violations)s is replaced with the names.

None
max_bytes int

Reject files larger than this.

MAX_BYTES

ModerationMiddleware

Moderate every uploaded file on matching paths; reject with a JSON error.