AI_Assessment_Feature_1 / chain_problems.py
Phoenix21's picture
try to handle this for the no more insomia bugs
1e87777 verified
raw
history blame
7.06 kB
# chain_problems.py
import json
import logging
from typing import Dict, Optional
from langchain import PromptTemplate, LLMChain
from models import chat_model
logger = logging.getLogger(__name__)
problem_prompt_template = PromptTemplate(
input_variables=["responses", "internal_report"],
template=(
"You are a wellness analyst. You have the following user responses to health-related questions:\n"
"{responses}\n\n"
"You also have an internal analysis report:\n"
"{internal_report}\n\n"
"From these inputs, determine a 'problem severity percentage' for the user in the following areas: "
"stress_management, low_therapy, balanced_weight, restless_night, lack_of_motivation, gut_health, anxiety, burnout.\n\n"
"Consider how these severity percentages will later be used to recommend suitable wellness packages such as:\n\n"
"1. Fitness Mobility\n"
"2. Balance Weight\n"
"3. No More Insomnia\n"
"4. Chronic Care\n"
"5. Mental Wellness\n"
"6. Focus Flow\n\n"
"Return your answer in JSON format with keys: stress_management, low_therapy, balanced_weight, restless_night, "
"lack_of_motivation, gut_health, anxiety, burnout.\n"
"Ensure severity percentages are numbers from 0 to 100.\n\n"
"JSON Output:"
)
)
problem_chain = LLMChain(llm=chat_model, prompt=problem_prompt_template)
def recommend_wellness_packages(
problems: Dict[str, float],
sleep_hours: Optional[float] = None
) -> Dict[str, str]:
"""
Given the severity dictionary and the user's reported sleep hours,
recommend one or more wellness packages.
Returns:
A dictionary with:
- 'recommended_packages': comma-separated string of package names
- 'recommendation_details': textual explanation of why these were chosen
"""
# Threshold for considering an issue "significant"
THRESHOLD = 50.0
recommended = []
rationale = []
# 1. Stress / Mood => "Mental Wellness", "Focus Flow"
if (
problems["stress_management"] >= THRESHOLD
or problems["anxiety"] >= THRESHOLD
or problems["burnout"] >= THRESHOLD
or problems["low_therapy"] >= THRESHOLD
or problems["lack_of_motivation"] >= THRESHOLD
):
recommended.append("Mental Wellness")
rationale.append(
"Mental Wellness Package suggested due to elevated stress, anxiety, "
"or motivation-related concerns."
)
if problems["lack_of_motivation"] >= THRESHOLD or problems["stress_management"] >= THRESHOLD:
recommended.append("Focus Flow")
rationale.append(
"Focus Flow Package recommended to improve concentration and reduce mental fatigue."
)
# 2. Balanced Weight / Gut Health => "Balance Weight"
if problems["balanced_weight"] >= THRESHOLD or problems["gut_health"] >= THRESHOLD:
recommended.append("Balance Weight")
rationale.append(
"Balance Weight Package suggested due to weight management or gut health concerns."
)
# 3. Restless nights => "No More Insomnia"
# **FIX**: Only recommend if user sleeps < 4 hours (to avoid recommending it for 10+ hours).
if sleep_hours is not None and sleep_hours < 4:
# If the user is sleeping less than 4 hours, we consider insomnia a big issue.
recommended.append("No More Insomnia")
rationale.append(
"No More Insomnia Package recommended because the user reported sleeping less than 4 hours."
)
# 4. High burnout => "Chronic Care"
if problems["burnout"] >= THRESHOLD:
recommended.append("Chronic Care")
rationale.append(
"Chronic Care Package recommended to help manage long-term stress and burnout."
)
# 5. If user has borderline or higher weight/stress => "Fitness Mobility"
if (
problems["balanced_weight"] >= (THRESHOLD * 0.7)
or problems["stress_management"] >= (THRESHOLD * 0.7)
):
recommended.append("Fitness Mobility")
rationale.append(
"Fitness Mobility Package may support better physical conditioning and relieve stress."
)
# Ensure uniqueness if appended multiple times
unique_packages = list(dict.fromkeys(recommended))
# Build a clear explanation
recommendation_details = "\n".join(rationale) if rationale else "No particular issues detected."
return {
"recommended_packages": ", ".join(unique_packages),
"recommendation_details": recommendation_details
}
def analyze_problems_with_chain(responses: Dict[str, str], internal_report: str) -> Dict[str, object]:
"""
Analyzes user responses and internal report to extract problem severity
and then recommends relevant wellness packages.
Returns:
A dictionary with:
- keys for each problem severity (stress_management, low_therapy, etc.)
- 'recommended_packages': comma-separated package names
- 'recommendation_details': textual explanation
"""
responses_str = "\n".join(f"{q}: {a}" for q, a in responses.items())
raw_text = problem_chain.run(responses=responses_str, internal_report=internal_report)
# Try to parse problem severities from LLM output
try:
start_idx = raw_text.find('{')
end_idx = raw_text.rfind('}') + 1
json_str = raw_text[start_idx:end_idx]
problems = json.loads(json_str)
# Ensure all eight keys exist
for key in [
"stress_management",
"low_therapy",
"balanced_weight",
"restless_night",
"lack_of_motivation",
"gut_health",
"anxiety",
"burnout"
]:
problems.setdefault(key, 0.0)
# Convert values to float
problems = {k: float(v) for k, v in problems.items()}
except Exception as e:
logger.error(f"Error parsing problem percentages from LLM: {e}")
# Default to zero severities
problems = {
"stress_management": 0.0,
"low_therapy": 0.0,
"balanced_weight": 0.0,
"restless_night": 0.0,
"lack_of_motivation": 0.0,
"gut_health": 0.0,
"anxiety": 0.0,
"burnout": 0.0
}
# --- EXTRACT USER SLEEP HOURS ---
# We assume the user answer is in responses["sleep_duration"] or similar key.
# If your data uses a different key for the hours of sleep, adjust accordingly.
sleep_hours = None
if "sleep_duration" in responses:
try:
sleep_hours = float(responses["sleep_duration"])
except ValueError:
sleep_hours = None
# Now get the recommendations based on problem severities + sleep_hours
recommendations = recommend_wellness_packages(problems, sleep_hours=sleep_hours)
# Merge and return
return {
**problems,
**recommendations
}