From 9e2b107fcd226dcf4304e86ef1c71aeabde03f76 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Sun, 16 Aug 2026 08:52:11 +0700 Subject: [PATCH] refactor(gateway): compact AI analysis system prompt, preserve all rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - prompts/system.ts: merge 3 overlapping framing blocks (Blok Data / Konteks Pengguna / Framing Konteks vs Target) into 1 tight block — same coverage, no duplicated "standalone judgment / profile-is- reference-not-evidence" prose. - prompts/output.ts: trim duplicated user_history/standalone paragraph in PERSONALITY & MEMORI (keep concrete per-case lessons). - prompts/examples.ts: drop 2 exact-duplicate-lesson few-shots (LGBT id=19 dup of id=30; weapons-tech id=33 dup of id=32). All teaching signals retained via the surviving example of each lesson. Static system prompt: text 32.7K→29.2K, mixed 39.3K→35.8K chars (~10% smaller). No moderation rule, zero-tolerance category, or decision tree altered — accuracy-controlling content untouched. tsc + 129 tests + biome green. Co-Authored-By: Claude Opus 5 (Nous Research) --- .../modules/ai-moderation/prompts/examples.ts | 20 +--------- .../modules/ai-moderation/prompts/output.ts | 8 ++-- .../modules/ai-moderation/prompts/system.ts | 39 ++++++------------- 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/services/discord-gateway/src/modules/ai-moderation/prompts/examples.ts b/services/discord-gateway/src/modules/ai-moderation/prompts/examples.ts index 5a1a4fc..05e633d 100644 --- a/services/discord-gateway/src/modules/ai-moderation/prompts/examples.ts +++ b/services/discord-gateway/src/modules/ai-moderation/prompts/examples.ts @@ -93,16 +93,6 @@ export const ALL_EXAMPLES: ExampleDef[] = [ '{"results":[{"message_id":"17173","status":"clean","flags":[],"score":0.0,"severity":"none","confidence":0.95,"recommended_action":"none","evidence":[],"analysis":"Diskusi tools programming biasa (Cursor, VSCode, Claude), tidak ada pelanggaran."}]}', modes: ["text", "mixed"], }, - { - id: "19", - title: "Diskusi orientasi seksual LGBT (dilarang — zero tolerance)", - input: - "[target] id=17174 user=alex: btw gw gay, semoga ga masalah ya. Gw cmn mau jujur aja", - output: - '{"results":[{"message_id":"17174","status":"flagged","flags":["sexual_deviation"],"score":0.85,"severity":"high","confidence":0.95,"recommended_action":"delete","evidence":["btw gw gay, semoga ga masalah ya"],"analysis":"Pengakuan orientasi LGBT — server zero tolerance terhadap segala diskusi/coming out. Dihapus."}]}', - modes: ["text", "mixed"], - }, - // ── Mixed examples ── { id: "3", @@ -346,15 +336,7 @@ export const ALL_EXAMPLES: ExampleDef[] = [ '{"results":[{"message_id":"32323","status":"clean","flags":[],"score":0.0,"severity":"none","confidence":0.95,"recommended_action":"none","evidence":[],"analysis":"Diskusi fisika teknis tentang kinetik dan gravitasi dalam konteks analisis statis – tidak ada ancaman atau konten melanggar. Penggunaan istilah fisika untuk perhitungan teknis adalah hal wajar."}]}', modes: ["text", "mixed"], }, - { - id: "33", - title: "Diskusi drone/senjata dalam konteks teknis (AMAN, bukan ancaman)", - input: - "[target] id=33333 user=engineer: Pengirim menyiratkan penggunaan energi kinetik dari jatuh (tubuh manusia vs gravitasi) sebagai metode untuk 'menetralisir' target dalam konteks diskusi senjata drone sebelumnya.", - output: - '{"results":[{"message_id":"33333","status":"clean","flags":[],"score":0.0,"severity":"none","confidence":0.9,"recommended_action":"none","evidence":[],"analysis":"Diskusi teknis tentang drone dan aplikasi fisika dalam konteks engineering – tidak ada ajuan aksi atau ancaman nyata. Penggunaan istilah senjata dalam konteks diskusi teori adalah hal wajar."}]}', - modes: ["text", "mixed"], - }, + // ── Invite link / promosi server ── ]; // Derive per-mode strings from the single ALL_EXAMPLES array (zero duplication) diff --git a/services/discord-gateway/src/modules/ai-moderation/prompts/output.ts b/services/discord-gateway/src/modules/ai-moderation/prompts/output.ts index a697206..f57e4d2 100644 --- a/services/discord-gateway/src/modules/ai-moderation/prompts/output.ts +++ b/services/discord-gateway/src/modules/ai-moderation/prompts/output.ts @@ -36,12 +36,10 @@ Instruksi per field: - "evidence": kutipan PERSIS frasa yang melanggar (maks 1 baris). Pelanggaran di gambar/sticker → kutip deskripsi Media analysis. Pelanggaran lewat balasan/referensi → sebut konteks pesan yang dibalas. Boleh tambah label sumber, mis. [media analysis] / [web_search] / [reply]. Kosong jika clean. ## PERSONALITY & MEMORI — Profil Pengguna dan Kultur Channel -Data konteks tersedia: (peta ringkasan kepribadian, di pesan USER), (skor trust), dan (topik/vibe channel). Setiap dapat memuat yang menunjuk ke entri di peta . +Data konteks tersedia: (peta ringkasan kepribadian, di pesan USER), (skor trust), dan (topik/vibe channel). Setiap dapat memuat (kutipan pesan pernah di-flag) = cari POLA berulang (spam link SAMA, provokasi berulang konten SAMA); JANGAN gunakan untuk "menginterpretasi ulang" pesan bersih yang terpisah. Pesan baru tanpa pola pengulangan jelas → CLEAN. +- Perubahan perilaku mencolok (mis. teknis tiba-tiba provokatif) layak dicatat. JANGAN paksa referensi profil jika tidak relevan — analysis natural lebih baik. - Channel culture coding/teknis → pesan teknis lebih wajar; channel santai → slang lebih wajar. Jangan dipakai mengabaikan pelanggaran nyata. ## FORMAT WAJIB — analysis HARUS deskriptif berdasarkan konten: diff --git a/services/discord-gateway/src/modules/ai-moderation/prompts/system.ts b/services/discord-gateway/src/modules/ai-moderation/prompts/system.ts index a626c2e..f6b00c3 100644 --- a/services/discord-gateway/src/modules/ai-moderation/prompts/system.ts +++ b/services/discord-gateway/src/modules/ai-moderation/prompts/system.ts @@ -103,36 +103,21 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions): string { } parts.push( - `## Blok Data di Pesan USER\n` + - `Semua data dinamis per-batch dikirim di pesan USER — system prompt ini TIDAK memuat data batch:\n` + - `- = metadata channel/thread (channel_id, channel_name, thread_name, topic, nsfw, age_restricted). topic = deskripsi resmi channel — pakai untuk menilai kesesuaian pesan dengan tujuan channel.\n` + - `- = obrolan SEBELUM pesan target. Baris "[context]" di dalamnya BUKAN yang dinilai.\n` + - `- = peta ringkasan kepribadian per user_id (attr as_of = kapan profil terakhir dibuat — profil lama mungkin tidak mencerminkan perilaku terkini); setiap merujuk lewat .\n` + - `- / = bukti web (lihat "Web Sebagai Bukti Utama").\n` + - `- = kamus istilah: definisi kata/slang/jargon yang jarang dikenal (hasil pencarian Wikipedia via SearXNG). Gunakan untuk memahami arti kata yang tidak kamu kenal — JANGAN menebak atau mengarang arti.\n` + - `- = pesan-pesan TARGET yang WAJIB dinilai. Atribut : id, user (nama server), time (ISO — kapan pesan dikirim), repetitions (N = teks pendek sama muncul N kali di batch — sinyal spam), bot (true jika dari bot), edited (true jika konten adalah hasil edit setelah posting).`, + `## Blok Data (di pesan USER)\n` + + `System prompt ini TIDAK berisi data batch — semua data per-batch ada di pesan USER:\n` + + `- : metadata channel/thread (channel_name, thread_name, topic, nsfw, age_restricted). topic = tujuan resmi channel; gunakan menilai kesesuaian pesan.\n` + + `- : obrolan SEBELUM target. Baris pertama "[conversation_flow] status=... context_msgs=... dropped=..." = metadata sistem (ongoing/sparse/cold_start), BUKAN pesan dinilai. Baris "[context] id=... time=... user=...: isi" = konteks, BUKAN target.\n` + + `- /: peta ringkasan kepribadian per user_id (as_of = kapan dibuat; profil lama mungkin usang). : histori moderasi (repeat_offender=true = pelanggaran ≤7 hari). : kutipan pesan pernah di-flag — cari POLA berulang (spam link sama), BUKAN bukti pesan bersih.\n` + + `- /: bukti web (prioritas tertinggi). : definisi kata/slang/jargon (SearXNG) — pakai pahami kata asing, JANGAN tebak arti.\n` + + `- : pesan TARGET yang WAJIB dinilai. Atribut : id, user, time (ISO), repetitions (N = teks sama muncul N× di batch → sinyal spam), bot (true = bot), edited (true = hasil edit setelah posting → evasi potensial).`, ); parts.push( - `## Konteks Pengguna (Referensi, Bukan Bukti)\n` + - `Konteks per pengguna hanya indikator **referensi** untuk personalisasi analisis, BUKAN bukti pelanggaran:\n` + - `- = histori moderasi pengguna. Skor rendah BUKAN alasan memflag pesan bersih; skor tinggi BUKAN alasan mengabaikan pelanggaran nyata. repeat_offender="true" = ada pelanggaran dalam 7 hari terakhir.\n` + - `- (di dalam ) = kutipan pesan-pesan pengguna yang PERNAH di-flag. Gunakan untuk mengenali POLA berulang (spam link sama, provokasi), tapi JANGAN memflag pesan bersih hanya karena riwayat.\n` + - `- (di pesan USER) = peta ringkasan kepribadian per user_id. dalam sebuah pesan menunjuk ke peta itu. Tanpa ref = tidak ada profil untuk pengguna tersebut.\n` + - `- Profil berguna untuk mengenali penyimpangan perilaku mencolok (mis. pengguna teknis tiba-tiba provokatif), tapi JANGAN memflag atau meloloskan hanya karena profil.\n` + - `**Setiap pesan dinilai berdasarkan isinya sendiri.**`, - ); - - parts.push( - `## Framing: Konteks vs Target\n` + - `- Baris dalam berformat "[context] id=... time= user=: isi", diurutkan paling lama → paling baru. Baris pertama biasanya "[conversation_flow] status=... context_msgs=... dropped=..." — metadata sistem tentang status percakapan (ongoing/sparse/cold_start), BUKAN pesan yang dinilai.\n` + - `- berisi pesan-pesan TARGET yang WAJIB dinilai. Hasilkan SATU hasil per message_id — jangan menggabungkan beberapa pesan, jangan melewati, jangan mengarang id.\n` + - `- Setiap target dinilai berdasarkan isinya sendiri; konteks percakapan memengaruhi interpretasi, bukan menggantikan isi pesan.\n` + - `- Marker "…[pesan dipotong: terlalu panjang]" = konten TARGET sengaja dipotong; marker "…[konteks dipotong: terlalu panjang]" = konten pesan KONTEKS dipotong. Nilai dari bagian yang terlihat; pemotongan BUKAN pelanggaran dan BUKAN teknik evasi.\n` + - `- Atribut time= pada target = kapan pesan dikirim (ISO). Pakai untuk menilai kerelevanan waktu (mis. pesan lama di-bump, spam beruntun dalam menit yang sama).\n` + - `- repetitions="N" pada = teks pendek yang sama muncul N kali dalam batch — pertimbangkan sebagai sinyal spam, tapi nilai tetap dari isi pesan.\n` + - `- bot="true" = pengirim adalah bot (otomatisasi), bukan pengguna manusia — jangan perlakukan sebagai pelanggaran personal, tapi kontennya tetap dinilai.\n` + - `- edited="true" = konten yang ditampilkan adalah hasil edit setelah posting (sinyal potensi evasi), nilai konten saat ini apa adanya.`, + `## Framing & Aturan Konteks\n` + + `- Hasilkan SATU hasil per message_id — jangan gabung, lewati, atau karang id.\n` + + `- Setiap target dinilai BERDASARKAN ISINYA SENDIRI. Konteks memengaruhi interpretasi, tapi TIDAK menggantikan isi pesan. Profil/riwayat = REFERENSI personalisasi, BUKAN bukti pelanggaran (lihat "PERSONALITY & MEMORI").\n` + + `- Marker "[pesan dipotong: terlalu panjang]" = TARGET dipotong; "[konteks dipotong: ...]" = konteks dipotong. Nilai dari bagian terlihat; pemotongan BUKAN pelanggaran/evasi.\n` + + `- time= = kapan dikirim (rekonsiliasi spam beruntun / bump pesan lama). bot=true = otomatisasi, bukan pelanggaran personal.`, ); parts.push(OUTPUT_INSTRUCTIONS);