from pathlib import Path
import os
import gradio as gr
from emotion_classifier import DEFAULT_MODEL_DIR, EmotionClassifier
classifier = EmotionClassifier()
THEME = gr.themes.Soft(
primary_hue="teal",
secondary_hue="rose",
neutral_hue="zinc",
radius_size="sm",
)
CSS = """
.emotion-shell {
max-width: 980px;
margin: 0 auto;
}
.status-box {
border-left: 4px solid #0f766e;
padding: 12px 14px;
background: #f8fafc;
}
.missing-box {
border-left: 4px solid #be123c;
padding: 12px 14px;
background: #fff1f2;
}
.emotion-card {
border: 1px solid #d4d4d8;
padding: 16px;
background: white;
}
.emotion-value {
font-size: 28px;
font-weight: 700;
color: #0f766e;
}
"""
def model_status() -> str:
model_dir = Path(os.getenv("EMOTION_MODEL_DIR", DEFAULT_MODEL_DIR))
if model_dir.exists():
return "
Local trained emotion model is ready.
"
return (
"Local emotion model is not available yet. "
"Add the trained saved_emotion_model folder before testing.
"
)
def _empty_result(message: str) -> tuple[str, list[list[str | float]], str]:
return (
f"{message}
",
[],
model_status(),
)
def predict_emotion(text: str) -> tuple[str, list[list[str | float]], str]:
if not (text or "").strip():
return _empty_result("Please enter a message to analyze.")
try:
result = classifier.explain(text or "", top_k=8)
emotion = result["prediction"]["emotion"]
confidence = result["prediction"]["confidence"]
card = (
""
"
Predicted emotion
"
f"
{emotion.title()}
"
f"
Confidence: {confidence:.1%}
"
"
"
)
evidence = [
[
item["word"],
item["impact"],
item["confidence_without_word"],
item["effect"],
]
for item in result["all_evidence"]
]
status = "Prediction generated by the local trained DistilBERT model.
"
return card, evidence, status
except FileNotFoundError:
return _empty_result("Local emotion model is not available yet.")
except ImportError as exc:
return _empty_result(f"Missing dependency: {exc}")
except Exception as exc:
print(f"Emotion UI error: {type(exc).__name__}: {exc}")
return _empty_result("Emotion analysis is unavailable right now. Please check the terminal logs.")
with gr.Blocks(title="Emotion Classifier") as interface:
with gr.Column(elem_classes=["emotion-shell"]):
gr.Markdown(
"""
# Emotion Classification
DistilBERT-based emotion analysis with confidence and word-level evidence.
"""
)
status = gr.HTML(value=model_status())
with gr.Row():
with gr.Column(scale=5):
text_input = gr.Textbox(
lines=7,
label="User message",
placeholder="Example: I feel overwhelmed and I cannot sleep.",
)
analyze_button = gr.Button("Analyze emotion", variant="primary")
with gr.Column(scale=4):
result_output = gr.HTML(label="Prediction")
evidence_output = gr.Dataframe(
headers=["Word", "Impact", "Confidence Without Word", "Effect"],
datatype=["str", "number", "number", "str"],
label="Word Evidence",
interactive=False,
)
summary_output = gr.HTML()
analyze_button.click(
fn=predict_emotion,
inputs=text_input,
outputs=[result_output, evidence_output, summary_output],
)
if __name__ == "__main__":
port = int(os.getenv("GRADIO_SERVER_PORT", "7860"))
interface.launch(theme=THEME, css=CSS, server_port=port)