# Discourse AI - NSFW

**URL:** https://meta.discourse.org/t/discourse-ai-nsfw/259600
**Category:** Site Management
**Tags:** ai, ai-nsfw
**Created:** [4월 24, 2023, 7:40오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600 "2023-04-24T19:40:19Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [4월 24, 2023, 7:40오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/1 "2023-04-24T19:40:19Z")

</div>

> 🔖 이 주제는 [Discourse AI](https://meta.discourse.org/t/discourse-ai/259214?slient=true) 플러그인의 NSFW(Not Safe For Work) 기능 설정에 대해 다룹니다.
> 
> 🙋 필요한 사용자 권한: 관리자

NSFW 모듈은 Discourse 인스턴스의 게시물 및 채팅 메시지에 업로드되는 모든 새 이미지의 NSFW 점수를 자동으로 분류할 수 있습니다. 이 시스템은 전문적이거나 공개적인 환경에서 부적절하거나 노골적일 수 있는 콘텐츠를 식별하고 관리하는 데 도움이 됩니다.

임계값을 초과하는 콘텐츠에 대한 자동 플래깅(신고)도 활성화할 수 있습니다.

### 설정

- **ai\_nsfw\_detection\_enabled** : 모듈을 활성화하거나 비활성화합니다.

- **ai\_nsfw\_inference\_service\_api\_endpoint** : 모듈이 사용하는 API가 실행 중인 URL입니다. CDCK 호스팅을 사용하는 경우 이 설정은 자동으로 처리됩니다. 자체 호스팅(self-hosting)을 사용하는 경우 [자체 호스팅 가이드](https://meta.discourse.org/t/discourse-ai-self-hosted-guide/259598/1)를 확인하세요.

- **ai\_nsfw\_inference\_service\_api\_key** : 위에서 설정한 API의 API 키입니다. CDCK 호스팅을 사용하는 경우 이 설정은 자동으로 처리됩니다. 자체 호스팅(self-hosting)을 사용하는 경우 [자체 호스팅 가이드](https://meta.discourse.org/t/discourse-ai-self-hosted-guide/259598/1)를 확인하세요.

- **ai\_nsfw\_models** : 이미지 분류에 사용할 모델입니다. 임계값이 다른 두 가지 모델을 제공합니다:

- **ai\_nsfw\_flag\_automatically** : 설정된 임계값을 초과하는 게시물/채팅 메시지를 자동으로 플래깅합니다. 이 설정이 비활성화된 경우, 분류 결과는 데이터베이스에 저장만 됩니다.

## 추가 자료

- [Discourse AI](https://meta.discourse.org/t/discourse-ai/259214?silent=true)
- [Install plugins on a self-hosted site](https://meta.discourse.org/t/install-plugins-in-discourse/19157?silent=true)

---

<div class="post-metadata">

### Author: ![nodomain](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nodomain/32/303402_2.png) [@nodomain](https://meta.discourse.org/u/nodomain)
#### Post date: [4월 29, 2023, 10:19오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/2 "2023-04-29T22:19:49Z")

</div>

감사합니다.

이미지를 업로드한 후 nsfw 서비스를 사용할 때 이 문제를 발견했습니다. 이미지 저장에는 S3를 사용하는데, 이것이 관련이 있는지 모르겠습니다.

```plaintext
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'

```

Sidekiq에서는 다음과 같이 보입니다:

 ![image](https://global.discourse-cdn.com/meta/original/4X/9/d/d/9dd61281f80b004c9e2efb54d9971c6b81311989.jpeg)

제가 무엇을 잘못하고 있는 건가요?

---

<div class="post-metadata">

### Author: ![nodomain](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nodomain/32/303402_2.png) [@nodomain](https://meta.discourse.org/u/nodomain)
#### Post date: [4월 30, 2023, 8:36오전 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/3 "2023-04-30T08:36:34Z")

</div>

이 문제는 S3와 관련이 있을 것 같습니다. 이미지를 업로드할 때 에러 로그에 다음과 같은 오류가 표시됩니다:  
S3 URL은 삭제되었습니다…

 ![image](https://global.discourse-cdn.com/meta/original/4X/7/8/3/7838b293e39bfa7fc76eb799e767756f89e69b24.png)

즉, 플러그인이 이미지를 너무 일찍 로드하려 하거나, 기타 이유로 이미지를 찾지 못하는 것으로 보입니다.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [4월 30, 2023, 7:48오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/4 "2023-04-30T19:48:34Z")

</div>

저는 S3에 CDN을 사용하거나 로컬 스토리지를 사용하는 사이트에서만 테스트했습니다. Object Storage를 사용하는 경우, 그 앞에 CDN을 사용하는 것을 권장합니다.

---

<div class="post-metadata">

### Author: ![nodomain](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nodomain/32/303402_2.png) [@nodomain](https://meta.discourse.org/u/nodomain)
#### Post date: [4월 30, 2023, 9:36오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/5 "2023-04-30T21:36:41Z")

</div>

네, 저희가 정확히 그렇게 하고 있습니다 - AWS CloudFront를 사용 중입니다. 스택은 [https://github.com/aws-samples/aws-cdk-for-discourse에](https://github.com/aws-samples/aws-cdk-for-discourse%EC%97%90) 기반하고 있습니다. 디버깅을 시도해서 결과를 공유하겠습니다.

---

<div class="post-metadata">

### Author: ![Noxitb](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/noxitb/32/387110_2.png) [@Noxitb](https://meta.discourse.org/u/Noxitb)
#### Post date: [5월 20, 2024, 3:41오전 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/7 "2024-05-20T03:41:25Z")

</div>

API 키는 어디서 받아야 하나요?

---

<div class="post-metadata">

### Author: ![NateDhaliwal](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/natedhaliwal/32/313494_2.png) [@NateDhaliwal](https://meta.discourse.org/u/NateDhaliwal)
#### Post date: [6월 6, 2024, 9:41오전 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/8 "2024-06-06T09:41:29Z")

</div>

관리자 패널 아래에 있어야 하지 않나요?

---

<div class="post-metadata">

### Author: ![Shauny](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/shauny/32/362012_2.png) [@Shauny](https://meta.discourse.org/u/Shauny)
#### Post date: [7월 15, 2024, 12:23오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/9 "2024-07-15T12:23:48Z")

</div>

이 기능은 제게 너무 민감하게 반응하는 것 같습니다. 너무 자주 플래그가 걸리거든요. 그냥 사람 사진만으로도 NSFW로 분류됩니다.

현재 임계값(threshold)을 60으로 설정해 두었는데, 이 수치를 높여야 하는지 낮춰야 하는지, 그리고 한계가 무엇인지 명확하지 않습니다. 100으로 설정하면 사실상 기능을 비활성화하는 것과 같은 효과가 있나요? 이에 대한 문서화가 거의 없는 것 같습니다.

또한, 독성(toxicity) 기능에서는 특정 역할을 대상으로 완전히 비활성화할 수 있는 옵션이 있는데, 왜 이 기능에는 그런 옵션이 없는지 궁금합니다. 저희 스태프들이 무례한 내용을 게시할 것이라고는 거의 생각하지 않는데, AI가 그들의 게시물을 계속 플래그 처리해서 늘 갈등이 생기고 있습니다. 이제 저희 포럼에서는 이게 거의 농담거리가 될 정도입니다.

opennsfw2를 사용 중입니다.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [8월 1, 2024, 4:02오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/10 "2024-08-01T16:02:47Z")

</div>

불행히도 이러한 구형 ML 모델은 유연성이 부족하며, 자체 인스턴스를 실행하는 데 필요한 사양은 낮지만, Discourse를 사용하는 다양한 커뮤니티에 있어 그 엄격함이 너무 큰 장애물이 된다는 것을 발견했습니다.

현재 계획은 이러한 구형 모델에 의존하는 모든 기능을 비추천(deprecate) 처리하고, 프롬프트를 조정하여 필요에 더 잘 맞도록 할 수 있는 현대적인 LLM으로 모든 것을 마이그레이션하는 것입니다.

---

<div class="post-metadata">

### Author: ![Shauny](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/shauny/32/362012_2.png) [@Shauny](https://meta.discourse.org/u/Shauny)
#### Post date: [10월 6, 2024, 4:08오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/12 "2024-10-06T16:08:26Z")

</div>

이 부분에 대해 어떤 변화가 있었나요? NSFW 감지기는 여전히 매우 부정확해서, 사람 사진 대부분에서 오작동합니다.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [10월 6, 2024, 5:26오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/13 "2024-10-06T17:26:37Z")

</div>

네, [What’s next for NSFW detection in Discourse AI](https://meta.discourse.org/t/what-s-next-for-nsfw-detection-in-discourse-ai/320653)에서 우리의 계획을 공유한 바 있습니다. 결론부터 말씀드리면, 훨씬 더 높은 정확도와 유연성을 위해 [Discourse AI Post Classifier - Automation rule](https://meta.discourse.org/t/discourse-ai-post-classifier-automation-rule/281227)을 사용하실 수 있습니다.

비전 LLM을 통한 NSFW 사용 사례에 대한 평가를 수행했으며 훌륭한 결과를 얻었습니다. 이에 따라 현재 엔터프라이즈 고객사 대상으로 해당 기능을 배포하고 있으며, 몇 주 안에 관련 가이드를 공개할 예정입니다.

---

<div class="post-metadata">

### Author: ![Saif](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/saif/32/318253_2.png) [@Saif](https://meta.discourse.org/u/Saif)
#### Post date: [12월 9, 2024, 6:05오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/14 "2024-12-09T18:05:40Z")

</div>



---

<div class="post-metadata">

### Author: ![Saif](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/saif/32/318253_2.png) [@Saif](https://meta.discourse.org/u/Saif)
#### Post date: [12월 9, 2024, 6:05오후 UTC](https://meta.discourse.org/t/discourse-ai-nsfw/259600/15 "2024-12-09T18:05:42Z")

</div>


