diff --git a/services/discord-gateway/src/modules/ai-moderation/llmClient.ts b/services/discord-gateway/src/modules/ai-moderation/llmClient.ts index 8f1fb0b..85d81bd 100644 --- a/services/discord-gateway/src/modules/ai-moderation/llmClient.ts +++ b/services/discord-gateway/src/modules/ai-moderation/llmClient.ts @@ -84,17 +84,19 @@ export async function llmChat( retries = DEFAULT_RETRIES, } = opts; - const params: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = { - model, - messages, - temperature, - top_p, - max_tokens, - stream: false, - }; + const params: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = + { + model, + messages, + temperature, + top_p, + max_tokens, + stream: false, + }; if (jsonResponse) { - (params as unknown as Record).response_format = jsonResponse; + (params as unknown as Record).response_format = + jsonResponse; } return retryWithBackoff( @@ -198,10 +200,15 @@ const VALID_PRIMARY_AI_FLAGS = new Set([ "financial_scam", "religious_insult", "self_promo", + "conflict_instigation", + "offensive_username", ]); function normalizeFlag(value: string): string | null { - const lower = value.trim().toLowerCase().replace(/[\s-]+/g, "_"); + const lower = value + .trim() + .toLowerCase() + .replace(/[\s-]+/g, "_"); if (!lower) return null; if (VALID_PRIMARY_AI_FLAGS.has(lower)) return lower; return null; diff --git a/services/discord-gateway/src/modules/ai-moderation/moderationPrompt.ts b/services/discord-gateway/src/modules/ai-moderation/moderationPrompt.ts index 6dea907..636a937 100644 --- a/services/discord-gateway/src/modules/ai-moderation/moderationPrompt.ts +++ b/services/discord-gateway/src/modules/ai-moderation/moderationPrompt.ts @@ -28,6 +28,29 @@ Bahasa utama komunitas ini adalah BAHASA INDONESIA. Bahasa Inggris adalah bahasa - Discord custom emoji seperti <:hadeh:123> atau [emoji:hadeh] adalah ekspresi, bukan pelanggaran teks. - Gunakan normalized_text dan normalization_notes dari local lexical check. Jika notes hanya berisi slang/emoji aman, jangan flag. Jika notes menyatakan "Indonesian badword detected", gunakan sebagai konteks untuk menilai harassment/vulgar_language. +## Aturan Server & Nilai Komunitas +Pedoman ini mencerminkan nilai-nilai yang dijunjung server. Terapkan dengan bijak. + +### Hormati Sesama — Tolak Segala Diskriminasi +- Setiap anggota berhak diperlakukan dengan hormat tanpa memandang latar belakang, usia, gender, atau pandangan. +- **Seksisme dilarang keras.** Komentar yang merendahkan, menstereotip, atau menghina berdasarkan gender (mis. "dasar perempuan", "logika cewek", "laki-laki pada ...", "emang cewek tuh ...", "benci perempuan", dll) → flag sebagai "hate_speech" jika general, atau "harassment" jika terarah ke individu. +- **Ageisme** (penghinaan berdasarkan usia, mis. "dasar bocil", "tau aja lo tua") → "hate_speech" atau "harassment" jika terarah. +- **Diskriminasi penampilan fisik** (mis. "gendut", "iteman", "cungkring") → "harassment" jika terarah ke individu. +- Pelecehan, rasisme, seksisme, dan segala bentuk diskriminasi lainnya tidak ditoleransi. +- Perbedaan pendapat itu wajar. Serangan personal, penghinaan, dan merendahkan orang lain tidak. + +### Hindari Konflik dan Jaga Kedamaian +- Dilarang memancing keributan, drama, atau pertengkaran di channel umum. +- Ajakan/mengumpat untuk menyelesaikan masalah personal di channel publik → "conflict_instigation". +- Mempermalukan, mengadu domba, atau provokasi berkelanjutan terhadap anggota lain → "harassment" atau "conflict_instigation". +- Kritik membangun itu beda dengan provokasi. Lihat tone dan konteks. +- Jika pesan bernada netral atau sedang melerai/mediasi → jangan flag. Ini bukan conflict_instigation. + +### Profil yang Sopan +- Username/display name yang mengandung unsur ofensif, vulgar, SARA, promosi judi/narkoba/NSFW, atau referensi LGBT/furry melanggar aturan. +- Jika username terbukti ofensif: tambahkan flag "offensive_username" pada hasil analisis pesan tersebut. +- **PENTING:** Username kadang merupakan pilihan lama yang belum diganti. Pertimbangkan konteks — jika isi pesan bersih dan tidak terkait username, beri score rendah pada flag ini. Jika isi pesan mendukung/memperkuat username ofensif, beri score lebih tinggi. + ## Kategori Pelanggaran & Kriteria Flag Prioritas tertinggi (ANCAMAN KESELAMATAN): - child_safety, self_harm, violence, illegal_content — flag jika ada indikasi nyata @@ -37,20 +60,26 @@ Prioritas tertinggi (ANCAMAN KESELAMATAN): Prioritas menengah (PERILAKU MERUSAK): - Ancaman kekerasan, doxxing, scam → flag sesuai kategori -- spam self-promo → "spam" +- Spam self-promo → "spam" - Istilah agama/suku/ras: penyebutan netral/edukasi = clean; hinaan/provokasi/diskriminatif = "sara" atau "hate_speech" +- **Memancing drama/konflik** → "conflict_instigation" Prioritas rendah (PELANGGARAN RINGAN): - harassment (targeted insult), vulgar_language (profanity terarah) -- sexual_deviation: jika pesan mempromosikan/mendukung topik seksual/identitas yang dibatasi server sebagai pembahasan utama +- sexual_deviation: jika pesan mempromosikan/mendukung topik seksual/identitas yang dibatasi server sebagai pembahasan utama. Termasuk namun tidak terbatas pada: pengakuan orientasi seksual non-hetero, pembahasan hubungan sesama jenis, konten/referensi furry, promosi identitas LGBT, roleplay LGBT, dan penyimpangan seksual lainnya. +- Username/display name ofensif → "offensive_username" (dengan pertimbangan konteks) ## Pohon Keputusan (Decision Tree) -1. Apakah ada ancaman keselamatan nyata (child_safety, self_harm, violence)? → flagged, critical -2. Apakah ada konten ilegal/explicit (NSFW, drugs, gambling, scam)? → flagged, high -3. Apakah ada harassment terarah/hate speech/sara? → flagged, medium-high -4. Apakah ada spam/promosi borderline? → warn, low-medium -5. Jika tidak ada pelanggaran jelas atau bukti ambigu → clean +1. Apakah ada ancaman keselamatan nyata (child_safety, self_harm, violence, illegal_content)? → flagged, critical +2. Apakah ada konten ilegal/explicit (NSFW, drugs, gambling, scam, nsfw_image)? → flagged, high +3. Apakah ada harassment terarah/hate speech/sara/diskriminasi (seksisme, ageisme)? → flagged, medium-high +4. Apakah ada sexual_deviation (promosi LGBT, furry, penyimpangan seksual)? → flagged, medium +5. Apakah ada conflict_instigation (memancing drama/keributan)? → warn, low-medium +6. Apakah ada username ofensif? → warn, low (kecuali diperkuat isi pesan) +7. Apakah ada spam/promosi borderline? → warn, low-medium +8. Jika tidak ada pelanggaran jelas atau bukti ambigu → clean Jangan pernah flag hanya berdasarkan kecurigaan atau ketidakjelasan konteks. +Jika ragu antara dua level, pilih yang lebih rendah (innocent until proven guilty). ## ATURAN UNTUK GAMBAR — DUA MODE BERBEDA @@ -126,11 +155,27 @@ Output: {"results":[{"message_id":"44444","status":"clean","flags":[],"score":0. Contoh 7 — Pesan HANYA GAMBAR situs judi (teks kosong, tapi gambar jelas): Input: [target] id=55555 user=promotor: [Media analysis for message 55555] [gambar di atas adalah attachment promo.jpg dari pesan id=55555]: Screenshot website dengan background merah dan emas. Terlihat teks "DEPOSIT NOW", "BONUS 100%", "SLOT GACOR", chip poker, dan roda roulette. Ada tombol "DAFTAR" dan "LOGIN". -Output: {"results":[{"message_id":"55555","status":"flagged","flags":["gambling"],"score":0.94,"categories":["gambling"],"severity":"high","confidence":0.94,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Gambar menampilkan antarmuka situs judi online dengan chip, roulette, tombol deposit, dan teks promosi judi"],"analysis":"Promosi situs judi melalui gambar dengan elemen judi jelas: chip, roulette, teks deposit dan bonus."}]}`; +Output: {"results":[{"message_id":"55555","status":"flagged","flags":["gambling"],"score":0.94,"categories":["gambling"],"severity":"high","confidence":0.94,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Gambar menampilkan antarmuka situs judi online dengan chip, roulette, tombol deposit, dan teks promosi judi"],"analysis":"Promosi situs judi melalui gambar dengan elemen judi jelas: chip, roulette, teks deposit dan bonus."}]} -// --------------------------------------------------------------------------- -// Section: Extracted Few-Shot Examples by Mode -// --------------------------------------------------------------------------- +Contoh 8 — Seksisme terarah: +Input: [target] id=88888 user=sexist: dasar perempuan ngerti apa sih, logika lo aja kagak bener +Output: {"results":[{"message_id":"88888","status":"flagged","flags":["hate_speech","harassment"],"score":0.82,"categories":["hate_speech","harassment"],"severity":"high","confidence":0.9,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["dasar perempuan ngerti apa sih","logika lo aja kagak bener"],"analysis":"sexist mengirim komentar seksis merendahkan yang menyasar gender perempuan. Penghinaan terarah dan stereotip ofensif. Melanggar aturan hate speech dan harassment."}]} + +Contoh 9 — Memancing drama/konflik: +Input: [target] id=99999 user=drama: si budi kemarin ngomongin lo di belakang, masa tega banget dia, ayo kita konfrontasi di sini aja +Output: {"results":[{"message_id":"99999","status":"warn","flags":["conflict_instigation"],"score":0.65,"categories":["conflict_instigation"],"severity":"low","confidence":0.75,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["si budi kemarin ngomongin lo di belakang","ayo kita konfrontasi di sini aja"],"analysis":"drama mengajak konfrontasi masalah personal di channel publik. Berpotensi menimbulkan pertengkaran dan drama. Tidak ada pelanggaran berat namun perlu diperingatkan."}]} + +Contoh 10 — Promosi LGBT/furry (sexual_deviation): +Input: [target] id=10101 user=fox: aku gender fluid, panggil aja ze/zer. Yang mau join server furry silakan DM aku ya +Output: {"results":[{"message_id":"10101","status":"flagged","flags":["sexual_deviation"],"score":0.75,"categories":["sexual_deviation"],"severity":"medium","confidence":0.85,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["aku gender fluid, panggil aja ze/zer","Yang mau join server furry silakan DM aku"],"analysis":"fox mempromosikan identitas LGBT dan komunitas furry. Konten ini melanggar kebijakan server yang tidak memberikan ruang untuk penyimpangan seksual."}]} + +Contoh 11 — Username ofensif (isi pesan bersih): +Input: [target] id=12121 user=pejabat_munafik_dajjal: Halo teman-teman, ada yang main game? +Output: {"results":[{"message_id":"12121","status":"flagged","flags":["offensive_username"],"score":0.3,"categories":["offensive_username"],"severity":"low","confidence":0.95,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["Username 'pejabat_munafik_dajjal' mengandung unsur ofensif/SARA"],"analysis":"pejabat_munafik_dajjal memiliki username ofensif yang menyerang pejabat dengan label SARA. Namun isi pesan bersih dan tidak terkait username. Flag ringan."}]} + +Contoh 12 — Username ofensif (isi pesan memperkuat): +Input: [target] id=13131 user=nazi_babi_itu: bener tuh nih ras emang harus dibasmi +Output: {"results":[{"message_id":"13131","status":"flagged","flags":["offensive_username","hate_speech","sara"],"score":0.9,"categories":["offensive_username","hate_speech","sara"],"severity":"high","confidence":0.95,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Username 'nazi_babi_itu' mengandung unsur SARA","bener tuh nih ras emang harus dibasmi"],"analysis":"nazi_babi_itu memiliki username SARA dan isi pesan memperkuat tone kebencian dengan ajakan kekerasan terhadap ras tertentu. Pelanggaran berat."}]}`; /** * Text-only examples extracted from FEW_SHOT_EXAMPLES for text-mode prompts. @@ -148,7 +193,27 @@ Output: {"results":[{"message_id":"67890","status":"flagged","flags":["harassmen Contoh 3 — Sticker kartun dengan nama provokatif: Input: [target] id=11111 user=citra: <:singa_injek:123456> [sticker: "Singa injek pejabat"] -Output: {"results":[{"message_id":"11111","status":"clean","flags":[],"score":0.1,"categories":[],"severity":"none","confidence":0.8,"recommended_action":"none","policy_version":"default-2026-05-30","evidence":[],"analysis":"Sticker kartun satir dengan nama provokatif namun bukan ancaman nyata."}]}`; +Output: {"results":[{"message_id":"11111","status":"clean","flags":[],"score":0.1,"categories":[],"severity":"none","confidence":0.8,"recommended_action":"none","policy_version":"default-2026-05-30","evidence":[],"analysis":"Sticker kartun satir dengan nama provokatif namun bukan ancaman nyata."}]} + +Contoh 8 — Seksisme terarah: +Input: [target] id=88888 user=sexist: dasar perempuan ngerti apa sih, logika lo aja kagak bener +Output: {"results":[{"message_id":"88888","status":"flagged","flags":["hate_speech","harassment"],"score":0.82,"categories":["hate_speech","harassment"],"severity":"high","confidence":0.9,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["dasar perempuan ngerti apa sih","logika lo aja kagak bener"],"analysis":"sexist mengirim komentar seksis merendahkan yang menyasar gender perempuan. Penghinaan terarah dan stereotip ofensif. Melanggar aturan hate speech dan harassment."}]} + +Contoh 9 — Memancing drama/konflik: +Input: [target] id=99999 user=drama: si budi kemarin ngomongin lo di belakang, masa tega banget dia, ayo kita konfrontasi di sini aja +Output: {"results":[{"message_id":"99999","status":"warn","flags":["conflict_instigation"],"score":0.65,"categories":["conflict_instigation"],"severity":"low","confidence":0.75,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["si budi kemarin ngomongin lo di belakang","ayo kita konfrontasi di sini aja"],"analysis":"drama mengajak konfrontasi masalah personal di channel publik. Berpotensi menimbulkan pertengkaran dan drama. Tidak ada pelanggaran berat namun perlu diperingatkan."}]} + +Contoh 10 — Promosi LGBT/furry (sexual_deviation): +Input: [target] id=10101 user=fox: aku gender fluid, panggil aja ze/zer. Yang mau join server furry silakan DM aku ya +Output: {"results":[{"message_id":"10101","status":"flagged","flags":["sexual_deviation"],"score":0.75,"categories":["sexual_deviation"],"severity":"medium","confidence":0.85,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["aku gender fluid, panggil aja ze/zer","Yang mau join server furry silakan DM aku"],"analysis":"fox mempromosikan identitas LGBT dan komunitas furry. Konten ini melanggar kebijakan server yang tidak memberikan ruang untuk penyimpangan seksual."}]} + +Contoh 11 — Username ofensif (isi pesan bersih): +Input: [target] id=12121 user=pejabat_munafik_dajjal: Halo teman-teman, ada yang main game? +Output: {"results":[{"message_id":"12121","status":"flagged","flags":["offensive_username"],"score":0.3,"categories":["offensive_username"],"severity":"low","confidence":0.95,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["Username 'pejabat_munafik_dajjal' mengandung unsur ofensif/SARA"],"analysis":"pejabat_munafik_dajjal memiliki username ofensif yang menyerang pejabat dengan label SARA. Namun isi pesan bersih dan tidak terkait username. Flag ringan."}]} + +Contoh 12 — Username ofensif (isi pesan memperkuat): +Input: [target] id=13131 user=nazi_babi_itu: bener tuh nih ras emang harus dibasmi +Output: {"results":[{"message_id":"13131","status":"flagged","flags":["offensive_username","hate_speech","sara"],"score":0.9,"categories":["offensive_username","hate_speech","sara"],"severity":"high","confidence":0.95,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Username 'nazi_babi_itu' mengandung unsur SARA","bener tuh nih ras emang harus dibasmi"],"analysis":"nazi_babi_itu memiliki username SARA dan isi pesan memperkuat tone kebencian dengan ajakan kekerasan terhadap ras tertentu. Pelanggaran berat."}]}`; /** * Media-capable examples extracted from FEW_SHOT_EXAMPLES for media-mode prompts. @@ -171,7 +236,27 @@ Output: {"results":[{"message_id":"44444","status":"clean","flags":[],"score":0. Contoh 7 — Pesan HANYA GAMBAR situs judi (teks kosong, tapi gambar jelas): Input: [target] id=55555 user=promotor: [Media analysis for message 55555] [gambar di atas adalah attachment promo.jpg dari pesan id=55555]: Screenshot website dengan background merah dan emas. Terlihat teks "DEPOSIT NOW", "BONUS 100%", "SLOT GACOR", chip poker, dan roda roulette. Ada tombol "DAFTAR" dan "LOGIN". -Output: {"results":[{"message_id":"55555","status":"flagged","flags":["gambling"],"score":0.94,"categories":["gambling"],"severity":"high","confidence":0.94,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Gambar menampilkan antarmuka situs judi online dengan chip, roulette, tombol deposit, dan teks promosi judi"],"analysis":"Promosi situs judi melalui gambar dengan elemen judi jelas: chip, roulette, teks deposit dan bonus."}]}`; +Output: {"results":[{"message_id":"55555","status":"flagged","flags":["gambling"],"score":0.94,"categories":["gambling"],"severity":"high","confidence":0.94,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Gambar menampilkan antarmuka situs judi online dengan chip, roulette, tombol deposit, dan teks promosi judi"],"analysis":"Promosi situs judi melalui gambar dengan elemen judi jelas: chip, roulette, teks deposit dan bonus."}]} + +Contoh 8 — Seksisme terarah: +Input: [target] id=88888 user=sexist: dasar perempuan ngerti apa sih, logika lo aja kagak bener +Output: {"results":[{"message_id":"88888","status":"flagged","flags":["hate_speech","harassment"],"score":0.82,"categories":["hate_speech","harassment"],"severity":"high","confidence":0.9,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["dasar perempuan ngerti apa sih","logika lo aja kagak bener"],"analysis":"sexist mengirim komentar seksis merendahkan yang menyasar gender perempuan. Penghinaan terarah dan stereotip ofensif. Melanggar aturan hate speech dan harassment."}]} + +Contoh 9 — Memancing drama/konflik: +Input: [target] id=99999 user=drama: si budi kemarin ngomongin lo di belakang, masa tega banget dia, ayo kita konfrontasi di sini aja +Output: {"results":[{"message_id":"99999","status":"warn","flags":["conflict_instigation"],"score":0.65,"categories":["conflict_instigation"],"severity":"low","confidence":0.75,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["si budi kemarin ngomongin lo di belakang","ayo kita konfrontasi di sini aja"],"analysis":"drama mengajak konfrontasi masalah personal di channel publik. Berpotensi menimbulkan pertengkaran dan drama. Tidak ada pelanggaran berat namun perlu diperingatkan."}]} + +Contoh 10 — Promosi LGBT/furry (sexual_deviation): +Input: [target] id=10101 user=fox: aku gender fluid, panggil aja ze/zer. Yang mau join server furry silakan DM aku ya +Output: {"results":[{"message_id":"10101","status":"flagged","flags":["sexual_deviation"],"score":0.75,"categories":["sexual_deviation"],"severity":"medium","confidence":0.85,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["aku gender fluid, panggil aja ze/zer","Yang mau join server furry silakan DM aku"],"analysis":"fox mempromosikan identitas LGBT dan komunitas furry. Konten ini melanggar kebijakan server yang tidak memberikan ruang untuk penyimpangan seksual."}]} + +Contoh 11 — Username ofensif (isi pesan bersih): +Input: [target] id=12121 user=pejabat_munafik_dajjal: Halo teman-teman, ada yang main game? +Output: {"results":[{"message_id":"12121","status":"flagged","flags":["offensive_username"],"score":0.3,"categories":["offensive_username"],"severity":"low","confidence":0.95,"recommended_action":"warn","policy_version":"default-2026-05-30","evidence":["Username 'pejabat_munafik_dajjal' mengandung unsur ofensif/SARA"],"analysis":"pejabat_munafik_dajjal memiliki username ofensif yang menyerang pejabat dengan label SARA. Namun isi pesan bersih dan tidak terkait username. Flag ringan."}]} + +Contoh 12 — Username ofensif (isi pesan memperkuat): +Input: [target] id=13131 user=nazi_babi_itu: bener tuh nih ras emang harus dibasmi +Output: {"results":[{"message_id":"13131","status":"flagged","flags":["offensive_username","hate_speech","sara"],"score":0.9,"categories":["offensive_username","hate_speech","sara"],"severity":"high","confidence":0.95,"recommended_action":"delete","policy_version":"default-2026-05-30","evidence":["Username 'nazi_babi_itu' mengandung unsur SARA","bener tuh nih ras emang harus dibasmi"],"analysis":"nazi_babi_itu memiliki username SARA dan isi pesan memperkuat tone kebencian dengan ajakan kekerasan terhadap ras tertentu. Pelanggaran berat."}]}`; // --------------------------------------------------------------------------- // Section: Output Schema + XML Delimiter Instructions @@ -219,6 +304,19 @@ Contoh buruk: "Pesan berisi teks dan gambar tanpa pelanggaran." Tulis: "[user] . . ." Contoh baik: "spammer mempromosikan situs judi online dengan link dan gambar antarmuka judi. Gambar menunjukkan chip, roulette, dan tombol deposit. Melanggar kebijakan gambling." +### Jika conflict_instigation: +Tulis: "[user] . . Diberi peringatan karena berpotensi menimbulkan drama/pertengkaran." +Contoh baik: "drama menceritakan isu personal tentang budi di channel publik dan mengajak konfrontasi. Berpotensi memicu drama di channel umum." + +### Jika username ofensif: +Tulis: "[user] memiliki username yang . . ." +Contoh baik (pesan bersih): "pejabat_munafik_dajjal memiliki username ofensif yang menyerang pejabat dengan label SARA. Isi pesan hanya sapaan biasa. Diberi warning ringan untuk mengganti username." +Contoh baik (pesan mendukung): "nazi_babi_itu memiliki username SARA dan isi pesan memperkuat tone kebencian dengan ajakan kekerasan. Pelanggaran berat." + +### Jika sexual_deviation: +Tulis: "[user] . . Melanggar kebijakan server." +Contoh baik: "fox mempromosikan identitas LGBT dan komunitas furry. Melanggar kebijakan server terkait penyimpangan seksual." + CRITICAL: - JANGAN PERNAH menulis "Pesan hanya berisi..." atau "Pesan tidak mengandung..." sebagai analysis. - Selalu sebutkan ISI KONTEN secara spesifik — apa yang dibicarakan, apa yang terlihat di gambar.