언어 장애

:warning: 이 기능은 이제 Discourse AI의 일부입니다. 이 플러그인은 더 이상 지원되지 않습니다.

:discourse2: 요약 Disorder는 잠재적으로 독성이 있는 콘텐츠를 자동으로 플래깅하여 Discourse 포럼의 관리자를 돕습니다.
:hammer_and_wrench: 저장소 링크 https://github.com/xfalcox/disorder
:open_book: 설치 가이드 Discourse에서 플러그인 설치 방법

공식 호스팅 서비스를 사용 중인 경우, 이 플러그인에 대한 관심을 등록하려면 지원팀에 문의해 주세요.

독성(Toxicity)

@hawk 님이 Dealing with Toxicity in Online Communities 말했듯이, 커뮤니티의 독성을 관리하는 것은 근본적으로 중요합니다.

Discourse는 커뮤니티의 독성을 관리하는 데 도움이 되는 다양한 도구를 기본으로 제공하지만, 우리는 이를 한층 더 개선할 방법을 항상 연구하고 있습니다. 특히 온라인 포럼에서 기계 학습과 AI의 가능한 적용 분야에 대해 연구해 왔습니다. 이제 이는 모든 커뮤니티에서 사용할 수 있는 실험적 플러그인이 되었습니다.

플러그인

Disorder는 인공지능과 기계 학습을 활용하여 커뮤니티를 관리하는 데 도움을 주며, 잠재적으로 문제가 될 수 있는 콘텐츠에 대해 관리 팀이 대응하기 쉽게 하고, 필요에 따라 사용자가 게시 전에 독성 있는 게시물을 수정하도록 유도할 수도 있습니다.

이는 Discourse에서 자체 호스팅 ML 모델을 사용하는 첫 번째 시도이며, 단순한 모델이지만 향후 더 복잡한 모델을 적용할 때 재사용할 수 있는 패턴을 제시합니다.

기능

백그라운드 플래깅

이는 사용자에게 완전히 투명하여 변경 사항을 인지하지 못하게 하므로, Disorder의 주요 작동 방식입니다.

새로운 게시물(또는 Discourse Chat을 사용한 채팅 메시지)이 생성될 때마다 비동기적으로 분류 대기열에 추가됩니다. 분류 결과가 설정 가능한 임계값을 초과하는 경우, 해당 게시물/채팅 메시지가 플래깅되어 관리 팀에게 경고가 표시되고, 플래그에 대한 최종 결정을 내릴 수 있습니다.

새 게시물 개입

예방이 최선의 치료법이라고 생각한다면, 이 보다 능동적인 옵션에 관심이 있을 수 있습니다.

새 게시물에 대한 동기식 분류를 활성화할 수 있으며, 독성 임계값을 초과할 경우 새 게시물 흐름에서 개입을 트리거하여 사용자가 커뮤니티 규칙이 정한 경계를 벗어날 수 있는 메시지를 검토하고 수정하도록 요청합니다.

이는 한 번만 발생하며, 모달을 닫은 후에는 사용자가 정상적으로 게시물을 게시할 수 있습니다.

작동 방식

이 플러그인은 Detoxify의 오픈 소스 모델을 통합하며, 원격 API 호출 모델을 사용하여 관리자가 각 커뮤니티의 필요에 맞게 추론 속도를 적절하게 확장할 수 있도록 합니다.

우리는 Discourse가 콘텐츠 분류를 수행하기 위해 호출하는 얇은 HTTP API를 제공하는 간단한 이미지를 제공합니다. 이 이미지는 Discourse를 실행하는 서버와 동일한 서버에서 실행하거나 완전히 다른 서버에서 실행할 수 있습니다.

Discourse 플러그인은 새 게시물/새 채팅 메시지 이벤트를 수신 대기하며 백그라운드 대기열에 분류 작업을 큐에 넣습니다. 결과를 데이터베이스에 저장하여 보고서를 추출할 수 있으며, 플래그 정확도를 시간에 따라 추적할 수 있도록 별도의 봇 사용자를 사용하여 콘텐츠를 플래깅합니다.

옵션

먼저, 이 플러그인은開箱即用(기본 설정으로 작동)하므로, 즉시 설정을 변경할 필요가 없습니다. 그러나 플러그인 동작을 변경하려면 사용할 수 있는 몇 가지 조절 항목이 있습니다.

플러그인 옵션에서 선택할 수 있는 3가지 다른 분류 모델을 제공합니다:

  • unbiased(기본값): 독성 분류에서 의도하지 않은 모델 편향을 줄이려는 모델

  • multilingual: 이탈리아어, 프랑스어, 러시아어, 포르투갈어, 스페인어 및 터키어를 분류할 수 있는 모델.

  • original: 가장 단순한 모델.

또한 플러그인이 다음을 수행하도록 조정할 수 있습니다:

  • 자동으로 플래깅
  • 독성 게시물에 대한 경고와 함께 동기식 개입 활성화 (실험적)
  • 독성 게시물에 대한 동기식 개입 활성화 (권장되지 않음)

위 모든 동작은 댓글이 각 분류 유형의 임계값을 초과하도록 분류될 때만 발생합니다:

  • toxicity (독성)
  • severe_toxicity (심각한 독성)
  • identity_attack (신원 공격)
  • insult (모욕)
  • threat (위협)
  • sexual_explicit (성적 노골적 내용)

자동 작업을 위한 각 분류 임계값을 조정할 수 있습니다.

분류 서비스

이 플러그인은 기본 설정으로 작동하도록 사전 구성됩니다. 이를 위해 Discourse(CDCK)가 실행하는 서비스와 통신하여 사용자 콘텐츠를 분류합니다. 해당 분류 API 서비스는 오픈 소스이며, 필요 시 서비스의 자체 복사본을 실행할 수 있습니다.

39개의 좋아요

호기심에 여쭤볼 것이 있는데요, "Disorder"와 Discourse의 Google Perspective API 구현 방식 사이에는 어떤 차이가 있나요?

7개의 좋아요

코드 측면에서는 완전히 다른 플러그인입니다.

조금 더 넓게 보면 같은 요구 사항을 충족하지만, 설계 방식은 다릅니다:

  • Disorder는 채팅과 게시물을 모두 다루지만, Perspective는 게시물만 다룹니다.

  • Perspective는 독점적 API와 제3자 API에 의존하며, 이로 인해 프라이버시, 신뢰성, 투명성 관련 문제가 발생할 수 있습니다.

  • Disorder는 새로운 모델을 쉽게 추가할 수 있는 패턴을 설정하여, 서비스를 발전시키거나 완전히 새로운 기능을 추가할 수 있습니다.

  • Disorder의 셀프호스팅 API는 API 호출당 과금과 속도 제한으로부터의 유연성과 자유를 제공합니다.

  • Disorder의 프론트엔드 범위는 상당히 작아, Discourse 업데이트에 대해 더 견고할 수 있습니다.

16개의 좋아요

좋아요. 어디서 어떻게 해야 하나요?

5개의 좋아요

team@discourse.org으로 이메일을 보내세요 :slight_smile:

6개의 좋아요

여기서 답변할 필요는 없지만, 다음 단계로 나아갈 방향에 대한 조언을 원하신다면, 주제의 텍스트를 기반으로 AI가 태그를 제안하는 기능이 유용할 수 있습니다. Soundcloud가 업로드된 파일에 대한 분석을 수행한 후 음악 장르 태그를 제안하는 방식과 유사한 것을 상상해 볼 수 있습니다. 이는 트래픽이 많은 사이트에서 사용자가 생성한 콘텐츠를 정리하는 데 유용합니다.

9개의 좋아요

제가 제대로 이해한 건지 여쭤봐도 될까요? 플러그인을 동반하기 위해 disorder API 인스턴스를 실행해야 하는 건가요? disorder 추론 서비스 API 엔드포인트 설정에는 https://disorder-testing.demo-by-discourse.com 이 기본적으로 입력되어 있습니다. 그러나 disorder 추론 서비스 API 키 는 기본적으로 비어 있습니다.

저희는 사용자 간의 많은 독성 행동을 겪고 있어, 현재는 플래깅과 리더들의 도움으로 궁극적으로 해결하고 있지만, 가능하다면 사용자가 부정적인 게시물을 확산시키는 것을 사전에 방지하고 싶습니다. 이 플러그인이 그런 역할을 수행할 수 있을 것 같아 테스트해 보고 싶습니다.

시도해 볼 수 있는 기존에 준비된 엔드포인트가 있을까요? 참고로 저희 사이트는 하루 약 15만 페이지뷰를 기록하고 있어, 준비가 덜 된 서버에 부하를 줄 수 있습니다.

저희는 스탠드얼론(Standalone) 환경입니다.

4개의 좋아요

직접 API 서버를 실행할 수 있지만, 플러그인은 기본적으로 https://disorder-testing.demo-by-discourse.com/로 설정되어 있어 바로 사용할 수 있습니다.

자체 호스팅 인스턴스에서 이 플러그인을 시험해 보고자 하는 사용자를 위해 해당 엔드포인트가 정확히 제공되었으므로, 인스턴스에서 이 엔드포인트를 사용해 주십시오. 기본 설정에서는 모든 API 호출이 백그라운드에서 이루어지므로, API가 중단되어도 사이트에 어떤 영향도 미치지 않아 안전하게 사용할 수 있습니다.

api key 설정은 선택 사항이며, API 서버에서 이를 활성화한 경우에만 필요합니다. https://disorder-testing.demo-by-discourse.com/의 공개 인스턴스에서는 활성화되어 있지 않습니다.

6개의 좋아요

감사합니다! 정말 완벽해 보여서 며칠 안에 한번 시도해 볼게요 :heart:

4개의 좋아요

미래를 위해 다른 ML 애플리케이션도 계획되어 있나요?

2개의 좋아요

일주일간 사용해 봤는데, 게시물을 경고하는 방식이 터무니없이 공격적이었습니다. 관리자가 충분히 없는 대규모 사이트에서만 사용하는 것을 추천합니다. AI가 더 좋아지길 바라지만, 아직은 그 정도가 되지 못합니다.

6개의 좋아요

정말 좋은 피드백입니다! 정확히 어떤 일이 발생했는지 이해하는 데 도움이 되도록 디버깅 통계를 공유해 주시겠어요?

아래와 같은 쿼리의 결과를 여기에나 DM으로 보내주시면 정말 큰 도움이 될 것입니다.

SELECT
  pcf.value,
  p.raw
FROM
  post_custom_fields AS pcf
INNER JOIN
  posts AS p ON p.id = pcf.post_id
WHERE
  pcf.name = 'disorder'
5개의 좋아요

아, 맞다! 그거 완전 잊고 있었네. 여기 있어. 사실 그렇게 많지는 않았지만, 그냥 불필요한 것들이었고 멤버들과 모드가 귀찮아하더라고. 그리고 DM을 스캔하는 기능에 대해서는 나도 확신이 없거든. 누군가 DM으로 괴롭힘을 당하는 경우에는 가치가 있을 수 있다는 건 알지만, 대부분은 우리가 DM을 보고 있다는 걸 알아서 사람들이 불편해할 것 같아.

1개의 좋아요

채팅을 사용하시나요? 게시물/DM에 있는 모든 귀찮은 플래그인가요?

우리는 채팅을 사용하지만, 모든 플래그가 게시물과 개인 메시지에 있었다고 확신합니다.

1개의 좋아요

우선, 디버깅을 더 진행할 수 있도록 피드백과 데이터를 공유해 주셔서 매우 감사드립니다.

이제 조사 결과를 말씀드리겠습니다!

해당 기간 동안 스태프가 아닌 사용자로부터 1,942개의 새 게시물이 등록되었습니다. 꽤 활발한 커뮤니티네요! 하지만 AI가 "게시물 신고에 지나치게 공격적"이라고 보기는 어렵습니다. 단 7개 게시물만 신고되었기 때문이죠.

그렇다고 해도, 그 7개 중 절반은 기본 임계값이 너무 낮아 발생한 명백한 오탐인 반면, 다른 절반은 AI가 맥락을 이해하기 어려운 경우(상대방을 바보라고 부르는 것과, 쇼핑하다가 누군가 나에게 바보처럼 굴었다는 이야기를 하는 것의 차이)이며, 하나는 제 생각에는 정확한 신고인 것 같습니다.

다시 시도해 보실 의사가 있으시다면, 모든 임계값을 85로 조정하고 original 모델로 전환하시면 지금까지 경험하신 과도한 신고 문제를 거의 모두 해결할 수 있을 것입니다. 일부 커뮤니티에서는 사설(PM)을 건너뛰는 것이 번거로울 수 있으므로, 이를 허용하는 사이트 설정을 추가하겠습니다.

8개의 좋아요

Falco님, 감사드립니다. "무모하다"고 표현한 것은 사과드립니다. 이미 사이트에서 여러 문제가 발생하고 있었는데, 신고 기능이 그 혼란을 더 키웠고, 당시에는 꽤 화가 난 상태였습니다.

제안해 주신 내용 감사히 받아들이고, 다시 한번 시도해 보겠습니다. 질문이 하나 있습니다. disorder flag automatically(무질서 자동 신고)를 비활성화하면 어떻게 되나요? 게시물이 무질서하다고 판단될 경우에도 여전히 어떤 형태로든 통지를 받을 수 있을까요? 게시물이 신고되지 않는 상태에서 어떤 설정이 효과적인지 테스트해 보고 싶기 때문입니다.

4개의 좋아요

해당 설정이 없으면 게시물을 AI로 처리하되, 어떠한 조치도 취하지 않습니다. 이 상태를 그대로 유지한 뒤 Data Explorer 쿼리를 실행하여 오탐(false positive)/미탐(false negative) 비율을 분석해 볼 수 있습니다.

또한, 스킵 목록에 그룹을 추가할 수 있는 다른 설정도 있습니다. 예를 들어, TL4/3의 게시물 분류를 건너뛰도록 할 수 있습니다. 이 방법도 도움이 될 수 있습니다.

Falco 님,

Disorder 플러그인 테스트를 시작했습니다. 전반적인 피드백은 긍정적입니다. 실제로 부적절한 내용을 잘 감지하지만, 우리 커뮤니티에서 허용되는 많은 내용까지 플래그를 매기고 있습니다. 이 플러그인을 테스트 중인 포럼의 특성(성인용)상, 커뮤니케이션에 여러 측면이 포함되어 있어 Disorder가 수많은 게시글을 플래그로 표시합니다. 어떤 임계값을 조정해야 하는지 확인하는 데 도움이 되는 SQL 쿼리를 제공해 주셔서 감사합니다. 그런데 각 플래그된 게시글에 대해 이 기준들을 Reviewable Scoring 테이블에 추가하는 것을 제안해도 될까요?

이 부분

플러그인이 이 뷰에 자체 데이터를 도입할 수 있는지 모르겠지만, 오진(false-positive) 결과를 줄이기 위해 어떤 기준을 조정해야 하는지 직원이 이해하는 데 큰 도움이 될 것입니다. 제 생각에는 이 뷰 내에서 트리거된 기준별 분해 내용을 드롭다운으로 추가하는 것입니다. 0에 해당하는 기준은 포함할 필요가 없습니다. 0보다 큰 기준은 표시되어야 하지만, 현재 설정된 임계값을 초과하는 기준만 굵은 글씨/빨간색으로 표시하면 됩니다.

Disorder 점수화 예시
  • Toxicity 65% [1]
  • Insult 73% [2]
  • Threat 12% [3]
  • Sexual explicit 2% [4]

필요하다면 SQL 쿼리 결과를 제공해 드릴 수 있습니다. Flag Queue 검토를 완료하기까지는 아직 많이 남아 있습니다.
다국어 모델을 사용 중이며 다른 모델은 시도해 보지 않았습니다. 일부 사용자가 모국어로 게시글을 작성하는 것을 선호하기 때문에, 다국어 모델로 시작하는 것이 좋겠다고 판단했습니다.


  1. 초과, 빨간 글씨 ↩︎

  2. 초과, 빨간 글씨 ↩︎

  3. 정상, 일반 글씨 ↩︎

  4. 정상, 일반 글씨 ↩︎

1개의 좋아요

다시 인사드립니다.

“original” 모델을 사용할 때 Disorder와 관련된 오류가 로그에 기록되고 있다는 것을 알려드리고자 합니다. 차이를 확인해 보기 위해刚才 multilingual 모델로 다시 변경해 보았습니다.

Job exception: undefined method `>=’ for nil:NilClass @classification[label] >= SiteSetting.send(“disorder_flag_threshold_#{label}”) ^^

세부 정보

/var/www/discourse/plugins/disorder/lib/classifier.rb:39:in `block in consider_flagging’

/var/www/discourse/plugins/disorder/lib/classifier.rb:38:in `filter’

/var/www/discourse/plugins/disorder/lib/classifier.rb:38:in `consider_flagging’

/var/www/discourse/plugins/disorder/lib/classifier.rb:25:in `classify!’

/var/www/discourse/plugins/disorder/app/jobs/regular/classify_post.rb:14:in `execute’

/var/www/discourse/app/jobs/base.rb:249:in `block (2 levels) in perform’

rails_multisite-4.0.1/lib/rails_multisite/connection_management.rb:80:in with_connection' /var/www/discourse/app/jobs/base.rb:236:in block in perform’

/var/www/discourse/app/jobs/base.rb:232:in `each’

/var/www/discourse/app/jobs/base.rb:232:in `perform’

sidekiq-6.5.8/lib/sidekiq/processor.rb:202:in `execute_job’

sidekiq-6.5.8/lib/sidekiq/processor.rb:170:in `block (2 levels) in process’

sidekiq-6.5.8/lib/sidekiq/middleware/chain.rb:177:in `block in invoke’

/var/www/discourse/lib/sidekiq/pausable.rb:134:in `call’

sidekiq-6.5.8/lib/sidekiq/middleware/chain.rb:179:in `block in invoke’

sidekiq-6.5.8/lib/sidekiq/middleware/chain.rb:182:in `invoke’

sidekiq-6.5.8/lib/sidekiq/processor.rb:169:in `block in process’

sidekiq-6.5.8/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch’

sidekiq-6.5.8/lib/sidekiq/job_retry.rb:113:in `local’

sidekiq-6.5.8/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch’

sidekiq-6.5.8/lib/sidekiq.rb:44:in `block in module:Sidekiq’

sidekiq-6.5.8/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch’

sidekiq-6.5.8/lib/sidekiq/processor.rb:263:in `stats’

sidekiq-6.5.8/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch’

sidekiq-6.5.8/lib/sidekiq/job_logger.rb:13:in `call’

sidekiq-6.5.8/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch’

sidekiq-6.5.8/lib/sidekiq/job_retry.rb:80:in `global’

sidekiq-6.5.8/lib/sidekiq/processor.rb:124:in `block in dispatch’

sidekiq-6.5.8/lib/sidekiq/job_logger.rb:39:in `prepare’

sidekiq-6.5.8/lib/sidekiq/processor.rb:123:in `dispatch’

sidekiq-6.5.8/lib/sidekiq/processor.rb:168:in `process’

sidekiq-6.5.8/lib/sidekiq/processor.rb:78:in `process_one’

sidekiq-6.5.8/lib/sidekiq/processor.rb:68:in `run’

sidekiq-6.5.8/lib/sidekiq/component.rb:8:in `watchdog’

sidekiq-6.5.8/lib/sidekiq/component.rb:17:in `block in safe_thread’

세부 정보 2
호스트명
process_id 65460
application_version 2f8ad17aed81bbfa2fd20b6cc9210be92779bd74
current_db default
current_hostname
job Jobs::ClassifyPost
problem_db default
time 1:52 pm
opts
post_id 604063
current_site_id default

P.S. 네, 다국어(multilingual) 모드에서는 이러한 오류가 발생하지 않습니다. 편향 없는(unbiased) 모델에서도 오류가 발생하지 않습니다.

1개의 좋아요