layahost
Menu · OpenAI moderation (beta)

OpenAI moderation replacement beta

POST /v1/moderations takes the same request and returns the same response as OpenAI's moderation endpoint, so the OpenAI SDKs work after you change the base URL and the key.

Beta, and tuned to be cautious. We set every category to raise few false alarms, so it misses more than OpenAI's own model: on OpenAI's evaluation set it flags about 38% of harmful texts, and it still flags 9% of our harmless everyday test texts, mostly violent figures of speech (“kill the process”, “my feet are killing me”). For toxicity and insults in comments, our Perspective-compatible scores are more accurate. Use this endpoint when you need OpenAI's format and categories, and check it on your own texts first.
Endpoint
POST https://layahost.com/v1/moderations

layahost is not affiliated with OpenAI. The scores come from a different model, the open Laya model, asked a few typed questions about each text and calibrated into OpenAI's categories. Why use it instead of OpenAI's free endpoint: your text is processed in the EU and never stored, you don't need an OpenAI account, and the same key gives you your own questions and flows when the fixed categories are not enough. How the two compare on real comments: OpenAI Moderation API vs layahost.

Migrate

POST /v1/moderations
from openai import OpenAI

client = OpenAI(
    api_key=LAYAHOST_API_KEY,
    base_url="https://layahost.com/v1",  # was: https://api.openai.com/v1
)

result = client.moderations.create(
    model="omni-moderation-latest",
    input="I will find you and hurt you.",
).results[0]

print(result.flagged, result.categories.violence, result.category_scores.violence)
POST /v1/moderations
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.LAYAHOST_API_KEY,
  baseURL: "https://layahost.com/v1", // was: https://api.openai.com/v1
});

const { results } = await client.moderations.create({
  model: "omni-moderation-latest",
  input: "I will find you and hurt you.",
});

console.log(results[0].flagged, results[0].category_scores.violence);
POST /v1/moderations
curl https://layahost.com/v1/moderations \
  -H "Authorization: Bearer $LAYAHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "omni-moderation-latest", "input": "I will find you and hurt you."}'

The response has OpenAI's shape: an id, the model you asked for, and one result per input with flagged, categories (true or false), category_scores (0 to 1) and category_applied_input_types (always ["text"]).

What is supported

FieldBehaviour
inputA string; a list of up to 32 strings (one result each); or a list of {"type": "text", "text": ...} parts, read as one text. Up to 32,000 characters per input. Image parts get 400: layahost moderates text only.
modelomni-moderation-latest</code>, <code>omni-moderation-2024-09-26</code>, <code>text-moderation-latest</code>, <code>text-moderation-stable</code>, <code>text-moderation-007, or leave it out. All of them get the same layahost moderation; the name is echoed back.
CategoriesAll 13: harassment</code>, <code>harassment/threatening</code>, <code>hate</code>, <code>hate/threatening</code>, <code>illicit</code>, <code>illicit/violent</code>, <code>self-harm</code>, <code>self-harm/intent</code>, <code>self-harm/instructions</code>, <code>sexual</code>, <code>sexual/minors</code>, <code>violence</code>, <code>violence/graphic.
ErrorsOpenAI's shape, {"error": {"message", "type", "param", "code"}}, so the SDKs raise their usual exceptions. An empty balance is 429 with code insufficient_quota, like OpenAI.
LanguagesCalibrated on English. Other languages are scored, but less accurately; test on your own texts first.

Pricing

OpenAI's moderation endpoint is free; ours is not. Each input is 8 decisions (one per question asked about it), so $0.00012 per text at the pay-as-you-go price, or 125,000 texts per million decisions on a plan. Failed requests are not billed. See pricing.

Accuracy

Every category is set to flag at most about 1% of the texts without it in the tuning half, so on everyday traffic false alarms stay rare at the cost of recall. Measured on the held-out half of OpenAI moderation evaluation set (Markov et al. 2022, "A Holistic Approach to Undesired Content Detection"), 1,680 texts, 8 labelled categories (MIT (Copyright (c) 2022 OpenAI), github.com/openai/moderation-api-release/blob/main/LICENSE), 837 texts that were not used to choose questions or fit calibration. AUC is the chance that a random positive text scores higher than a random clean one (1.0 is perfect, 0.5 is guessing); precision and recall are at our flagged threshold for each category.

CategoryPositivesAUCPrecisionRecall
harassment390.92770%41%
hate830.92488%17%
hate/threatening210.95969%43%
self-harm250.98474%68%
sexual1130.95986%37%
sexual/minors410.91242%12%
violence450.927100%31%
violence/graphic120.79533%8%
flagged82%38%

The dataset has no labels for harassment/threatening</code>, <code>illicit</code>, <code>illicit/violent</code>, <code>self-harm/intent</code>, <code>self-harm/instructions. We score them with questions checked on a small hand-written set only, so treat those scores as rough. In particular self-harm/intent, self-harm/instructions and illicit/violent also fire on violent threats against others and on recovery stories: use them as hints, not as decisions.

We also wrote 160 harmless everyday texts (support tickets, reviews, harsh complaints, idioms such as “I could murder a pizza” or “shoot the video”) and never tuned on them: 8.7% were flagged, mostly as violence or self-harm for violent figures of speech.

Where we are clearly behind OpenAI's own model on this set: violence/graphic and sexual/minors, and harassment misses many direct threats (harassment/threatening catches some). The set is about one-third harmful, so on everyday traffic, where harmful text is rare, precision is lower than in the table.

Scores are calibrated probabilities, but they come from a different model than OpenAI's, so the same threshold does not mean the same thing. If your code acts on category_scores with fixed thresholds, re-tune them on a test set of your own texts, or use flagged and categories.