Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,12 +6,10 @@ import re
|
|
| 6 |
from dataclasses import dataclass
|
| 7 |
from typing import List, Dict, Tuple
|
| 8 |
|
| 9 |
-
# ---- Language detection
|
| 10 |
ARABIC_RE = re.compile(r"[\u0600-\u06FF]")
|
| 11 |
def detect_lang(text: str) -> str:
|
| 12 |
-
if ARABIC_RE.search(text)
|
| 13 |
-
return "ur"
|
| 14 |
-
return "en"
|
| 15 |
|
| 16 |
# ---- Guardrails ----
|
| 17 |
@dataclass
|
|
@@ -43,18 +41,15 @@ class Guardrails:
|
|
| 43 |
return ("SOFT", p)
|
| 44 |
return ("OK", "")
|
| 45 |
|
| 46 |
-
# ----
|
| 47 |
-
def tiny_response(user_msg: str, history: List[Tuple[str,
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
if lang == 'ur':
|
| 51 |
-
return prefix_ur + "میں آپ کی رہنمائی کے لیے حاضر ہوں۔ براہِ کرم سوال واضح کریں یا کوئی مثال دیں۔"
|
| 52 |
else:
|
| 53 |
-
return
|
| 54 |
|
| 55 |
-
# ---- RAG (
|
| 56 |
RAG_DOCS: List[Dict] = []
|
| 57 |
-
|
| 58 |
def add_doc(text: str):
|
| 59 |
if not text.strip():
|
| 60 |
return 0
|
|
@@ -75,55 +70,36 @@ def retrieve(query: str, k: int = 3) -> List[str]:
|
|
| 75 |
# ---- Load guardrails ----
|
| 76 |
GUARD = Guardrails.from_yaml("guardrails.yaml")
|
| 77 |
|
| 78 |
-
SYSTEM_PROMPT_UR = (
|
| 79 |
-
"آپ safePak ہیں: مقامی زبانوں میں واضح، مہذب اور ذمہ دار جوابات دیں۔ "
|
| 80 |
-
"نفرت انگیزی، خود نقصان، غیر قانونی ہدایات یا ذاتی حساس معلومات میں براہِ راست مدد نہ دیں۔ "
|
| 81 |
-
"ضرورت پڑنے پر محفوظ متبادل فراہم کریں۔"
|
| 82 |
-
)
|
| 83 |
-
SYSTEM_PROMPT_EN = (
|
| 84 |
-
"You are safePak: helpful, clear, and responsible. Avoid facilitating hate, self-harm, or illegal activity. "
|
| 85 |
-
"Offer safe alternatives when needed."
|
| 86 |
-
)
|
| 87 |
-
|
| 88 |
# ---- Chat logic ----
|
| 89 |
-
def chat_fn(user_msg: str, chat_history: List[Tuple[str,
|
| 90 |
if not user_msg:
|
| 91 |
return chat_history
|
| 92 |
|
| 93 |
lang = detect_lang(user_msg)
|
| 94 |
-
status,
|
|
|
|
| 95 |
if status == "BLOCK":
|
| 96 |
-
msg = GUARD.refusal_msg_ur if lang
|
| 97 |
-
|
| 98 |
-
return chat_history
|
| 99 |
|
| 100 |
-
context = []
|
| 101 |
-
|
| 102 |
-
context = retrieve(user_msg, k=3)
|
| 103 |
|
| 104 |
-
model_reply = tiny_response(user_msg, chat_history, lang)
|
| 105 |
if context:
|
| 106 |
-
if lang
|
| 107 |
-
|
| 108 |
else:
|
| 109 |
-
|
| 110 |
|
| 111 |
if status == "SOFT":
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
"
|
| 115 |
-
|
| 116 |
-
)
|
| 117 |
-
else:
|
| 118 |
-
model_reply = (
|
| 119 |
-
"Note: Your question may include sensitive topics. Responding with general guidance only.\n\n"
|
| 120 |
-
+ model_reply
|
| 121 |
-
)
|
| 122 |
|
| 123 |
-
|
| 124 |
-
return chat_history
|
| 125 |
|
| 126 |
-
# ----
|
| 127 |
def ingest_files(files: List[gr.File]):
|
| 128 |
for f in files or []:
|
| 129 |
try:
|
|
@@ -134,16 +110,13 @@ def ingest_files(files: List[gr.File]):
|
|
| 134 |
return f"Docs in store: {len(RAG_DOCS)}"
|
| 135 |
|
| 136 |
# ---- UI ----
|
| 137 |
-
with gr.Blocks(title="safePak –
|
| 138 |
-
gr.Markdown(""
|
| 139 |
-
# safePak (Starter)
|
| 140 |
-
**لوکل-فرسٹ** ڈیزائن کے ساتھ ایک سادہ ڈیمو۔ یہ Space آن لائن چلتا ہے، مگر آپ اسی UI/لاجک کو اپنی مقامی ایپ میں منتقل کر سکتے ہیں۔
|
| 141 |
-
""")
|
| 142 |
|
| 143 |
with gr.Row():
|
| 144 |
use_rag = gr.Checkbox(label="Use local knowledge (RAG)", value=True)
|
| 145 |
with gr.Column():
|
| 146 |
-
file_uploader = gr.Files(label="Upload .txt files
|
| 147 |
ingest_btn = gr.Button("Ingest files")
|
| 148 |
rag_status = gr.Markdown("Docs in store: 0")
|
| 149 |
|
|
@@ -151,7 +124,7 @@ with gr.Blocks(title="safePak – Local-first Starter", css=".wrap {max-width: 9
|
|
| 151 |
msg = gr.Textbox(label="پیغام / Message", placeholder="یہاں لکھیں…", lines=2)
|
| 152 |
clear = gr.Button("Clear")
|
| 153 |
|
| 154 |
-
ingest_btn.click(ingest_files,
|
| 155 |
msg.submit(lambda u,h,r: (chat_fn(u,h,r), ""), [msg,chatbot,use_rag], [chatbot,msg])
|
| 156 |
clear.click(lambda: ([], "Docs in store: 0"), [], [chatbot, rag_status])
|
| 157 |
|
|
|
|
| 6 |
from dataclasses import dataclass
|
| 7 |
from typing import List, Dict, Tuple
|
| 8 |
|
| 9 |
+
# ---- Language detection ----
|
| 10 |
ARABIC_RE = re.compile(r"[\u0600-\u06FF]")
|
| 11 |
def detect_lang(text: str) -> str:
|
| 12 |
+
return "ur" if ARABIC_RE.search(text) else "en"
|
|
|
|
|
|
|
| 13 |
|
| 14 |
# ---- Guardrails ----
|
| 15 |
@dataclass
|
|
|
|
| 41 |
return ("SOFT", p)
|
| 42 |
return ("OK", "")
|
| 43 |
|
| 44 |
+
# ---- Tiny placeholder model ----
|
| 45 |
+
def tiny_response(user_msg: str, history: List[Tuple[str,str]], lang: str) -> str:
|
| 46 |
+
if lang == "ur":
|
| 47 |
+
return "safePak: میں آپ کی رہنمائی کے لیے حاضر ہوں۔ براہِ کرم سوال واضح کریں یا کوئی مثال دیں۔"
|
|
|
|
|
|
|
| 48 |
else:
|
| 49 |
+
return "safePak: I'm here to help. Please clarify your question or share an example."
|
| 50 |
|
| 51 |
+
# ---- Toy RAG (in-memory) ----
|
| 52 |
RAG_DOCS: List[Dict] = []
|
|
|
|
| 53 |
def add_doc(text: str):
|
| 54 |
if not text.strip():
|
| 55 |
return 0
|
|
|
|
| 70 |
# ---- Load guardrails ----
|
| 71 |
GUARD = Guardrails.from_yaml("guardrails.yaml")
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
# ---- Chat logic ----
|
| 74 |
+
def chat_fn(user_msg: str, chat_history: List[Tuple[str,str]], use_rag: bool):
|
| 75 |
if not user_msg:
|
| 76 |
return chat_history
|
| 77 |
|
| 78 |
lang = detect_lang(user_msg)
|
| 79 |
+
status, _ = GUARD.check(user_msg)
|
| 80 |
+
|
| 81 |
if status == "BLOCK":
|
| 82 |
+
msg = GUARD.refusal_msg_ur if lang=="ur" else GUARD.refusal_msg_en
|
| 83 |
+
return chat_history + [(user_msg, msg)]
|
|
|
|
| 84 |
|
| 85 |
+
context = retrieve(user_msg, k=3) if use_rag else []
|
| 86 |
+
reply = tiny_response(user_msg, chat_history, lang)
|
|
|
|
| 87 |
|
|
|
|
| 88 |
if context:
|
| 89 |
+
if lang=="ur":
|
| 90 |
+
reply += "\n\n(متعلقہ مواد)\n- " + "\n- ".join(context)
|
| 91 |
else:
|
| 92 |
+
reply += "\n\n(Related)\n- " + "\n- ".join(context)
|
| 93 |
|
| 94 |
if status == "SOFT":
|
| 95 |
+
note = ("احتیاط: آپ کے سوال میں حساس موضوعات شامل ہو سکتے ہیں۔ معلومات عمومی رہنمائی کی حد تک دی جا رہی ہے۔\n\n"
|
| 96 |
+
if lang=="ur" else
|
| 97 |
+
"Note: Your question may include sensitive topics. Responding with general guidance only.\n\n")
|
| 98 |
+
reply = note + reply
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
+
return chat_history + [(user_msg, reply)]
|
|
|
|
| 101 |
|
| 102 |
+
# ---- Ingest files ----
|
| 103 |
def ingest_files(files: List[gr.File]):
|
| 104 |
for f in files or []:
|
| 105 |
try:
|
|
|
|
| 110 |
return f"Docs in store: {len(RAG_DOCS)}"
|
| 111 |
|
| 112 |
# ---- UI ----
|
| 113 |
+
with gr.Blocks(title="safePak – Starter", css=".wrap {max-width: 900px; margin: 0 auto}") as demo:
|
| 114 |
+
gr.Markdown("# safePak (Starter)\n**لوکل-فرسٹ** ڈیزائن کے ساتھ ایک سادہ ڈیمو۔")
|
|
|
|
|
|
|
|
|
|
| 115 |
|
| 116 |
with gr.Row():
|
| 117 |
use_rag = gr.Checkbox(label="Use local knowledge (RAG)", value=True)
|
| 118 |
with gr.Column():
|
| 119 |
+
file_uploader = gr.Files(label="Upload .txt files", file_types=[".txt"], file_count="multiple")
|
| 120 |
ingest_btn = gr.Button("Ingest files")
|
| 121 |
rag_status = gr.Markdown("Docs in store: 0")
|
| 122 |
|
|
|
|
| 124 |
msg = gr.Textbox(label="پیغام / Message", placeholder="یہاں لکھیں…", lines=2)
|
| 125 |
clear = gr.Button("Clear")
|
| 126 |
|
| 127 |
+
ingest_btn.click(ingest_files, [file_uploader], [rag_status])
|
| 128 |
msg.submit(lambda u,h,r: (chat_fn(u,h,r), ""), [msg,chatbot,use_rag], [chatbot,msg])
|
| 129 |
clear.click(lambda: ([], "Docs in store: 0"), [], [chatbot, rag_status])
|
| 130 |
|