| """ |
| Project Jarvis — Autonomous Pattern Engine (ML Core) |
| Discovers user habits and routines by analyzing interaction history. |
| """ |
| import logging |
| from typing import List, Dict, Any, Optional |
| from datetime import datetime |
| from sqlalchemy import func |
| from app.models.entities import InteractionLog |
| from app.core.database import SessionLocal |
|
|
| logger = logging.getLogger("friday.patterns") |
|
|
| def discover_routines() -> List[Dict[str, Any]]: |
| """ |
| Analyzes historical InteractionLogs to identify recurring patterns. |
| Uses simple frequency-time clustering as a baseline for ML discovery. |
| """ |
| db = SessionLocal() |
| try: |
| |
| logs = db.query(InteractionLog).all() |
| if not logs: |
| return [] |
|
|
| |
| |
| intent_hour_map = {} |
| for log in logs: |
| hour = log.timestamp.hour |
| key = (hour, log.intent) |
| intent_hour_map[key] = intent_hour_map.get(key, 0) + 1 |
|
|
| |
| routines = [] |
| for (hour, intent), count in intent_hour_map.items(): |
| if count >= 2: |
| |
| time_str = f"{hour:02d}:00" |
| label = f"Recurring {intent.capitalize()}" |
| |
| |
| if intent == "automation": |
| label = "System Maintenance Protocol" |
| elif intent == "search": |
| label = "Deep Intelligence Routine" |
| elif intent == "expense": |
| label = "Sovereign Audit" |
| |
| routines.append({ |
| "time": time_str, |
| "intent": intent, |
| "label": label, |
| "confidence": min(count / 5.0, 1.0) |
| }) |
|
|
| |
| routines.sort(key=lambda x: x["time"]) |
| logger.info(f"PatternEngine: Discovered {len(routines)} autonomous routines.") |
| return routines |
| except Exception as e: |
| logger.error(f"Pattern discovery failed: {e}") |
| return [] |
| finally: |
| db.close() |
|
|
| def get_predicted_action(session_id: str) -> Optional[Dict[str, Any]]: |
| """ |
| Predicts the user's next likely action based on the current hour. |
| """ |
| now_hour = datetime.now().hour |
| routines = discover_routines() |
| |
| for r in routines: |
| |
| r_hour = int(r["time"].split(":")[0]) |
| if r_hour == now_hour: |
| return r |
| return None |
|
|