Upload Moderation: Node.js NSFW, Violence, Hate-Symbol Classification + JSON Fallback
Short answer: for media support tickets that include an image, keep classification, policy enforcement, and tenant cost accounting as three separate steps. Send the image to a multimodal chat model with a strict JSON Schema, validate the returned object locally, and send invalid or uncertain cases to review. The fallback is a queue, not a guess. That design matters because a support agent is usually triaging a complaint, not publishing a photo. The same upload might be evidence of a violent broadcast, a screenshot containing a hate symbol, or an ordinary account avatar. A boolean called safe throws away the context that the agent needs. Keep it boring. How can a Node.js image moderation flow classify risky uploads without trusting JSON? Start with a versioned taxonomy. For this media workflow, I would keep nsfw , violence , and hate_symbols as separate observations, add uncertain , and retain a short evidence string. The model describes what it can see; application code decides whether a ticket is visible, blocked, or waiting for a human. This boundary also makes an eval harness useful: a prompt change can be tested independently from the enforcement policy. The tempting shortcut is to ask for a sentence and search it for words. It feels flexible in a notebook, then becomes difficult to replay: punctuation changes the parser, a missing category looks like a negative result, and a tenant's policy cannot be reconstructed from a free-form answer. Typed output is not a safety decision, but it gives the rest of the pipeline a stable input. Here is a deliberately small adapter. The surrounding Node.js upload service can call the same contract from any language; the example keeps the model call behind an OpenAI-compatible chat client and uses environment variables for the concrete base URL and model. It does not publish an upload merely because the response parses. import json import os from openai import OpenAI MODERATION_SCHEMA = { " name " : " media_upload_labels " , "