Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions InsurGenie_PPT_Content.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
=========================================
INSURGENIE - PPT / PITCH DECK CONTENT
=========================================

SLIDE 1: TITLE SLIDE
• Project Name: InsurGenie
• Tagline: AI-Powered Dynamic Insurance & Reverse Underwriting

SLIDE 2: THE PROBLEM WITH TRADITIONAL INSURANCE
• Outdated Metrics: Relies heavily on static demographics (Age, Gender, Zip Code) instead of actual behavior.
• Lack of Transparency: Users don't know exactly why their premiums are so high.
• Zero Incentive: Safe drivers and healthy individuals are penalized to subsidize risky users, with no ongoing motivation to improve.

SLIDE 3: THE INSURGENIE SOLUTION
• Real-time AI Risk Engine: Ingests dynamic data points from wearables (Health) and vehicle telematics (Driving).
• Dynamic Pricing Models: Calculates a continuously updating "Risk Score" (0.0 to 1.0) and assigns users to one of 7 tiers (Elite to Extreme).
• Empowering the User: The safer they live, the less they pay.

SLIDE 4: GAMIFIED DASHBOARD & REWARDS
• Unified Ecosystem: Displays a comprehensive breakdown of Health, Driving, and Lifestyle risk metrics.
• Financial Reinforcement: Positively framed UI highlighting "Insurance Savings" directly tied to lifestyle choices.
• Milestone Tracking: Next savings milestones and progress bars incentivize users to stick to healthier goals.

SLIDE 5: REVERSE UNDERWRITING (THE CROWN JEWEL)
• A complete flip of conventional insurance practices.
• Goal Setting: Users actively choose a target insurance plan tier (e.g., "I want to pay ₹799/month on the Elite Plan").
• AI Roadmap: The AI analyzes their current data and generates a highly personalized, actionable roadmap to qualify for that rate (e.g., "Walk 8,000 steps daily," "Reduce hard braking by 15%").

SLIDE 6: CONTEXT-AWARE AI CHATBOT
• 24/7 intelligent insurance assistant built right into the dashboard.
• Explainability: Helps users understand policy details, how their risk score was calculated, and interprets complex insurance jargon instantly.

SLIDE 7: HOW IT WORKS (THE USER JOURNEY)
1. Connect Data: Seamlessly link wearables and vehicle telematics.
2. AI-Powered Assessment: Receive an instant, real-time risk evaluation.
3. Monitor via Dashboard: Track health/driving scores and watch savings grow.
4. Set Targets: Use Reverse Underwriting to chart a path to lower premiums.
5. Re-Insure: Meet the goals and automatically unlock better rates.

SLIDE 8: SUMMARY OF TECHNICAL WORK
• Frontend: Built with React/Vite, featuring dark-mode sleek UI, dynamic routing, component-driven tables, and deep interactive states.
• Backend/AI: FastAPI Python backend natively connected to Groq LLMs to handle complex logic securely.
• Cloud & Data: Fully integrated Supabase environment tying user profiles with risk scores and real-time state management.
16 changes: 15 additions & 1 deletion backend/app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,18 @@ def create_or_get_user(user_info):
}

insert_res = supabase.table("users").insert(new_user).execute()
return insert_res.data[0]
return insert_res.data[0]

def get_current_user(user_id: int):
res = (
supabase
.table("users")
.select("*")
.eq("id", user_id)
.execute()
)

if res.data:
return res.data[0]

return None
45 changes: 45 additions & 0 deletions backend/app/controllers/chatbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import os
from pydantic import BaseModel
from typing import Optional, Dict, Any
from fastapi import APIRouter
from groq import Groq
from dotenv import load_dotenv

load_dotenv()

router = APIRouter()

GROQ_API_KEY = os.getenv("GROQ_API_KEY")
client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None

class ChatMessage(BaseModel):
message: str
context: Optional[Dict[str, Any]] = None

@router.post("/chat")
def chat_endpoint(data: ChatMessage):
if not client:
return {"reply": "I am currently offline. Please check the GROQ API key configuration."}

system_prompt = (
"You are InsureGenie, an AI assistant for an insurance platform. "
"You help users understand their health, driving risk, and insurance policies. "
"Be concise, friendly, and helpful."
)
if data.context:
system_prompt += f"\nHere is the user's current context based on their dashboard: {data.context}"

try:
chat_completion = client.chat.completions.create(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": data.message}
],
model="llama-3.3-70b-versatile",
temperature=0.5,
max_tokens=1024,
)
reply = chat_completion.choices[0].message.content
return {"reply": reply}
except Exception as e:
return {"reply": f"Error communicating with the bot: {str(e)}"}
242 changes: 242 additions & 0 deletions backend/app/controllers/reverse_underwriting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import os
import json
from groq import Groq
from dotenv import load_dotenv
from app.database import supabase

load_dotenv()

GROQ_API_KEY = os.getenv("GROQ_API_KEY")
client = Groq(api_key=GROQ_API_KEY) if GROQ_API_KEY else None

PLAN_DETAILS = {
1: {"name": "Elite", "risk_range": "Below 0.20", "premium": 350, "label": "Best users"},
2: {"name": "Pro", "risk_range": "0.20 - 0.30", "premium": 380, "label": "Very safe"},
3: {"name": "Advanced", "risk_range": "0.30 - 0.45", "premium": 420, "label": "Slight risk"},
4: {"name": "Guarded", "risk_range": "0.45 - 0.60", "premium": 450, "label": "Moderate"},
5: {"name": "Risky", "risk_range": "0.60 - 0.75", "premium": 500, "label": "Neutral"},
6: {"name": "Critical", "risk_range": "0.75 - 0.90", "premium": 550, "label": "Risk loading"},
7: {"name": "Extreme", "risk_range": "0.90 - 1.00", "premium": 650, "label": "Very risky"},
}


def get_reverse_underwriting_advice(user_id: int, target_plan_level: int) -> dict:

# 1. Validate plan level
if target_plan_level not in PLAN_DETAILS:
return {"success": False, "error": "Invalid target plan level. Must be between 1 and 7."}

# 2. Fetch current premium / risk data
premium_resp = (
supabase.table("premium")
.select("*")
.eq("user_id", user_id)
.order("created_at", desc=True)
.limit(1)
.execute()
)
if not premium_resp.data:
return {"success": False, "error": "No policy data found. Please calculate your insurance quote first."}

premium = premium_resp.data[0]
current_plan_level = int(premium.get("policy_plan_id", 5))

if target_plan_level >= current_plan_level:
current_name = PLAN_DETAILS[current_plan_level]["name"]
return {
"success": False,
"error": (
f"Please select a plan better than your current plan "
f"({current_name}, Level {current_plan_level}). "
f"Choose a plan with a lower level number."
),
}

# 3. Recent activity (7-day avg)
activity_resp = (
supabase.table("user_activity")
.select("steps, calories, active_minutes")
.eq("user_id", user_id)
.order("recorded_at", desc=True)
.limit(7)
.execute()
)
activity = activity_resp.data or []
avg_steps = int(sum(a.get("steps", 0) for a in activity) / len(activity)) if activity else 0
avg_calories = int(sum(a.get("calories", 0) for a in activity) / len(activity)) if activity else 0
avg_active_min = int(sum(a.get("active_minutes", 0) for a in activity) / len(activity)) if activity else 0

# 4. Wellness score
score_resp = (
supabase.table("user_score")
.select("score, reward")
.eq("user_id", user_id)
.execute()
)
score_data = score_resp.data[0] if score_resp.data else {"score": 0, "reward": 0}

# 5. Insurance inputs for BMI / heart rate (best-effort)
bmi = "unknown"
heart_rate = "unknown"
try:
input_resp = (
supabase.table("insurance_inputs")
.select("bmi, heart_rate")
.eq("user_id", user_id)
.order("created_at", desc=True)
.limit(1)
.execute()
)
if input_resp.data:
bmi = input_resp.data[0].get("bmi", "unknown")
heart_rate = input_resp.data[0].get("heart_rate", "unknown")
except Exception:
pass

# 6. Build variables
current_plan = PLAN_DETAILS[current_plan_level]
target_plan = PLAN_DETAILS[target_plan_level]
monthly_savings = current_plan["premium"] - target_plan["premium"]
current_risk = premium.get("risk_score", 0.5)
health_risk = premium.get("health_risk", "medium")
lifestyle_risk = premium.get("lifestyle_risk", "medium")
driving_risk = premium.get("driving_risk", "medium")

# 7. Build LLM prompt
prompt = f"""
You are an expert insurance underwriter and health coach for InsureGenie, an AI-powered insurance platform.

A user wants to upgrade their insurance plan from their current plan to a better (lower risk) plan.
Your job is to generate a specific, data-driven, actionable improvement roadmap.

CURRENT USER PROFILE:
- Current Plan: {current_plan['name']} (Level {current_plan_level})
- Current Monthly Premium: Rs {current_plan['premium']}/month
- Current Risk Score: {current_risk:.2f} (scale: 0.0 = lowest risk, 1.0 = highest risk)
- Health Risk Category: {health_risk}
- Lifestyle Risk Category: {lifestyle_risk}
- Driving Risk Category: {driving_risk}
- Current BMI: {bmi}
- Resting Heart Rate: {heart_rate} bpm
- Wellness Points Earned: {score_data['score']}

RECENT ACTIVITY (7-day average):
- Daily Steps: {avg_steps}
- Daily Calories Burned: {avg_calories}
- Daily Active Minutes: {avg_active_min}

TARGET PLAN:
- Plan: {target_plan['name']} (Level {target_plan_level})
- Monthly Premium: Rs {target_plan['premium']}/month
- Required Risk Score Range: {target_plan['risk_range']}
- Monthly Savings if Achieved: Rs {monthly_savings}

Return ONLY a valid JSON object — no markdown, no code fences, no extra text.
The JSON must exactly follow this structure:

{{
"summary": "Two sentences summarizing what must change and how achievable this is given the current profile.",
"health_actions": [
"Specific health action with exact target numbers",
"Specific health action with exact target numbers",
"Specific health action with exact target numbers"
],
"lifestyle_actions": [
"Specific daily activity target with exact numbers",
"Specific daily activity target with exact numbers",
"Specific daily activity target with exact numbers"
],
"driving_actions": [
"Specific driving improvement action",
"Specific driving improvement action"
],
"timeline": "Realistic estimate such as 3 to 6 months with consistent effort",
"targets": {{
"daily_steps": 10000,
"daily_calories_burned": 500,
"daily_active_minutes": 45,
"target_bmi_range": "18.5 - 24.9",
"risk_score_needed": 0.35
}},
"difficulty": "Easy or Moderate or Challenging"
}}

Focus improvements on the weakest areas: health is {health_risk}, lifestyle is {lifestyle_risk}, driving is {driving_risk}.
Do not use emojis. Be specific with numbers. Be encouraging but realistic.
""".strip()

# 8. Call Groq
if not client:
return {"success": False, "error": "AI service not configured. Please check GROQ_API_KEY in backend .env"}

try:
completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": (
"You are a precise AI insurance underwriter. "
"Always return only valid JSON with no markdown formatting, no emojis, no extra explanation."
),
},
{"role": "user", "content": prompt},
],
model="llama-3.3-70b-versatile",
temperature=0.3,
max_tokens=1000,
)
raw = completion.choices[0].message.content.strip()

# Strip markdown code fences if model wraps them anyway
if raw.startswith("```"):
parts = raw.split("```")
raw = parts[1] if len(parts) > 1 else raw
if raw.startswith("json"):
raw = raw[4:]
raw = raw.strip()
if raw.endswith("```"):
raw = raw[:-3].strip()

advice = json.loads(raw)

except json.JSONDecodeError:
advice = {
"summary": "The AI returned an unstructured response. Key actions are listed below.",
"health_actions": ["Maintain a BMI between 18.5 and 24.9", "Keep resting heart rate below 80 bpm", "Get an annual health check-up"],
"lifestyle_actions": [f"Increase daily steps from {avg_steps} to 10,000", "Burn at least 400 calories per day through exercise", "Achieve 30 active minutes daily"],
"driving_actions": ["Avoid speeding violations for 12 consecutive months", "Maintain a clean driving record"],
"timeline": "3 to 6 months with consistent effort",
"targets": {
"daily_steps": 10000,
"daily_calories_burned": 400,
"daily_active_minutes": 30,
"target_bmi_range": "18.5 - 24.9",
"risk_score_needed": float(target_plan_level) * 0.13,
},
"difficulty": "Moderate",
}
except Exception as e:
return {"success": False, "error": f"AI service error: {str(e)}"}

return {
"success": True,
"current_plan": current_plan["name"],
"current_level": current_plan_level,
"target_plan": target_plan["name"],
"target_level": target_plan_level,
"current_risk": round(current_risk, 2),
"monthly_savings": monthly_savings,
"current_premium": current_plan["premium"],
"target_premium": target_plan["premium"],
"advice": advice,
"current_metrics": {
"health_risk": health_risk,
"lifestyle_risk": lifestyle_risk,
"driving_risk": driving_risk,
"avg_steps": avg_steps,
"avg_calories": avg_calories,
"avg_active_mins": avg_active_min,
"bmi": bmi,
"heart_rate": heart_rate,
},
}
Loading