Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,94 +8,84 @@ CHOSEN_BREED = "Golden Retrievers"
|
|
| 8 |
# Page setup
|
| 9 |
st.set_page_config(page_title=f"The {CHOSEN_BREED} Expert", page_icon="π")
|
| 10 |
st.title(f"π Only {CHOSEN_BREED}")
|
| 11 |
-
st.caption(f"Powered by Perplexity API.
|
| 12 |
|
| 13 |
# --- AUTHENTICATION ---
|
| 14 |
perplexity_api_key = os.getenv("PERPLEXITY_API_KEY")
|
| 15 |
|
| 16 |
if not perplexity_api_key:
|
| 17 |
-
st.error("β οΈ PERPLEXITY_API_KEY not found in secrets.
|
| 18 |
st.stop()
|
| 19 |
|
| 20 |
-
# Initialize Client
|
| 21 |
client = OpenAI(
|
| 22 |
api_key=perplexity_api_key,
|
| 23 |
base_url="https://api.perplexity.ai"
|
| 24 |
)
|
| 25 |
|
| 26 |
-
# --- STRICT SYSTEM PROMPT ---
|
| 27 |
-
system_instruction = f"""
|
| 28 |
-
You are a highly specialized AI assistant with a STRICT filter.
|
| 29 |
-
You must adhere to the following funnel of allowed topics:
|
| 30 |
-
|
| 31 |
-
1. LEVEL 1: Is the topic about Pets? (If NO -> Refuse)
|
| 32 |
-
2. LEVEL 2: Is the topic about Dogs? (If NO -> Refuse)
|
| 33 |
-
3. LEVEL 3: Is the topic about {CHOSEN_BREED}? (If NO -> Refuse)
|
| 34 |
-
|
| 35 |
-
Your Goal: Provide accurate, helpful information specifically about {CHOSEN_BREED}.
|
| 36 |
-
|
| 37 |
-
RESTRICTIONS:
|
| 38 |
-
- If the user asks about Cats, Hamsters, or Birds: REFUSE. Say "I only talk about dogs."
|
| 39 |
-
- If the user asks about German Shepherds, Pugs, or Labradors: REFUSE. Say "I am specialized only in {CHOSEN_BREED}."
|
| 40 |
-
- If the user asks about Math, Weather, or Politics: REFUSE. Say "I only discuss {CHOSEN_BREED}."
|
| 41 |
-
|
| 42 |
-
Refusal Message Style: Be polite but firm. Do not apologize profusely, just state your limitation.
|
| 43 |
-
"""
|
| 44 |
-
|
| 45 |
# --- CHAT LOGIC ---
|
| 46 |
-
|
| 47 |
-
# Initialize chat history
|
| 48 |
if "messages" not in st.session_state:
|
| 49 |
-
# We keep the greeting in the UI state, but we will filter it out for the API later
|
| 50 |
st.session_state["messages"] = [
|
| 51 |
-
{"role": "assistant", "content": f"Hello! I
|
| 52 |
]
|
| 53 |
|
| 54 |
-
# Display chat messages
|
| 55 |
for msg in st.session_state.messages:
|
| 56 |
st.chat_message(msg["role"]).write(msg["content"])
|
| 57 |
|
| 58 |
-
|
| 59 |
-
if prompt := st.chat_input():
|
| 60 |
|
| 61 |
-
#
|
| 62 |
-
# If the last message was from the user, it means the previous API call failed.
|
| 63 |
-
# We must remove it to prevent sending "User, User" sequence which breaks the API.
|
| 64 |
if st.session_state.messages and st.session_state.messages[-1]["role"] == "user":
|
| 65 |
st.session_state.messages.pop()
|
| 66 |
|
| 67 |
-
#
|
| 68 |
-
st.session_state.messages.append({"role": "user", "content":
|
| 69 |
-
st.chat_message("user").write(
|
| 70 |
|
| 71 |
-
#
|
| 72 |
-
#
|
| 73 |
-
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
history_to_send = st.session_state.messages[-10:] # Get last 10
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
#
|
| 85 |
try:
|
| 86 |
response = client.chat.completions.create(
|
| 87 |
model="sonar",
|
| 88 |
messages=api_messages,
|
| 89 |
-
temperature=0.
|
| 90 |
)
|
| 91 |
|
| 92 |
-
bot_reply = response.choices[0].message.content
|
| 93 |
-
|
| 94 |
-
#
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
except Exception as e:
|
| 99 |
-
st.error(f"An error occurred: {e}")
|
| 100 |
-
# Optional: Print the message structure for debugging if needed
|
| 101 |
-
# st.write(api_messages)
|
|
|
|
| 8 |
# Page setup
|
| 9 |
st.set_page_config(page_title=f"The {CHOSEN_BREED} Expert", page_icon="π")
|
| 10 |
st.title(f"π Only {CHOSEN_BREED}")
|
| 11 |
+
st.caption(f"Powered by Perplexity API. Strictly restricted to {CHOSEN_BREED}.")
|
| 12 |
|
| 13 |
# --- AUTHENTICATION ---
|
| 14 |
perplexity_api_key = os.getenv("PERPLEXITY_API_KEY")
|
| 15 |
|
| 16 |
if not perplexity_api_key:
|
| 17 |
+
st.error("β οΈ PERPLEXITY_API_KEY not found in secrets.")
|
| 18 |
st.stop()
|
| 19 |
|
|
|
|
| 20 |
client = OpenAI(
|
| 21 |
api_key=perplexity_api_key,
|
| 22 |
base_url="https://api.perplexity.ai"
|
| 23 |
)
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
# --- CHAT LOGIC ---
|
|
|
|
|
|
|
| 26 |
if "messages" not in st.session_state:
|
|
|
|
| 27 |
st.session_state["messages"] = [
|
| 28 |
+
{"role": "assistant", "content": f"Hello! I only answer questions about {CHOSEN_BREED}. Try me!"}
|
| 29 |
]
|
| 30 |
|
|
|
|
| 31 |
for msg in st.session_state.messages:
|
| 32 |
st.chat_message(msg["role"]).write(msg["content"])
|
| 33 |
|
| 34 |
+
if user_input := st.chat_input():
|
|
|
|
| 35 |
|
| 36 |
+
# 1. Clean up previous failed user messages to prevent "User, User" errors
|
|
|
|
|
|
|
| 37 |
if st.session_state.messages and st.session_state.messages[-1]["role"] == "user":
|
| 38 |
st.session_state.messages.pop()
|
| 39 |
|
| 40 |
+
# 2. Display User Message
|
| 41 |
+
st.session_state.messages.append({"role": "user", "content": user_input})
|
| 42 |
+
st.chat_message("user").write(user_input)
|
| 43 |
|
| 44 |
+
# 3. CONSTRUCT THE STRICT PROMPT (The "Secret Sauce")
|
| 45 |
+
# We don't just send the user input. We wrap it in a strict logic gate.
|
| 46 |
+
# We ask Perplexity to output "REFUSAL_TRIGGERED" if it fails the test.
|
| 47 |
|
| 48 |
+
strict_content = f"""
|
| 49 |
+
Task: Check if the following query is specifically about the dog breed "{CHOSEN_BREED}".
|
|
|
|
| 50 |
|
| 51 |
+
User Query: "{user_input}"
|
| 52 |
+
|
| 53 |
+
RULES:
|
| 54 |
+
1. If the query is about "{CHOSEN_BREED}", answer it helpfully.
|
| 55 |
+
2. If the query is about general dogs (but not this specific breed), cats, weather, math, sports, or ANY other topic:
|
| 56 |
+
YOU MUST REPLY WITH EXACTLY ONE WORD: "REFUSAL_TRIGGERED"
|
| 57 |
+
|
| 58 |
+
Do not explain. Do not search for the weather. Do not answer the question if it violates Rule 2.
|
| 59 |
+
"""
|
| 60 |
+
|
| 61 |
+
# 4. Prepare Messages
|
| 62 |
+
# Note: We do NOT send the full chat history for the "Strict Check" to prevent it from getting confused by context.
|
| 63 |
+
# We treat every query as a fresh strict check.
|
| 64 |
+
api_messages = [
|
| 65 |
+
{"role": "system", "content": "You are a strict validation machine. You only output answers for Golden Retrievers."},
|
| 66 |
+
{"role": "user", "content": strict_content}
|
| 67 |
+
]
|
| 68 |
|
| 69 |
+
# 5. Call API
|
| 70 |
try:
|
| 71 |
response = client.chat.completions.create(
|
| 72 |
model="sonar",
|
| 73 |
messages=api_messages,
|
| 74 |
+
temperature=0.0, # Zero temperature for maximum strictness
|
| 75 |
)
|
| 76 |
|
| 77 |
+
bot_reply = response.choices[0].message.content.strip()
|
| 78 |
+
|
| 79 |
+
# 6. POST-PROCESSING GUARDRAIL
|
| 80 |
+
# If the model obeyed our "REFUSAL_TRIGGERED" command, we intercept it.
|
| 81 |
+
if "REFUSAL_TRIGGERED" in bot_reply or "REFUSAL" in bot_reply:
|
| 82 |
+
final_reply = f"π« I cannot answer that. I am strictly programmed to discuss **{CHOSEN_BREED}** only."
|
| 83 |
+
else:
|
| 84 |
+
final_reply = bot_reply
|
| 85 |
+
|
| 86 |
+
# 7. Show Result
|
| 87 |
+
st.session_state.messages.append({"role": "assistant", "content": final_reply})
|
| 88 |
+
st.chat_message("assistant").write(final_reply)
|
| 89 |
|
| 90 |
except Exception as e:
|
| 91 |
+
st.error(f"An error occurred: {e}")
|
|
|
|
|
|