Repository navigation
feat(nsfw): classify NSFW pictures with a local model, per namespace - #306
Merged
Merged
Conversation
Off by default. An admin turns it on for every namespace (Settings → NSFW) or
an owner for theirs (the namespace's page, the API or MCP). The new nsfw step
scores a video's sampled frames, a document's pages or an image with
AdamCodd/vit-base-nsfw-detector (Apache-2.0, 8-bit ONNX, pinned and checked
against its SHA-256), fetched on first use with ONNX Runtime, and flags the
resource when a picture scores at least the namespace's threshold.
- Settings section nsfw {enabled, threshold, display, max_frames}; a
namespace's own enabled, threshold and display win over it.
- Flagged resources are blurred until someone shows them, hidden from the
Library, or shown with a label; editors mark them NSFW or not, with Undo.
- API: /namespaces/{name}/nsfw (+ classify), /resources/{rid}/nsfw,
/resources/nsfw, the Library's sensitive filter; MCP nsfw_settings,
set_nsfw, mark_nsfw.
- Threat model: N-NSFW (blur and hide are display, not access control).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T7gfZuuw4gDJ7sYnKsLKbW
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T7gfZuuw4gDJ7sYnKsLKbW
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T7gfZuuw4gDJ7sYnKsLKbW
Merged
16 of 22 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Adeel · project thread
Description
Before: Lens had no way to tell which videos, documents or images contain NSFW pictures.
After: an admin turns on Settings → NSFW for every namespace, or an owner turns it on from the namespace's page for theirs. It is off by default. A new
nsfwstep then scores a video's sampled frames, a document's pages or an image with a model that runs on the server. When a picture scores at least the threshold, the resource is flagged.Flagged resources follow the namespace's display setting:
Editors can mark a resource NSFW or Not NSFW, with Undo. Classify existing classifies what was there before. Agents can do all of this through the API and MCP.
How it works:
objectsextra), and only when some namespace has classification turned on.nsfw.enabled,threshold(0.8),display(blur, hide or show) andmax_frames(300). A namespace's ownenabled,thresholdanddisplayare stored on the space record and override the archive's;nullfollows the archive.GET/PUT /namespaces/{name}/nsfwPOST /namespaces/{name}/nsfw/classifyPUT /resources/{rid}/nsfwGET /resources/nsfwsensitivefilter onGET /resourcesnsfwon resources, players, Library rows, search hits and photo hitsnsfw_settings,set_nsfwandmark_nsfw./library?namespace=…&nsfw=only);Motivation and Context
Adeel asked to "classify nsfw with a local model if enabled, or enabled for a namespace".
Types of changes
!in the title)Checklist:
tests/api/test_nsfw.py, with a fake model, a tiny real ONNX model, and the real model behindLENS_TEST_NSFW_MODEL, which passed locally with red ≈ 0.93. Also__tests__/nsfw.test.tsx.docs/accordingly: newdocs/nsfw.md, plus api, mcp, components and configuration.mkdocs build --strictis clean.## UnreleasedinCHANGELOG.md.Done questions (AGENTS.md)
nsfw_settings,set_nsfwandmark_nsfw..envedit or manual step is needed.ci/validate_threat_model.pypasses.max_framespictures per resource. The work runs inside the job's run row in the activity ledger, like the objects step.recording.nsfw,space.nsfw, thensfwsettings section), and a missing field means "not classified" or "follow the archive". Olderworkers.stepslists that includeobjectsalso runnsfw.make openapi.docs/nsfw.md):describestep for flagged pictures;🤖 Generated with Claude Code
https://claude.ai/code/session_01T7gfZuuw4gDJ7sYnKsLKbW
Generated by Claude Code