File size: 2,857 Bytes
0e5fdb5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | """Canned, language-matched refusals for the guardrail layer.
Centralized so the three refusal sites — the `out_of_scope` router branch, the
input-guard block, and the content-filter fallback — speak with one voice.
Deterministic on purpose (no LLM): the refusal must not call the same model that
just refused or failed. Language is picked with a tiny marker check (EN default,
ID when Indonesian markers are present), mirroring the lightweight detector in
`handlers/help.py` — enough for a one-line reply without an LLM round-trip.
"""
from __future__ import annotations
import re
# Subset of help.py's ID marker set — enough to pick EN vs ID for a short refusal.
# Includes the common Indonesian injection verbs ("lupakan"=forget, "abaikan"=ignore)
# so an ID-language jailbreak still gets an ID-language refusal.
_ID_MARKERS = frozenset({
"yang", "dan", "apa", "gimana", "bagaimana", "kenapa", "mengapa", "aku", "saya",
"tolong", "ini", "itu", "untuk", "dengan", "tidak", "nggak", "enggak", "bisa",
"mau", "buat", "dari", "kamu", "berapa", "kapan", "siapa", "dimana", "adalah",
"akan", "sudah", "belum", "lupakan", "abaikan", "kredensial", "tunjukkan",
})
def _is_indonesian(message: str) -> bool:
tokens = re.findall(r"[a-z']+", (message or "").lower())
return any(t in _ID_MARKERS for t in tokens)
# Off-topic / out-of-scope: the request is benign but outside what the assistant does.
_OUT_OF_SCOPE = {
"en": (
"That's outside what I can help with — I'm a data assistant, so I can only work "
"with the sources you've connected to Data Eyond. Ask me a question about your "
"data, or type /help to see what I can do."
),
"id": (
"Itu di luar yang bisa saya bantu — saya asisten data, jadi saya hanya bisa "
"bekerja dengan sumber data yang Anda hubungkan ke Data Eyond. Ajukan pertanyaan "
"tentang data Anda, atau ketik /help untuk melihat yang bisa saya lakukan."
),
}
# Blocked: a manipulation / injection / secret-extraction / abuse attempt.
_BLOCKED = {
"en": (
"I can't help with that request. I'm here to analyze the data you've connected — "
"ask me a question about your data and I'll take it from there."
),
"id": (
"Saya tidak bisa membantu permintaan tersebut. Saya di sini untuk menganalisis "
"data yang Anda hubungkan — ajukan pertanyaan tentang data Anda dan saya bantu."
),
}
def out_of_scope_message(message: str) -> str:
"""Refusal for a benign but out-of-scope request (the `out_of_scope` intent)."""
return _OUT_OF_SCOPE["id" if _is_indonesian(message) else "en"]
def blocked_message(message: str) -> str:
"""Refusal for a blocked request (injection / secrets / abuse / content-filter)."""
return _BLOCKED["id" if _is_indonesian(message) else "en"]
|