from sqlalchemy import create_engine, Column, String, Text, DateTime from sqlalchemy.orm import declarative_base, sessionmaker from sqlalchemy import text as sql_text from contextlib import contextmanager from datetime import datetime SQLALCHEMY_DATABASE_URL = "sqlite:///./automl_studio.db" engine = create_engine( SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} ) SessionLocal = sessionmaker( autocommit=False, autoflush=False, bind=engine, expire_on_commit=False, ) Base = declarative_base() @contextmanager def get_db(): """Context manager for safe, exception-aware DB session lifecycle.""" db = SessionLocal() try: yield db db.commit() except Exception: db.rollback() raise finally: db.close() class DatasetModel(Base): __tablename__ = "datasets" id = Column(String, primary_key=True, index=True) file_path = Column(String) profile_json = Column(Text) parent_dataset_id = Column(String, nullable=True) source_type = Column(String, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class JobModel(Base): __tablename__ = "jobs" id = Column(String, primary_key=True, index=True) dataset_id = Column(String) status = Column(String) history_json = Column(Text, default="[]") results_json = Column(Text, nullable=True) model_path = Column(String, nullable=True) error = Column(Text, nullable=True) insights_json = Column(Text, nullable=True) reasoning_json = Column(Text, default="[]") story = Column(Text, nullable=True) params_json = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class MetaLearningRecord(Base): __tablename__ = "meta_learning" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) meta_features_json = Column(Text) best_model = Column(String) best_score = Column(String) task_type = Column(String) metric_name = Column(String) leaderboard_json = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class ExperimentRun(Base): __tablename__ = "experiment_runs" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) job_id = Column(String, index=True) dataset_id = Column(String, nullable=True) model_name = Column(String, nullable=True) metric_name = Column(String, nullable=True) score = Column(String, nullable=True) hyperparams_json = Column(Text, nullable=True) metrics_json = Column(Text, nullable=True) leaderboard_json = Column(Text, nullable=True) feature_count = Column(String, nullable=True) row_count = Column(String, nullable=True) task_type = Column(String, nullable=True) mode = Column(String, nullable=True) goal = Column(String, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class DriftCheck(Base): __tablename__ = "drift_checks" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) job_id = Column(String, index=True) dataset_id = Column(String, nullable=True) uploaded_name = Column(String, nullable=True) status = Column(String, nullable=True) drift_score_pct = Column(String, nullable=True) report_json = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class DriftSchedule(Base): __tablename__ = "drift_schedules" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) job_id = Column(String, index=True) enabled = Column(String, nullable=True, default="true") frequency_days = Column(String, nullable=True, default="7") warning_threshold = Column(String, nullable=True, default="0.1") critical_threshold = Column(String, nullable=True, default="0.2") last_alert_status = Column(String, nullable=True) last_alert_summary = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class ModelRegistryEntry(Base): __tablename__ = "model_registry" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) run_id = Column(String, index=True) label = Column(String, nullable=True) note = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class TeamNote(Base): __tablename__ = "team_notes" id = Column( String, primary_key=True, index=True, default=lambda: __import__("uuid").uuid4().hex, ) entity_type = Column(String, nullable=True) entity_id = Column(String, index=True) note = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) Base.metadata.create_all(bind=engine) def _run_migrations(): statements = [ "ALTER TABLE jobs ADD COLUMN created_at DATETIME", "ALTER TABLE jobs ADD COLUMN story TEXT", "ALTER TABLE jobs ADD COLUMN params_json TEXT", "ALTER TABLE jobs ADD COLUMN insights_json TEXT", "ALTER TABLE jobs ADD COLUMN reasoning_json TEXT", "ALTER TABLE jobs ADD COLUMN model_path TEXT", "ALTER TABLE datasets ADD COLUMN created_at DATETIME", "ALTER TABLE datasets ADD COLUMN parent_dataset_id TEXT", "ALTER TABLE datasets ADD COLUMN source_type TEXT", "ALTER TABLE drift_schedules ADD COLUMN warning_threshold TEXT", "ALTER TABLE drift_schedules ADD COLUMN critical_threshold TEXT", "ALTER TABLE drift_schedules ADD COLUMN last_alert_status TEXT", "ALTER TABLE drift_schedules ADD COLUMN last_alert_summary TEXT", """CREATE TABLE IF NOT EXISTS meta_learning ( id TEXT PRIMARY KEY, meta_features_json TEXT NOT NULL, best_model TEXT, best_score TEXT, task_type TEXT, metric_name TEXT, leaderboard_json TEXT, created_at DATETIME )""", """CREATE TABLE IF NOT EXISTS experiment_runs ( id TEXT PRIMARY KEY, job_id TEXT, dataset_id TEXT, model_name TEXT, metric_name TEXT, score TEXT, hyperparams_json TEXT, metrics_json TEXT, leaderboard_json TEXT, feature_count TEXT, row_count TEXT, task_type TEXT, mode TEXT, goal TEXT, created_at DATETIME )""", """CREATE TABLE IF NOT EXISTS drift_checks ( id TEXT PRIMARY KEY, job_id TEXT, dataset_id TEXT, uploaded_name TEXT, status TEXT, drift_score_pct TEXT, report_json TEXT, created_at DATETIME )""", """CREATE TABLE IF NOT EXISTS drift_schedules ( id TEXT PRIMARY KEY, job_id TEXT, enabled TEXT, frequency_days TEXT, warning_threshold TEXT, critical_threshold TEXT, last_alert_status TEXT, last_alert_summary TEXT, created_at DATETIME, updated_at DATETIME )""", """CREATE TABLE IF NOT EXISTS model_registry ( id TEXT PRIMARY KEY, run_id TEXT, label TEXT, note TEXT, created_at DATETIME, updated_at DATETIME )""", """CREATE TABLE IF NOT EXISTS team_notes ( id TEXT PRIMARY KEY, entity_type TEXT, entity_id TEXT, note TEXT, created_at DATETIME )""", ] with engine.connect() as conn: for stmt in statements: try: conn.execute(sql_text(stmt)) conn.commit() except Exception: pass _run_migrations()