Discourse AI - NSFW

:bookmark: Dieses Thema behandelt die Konfiguration der NSFW-Funktion (Not Safe For Work) des Discourse AI-Plugins.

:person_raising_hand: Erforderliche Benutzerebene: Administrator

Die NSFW-Module können den NSFW-Score jedes neuen Bild-Uploads in Beiträgen und Chat-Nachrichten in Ihrer Discourse-Instanz automatisch klassifizieren. Dieses System hilft bei der Identifizierung und Verwaltung von Inhalten, die für ein professionelles oder öffentliches Umfeld unangemessen oder explizit sein können.

Sie können auch die automatische Kennzeichnung von Inhalten aktivieren, die einen Schwellenwert überschreiten.

Einstellungen

  • ai_nsfw_detection_enabled: Aktiviert oder deaktiviert das Modul

  • ai_nsfw_inference_service_api_endpoint: URL, unter der die API für das Modul ausgeführt wird. Wenn Sie CDCK-Hosting verwenden, wird dies automatisch für Sie erledigt. Wenn Sie selbst hosten, lesen Sie die Anleitung für Self-Hosting.

  • ai_nsfw_inference_service_api_key: API-Schlüssel für die oben konfigurierte API. Wenn Sie CDCK-Hosting verwenden, wird dies automatisch für Sie erledigt. Wenn Sie selbst hosten, lesen Sie die Anleitung für Self-Hosting.

  • ai_nsfw_models: Das Modell, das wir für die Bildklassifizierung verwenden. Wir bieten zwei verschiedene mit ihren Schwellenwerten an:

    • opennsfw2 gibt einen einzelnen Score zwischen 0,0 und 1,0 zurück. Legen Sie den Schwellenwert für einen als NSFW betrachteten Upload über die Einstellung ai_nsfw_flag_threshold_general fest.
    • nsfw_detector gibt Scores für vier Kategorien zurück: drawings, hentai, porn und sexy. Legen Sie den Schwellenwert für jede Kategorie über die entsprechende Einstellung ai_nsfw_flag_threshold_${category} fest. Wenn der allgemeine Wert niedriger ist als einer dieser Werte, betrachten wir den Inhalt als NSFW.
  • ai_nsfw_flag_automatically: Kennzeichnet automatisch Beiträge/Chat-Nachrichten, die über den konfigurierten Schwellenwerten liegen. Wenn diese Einstellung deaktiviert ist, speichern wir nur die Klassifizierungsergebnisse in der Datenbank.

Zusätzliche Ressourcen

11 „Gefällt mir“

Danke.

Ich habe dieses Problem beim Verwenden des NSFW-Dienstes nach dem Hochladen eines Bildes festgestellt. Ich verwende S3 für die Bildspeicherung, falls das relevant ist.

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 sieht es so aus:

Was mache ich falsch?

Ich glaube, das hat vielleicht mit S3 zu tun. Beim Hochladen eines Bildes zeigen die Fehlerprotokolle diese Fehler an:
URL zu S3 geschwärzt…

Es scheint also, dass das Plugin versucht, das Bild zu früh zu laden, oder es nicht aus anderen Gründen findet.

Ich habe es nur mit Websites getestet, die ein CDN für S3 verwenden oder lokalen Speicher nutzen. Bei Verwendung von Object Storage empfehle ich, ein CDN davor zu schalten.

1 „Gefällt mir“

Das ist genau das, was wir tun – AWS Cloudfront. Der Stack basiert auf GitHub - aws-samples/aws-cdk-for-discourse: AWS CDK for Discourse. Ich werde versuchen, das Problem zu debuggen und meine Ergebnisse zu posten.

2 „Gefällt mir“

Woher bekomme ich den API-Schlüssel dafür?

Es sollte unter dem Admin-Panel sein, oder?

Das scheint mir viel zu empfindlich zu sein, es markiert viel zu oft Dinge. Nur Bilder von Menschen werden als NSFW markiert.

Ich habe die Schwellenwerte auf 60 eingestellt. Es ist nicht klar, ob ich diese Zahl erhöhen oder verringern soll und was die Grenze ist? Wenn ich sie auf 100 setze, ist das im Grunde eine Deaktivierung? Es scheint nicht viele Dokumentationen dazu zu geben.

Außerdem, warum gibt es keine Möglichkeit, es für bestimmte Rollen vollständig zu deaktivieren, wie es bei Toxizität der Fall ist? Ich bin ziemlich sicher, dass unsere Mitarbeiter nichts Unhöfliches posten werden, trotzdem streiten sie ständig mit der KI, weil sie deren Inhalte markiert. Es ist auf meinem Forum zu einem Witz geworden.

Verwendet opennsfw2.

1 „Gefällt mir“

Leider mangelt es diesen älteren ML-Modellen an Flexibilität, und obwohl sie die Anforderungen für den Betrieb Ihrer eigenen Instanz gering halten, stellten wir fest, dass die Strenge ein zu großes Hindernis für die vielfältigen Gemeinschaften darstellte, die Discourse nutzen.

Derzeit ist unser Plan, alle Funktionen, die auf diesen alten Modellen basieren, einzustellen und alles auf moderne LLMs zu migrieren, wo Sie die Eingabeaufforderung an Ihre Bedürfnisse anpassen können.

1 „Gefällt mir“

Hat sich hier überhaupt etwas geändert? Der NSFW-Detektor ist immer noch miserabel ungenau und löst bei den meisten Bildern mit Personen aus.

Ja, wir haben unseren Plan unter Was kommt als Nächstes für die NSFW-Erkennung in Discourse AI kommuniziert, aber die Kurzfassung ist, dass Sie Discourse AI Post Classifier - Automatisierungsregel für eine viel bessere Genauigkeit und Flexibilität verwenden können.

Wir haben Auswertungen für den NSFW-Anwendungsfall mithilfe von Vision LLMs durchgeführt und großartige Ergebnisse erzielt. Daher führen wir dies derzeit für unsere Enterprise-Kunden ein und werden unsere Anleitungen dazu in den kommenden Wochen veröffentlichen.

2 „Gefällt mir“