Spaces:
Build error
Build error
| from fastapi import APIRouter, Depends, HTTPException, Query | |
| from sqlalchemy.orm import Session | |
| from pydantic import BaseModel | |
| from typing import List, Optional | |
| from app.database.database import get_db | |
| from app.database.models import User | |
| from app.middleware.cache import cache | |
| # Import AI helper engines | |
| from app.ai.forecasting import predict_future_balance, forecast_savings_and_investments, simulate_future_scenarios | |
| from app.ai.simulation import simulate_purchase_impact, simulate_investment_impact, simulate_subscription_cancellation | |
| from app.ai.behavior import analyze_spending_behavior | |
| from app.ai.coaching import calculate_financial_health_score, generate_daily_briefing | |
| from app.ai.subscriptions import analyze_subscriptions | |
| from app.ai.fraud import evaluate_transaction_for_fraud, get_user_fraud_alerts | |
| from app.ai.chat import get_chat_response | |
| router = APIRouter(prefix="/api/ai", tags=["AI Intelligence"]) | |
| # Fallback helper to retrieve a valid user ID for demonstration | |
| def get_user_id_fallback(db: Session, user_id: Optional[str] = None) -> str: | |
| if user_id: | |
| return user_id | |
| user = db.query(User).first() | |
| if not user: | |
| raise HTTPException(status_code=404, detail="No users found in database. Please seed the database first.") | |
| return user.id | |
| # Pydantic Schemas for input | |
| class PurchaseRequest(BaseModel): | |
| amount: float | |
| merchant: str | |
| category: str | |
| class InvestmentRequest(BaseModel): | |
| monthly_sip: float | |
| asset_type: str | |
| lump_sum: float = 0.0 | |
| class SubscriptionSimulationRequest(BaseModel): | |
| subscription_ids: List[str] | |
| class ChatMessageRequest(BaseModel): | |
| message: str | |
| # βββ FINANCIAL TWIN FORECASTS ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_twin_predict(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:twin:predict:{uid}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = predict_future_balance(db, uid) | |
| cache.set(cache_key, result, ttl=300) # cache for 5 minutes | |
| return result | |
| def get_twin_future(user_id: Optional[str] = None, months: int = Query(default=12, ge=1, le=60), db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:twin:future:{uid}:{months}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = forecast_savings_and_investments(db, uid, months) | |
| cache.set(cache_key, result, ttl=300) | |
| return result | |
| def get_twin_scenarios(user_id: Optional[str] = None, months: int = Query(default=6, ge=1, le=24), db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:twin:scenarios:{uid}:{months}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = simulate_future_scenarios(db, uid, months) | |
| cache.set(cache_key, result, ttl=300) | |
| return result | |
| # βββ SIMULATION ENDPOINTS ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def post_simulate_purchase(req: PurchaseRequest, user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| return simulate_purchase_impact(db, uid, req.amount, req.category, req.merchant) | |
| def post_simulate_investment(req: InvestmentRequest, user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| return simulate_investment_impact(db, uid, req.monthly_sip, req.asset_type, req.lump_sum) | |
| def post_simulate_subscription(req: SubscriptionSimulationRequest, user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| return simulate_subscription_cancellation(db, uid, req.subscription_ids) | |
| # βββ BEHAVIORAL ANALYTICS βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_behavior_insights(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:behavior:insights:{uid}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = analyze_spending_behavior(db, uid) | |
| cache.set(cache_key, result, ttl=600) # cache for 10 minutes | |
| return result | |
| # βββ COACHING & BRIEFINGS βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_coaching_briefing(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| # Cache briefings for 1 hour to prevent excessive LLM costs | |
| cache_key = f"ai:coaching:briefing:{uid}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = generate_daily_briefing(db, uid) | |
| cache.set(cache_key, result, ttl=3600) | |
| return result | |
| def get_coaching_score(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:coaching:score:{uid}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = calculate_financial_health_score(db, uid) | |
| cache.set(cache_key, result, ttl=600) | |
| return result | |
| # βββ SUBSCRIPTION OPTIMIZATION ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_subscriptions_optimize(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| cache_key = f"ai:subs:optimize:{uid}" | |
| cached = cache.get(cache_key) | |
| if cached: | |
| return cached | |
| result = analyze_subscriptions(db, uid) | |
| cache.set(cache_key, result, ttl=600) | |
| return result | |
| # βββ FRAUD & SECURITY βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_fraud_analysis(user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| return get_user_fraud_alerts(db, uid) | |
| def post_fraud_evaluate(transaction_id: str, db: Session = Depends(get_db)): | |
| return evaluate_transaction_for_fraud(db, transaction_id) | |
| # βββ CONTEXTUAL CHAT ENDPOINT ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def post_chat(req: ChatMessageRequest, user_id: Optional[str] = None, db: Session = Depends(get_db)): | |
| uid = get_user_id_fallback(db, user_id) | |
| response_msg = get_chat_response(db, uid, req.message) | |
| return {"response": response_msg} | |