Discourse AI - NSFW

:bookmark: Questo argomento copre la configurazione della funzionalità NSFW (Not Safe For Work) del plugin Discourse AI.

:person_raising_hand: Livello utente richiesto: Amministratore

I moduli NSFW possono classificare automaticamente il punteggio NSFW di ogni nuovo caricamento di immagini nei post e nei messaggi di chat nella tua istanza Discourse. Questo sistema aiuta a identificare e gestire contenuti che potrebbero essere inappropriati o espliciti per un ambiente professionale o pubblico.

Puoi anche abilitare il contrassegno automatico dei contenuti che superano una soglia.

Impostazioni

  • ai_nsfw_detection_enabled: Abilita o disabilita il modulo

  • ai_nsfw_inference_service_api_endpoint: URL in cui è in esecuzione l’API per il modulo. Se stai utilizzando l’hosting CDCK, questo viene gestito automaticamente per te. Se stai auto-ospitando, consulta la guida all’auto-hosting.

  • ai_nsfw_inference_service_api_key: Chiave API per l’API configurata sopra. Se stai utilizzando l’hosting CDCK, questo viene gestito automaticamente per te. Se stai auto-ospitando, consulta la guida all’auto-hosting.

  • ai_nsfw_models: Il modello che utilizzeremo per la classificazione delle immagini. Offriamo due diversi modelli con le loro soglie:

    • opennsfw2 restituisce un singolo punteggio tra 0.0 e 1.0. Imposta la soglia affinché un caricamento sia considerato NSFW tramite l’impostazione ai_nsfw_flag_threshold_general.
    • nsfw_detector restituisce punteggi per quattro categorie: drawings, hentai, porn e sexy. Imposta la soglia per ciascuna tramite l’impostazione corrispondente ai_nsfw_flag_threshold_${category}. Se quello generale è inferiore a uno di questi, considereremo il contenuto NSFW.
  • ai_nsfw_flag_automatically: Contrassegna automaticamente i post/messaggi di chat che superano le soglie configurate. Quando questa impostazione è disabilitata, memorizziamo solo i risultati della classificazione nel database.

Risorse aggiuntive

11 Mi Piace

Grazie.

Ho riscontrato questo problema durante l’utilizzo del servizio nsfw, dopo aver caricato un’immagine. Utilizzo S3 per l’archiviazione delle immagini, se questo è rilevante.

INFO:     10.0.2.145:23412 - "POST /api/v1/classify HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 94, in receive
    return self.receive_nowait()
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 89, in receive_nowait
    raise WouldBlock
anyio.WouldBlock

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 77, in call_next
    message = await recv_stream.receive()
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 114, in receive
    raise EndOfStream
anyio.EndOfStream

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/uvicorn/protocols/http/h11_impl.py", line 404, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "/usr/local/lib/python3.9/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/applications.py", line 124, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.9/dist-packages/starlette_exporter/middleware.py", line 289, in __call__
    await self.app(scope, receive, wrapped_send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/cors.py", line 84, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 106, in __call__
    response = await self.dispatch_func(request, call_next)
  File "./app.py", line 49, in dispatch
    response = await call_next(request)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 80, in call_next
    raise app_exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 69, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 706, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 66, in app
    response = await func(request)
  File "./app.py", line 79, in classify
    results = models[parsed_params.model](tfile)
  File "/usr/local/lib/python3.9/dist-packages/opennsfw2/_inference.py", line 31, in predict_image
    pil_image = Image.open(image_path)
  File "/usr/local/lib/python3.9/dist-packages/PIL/Image.py", line 3283, in open
    raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file '/tmp/tmpbqq82655'
ERROR:uvicorn.error:Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 94, in receive
    return self.receive_nowait()
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 89, in receive_nowait
    raise WouldBlock
anyio.WouldBlock

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 77, in call_next
    message = await recv_stream.receive()
  File "/usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py", line 114, in receive
    raise EndOfStream
anyio.EndOfStream

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/uvicorn/protocols/http/h11_impl.py", line 404, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "/usr/local/lib/python3.9/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/applications.py", line 124, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.9/dist-packages/starlette_exporter/middleware.py", line 289, in __call__
    await self.app(scope, receive, wrapped_send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/cors.py", line 84, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 106, in __call__
    response = await self.dispatch_func(request, call_next)
  File "./app.py", line 49, in dispatch
    response = await call_next(request)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 80, in call_next
    raise app_exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py", line 69, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/usr/local/lib/python3.9/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 706, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.9/dist-packages/starlette/routing.py", line 66, in app
    response = await func(request)
  File "./app.py", line 79, in classify
    results = models[parsed_params.model](tfile)
  File "/usr/local/lib/python3.9/dist-packages/opennsfw2/_inference.py", line 31, in predict_image
    pil_image = Image.open(image_path)
  File "/usr/local/lib/python3.9/dist-packages/PIL/Image.py", line 3283, in open
    raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file '/tmp/tmpbqq82655'

In Sidekiq sembra così:

Cosa sto sbagliando?

Penso che questo possa essere correlato a S3. Durante il caricamento di un’immagine, i log degli errori mostrano questi errori:
URL a S3 oscurato…

Quindi sembra che il plugin tenti di caricare l’immagine troppo presto o non la trovi per altri motivi.

L’ho testato solo con siti che utilizzano una CDN per S3 o che utilizzano l’archiviazione locale. Se si utilizza Object Storage, si consiglia di utilizzare una CDN per metterlo di fronte.

1 Mi Piace

È esattamente quello che facciamo: AWS Cloudfront. Lo stack si basa su GitHub - aws-samples/aws-cdk-for-discourse: AWS CDK for Discourse. Proverò a eseguire il debug e pubblicherò i miei risultati.

2 Mi Piace

Dove ottengo la chiave API per questo?

Dovrebbe essere sotto il pannello Admin, no?

Sembra essere troppo sensibile per me, segnala le cose troppo spesso. Anche le semplici foto di persone vengono segnalate come NSFW.

Ho le soglie a 60. Non è chiaro se dovrei aumentare o diminuire questo numero e qual è il limite? Se lo imposto a 100, è essenzialmente disattivarlo? Non sembra esserci molta documentazione a riguardo.

Inoltre, perché non c’è modo di disattivarlo completamente per determinati ruoli, come avviene per la tossicità? Sono abbastanza sicuro che i membri del nostro staff non pubblicheranno nulla di offensivo, eppure combattono costantemente con l’IA perché segnala le loro cose. È diventato un po’ uno scherzo sul mio forum.

Utilizzo opennsfw2.

1 Mi Piace

Purtroppo quei vecchi modelli ML mancano di flessibilità e, sebbene siano leggeri per i requisiti di esecuzione della propria istanza, abbiamo scoperto che la rigidità era un ostacolo troppo grande per il set diversificato di community che utilizzano Discourse.

Attualmente il nostro piano è di deprecate tutte le funzionalità che si basano su quei vecchi modelli e migrare tutto a LLM moderni, dove potrai modificare il prompt per adattarlo meglio alle tue esigenze.

1 Mi Piace

C’è stato qualche cambiamento a riguardo? Il rilevatore NSFW è ancora terribilmente inaccurato e si attiva sulla maggior parte delle immagini con persone.

Sì, abbiamo comunicato il nostro piano in Cosa succederà per il rilevamento NSFW in Discourse AI, ma in breve puoi usare Classificatore di post di Discourse AI - Regola di automazione per una precisione e flessibilità molto maggiori.

Abbiamo eseguito valutazioni per il caso d’uso NSFW tramite LLM di visione e abbiamo ottenuto ottimi risultati, quindi stiamo attualmente implementando questo per i nostri clienti Enterprise e pubblicheremo le nostre guide a riguardo nelle prossime settimane.

2 Mi Piace