Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
|
| 4 |
+
from langchain_community.vectorstores import FAISS
|
| 5 |
+
from langchain_community.embeddings import HuggingFaceEmbeddings
|
| 6 |
+
from langchain_groq import ChatGroq
|
| 7 |
+
from langchain_core.prompts import ChatPromptTemplate
|
| 8 |
+
from langchain.chains.combine_documents import create_stuff_documents_chain
|
| 9 |
+
from langchain.chains import create_retrieval_chain
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
# ---------- Konfiguracja API Groq ----------
|
| 13 |
+
|
| 14 |
+
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
| 15 |
+
if not GROQ_API_KEY:
|
| 16 |
+
raise RuntimeError("GROQ_API_KEY is not set. Add it as a secret in your Hugging Face Space.")
|
| 17 |
+
|
| 18 |
+
# ---------- Ładowanie FAISS i embeddingów ----------
|
| 19 |
+
|
| 20 |
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 21 |
+
FAISS_PATH = os.path.join(BASE_DIR, "my_faiss_index_2")
|
| 22 |
+
|
| 23 |
+
embedding_model = HuggingFaceEmbeddings(
|
| 24 |
+
model_name="jinaai/jina-embeddings-v2-base-en",
|
| 25 |
+
model_kwargs={"trust_remote_code": True}
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
vector_store = FAISS.load_local(
|
| 29 |
+
FAISS_PATH,
|
| 30 |
+
embedding_model,
|
| 31 |
+
allow_dangerous_deserialization=True,
|
| 32 |
+
)
|
| 33 |
+
retriever = vector_store.as_retriever()
|
| 34 |
+
|
| 35 |
+
print("FAISS index loaded correctly.")
|
| 36 |
+
|
| 37 |
+
# ---------- Model Groq ----------
|
| 38 |
+
|
| 39 |
+
chat = ChatGroq(
|
| 40 |
+
api_key=GROQ_API_KEY,
|
| 41 |
+
model_name="llama-3.3-70b-versatile",
|
| 42 |
+
temperature=0.7,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
# ---------- System prompt dla bota BASIC (bez SPT) ----------
|
| 46 |
+
|
| 47 |
+
system_prompt_basic = """
|
| 48 |
+
You are a compassionate, supportive, and non-judgmental well-being assistant.
|
| 49 |
+
You help users talk about their feelings, everyday experiences, challenges, and personal growth.
|
| 50 |
+
|
| 51 |
+
Core principles:
|
| 52 |
+
- Always validate the user’s feelings and experiences.
|
| 53 |
+
- Listen carefully and respond with warmth, empathy, and respect.
|
| 54 |
+
- Never judge, shame, or blame the user.
|
| 55 |
+
- Do NOT give medical advice or make diagnoses.
|
| 56 |
+
- You are an AI assistant, not a human. Do not invent your own experiences.
|
| 57 |
+
|
| 58 |
+
Conversation style:
|
| 59 |
+
- Use clear, simple, natural language.
|
| 60 |
+
- Adapt the length of your answer to the user’s message:
|
| 61 |
+
* If the user only greets you or writes something very short and neutral
|
| 62 |
+
(e.g. "hi", "hello", "what’s up"), reply in 1–2 short sentences and, if appropriate,
|
| 63 |
+
add one simple question.
|
| 64 |
+
* If the user briefly mentions a problem in 1–2 short sentences, reply in about 3–5 sentences
|
| 65 |
+
(one short paragraph) plus one open question.
|
| 66 |
+
* If the user writes a longer and more serious message, you may reply in up to 2 short paragraphs
|
| 67 |
+
(max ~8 sentences) with more depth and guidance.
|
| 68 |
+
- Avoid starting answers by repeating or paraphrasing the user’s question
|
| 69 |
+
(for example, do NOT start with "You’re looking for website blockers..."
|
| 70 |
+
right after the user asked "What website blockers would you recommend?").
|
| 71 |
+
Instead, answer directly first, then add context if helpful.
|
| 72 |
+
- Avoid repeating the same phrases in every answer (e.g. "it takes a lot of courage",
|
| 73 |
+
"many people feel this way"). Use them only when they truly add value.
|
| 74 |
+
- Reflect back what the user said in your own words to show understanding,
|
| 75 |
+
but keep reflections short (one sentence) and non-repetitive.
|
| 76 |
+
- Stay focused on the user’s topic and feelings instead of giving generic speeches.
|
| 77 |
+
- In each answer, you may ask at most ONE open-ended question that naturally follows
|
| 78 |
+
from what the user just shared.
|
| 79 |
+
|
| 80 |
+
Support and suggestions:
|
| 81 |
+
- It is OK to offer simple, concrete suggestions (e.g. "You could try...", "Some people find it helpful to...")
|
| 82 |
+
as long as they are non-medical and non-prescriptive.
|
| 83 |
+
- If the user asks a specific, practical question (e.g. "what website blockers would you recommend?",
|
| 84 |
+
"what can I do instead of gambling?", "how can I talk to my parents about this?"),
|
| 85 |
+
answer directly first (give 2–4 realistic ideas), then optionally add one short question.
|
| 86 |
+
- Do NOT tell the user what they "must" or "have to" do. Instead, offer 1–3 options or ideas they might consider.
|
| 87 |
+
|
| 88 |
+
Safety:
|
| 89 |
+
- If the user mentions self-harm, suicide, or harm to others, respond with extra care.
|
| 90 |
+
- Encourage them to reach out to a trusted person (friend, family member) or a mental health professional.
|
| 91 |
+
- You are not a crisis service and cannot provide emergency help.
|
| 92 |
+
- If the user talks about illegal, abusive or harmful sexual behaviour
|
| 93 |
+
(for example sexual activity with animals, sexual activity with minors,
|
| 94 |
+
or any non-consensual acts), you must:
|
| 95 |
+
* clearly state that you cannot support, encourage or explore such behaviour,
|
| 96 |
+
* make it clear that these actions can seriously harm others and are not acceptable,
|
| 97 |
+
* gently redirect the conversation to the user’s emotions, underlying distress,
|
| 98 |
+
or to seeking professional help.
|
| 99 |
+
Do NOT treat this as a normal preference, and do NOT ask for explicit details.
|
| 100 |
+
|
| 101 |
+
Your goal in each answer:
|
| 102 |
+
1. Acknowledge and validate the user’s emotions.
|
| 103 |
+
2. Gently help them explore their thoughts, needs, and possible options.
|
| 104 |
+
3. Support their autonomy – suggest, do not command.
|
| 105 |
+
4. Ask at most one open-ended question to keep the conversation going in a supportive way
|
| 106 |
+
(or none, if a suggestion-focused answer feels more natural).
|
| 107 |
+
"""
|
| 108 |
+
|
| 109 |
+
# ---------- Prompt + RAG chain ----------
|
| 110 |
+
|
| 111 |
+
prompt_basic = ChatPromptTemplate.from_messages([
|
| 112 |
+
("system", system_prompt_basic),
|
| 113 |
+
("human", """
|
| 114 |
+
Use the following context from similar mental-health conversations to inspire your answer
|
| 115 |
+
(do NOT mention the dataset explicitly):
|
| 116 |
+
<context>
|
| 117 |
+
{context}
|
| 118 |
+
</context>
|
| 119 |
+
|
| 120 |
+
User message: {input}
|
| 121 |
+
""")
|
| 122 |
+
])
|
| 123 |
+
|
| 124 |
+
document_chain_basic = create_stuff_documents_chain(chat, prompt_basic)
|
| 125 |
+
rag_chain_basic = create_retrieval_chain(retriever, document_chain_basic)
|
| 126 |
+
|
| 127 |
+
# ---------- Prosty filtr bezpieczeństwa ----------
|
| 128 |
+
|
| 129 |
+
DISALLOWED_PATTERNS = [
|
| 130 |
+
"fuck a goat",
|
| 131 |
+
"sex with a goat",
|
| 132 |
+
"sex with animals",
|
| 133 |
+
"bestiality",
|
| 134 |
+
# możesz dodać inne oczywiste warianty
|
| 135 |
+
]
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def chat_fn(message, history):
|
| 139 |
+
text = (message or "").lower()
|
| 140 |
+
|
| 141 |
+
if any(pattern in text for pattern in DISALLOWED_PATTERNS):
|
| 142 |
+
return (
|
| 143 |
+
"I can’t talk about sexual activity with animals or any behaviour that could harm someone. "
|
| 144 |
+
"Jeśli takie myśli Cię niepokoją albo powodują cierpienie, warto porozmawiać z psychologiem "
|
| 145 |
+
"lub innym specjalistą. Jeśli chcesz, możemy skupić się na tym, co teraz czujesz "
|
| 146 |
+
"i co najbardziej Cię obciąża."
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
result = rag_chain_basic.invoke({"input": message})
|
| 150 |
+
return result["answer"]
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
demo = gr.ChatInterface(
|
| 154 |
+
fn=chat_fn,
|
| 155 |
+
title="Wellbeing RAG Chatbot (basic)",
|
| 156 |
+
description="Empatyczny chatbot well-being bez SPT (bot kontrolny).",
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
if __name__ == "__main__":
|
| 160 |
+
demo.launch()
|