Dieses Thema behandelt die Konfiguration der NSFW-Funktion (Not Safe For Work) des Discourse AI-Plugins.
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,0und1,0zurück. Legen Sie den Schwellenwert für einen als NSFW betrachteten Upload über die Einstellungai_nsfw_flag_threshold_generalfest.- nsfw_detector gibt Scores für vier Kategorien zurück:
drawings,hentai,pornundsexy. Legen Sie den Schwellenwert für jede Kategorie über die entsprechende Einstellungai_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
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.
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.
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.
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.
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.

