mood-assistant / app.py
lilianma's picture
Update app.py
ee0765e verified
import gradio as gr
import pandas as pd
from datetime import datetime
from sentiment import analyze_sentiment
from reply_style import warm_reply
def sentiment_to_numeric(label: str, score: float) -> float:
label = label.lower()
if label == "positive":
return round(score, 3)
elif label == "negative":
return round(-score, 3)
else: # neutral
return 0.0
def confidence_level(score: float) -> str:
score = float(score)
if score < 0.4:
return "low"
elif score < 0.7:
return "medium"
return "high"
def chatbot_response(user_input, chat_messages, mood_log, memory):
# State 初始化(避免 None)
chat_messages = chat_messages or [] # list[dict]
mood_log = mood_log or [] # list[dict]
memory = memory or [] # list[dict] (Groq messages)
user_input = (user_input or "").strip()
if not user_input:
chat_messages = chat_messages + [{"role": "assistant", "content": "(你沒有輸入內容哦)"}]
return chat_messages, chat_messages, mood_log, memory, ""
# 1) 顯示:使用者訊息
chat_messages = chat_messages + [{"role": "user", "content": user_input}]
# 2) 情緒分析
sentiment, score = analyze_sentiment(user_input)
# 3) 生成回覆(warm_reply 必須回傳 reply, memory)
reply, memory = warm_reply(user_input, sentiment, score, memory)
# 4) 顯示:助理回覆
chat_messages = chat_messages + [{"role": "assistant", "content": reply}]
# 5) 記錄心情(含轉換後欄位)
sentiment_numeric = sentiment_to_numeric(sentiment, score)
confidence_lvl = confidence_level(score)
if mood_log:
prev = mood_log[-1]
delta_sentiment = sentiment_numeric - float(prev.get("sentiment_numeric", 0.0))
delta_confidence = float(score) - float(prev.get("confidence_score", 0.0))
else:
delta_sentiment = 0.0
delta_confidence = 0.0
mood_log.append({
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"text": user_input,
"sentiment_label": sentiment,
"sentiment_numeric": sentiment_numeric,
"confidence_score": round(float(score), 3),
"confidence_level": confidence_lvl,
"delta_sentiment": round(delta_sentiment, 3),
"delta_confidence": round(delta_confidence, 3),
})
# 最後回傳 msg="" 清空輸入框
return chat_messages, chat_messages, mood_log, memory, ""
def export_csv(mood_log):
if not mood_log:
return None
df = pd.DataFrame(mood_log)
columns = [
"timestamp",
"text",
"sentiment_label",
"sentiment_numeric",
"confidence_score",
"confidence_level",
"delta_sentiment",
"delta_confidence",
]
for c in columns:
if c not in df.columns:
df[c] = None
df = df[columns]
df.to_csv("mood_analysis.csv", index=False, encoding="utf-8-sig")
return "mood_analysis.csv"
def reset_session():
# 回傳:chat_state, mood_state, memory_state, msg, chatbot
return [], [], [], "", []
with gr.Blocks() as demo:
gr.Markdown("# 跟我聊聊天")
chatbot = gr.Chatbot(height=420)
chat_state = gr.State([]) # messages list (dict)
mood_state = gr.State([]) # mood log list (dict)
memory_state = gr.State([]) # groq memory list (dict)
with gr.Row():
msg = gr.Textbox(placeholder="輸入訊息…", show_label=False, scale=5)
submit = gr.Button("送出", scale=1)
msg.submit(
chatbot_response,
inputs=[msg, chat_state, mood_state, memory_state],
outputs=[chatbot, chat_state, mood_state, memory_state, msg],
)
submit.click(
chatbot_response,
inputs=[msg, chat_state, mood_state, memory_state],
outputs=[chatbot, chat_state, mood_state, memory_state, msg],
)
with gr.Row():
export_btn = gr.Button("匯出心情記錄 CSV")
download_file = gr.File(label="File")
export_btn.click(export_csv, inputs=[mood_state], outputs=[download_file])
with gr.Row():
reset_btn = gr.Button("清除本次對話/記憶")
reset_btn.click(
reset_session,
inputs=None,
outputs=[chat_state, mood_state, memory_state, msg, chatbot],
)
demo.launch()