Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -204,29 +204,7 @@ class KBIndex:
|
|
| 204 |
scored.sort(key=lambda x: x[0], reverse=True)
|
| 205 |
return [c for s,c in scored[:top_k] if s>0]
|
| 206 |
|
| 207 |
-
|
| 208 |
-
# Safety: prohibited operational keywords (simple list)
|
| 209 |
-
# -------------------------
|
| 210 |
-
PROHIBITED_TERMS = [
|
| 211 |
-
"attack", "ambush", "engage", "deploy", "movement", "route", "strike", "fire support",
|
| 212 |
-
"kill", "assault", "breach", "infiltrate", "explosive", "IED", "sniper", "armament",
|
| 213 |
-
"target", "targeting", "weapons system", "munition", "airstrike", "artillery", "raid"
|
| 214 |
-
]
|
| 215 |
-
PROHIBITED_RE = re.compile(r"\b(" + "|".join(re.escape(w) for w in PROHIBITED_TERMS) + r")\b", re.IGNORECASE)
|
| 216 |
-
|
| 217 |
-
def safety_check_and_redact(text):
|
| 218 |
-
"""
|
| 219 |
-
If text contains any prohibited operational words, return a refusal message
|
| 220 |
-
and a safe administrative alternative instead of the original text.
|
| 221 |
-
"""
|
| 222 |
-
if PROHIBITED_RE.search(text):
|
| 223 |
-
return (
|
| 224 |
-
"[REFUSAL — SAFETY]\n"
|
| 225 |
-
"I cannot provide operational, tactical, or targeting instructions. "
|
| 226 |
-
"Below is a **non-actionable administrative alternative** focusing on doctrine, SOPs, training and audits.\n\n"
|
| 227 |
-
+ generate_admin_alternative(text)
|
| 228 |
-
)
|
| 229 |
-
return text
|
| 230 |
|
| 231 |
def generate_admin_alternative(original_text):
|
| 232 |
# Produce a generic admin-oriented alternative (deterministic)
|
|
@@ -257,9 +235,8 @@ def call_chat_api(messages, max_tokens=900, model="gpt-4o-mini"):
|
|
| 257 |
SYSTEM_SAFE = (
|
| 258 |
"You are an institutional analyst. You MUST follow these rules: "
|
| 259 |
"1) Provide ONLY non-actionable, administrative, doctrinal or training-oriented analysis. "
|
| 260 |
-
"2)
|
| 261 |
-
"3)
|
| 262 |
-
"4) Cite the KB chunk ids / filenames you used in reasoning. "
|
| 263 |
"Output must be explicit that it's NON-ACTIONABLE."
|
| 264 |
)
|
| 265 |
|
|
@@ -289,7 +266,6 @@ def build_enhanced_prompt(a_map, b_map, c_map, gate_text, retrieved_A, retrieved
|
|
| 289 |
user_parts = []
|
| 290 |
user_parts.append("Produce a NON-ACTIONABLE Enhanced Staff Advisory for a commander.")
|
| 291 |
user_parts.append("Include: Executive Summary; Key doctrinal/organizational gaps; Prioritized Administrative Remediations; Measurement/audit suggestions; Sources cited.")
|
| 292 |
-
user_parts.append("DO NOT include any tactical or operational instructions.")
|
| 293 |
user_parts.append("\nSection A answers and relevant KB excerpts:\n")
|
| 294 |
for i, q in enumerate(ENH_SECTION_A):
|
| 295 |
ans = a_map.get(q, "[no answer]")
|
|
|
|
| 204 |
scored.sort(key=lambda x: x[0], reverse=True)
|
| 205 |
return [c for s,c in scored[:top_k] if s>0]
|
| 206 |
|
| 207 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
def generate_admin_alternative(original_text):
|
| 210 |
# Produce a generic admin-oriented alternative (deterministic)
|
|
|
|
| 235 |
SYSTEM_SAFE = (
|
| 236 |
"You are an institutional analyst. You MUST follow these rules: "
|
| 237 |
"1) Provide ONLY non-actionable, administrative, doctrinal or training-oriented analysis. "
|
| 238 |
+
"2) If asked for operational content, refuse and instead produce administrative alternatives (SOPs, audits, training, doctrine). "
|
| 239 |
+
"3) Cite the KB chunk ids / filenames you used in reasoning. "
|
|
|
|
| 240 |
"Output must be explicit that it's NON-ACTIONABLE."
|
| 241 |
)
|
| 242 |
|
|
|
|
| 266 |
user_parts = []
|
| 267 |
user_parts.append("Produce a NON-ACTIONABLE Enhanced Staff Advisory for a commander.")
|
| 268 |
user_parts.append("Include: Executive Summary; Key doctrinal/organizational gaps; Prioritized Administrative Remediations; Measurement/audit suggestions; Sources cited.")
|
|
|
|
| 269 |
user_parts.append("\nSection A answers and relevant KB excerpts:\n")
|
| 270 |
for i, q in enumerate(ENH_SECTION_A):
|
| 271 |
ans = a_map.get(q, "[no answer]")
|