NOPE

Ocular OSS

Self-hosted behavioral safety classifier for human–AI conversations. Reads signals across both sides of the dialogue — the shape of the conversation, not the surface of one turn — and returns one salience score per call with 12 axes of depth behind it.

Apache 2.0 · source ships inside the image at /app/.

What Ocular is → · Docs & API reference → · Commercial engagement

Download the Docker image

API at a glance

One HTTP endpoint: POST /classify. Single message or full conversation; same response shape either way.

  • The contract. A continuous salience score in [0, 1] plus subject (self / other / unknown). Pick the cutoff that fits your action — reference bands are watch ≥ 0.30, danger ≥ 0.60. This is what your code keys off.
  • Interpretive depth. 8 user-side risk axes + 4 AI-concern axes, each with a level and a calibrated score, plus imminence. Surface in dashboards; explains the salience score, doesn't replace it.
  • Diagnostic context. fiction and authenticity are already factored into the salience score server-side — surfaced so you can see what shifted the call, not for client-side filtering. Don't re-aggregate.

Request

POST /classify
content-type: application/json

{
  "messages": [
    {"role": "user", "content": "I've been feeling hopeless for weeks and I don't know how much longer I can keep going."}
  ]
}

Response

{
  "salience": 0.3419,
  "subject": "self",
  "imminence": {"level": "minimal", "score": 0.0009},
  "fiction": 0.0,
  "authenticity": 0.9768,
  "signals": {
    "user": {
      "suicide": {"level": "high", "score": 0.2692},
      "self_harm": {"level": "minimal", "score": 0.0},
      "harm_to_others": {"level": "minimal", "score": 0.0},
      "abuse": {"level": "minimal", "score": 0.044},
      "sexual_violence": {"level": "minimal", "score": 0.044},
      "exploitation": {"level": "minimal", "score": 0.044},
      "stalking": {"level": "minimal", "score": 0.044},
      "self_neglect": {"level": "minimal", "score": 0.0}
    },
    "ai": {
      "harm_provision": {"level": "minimal", "score": 0.0},
      "emotional_failure": {"level": "minimal", "score": 0.0},
      "manipulation": {"level": "minimal", "score": 0.0},
      "safeguarding_failure": {"level": "minimal", "score": 0.0}
    }
  },
  "meta": {"version": "1.0.0", "build": "c13d837", "inference_ms": 53}
}

Full schema, fields, and salience semantics at the API reference.

Install + run

# After submitting the form below, you'll get the two tarballs:
zstd -d -c ocular-platform-oss-1.0.0.tar.zst | docker load
tar xzf customer-bundle-oss-1.0.0.tar.gz
cd ocular-oss-1.0.0
cp customer.env.example .env          # then set OCULAR_VERSION=1.0.0 in .env
docker compose --env-file .env -f customer-compose.yml up -d

# Classify
curl http://localhost:8080/classify -H 'content-type: application/json' \
  -d '{"messages":[{"role":"user","content":"..."}]}'

Full walkthrough in deployment.md inside the bundle, mirrored at docs/deployment.md.

Requirements

GPU
~6.4 GB VRAM (measured peak); a 12 GB card is comfortable. The 24 GB A10G-class card is the latency reference, not a minimum.
Host
Linux + NVIDIA Container Toolkit.
Latency
~30 ms per call on the reference GPU; longer on smaller cards.
Footprint
One container; ~6.4 GB VRAM peak.

Trajectory / throughput / tuning details at docs/deployment.md.

In this release · 1.0.0
  • Breaking: verdict is replaced by a continuous salience score. The categorical verdict field is gone. The response now leads with salience — one score in [0, 1] you threshold yourself (reference bands watch ≥ 0.30, danger ≥ 0.60). If you parsed verdict, switch to salience.
  • Semver on the HTTP contract: meta.version is the contract version (1.0.0), meta.build the source commit. A PATCH may shift scores on borderline traffic — pin the exact tag for byte-stable scoring. See api-reference#versioning.
  • Per-axis depth is unchanged: 8 user-side + 4 AI-concern axes nested under signals.user / signals.ai, each with a level and calibrated score, plus imminence, fiction, and authenticity.
  • Signal codes are family-grouped public identifiers (USER_SUICIDE_HEAD_A, etc.) — opaque diagnostic output, not part of the contract; do not key off them.

Get the image

Tell us who you are and the download links come back on the next screen. We share Ocular openly because we want to learn from how it's deployed — your context helps us calibrate, and we'll share back what we're seeing.

Ocular is a behavioral signal classifier — not predictive, not diagnostic, not a substitute for clinical judgment, human review, or emergency services. Operator sets thresholds and response policies. Coverage and calibration are still maturing; treat outputs as signal, not ground truth. See the model card for limits and intended use.

We log this so we know who's deploying. No marketing email.