AI_Agent_Server / backend /mood_extraction.py
Sidreds06's picture
bug fixes
81c40fc
import re
from google.cloud import firestore
from datetime import datetime, timedelta, timezone
from backend.config import gpt4o
db = firestore.Client()
from backend.credentials import setup_google_credentials
setup_google_credentials()
COMMON_EMOTIONS = [
"grateful", "hope", "content", "connected", "drained",
"envy", "disappointed", "relief", "happy", "sad", "angry",
"anxious", "excited", "calm", "lonely", "overwhelmed"
]
def get_recent_mood_entries(user_id: str, days: int = 60):
now = datetime.now(timezone.utc)
min_date = now - timedelta(days=days)
entries_ref = db.collection("mood_entries").document("entries").collection(user_id)
docs = entries_ref.stream()
recent_entries = []
for doc in docs:
data = doc.to_dict()
end_date_val = data.get("endDate")
if end_date_val:
try:
if isinstance(end_date_val, datetime):
end_date = end_date_val
else:
end_date = datetime.fromisoformat(str(end_date_val))
if end_date.tzinfo:
end_date_utc = end_date.astimezone(timezone.utc)
else:
end_date_utc = end_date.replace(tzinfo=timezone.utc)
if end_date_utc >= min_date:
recent_entries.append(data)
except Exception as e:
continue
return recent_entries
def _find_emotions(text):
emotions_found = []
for e in COMMON_EMOTIONS:
if re.search(r'\b' + re.escape(e) + r'\b', text, re.IGNORECASE):
emotions_found.append(e)
return list(set(emotions_found))
def _find_mood(text):
moods = ["good", "bad", "neutral", "happy", "sad", "ok", "great", "awful", "fine"]
for mood in moods:
if re.search(r'\b' + re.escape(mood) + r'\b', text, re.IGNORECASE):
return mood
return None
async def extract_mood_details(user_message: str, conversation_history: list = None) -> dict:
details = {
"emotions": [],
"mood": None,
"note": None,
"endDate": None,
"missing_fields": []
}
text = user_message.strip()
details["emotions"] = _find_emotions(text)
details["mood"] = _find_mood(text)
details["note"] = text
# Set endDate to now unless extracted
details["endDate"] = datetime.now(timezone.utc).isoformat()
# Fallback to LLM if missing
if not details["emotions"] or not details["mood"]:
llm_resp = await gpt4o.ainvoke([
{
"role": "system",
"content": (
"Extract the following from the user's message:\n"
"1. A list of specific emotions (words only, as a JSON list)\n"
"2. The overall mood (one word, like 'good', 'bad', or 'neutral')\n"
"Reply in strict JSON:\n"
"{\"emotions\": [...], \"mood\": \"...\"}"
)
},
{
"role": "user",
"content": user_message
}
])
import json
try:
llm_json = json.loads(llm_resp.content)
if not details["emotions"] and "emotions" in llm_json:
details["emotions"] = llm_json["emotions"]
if not details["mood"] and "mood" in llm_json:
details["mood"] = llm_json["mood"]
except Exception:
pass
if not details["mood"]:
details["missing_fields"].append("mood")
if not details["emotions"]:
details["missing_fields"].append("emotions")
return details
def generate_mood_confirmation_prompt(details: dict) -> str:
missing = details["missing_fields"]
if not missing:
return None
prompts = []
if "mood" in missing:
prompts.append("How would you describe your overall mood?")
if "emotions" in missing:
prompts.append("Which emotions did you experience? (e.g., grateful, anxious, calm, etc.)")
if len(prompts) == 1:
return prompts[0]
elif len(prompts) == 2:
return f"{prompts[0]} Also, {prompts[1].lower()}"
else:
return "Could you share more about how you're feeling?"