ishaq101's picture
/fix validator and report (#10)
0e5fdb5
Raw
History Blame Contribute Delete
2.86 kB
"""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"]