Skip to content

Database

src.database

src.database.core

SQLAlchemy database configuration and session management.

This module provides the core database infrastructure: - Explicit engine initialization against the embedded PostgreSQL cluster - Session factory for transaction management - Declarative base for ORM models - Dependency injection helper for FastAPI endpoints

Initialization contract (PostgreSQL migration): The engine URL is only known at runtime, once the embedded cluster (src.launcher.postgres_runtime) is up. Nothing is bound at import time::

    from src.database import core

    engine = core.init_database(handle.sqlalchemy_url)  # lifespan step 1

- ``SessionLocal`` is a module-level factory, UNBOUND until
  ``init_database()`` configures it in place. Importing it by value is
  safe (the factory object is stable).
- ``db_engine`` MUST NOT be imported by value: it is rebound by
  ``init_database()``, so an imported copy stays frozen at ``None``.
  Access it as ``core.db_engine``, or use the engine returned by
  ``init_database()``.
Example

Use in FastAPI endpoint::

from fastapi import Depends
from sqlalchemy.orm import Session
from src.database.core import get_db
from src.entities.Llm import Llm

@router.get("/models")
async def list_models(db: Session = Depends(get_db)):
    models = db.query(Llm).all()
    return {"models": models}
Note
  • Always use get_db() for endpoint dependency injection
  • Manual sessions (SessionLocal()) must be explicitly closed in finally blocks; they require init_database() to have run first
  • Session is NOT thread-safe; create one per request

get_db()

Provide database session for FastAPI dependency injection.

Yields a SQLAlchemy session that is automatically closed after the request completes. Ensures proper cleanup even if exceptions occur.

Yields:

Name Type Description
Session

Active database session bound to the embedded PostgreSQL

cluster (after init_database()).

Source code in backend/src/database/core.py
def get_db():
    """Provide database session for FastAPI dependency injection.

    Yields a SQLAlchemy session that is automatically closed after the
    request completes. Ensures proper cleanup even if exceptions occur.

    Yields:
        Session: Active database session bound to the embedded PostgreSQL
        cluster (after init_database()).
    """
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

init_database(sqlalchemy_url)

Create the SQLAlchemy engine and bind the session factory to it.

Called once the embedded PostgreSQL cluster is up (FastAPI lifespan, step 1) and by the test harness against throwaway clusters.

Parameters:

Name Type Description Default
sqlalchemy_url str

postgresql+psycopg://… URL from postgres_runtime.PostgresHandle.sqlalchemy_url.

required

Returns:

Type Description
Engine

The live engine (also published as core.db_engine).

Source code in backend/src/database/core.py
def init_database(sqlalchemy_url: str) -> Engine:
    """Create the SQLAlchemy engine and bind the session factory to it.

    Called once the embedded PostgreSQL cluster is up (FastAPI lifespan,
    step 1) and by the test harness against throwaway clusters.

    Args:
        sqlalchemy_url: ``postgresql+psycopg://…`` URL from
            ``postgres_runtime.PostgresHandle.sqlalchemy_url``.

    Returns:
        The live engine (also published as ``core.db_engine``).
    """
    global db_engine
    db_engine = create_engine(sqlalchemy_url)
    SessionLocal.configure(bind=db_engine)
    logger.info(f"Database bound: {_sanitize_url_for_log(sqlalchemy_url)}")
    return db_engine

src.database.seed

Database initialization and seeding for application startup.

This module provides a clean, type-safe API for database initialization: - Table creation via SQLAlchemy ORM - Model seeding from HuggingFace Hub - Job cleanup and recovery - Hardware profiling - Startup state initialization

Architecture

┌─────────────────────────────────────────────────────────┐ │ Database_Seeder (Facade) │ │ ├─> create_tables() │ │ ├─> populate_startup_data() │ │ └─> delete_all_data() [DEV ONLY] │ └─────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────┐ │ Specialized Seeders │ │ ├─> Model_Seeder: Base + derived models │ │ ├─> Job_Cleanup_Service: Jobs + orphaned models │ │ ├─> Hardware_Initializer: System profiling │ │ └─> Startup_Initializer: First-run flags │ └─────────────────────────────────────────────────────────┘

Example

Automatic startup (production)::

from src.database.seed import Database_Seeder

seeder = Database_Seeder()
await seeder.create_tables()
await seeder.populate_startup_data()

Manual reset (development only)::

seeder = Database_Seeder()
await seeder.delete_all_data()  # Requires confirmation
Design Principles
  • Single Responsibility: Each class handles one seeding concern
  • Type Safety: Full type hints, Pydantic for validation
  • Error Handling: Custom exceptions with structured logging
  • Testability: Dependency injection for all external services
  • Idempotency: Safe to run multiple times
  • Separation of Concerns: Business logic separated from I/O
Note

This module uses a facade pattern to provide a simple API while maintaining clean separation of concerns internally.

Database_Seeder

Facade for all database seeding operations.

Provides a simple, high-level API for database initialization while maintaining clean separation of concerns internally.

Example

::

seeder = Database_Seeder()
await seeder.create_tables()
await seeder.populate_startup_data()

backfill_local_model_sizes(db)

One-shot: correct already-downloaded models' displayed size from disk (#220).

Legacy local rows carry a catalog-time size guess (whole-repo sum or an FP16-ish estimate) that was NEVER measured. For every local (local==1) model whose weights still exist, measure the real on-disk footprint and rewrite metadata.size / disk_size_gb only when it diverges from the stored value. A handful of local dirs -> a cheap filesystem walk, so boot is not slowed measurably. Defensive: missing dirs are skipped silently (orphans are legitimate since #225/#208) and any per-row error is swallowed so the backfill never blocks boot.

Returns:

Type Description
int

Number of rows whose metadata was corrected.

Source code in backend/src/database/seed.py
def backfill_local_model_sizes(self, db: Session) -> int:
    """One-shot: correct already-downloaded models' displayed size from disk (#220).

    Legacy local rows carry a catalog-time size guess (whole-repo sum or an
    FP16-ish estimate) that was NEVER measured. For every local (local==1)
    model whose weights still exist, measure the real on-disk footprint and
    rewrite ``metadata.size`` / ``disk_size_gb`` only when it diverges from the
    stored value. A handful of local dirs -> a cheap filesystem walk, so boot
    is not slowed measurably. Defensive: missing dirs are skipped silently
    (orphans are legitimate since #225/#208) and any per-row error is
    swallowed so the backfill never blocks boot.

    Returns:
        Number of rows whose metadata was corrected.
    """
    corrected = 0
    measured_cache: Dict[str, float] = {}
    try:
        local_models = db.query(Llm).filter(Llm.local == 1).all()
    except Exception as e:
        logger.warning(f"Model-size backfill skipped (query failed): {e}")
        return 0

    for llm in local_models:
        try:
            link = llm.link
            if not link or not Path(link).is_dir():
                continue
            measured = measured_cache.get(link)
            if measured is None:
                measured = measure_dir_size_gb(link)
                measured_cache[link] = measured
            if measured <= 0:
                continue
            new_meta = rewrite_size_in_metadata(llm.model_metadata, measured)
            if new_meta != llm.model_metadata:
                llm.model_metadata = new_meta
                corrected += 1
        except Exception as e:
            logger.warning(
                f"Model-size backfill skipped for LLM {getattr(llm, 'id', '?')}: {e}"
            )
            continue

    if corrected:
        db.commit()
    logger.info(f"Model-size backfill: {corrected} local model(s) corrected from disk")
    return corrected

backfill_wire_tools(db)

One-shot per model: verify the tool-call wire capability (#298).

Models downloaded before the supports_tools_wire column existed carry NULL (unverified) and therefore route every KB turn systematic. For every local (local==1) row still NULL whose artifact exists, compute the verdict via the active engine (tokenizer-level, no model load) and persist it. A None verdict (engine unavailable, unreadable artifact) leaves the row NULL so a transient failure is retried on the next boot instead of being pinned to False. Shared links (a KB assistant and its base) are computed once. Defensive like backfill_local_model_sizes: any per-row error is swallowed so the backfill never takes the app down.

Returns:

Type Description
int

Number of rows whose wire capability was persisted.

Source code in backend/src/database/seed.py
def backfill_wire_tools(self, db: Session) -> int:
    """One-shot per model: verify the tool-call wire capability (#298).

    Models downloaded before the ``supports_tools_wire`` column existed
    carry NULL (unverified) and therefore route every KB turn systematic.
    For every local (local==1) row still NULL whose artifact exists,
    compute the verdict via the active engine (tokenizer-level, no model
    load) and persist it. A None verdict (engine unavailable, unreadable
    artifact) leaves the row NULL so a transient failure is retried on the
    next boot instead of being pinned to False. Shared links (a KB
    assistant and its base) are computed once. Defensive like
    ``backfill_local_model_sizes``: any per-row error is swallowed so the
    backfill never takes the app down.

    Returns:
        Number of rows whose wire capability was persisted.
    """
    from src.domains.llms.repository import detect_wire_tools

    updated = 0
    verdict_cache: Dict[str, Optional[bool]] = {}
    try:
        pending = db.query(Llm).filter(Llm.local == 1, Llm.supports_tools_wire.is_(None)).all()
    except Exception as e:
        logger.warning(f"Wire-capability backfill skipped (query failed): {e}")
        return 0

    for llm in pending:
        try:
            link = llm.link
            if not link or not Path(link).exists():
                continue
            if link in verdict_cache:
                verdict = verdict_cache[link]
            else:
                verdict = detect_wire_tools(link)
                verdict_cache[link] = verdict
            if verdict is None:
                continue
            llm.supports_tools_wire = verdict
            updated += 1
        except Exception as e:
            logger.warning(
                f"Wire-capability backfill skipped for LLM {getattr(llm, 'id', '?')}: {e}"
            )
            continue

    if updated:
        db.commit()
    logger.info(f"Wire-capability backfill: {updated} local model(s) verified")
    return updated

build_fresh_catalog(model_seeder)

Fetch + build the fresh remote catalog (base + derived, deduped) from HF for the active engine format. NO DB writes — returns detached Llm objects.

Shared by the runtime resync (atomic swap) and the build-time snapshot generator (src/database/catalog_snapshot.py), so both produce an identical catalog from the same discovery + resolver + dedup path.

Source code in backend/src/database/seed.py
def build_fresh_catalog(self, model_seeder: "Model_Seeder") -> Tuple[List[Llm], List[Llm]]:
    """Fetch + build the fresh remote catalog (base + derived, deduped) from HF
    for the active engine format. NO DB writes — returns detached Llm objects.

    Shared by the runtime resync (atomic swap) and the build-time snapshot
    generator (src/database/catalog_snapshot.py), so both produce an identical
    catalog from the same discovery + resolver + dedup path.
    """
    fresh_base = model_seeder.build_base_models(self.FOUNDATION_ORGS)
    # Derived: one engine-format search per foundation family + a global
    # top-downloads pass (empty term), so popular community fine-tunes surface
    # whether or not they carry a family name. All runnable by construction.
    searches = [Search_Config(term, ftype, 7.0) for _org, ftype, term in self.FOUNDATION_ORGS]
    searches.append(Search_Config("", "community", 7.0))
    fresh_derived = model_seeder.build_derived_models(
        searches, top_per_search=30, max_checked=200
    )
    # Drop derived rows that are just another quant of a base model (same
    # normalized slug), so each base appears once (as the curated ⭐ entry).
    base_keys = {base_key(m.link) for m in fresh_base}
    fresh_derived = [d for d in fresh_derived if base_key(d.link) not in base_keys]
    return fresh_base, fresh_derived

create_tables() async

Create all database tables from SQLAlchemy models.

Idempotent operation - safe to call multiple times. Requires init_database() to have run first. Anti-B1: reads the LIVE engine via attribute access — an imported-by-value db_engine would stay frozen at None forever.

Source code in backend/src/database/seed.py
async def create_tables(self) -> None:
    """Create all database tables from SQLAlchemy models.

    Idempotent operation - safe to call multiple times. Requires
    init_database() to have run first. Anti-B1: reads the LIVE engine via
    attribute access — an imported-by-value `db_engine` would stay frozen
    at None forever.
    """
    if core.db_engine is None:
        raise RuntimeError(
            "Database not initialized: call init_database() before create_tables()"
        )
    try:
        # Create MISSING tables from the models. Schema EVOLUTION of an
        # existing (persisted) database is handled by Alembic at startup
        # (src.database.migrations.run_migrations), not here — this primitive
        # is the from-scratch creation used by tests and first boot.
        Base.metadata.create_all(bind=core.db_engine)
        logger.info("Database tables created successfully")
    except Exception as e:
        logger.error(f"Failed to create tables: {e}", exc_info=True)
        raise

delete_all_data() async

Delete all data from database and file storage.

DESTRUCTIVE OPERATION - DEVELOPMENT ONLY

Requires interactive confirmation before proceeding.

Warning

Never expose this in production. No undo available.

Source code in backend/src/database/seed.py
async def delete_all_data(self) -> None:
    """Delete all data from database and file storage.

    **DESTRUCTIVE OPERATION - DEVELOPMENT ONLY**

    Requires interactive confirmation before proceeding.

    Warning:
        Never expose this in production. No undo available.
    """
    logger.warning("Preparing to delete all data from the database")
    response = input("Are you sure you want to delete ALL data? (yes/no): ")

    if response.lower() not in ("yes", "y"):
        logger.info("Database deletion cancelled")
        return

    db = SessionLocal()
    try:
        logger.warning("Deleting all data...")

        # Delete file storage
        self._delete_storage_directories()

        # Delete database records
        db.query(StartupVariables).delete()
        db.query(KBJobModel).delete()
        db.query(KnowledgeDocument).delete()
        db.query(KnowledgeBase).delete()
        db.query(HardwareProfile).delete()
        db.query(DownloadJobModel).delete()
        db.query(Message).delete()
        db.query(Conversation).delete()
        db.query(Llm).delete()

        db.commit()
        logger.warning("All data deleted successfully")

    except Exception as e:
        logger.error(f"Error deleting data: {e}", exc_info=True)
        db.rollback()
        raise
    finally:
        db.close()

populate_startup_data(db=None) async

Populate database with startup data.

Parameters:

Name Type Description Default
db Optional[Session]

Optional database session. If None, creates new session.

None

Returns:

Type Description
Dict[str, Any]

Dictionary with operation results and counts.

Raises:

Type Description
Exception

If any critical seeding step fails.

Source code in backend/src/database/seed.py
async def populate_startup_data(self, db: Optional[Session] = None) -> Dict[str, Any]:
    """Populate database with startup data.

    Args:
        db: Optional database session. If None, creates new session.

    Returns:
        Dictionary with operation results and counts.

    Raises:
        Exception: If any critical seeding step fails.
    """
    should_close = db is None
    if db is None:
        db = SessionLocal()

    try:
        results = {
            "base_models_added": 0,
            "derived_models_added": 0,
            "jobs_cleaned": {},
            "hardware_initialized": False,
            "startup_vars_initialized": False,
            "offline_mode": False,
            "models_seeded": False,
        }

        # Initialize startup variables first
        logger.info("Initializing startup variables...")
        startup_init = Startup_Initializer(db)
        results["startup_vars_initialized"] = startup_init.initialize_if_needed()

        # Get or create startup variables singleton
        startup_vars = db.query(StartupVariables).first()
        if not startup_vars:
            startup_vars = StartupVariables()
            db.add(startup_vars)
            db.commit()
            db.refresh(startup_vars)

        # Reconcile the catalog with the bundled snapshot at EVERY boot
        # (#131, #163): zero network, so downloads are never starved by a
        # live HF resync and the catalog never mutates mid-session — it
        # follows app releases instead.
        reconcile = self.reconcile_catalog_from_snapshot(db)
        if reconcile.get("resynced"):
            results["base_models_added"] = reconcile.get("base_models_added", 0)
            results["derived_models_added"] = reconcile.get("derived_models_added", 0)
            results["models_seeded"] = True
        elif db.query(Llm).filter(Llm.local == 0).count() == 0:
            # No snapshot bundled (e.g. bare dev tree) and the catalog is
            # still empty → minimal offline fallback so the app has models.
            results["base_models_added"] = Model_Seeder(
                db, offline_mode=True
            ).seed_initial_catalog()
        results["offline_mode"] = False

        # Cleanup jobs (always run)
        logger.info("Cleaning up unfinished jobs...")
        job_cleanup = Job_Cleanup_Service(db)
        results["jobs_cleaned"] = job_cleanup.cleanup_all_unfinished_jobs()

        # Correct already-downloaded models' displayed size from disk (#220):
        # the catalog value was a guess, never measured. Runs after orphan
        # cleanup so a to-be-removed dir is never measured; cheap and defensive.
        self.backfill_local_model_sizes(db)

        # Initialize hardware
        logger.info("Initializing hardware info...")
        hw_init = Hardware_Initializer(db)
        results["hardware_initialized"] = hw_init.initialize_if_needed()

        logger.info(
            f"Startup population completed: "
            f"base={results['base_models_added']}, "
            f"derived={results['derived_models_added']}, "
            f"jobs_cleaned={sum(results['jobs_cleaned'].values())}, "
            f"offline_mode={results['offline_mode']}, "
            f"models_seeded={results['models_seeded']}"
        )

        return results

    except Exception as e:
        logger.error(f"Error during startup population: {e}", exc_info=True)
        db.rollback()
        raise
    finally:
        if should_close:
            db.close()

reconcile_catalog_from_snapshot(db)

Reconcile the remote catalog (local=0) with the BUNDLED snapshot (#131, #163).

Runs at every boot: the catalog follows app releases (the snapshot ships with the build) instead of a live HF resync, so it is fully offline — zero network calls, no HF client — and never mutates mid-session. Loads the snapshot through the same mechanism as first-boot seeding (load_catalog_snapshot + dict_to_llm), keeps the existing catalog untouched when no snapshot (or a base-model-less one) is available, and stamps StartupVariables (models_seeded / last_seeded_at / offline_mode) on success.

Source code in backend/src/database/seed.py
def reconcile_catalog_from_snapshot(self, db: Session) -> Dict[str, Any]:
    """Reconcile the remote catalog (local=0) with the BUNDLED snapshot (#131, #163).

    Runs at every boot: the catalog follows app releases (the snapshot ships
    with the build) instead of a live HF resync, so it is fully offline —
    zero network calls, no HF client — and never mutates mid-session. Loads
    the snapshot through the same mechanism as first-boot seeding
    (``load_catalog_snapshot`` + ``dict_to_llm``), keeps the existing catalog
    untouched when no snapshot (or a base-model-less one) is available, and
    stamps ``StartupVariables`` (models_seeded / last_seeded_at / offline_mode)
    on success.
    """
    from src.database.catalog_snapshot import load_catalog_snapshot, dict_to_llm

    tag = getattr(config.LLM_Engine, "FORMAT_TAG", None)
    entries = load_catalog_snapshot(tag) if tag else []
    if not entries:
        logger.info("No bundled catalog snapshot - keeping the existing catalog")
        return {"resynced": False}
    fresh = [dict_to_llm(e) for e in entries]
    fresh_base = [m for m in fresh if m.is_base]
    fresh_derived = [m for m in fresh if not m.is_base]
    if not fresh_base:
        logger.warning("Snapshot carries no base models - keeping the existing catalog")
        return {"resynced": False}
    res = self.reconcile_remote_catalog(db, fresh_base, fresh_derived)
    if res.get("resynced"):
        startup_vars = db.query(StartupVariables).first()
        if startup_vars:
            startup_vars.models_seeded = True
            startup_vars.last_seeded_at = datetime.now()
            # The full snapshot is NOT the degraded JSON fallback: clear the
            # offline flag a fallback-only first boot may have left behind.
            startup_vars.offline_mode = False
            db.commit()
    return res

reconcile_remote_catalog(db, fresh_base, fresh_derived)

Reconcile the remote catalog (local=0) with a fresh model set IN PLACE (#123).

Matches existing rows by link (the HF repo id): existing models are updated in place, genuinely new ones inserted, and models that vanished from the fresh set deleted. Rows are no longer dropped-and-reinserted, so catalog IDs stay stable across restarts (the frontend's fetched IDs never go stale). Downloaded (local=1) and in-progress (local=2) models are NEVER touched. The fresh set is fully loaded BEFORE any write, so a missing/broken source leaves the existing catalog intact.

Source code in backend/src/database/seed.py
def reconcile_remote_catalog(
    self, db: Session, fresh_base: List[Llm], fresh_derived: List[Llm]
) -> Dict[str, Any]:
    """Reconcile the remote catalog (local=0) with a fresh model set IN PLACE (#123).

    Matches existing rows by ``link`` (the HF repo id): existing models are
    updated in place, genuinely new ones inserted, and models that vanished from
    the fresh set deleted. Rows are no longer dropped-and-reinserted, so catalog
    IDs stay stable across restarts (the frontend's fetched IDs never go stale).
    Downloaded (local=1) and in-progress (local=2) models are NEVER touched. The
    fresh set is fully loaded BEFORE any write, so a missing/broken source leaves
    the existing catalog intact.
    """
    existing = {row.link: row for row in db.query(Llm).filter(Llm.local == 0).all()}
    added = updated = 0
    seen_links: set = set()
    for fresh in fresh_base + fresh_derived:
        if fresh.link in seen_links:  # guard against dup links in the fresh set
            continue
        seen_links.add(fresh.link)
        current = existing.get(fresh.link)
        if current is None:
            # category is NOT NULL: an unclassified fresh row (pre-#122
            # snapshot / bare fixture) lands on the default bucket — the
            # None -> "general" coalesce applies ONLY at insert (#192).
            if fresh.category is None:
                fresh.category = "general"
            db.add(fresh)  # genuinely new → insert (new id)
            added += 1
        else:
            for field in self._RESYNC_FIELDS:  # refresh in place → id preserved
                value = getattr(fresh, field)
                # An unclassified fresh row (category=None: pre-#122 snapshot
                # or bare test fixture) must NEVER clobber a classified one —
                # KEEP the existing category (#192, regression of #184: stale
                # snapshots collapsed the whole catalog to "general" at every
                # boot). Fresh rows carrying a REAL category still propagate.
                if field in self._PRESERVE_ON_NONE and value is None:
                    continue
                setattr(current, field, value)
            updated += 1

    removed = 0
    for link, row in existing.items():
        if link not in seen_links:  # gone from HF → drop the suggestion
            db.delete(row)
            removed += 1
    db.commit()
    logger.info(
        f"Remote catalog reconciled in place: {added} added, {updated} updated, "
        f"{removed} removed ({len(fresh_base)} base + {len(fresh_derived)} derived; "
        f"downloaded/in-progress untouched)"
    )
    return {
        "base_models_added": added,
        "derived_models_added": updated,
        "base_models_removed": removed,
        "resynced": True,
    }

Hardware_Initializer(db)

Handles system hardware profiling and persistence.

Initialize hardware initializer.

Parameters:

Name Type Description Default
db Session

Active database session.

required
Source code in backend/src/database/seed.py
def __init__(self, db: Session):
    """Initialize hardware initializer.

    Args:
        db: Active database session.
    """
    self.db = db
    self.service = Hardware_Service(Hardware_Repository(db))

initialize_if_needed()

Initialize hardware info if not already present.

Uses service layer to get or create hardware profile.

Returns:

Type Description
bool

True if initialization was performed, False if already existed.

Source code in backend/src/database/seed.py
def initialize_if_needed(self) -> bool:
    """Initialize hardware info if not already present.

    Uses service layer to get or create hardware profile.

    Returns:
        True if initialization was performed, False if already existed.
    """
    try:
        # Deliberately no "a row exists, skip" short-circuit here. That is
        # what stranded every existing install on the numbers its FIRST boot
        # produced: #365 fixed a 448 GB/s card being profiled at 13 GB/s, and
        # the corrected build still served the stored 13 because this method
        # returned before the service could look at it. The only way out was
        # Clear All Data, which also destroys models and conversations.
        #
        # get_or_create_profile owns validity (backend match AND profiling
        # version) and returns the cached row untouched when it is still
        # good, so the common boot stays as cheap as it was.
        previous = self.db.query(HardwareProfile).first()
        previous_id = previous.id if previous else None

        profile = self.service.get_or_create_profile()
        self.db.commit()

        if previous_id is None:
            logger.info(f"Hardware info initialized: backend={profile.backend_type}")
            return True
        if profile.id != previous_id:
            logger.info(f"Hardware info re-profiled: backend={profile.backend_type}")
            return True

        logger.debug("Hardware info already initialized, skipping")
        return False

    except Exception as e:
        logger.exception(f"Hardware initialization failed: {e}")
        self.db.rollback()
        # Create fallback profile on error
        self._create_fallback_profile()
        return True

Job_Cleanup_Service(db)

Handles cleanup of interrupted jobs and orphaned resources.

Responsibilities: - Mark interrupted jobs (download, KB) as failed - Remove incomplete model files and temp directories - Cleanup orphaned model directories without database entries

Initialize job cleanup service.

Parameters:

Name Type Description Default
db Session

Active database session.

required
Source code in backend/src/database/seed.py
def __init__(self, db: Session):
    """Initialize job cleanup service.

    Args:
        db: Active database session.
    """
    self.db = db

cleanup_all_unfinished_jobs()

Mark all interrupted jobs as failed and cleanup resources.

Returns:

Type Description
Dict[str, int]

Dictionary with counts: {"download": N, "kb": N, "orphaned": N}

Source code in backend/src/database/seed.py
def cleanup_all_unfinished_jobs(self) -> Dict[str, int]:
    """Mark all interrupted jobs as failed and cleanup resources.

    Returns:
        Dictionary with counts: {"download": N, "kb": N, "orphaned": N}
    """
    counts = {
        "download": self._cleanup_download_jobs(),
        "kb": self._cleanup_kb_jobs(),
        "orphaned": self._cleanup_orphaned_models(),
    }

    total = sum(counts.values())
    if total > 0:
        logger.info(
            f"Cleaned up {total} unfinished jobs: "
            f"download={counts['download']}, "
            f"kb={counts['kb']}, "
            f"orphaned={counts['orphaned']}"
        )

    return counts

Model_Config(name, link, model_type, safetensors_total=None, category='general') dataclass

Configuration for a base model to seed.

The optional fields carry the signals captured at discovery time (one list_models(expand=[...]) call) so classification doesn't need extra HF round-trips: safetensors_total → real param size, category → capability bucket (#122).

__post_init__()

Validate model configuration.

Source code in backend/src/database/seed.py
def __post_init__(self) -> None:
    """Validate model configuration."""
    if not self.name or not self.link or not self.model_type:
        raise ValueError(f"Invalid model config: {self}")

Model_Seeder(db, hf_api=None, quality_filters=None, offline_mode=False)

Handles seeding of base and derived models from HuggingFace.

Supports both online and offline modes: - Online: Fetches fresh metadata from HuggingFace API - Offline: Uses embedded JSON fallback with minimal metadata

Initialize model seeder.

Parameters:

Name Type Description Default
db Session

Active database session.

required
hf_api

HuggingFace API client (None if offline).

None
quality_filters Optional[Quality_Filters]

Quality filtering configuration.

None
offline_mode bool

If True, skip API calls and use fallback data.

False
Source code in backend/src/database/seed.py
def __init__(
    self,
    db: Session,
    hf_api=None,
    quality_filters: Optional[Quality_Filters] = None,
    offline_mode: bool = False,
):
    """Initialize model seeder.

    Args:
        db: Active database session.
        hf_api: HuggingFace API client (None if offline).
        quality_filters: Quality filtering configuration.
        offline_mode: If True, skip API calls and use fallback data.
    """
    self.db = db
    self.hf_api = hf_api
    self.filters = quality_filters or Quality_Filters()
    self.offline_mode = offline_mode

build_base_models(orgs)

Discover each foundation org's chat models and build (don't persist) the base catalog rows, each resolved to its engine-format quant.

Per candidate: discover → prefer-instruct → resolve_quant → build. A base with no quant for the active engine is skipped. Resolved quants are deduped (same repo never seeded twice — #122). HF metadata failure falls back to default metadata so one bad model never drops the rest. orgs is the FOUNDATION_ORGS list of (org, family_type, search_term).

Source code in backend/src/database/seed.py
def build_base_models(self, orgs) -> List[Llm]:
    """Discover each foundation org's chat models and build (don't persist) the
    base catalog rows, each resolved to its engine-format quant.

    Per candidate: discover → prefer-instruct → resolve_quant → build. A base
    with no quant for the active engine is skipped. Resolved quants are deduped
    (same repo never seeded twice — #122). HF metadata failure falls back to
    default metadata so one bad model never drops the rest. `orgs` is the
    FOUNDATION_ORGS list of (org, family_type, search_term).
    """
    out: List[Llm] = []
    seen_quant: set = set()
    tag = self._format_tag()
    for org, model_type, _term in orgs:
        candidates = self._prefer_instruct_siblings(
            self.discover_instruct_models(org, model_type)
        )
        for model_config in candidates:
            try:
                quant_link = resolve_quant(model_config.link, tag, self.hf_api)
            except Exception as e:
                logger.warning(f"resolve_quant failed for {model_config.link}: {e}")
                quant_link = None
            if not quant_link or quant_link in seen_quant:
                continue
            try:
                out.append(self._create_base_llm(model_config, quant_link))
                seen_quant.add(quant_link)
            except HuggingFaceAPIException as e:
                logger.warning(f"HF metadata failed for {model_config.link}, fallback: {e}")
                try:
                    out.append(self._create_base_llm_fallback(model_config, quant_link))
                    seen_quant.add(quant_link)
                except Exception as fe:
                    # The model is skipped; the catalog goes on without it.
                    logger.warning(
                        f"Fallback build failed for {model_config.link}, skipping it: {fe}",
                        exc_info=True,
                    )
            except Exception as e:
                logger.warning(
                    f"Failed to build base model {model_config.link}, skipping it: {e}",
                    exc_info=True,
                )
    return out

build_derived_models(searches, top_per_search=30, max_checked=200)

Build (do NOT persist) derived/community catalog rows from HF search.

Best-effort: a failing search is logged and skipped, never aborts the rest. Returns detached Llm objects for an atomic swap (no add/commit here).

Source code in backend/src/database/seed.py
def build_derived_models(
    self,
    searches: List[Search_Config],
    top_per_search: int = 30,
    max_checked: int = 200,
) -> List[Llm]:
    """Build (do NOT persist) derived/community catalog rows from HF search.

    Best-effort: a failing search is logged and skipped, never aborts the rest.
    Returns detached Llm objects for an atomic swap (no add/commit here).
    """
    out: List[Llm] = []
    seen: set = set()
    for search_config in searches:
        try:
            # Bounded limit: get_hf_api() returns a retrying client that
            # materializes list_models (to retry 429s that surface during lazy
            # pagination), so an unbounded search must not be requested here.
            results = self.hf_api.list_models(
                **config.LLM_Engine.community_search_kwargs(search_config.search_term),
                sort="downloads",
                limit=max_checked,
            )
        except Exception as e:
            logger.warning(f"HF search '{search_config.search_term}' failed, skipping: {e}")
            continue
        added = checked = 0
        for model_info in results:
            if added >= top_per_search or checked >= max_checked:
                break
            checked += 1
            if not self._passes_quality_filters(model_info):
                continue
            # #242: this path is filtered only by format tag, so ASR/embedding/
            # OCR/media-gen community repos would otherwise enter the catalog.
            # Reject them by name family + non-chat pipeline (needs the
            # pipeline_tag/tags expand added to community_search_kwargs).
            slug = model_info.id.split("/")[-1]
            if is_nonchat_task(slug, getattr(model_info, "pipeline_tag", None)):
                continue
            # The app downloads with no HF token: a gated repo lists fine but
            # 401s on download, so it never enters the catalog. Checked BEFORE
            # the dedup so a public twin of the same model still gets in.
            if is_gated(model_info):
                continue
            # Dedup by normalized key so the same finetune from two quanters
            # (bartowski/Foo-GGUF vs mradermacher/Foo-GGUF) appears once.
            mkey = base_key(model_info.id)
            if mkey in seen:
                continue
            # Runnable by construction (came from filter=FORMAT_TAG); only drop
            # the rare KNOWN_BROKEN load-crashers.
            if not config.LLM_Engine.is_runnable(model_info.id):
                continue
            # The gguf tag says nothing about the files: a repo whose weights are
            # raw byte chunks (or a split missing a part) would be refused at
            # download, so it never becomes a row. Checked BEFORE the dedup, like
            # the gated gate, so a loadable twin of the same model still gets in.
            if getattr(config.LLM_Engine, "USES_GGUF", False):
                try:
                    downloadable = has_downloadable_gguf(model_info.id, self.hf_api)
                except Exception as e:
                    # An unverified repo is never offered; this build goes on
                    # without it and the next resync lists it again.
                    logger.warning(
                        f"Could not list the files of derived {model_info.id}, skipping it: {e}"
                    )
                    continue
                if not downloadable:
                    logger.info(
                        f"Skipping derived {model_info.id}: no loadable GGUF artefact "
                        f"(e.g. weights published as raw byte chunks)"
                    )
                    continue
            try:
                out.append(self._create_derived_llm(model_info, search_config))
                seen.add(mkey)
                added += 1
            except Exception as e:
                logger.warning(f"Failed to build derived {model_info.id}: {e}")
    return out

discover_instruct_models(org, model_type, top_n=14, vision_top_n=8, min_downloads=2000, fresh_top_n=FRESH_TOP_N, fresh_min_downloads=FRESH_MIN_DOWNLOADS)

Discover an org's chat-capable models (text + multimodal) as base candidates.

Text and vision get SEPARATE quotas (top_n / vision_top_n) so a busy text family never starves the multimodal pass — the real VLMs must reach Base (#122). For each relevant pipeline_tag (drops the org's CLIP / Whisper / BERT, and keeps VLMs out of the text bucket) it runs TWO ranked passes with expand so safetensors/tags/pipeline come back in ONE call each:

  • the classic top-repos-by-downloads pass (quota top_n/vision_top_n);
  • a FRESHNESS pass sorted by creation date, newest first (#305): cumulative downloads structurally hide recent releases, so the newest repos get their own small quota (fresh_top_n) behind a higher downloads floor (fresh_min_downloads). Fresh candidates ADD to the downloads-ranked set — they never displace it.

Both passes share the same rejection rules — quant/merge/adapter derivatives (base_model relation tags), intermediate artifacts, raw pretrains — and dedup by normalized slug. Anything without an engine-format quant self-corrects later (the resolver returns None).

Source code in backend/src/database/seed.py
def discover_instruct_models(
    self,
    org: str,
    model_type: str,
    top_n: int = 14,
    vision_top_n: int = 8,
    min_downloads: int = 2000,
    fresh_top_n: int = FRESH_TOP_N,
    fresh_min_downloads: int = FRESH_MIN_DOWNLOADS,
) -> List[Model_Config]:
    """Discover an org's chat-capable models (text + multimodal) as base candidates.

    Text and vision get SEPARATE quotas (``top_n`` / ``vision_top_n``) so a busy
    text family never starves the multimodal pass — the real VLMs must reach Base
    (#122). For each relevant ``pipeline_tag`` (drops the org's CLIP / Whisper /
    BERT, and keeps VLMs out of the text bucket) it runs TWO ranked passes with
    ``expand`` so safetensors/tags/pipeline come back in ONE call each:

    - the classic top-repos-by-downloads pass (quota ``top_n``/``vision_top_n``);
    - a FRESHNESS pass sorted by creation date, newest first (#305): cumulative
      downloads structurally hide recent releases, so the newest repos get their
      own small quota (``fresh_top_n``) behind a higher downloads floor
      (``fresh_min_downloads``). Fresh candidates ADD to the downloads-ranked
      set — they never displace it.

    Both passes share the same rejection rules — quant/merge/adapter derivatives
    (``base_model`` relation tags), intermediate artifacts, raw pretrains — and
    dedup by normalized slug. Anything without an engine-format quant
    self-corrects later (the resolver returns None).
    """
    out: List[Model_Config] = []
    seen: set = set()

    def fetch(pipeline: str, sort: str) -> list:
        try:
            return list(
                self.hf_api.list_models(
                    author=org,
                    pipeline_tag=pipeline,
                    sort=sort,
                    limit=80,
                    expand=[
                        "safetensors",
                        "cardData",
                        "tags",
                        "pipeline_tag",
                        "gated",
                        "downloads",
                    ],
                )
            )
        except Exception as e:
            logger.warning(f"Org discovery failed for {org}/{pipeline} (sort={sort}): {e}")
            return []

    def accept(m, floor: int) -> Optional[Model_Config]:
        """One candidate through every rejection rule; None means rejected.
        Shared by both passes so the freshness door can't bypass a filter."""
        if (getattr(m, "downloads", 0) or 0) < floor:
            return None
        name = m.id.split("/")[-1]
        pipeline_tag = getattr(m, "pipeline_tag", None)
        tags = list(getattr(m, "tags", None) or [])
        if set(re.split(r"[-_.]", name.lower())) & self.ARTIFACT_TOKENS:
            return None
        if is_nonchat_task(name, pipeline_tag):
            return None
        if is_derivative(tags):
            return None
        # #182: the Base catalog is chat-only. Keep only conversational
        # (instruct/chat) releases; raw pretrains (Llama-3.2-1B,
        # Mistral-7B-v0.1) are dropped and reachable only via HF search.
        if not is_conversational(tags, name):
            return None
        key = base_key(m.id)
        if key in seen:
            return None
        seen.add(key)
        return Model_Config(
            name,
            m.id,
            model_type,
            safetensors_total=_safetensors_total(m),
            category=categorize(name, tags, pipeline_tag),
        )

    for pipelines, cap in ((self.TEXT_PIPELINES, top_n), (self.VISION_PIPELINES, vision_top_n)):
        added = 0
        fresh_added = 0
        for pipeline in pipelines:
            if added < cap:
                for m in fetch(pipeline, "downloads"):
                    if added >= cap:
                        break
                    if (mc := accept(m, min_downloads)) is not None:
                        out.append(mc)
                        added += 1
            # Freshness pass (#305): newest repos first (`created_at` on the
            # installed huggingface_hub maps to the raw API's `createdAt`,
            # descending). Own quota, higher floor, same filters and dedup.
            if fresh_added < fresh_top_n:
                for m in fetch(pipeline, "created_at"):
                    if fresh_added >= fresh_top_n:
                        break
                    if (mc := accept(m, fresh_min_downloads)) is not None:
                        out.append(mc)
                        fresh_added += 1
    return out

seed_base_models_offline()

Seed base models from embedded JSON fallback (offline mode).

Used when internet is unavailable or HuggingFace API fails. Loads models from static JSON file with minimal but sufficient metadata.

Returns:

Type Description
int

Number of models successfully added from fallback.

Raises:

Type Description
FileSystemException

If fallback JSON is missing or corrupted.

DatabaseException

If database operations fail.

Note

This method ONLY seeds base models. Derived models are skipped in offline mode as they require fresh HuggingFace searches.

Example

seeder = Model_Seeder(db, offline_mode=True) count = seeder.seed_base_models_offline() print(f"Seeded {count} base models in offline mode")

Source code in backend/src/database/seed.py
def seed_base_models_offline(self) -> int:
    """Seed base models from embedded JSON fallback (offline mode).

    Used when internet is unavailable or HuggingFace API fails. Loads
    models from static JSON file with minimal but sufficient metadata.

    Returns:
        Number of models successfully added from fallback.

    Raises:
        FileSystemException: If fallback JSON is missing or corrupted.
        DatabaseException: If database operations fail.

    Note:
        This method ONLY seeds base models. Derived models are skipped
        in offline mode as they require fresh HuggingFace searches.

    Example:
        >>> seeder = Model_Seeder(db, offline_mode=True)
        >>> count = seeder.seed_base_models_offline()
        >>> print(f"Seeded {count} base models in offline mode")
    """
    logger.warning("Seeding in OFFLINE mode using fallback data")

    fallback_models = load_base_models_fallback()
    added_count = 0

    for model_data in fallback_models:
        # Offline: there is no HF to resolve a quant, so seed the bundled link
        # as-is (the offline JSON should already carry resolved quant links).
        actual_link = model_data["link"]
        if self._link_exists(actual_link):
            logger.debug(f"Skipping existing model: {actual_link}")
            continue

        try:
            # Create model config from JSON data
            model_config = Model_Config(
                name=model_data["name"], link=model_data["link"], model_type=model_data["type"]
            )

            # Create LLM entity with fallback metadata
            llm = self._create_base_llm_from_json(model_data)
            self.db.add(llm)
            self.db.flush()
            added_count += 1
            logger.info(f"Added base model (offline): {model_data['name']}")

        except Exception as e:
            logger.warning(
                f"Failed to add offline model {model_data['name']}, skipping it: {e}",
                exc_info=True,
            )
            continue

    self.db.commit()
    logger.info(f"Offline seeding complete: {added_count} base models added")
    return added_count

seed_from_snapshot()

Seed the remote catalog (local=0) from the bundled build-time snapshot for the active engine format (#112). Instant, zero HF calls — this is the first-boot catalog. Returns the number of rows added (0 if no snapshot).

Source code in backend/src/database/seed.py
def seed_from_snapshot(self) -> int:
    """Seed the remote catalog (local=0) from the bundled build-time snapshot
    for the active engine format (#112). Instant, zero HF calls — this is the
    first-boot catalog. Returns the number of rows added (0 if no snapshot)."""
    from src.database.catalog_snapshot import load_catalog_snapshot, dict_to_llm

    tag = self._format_tag()
    if not tag:
        return 0
    entries = load_catalog_snapshot(tag)
    if not entries:
        return 0
    self.db.add_all([dict_to_llm(e) for e in entries])
    self.db.commit()
    logger.info(f"Seeded {len(entries)} catalog entries from the {tag} snapshot")
    return len(entries)

seed_initial_catalog()

First-boot catalog: the bundled build-time snapshot if present (instant, full, zero HF calls — #112), else the minimal offline fallback JSON. Best-effort: returns 0 rather than raising if neither is available, so boot never crashes on a missing artifact.

Source code in backend/src/database/seed.py
def seed_initial_catalog(self) -> int:
    """First-boot catalog: the bundled build-time snapshot if present (instant,
    full, zero HF calls — #112), else the minimal offline fallback JSON.
    Best-effort: returns 0 rather than raising if neither is available, so boot
    never crashes on a missing artifact."""
    try:
        count = self.seed_from_snapshot()
        if count:
            return count
    except Exception as e:
        logger.warning(f"Snapshot seed skipped: {e}")
    try:
        return self.seed_base_models_offline()
    except Exception as e:
        logger.warning(f"Offline fallback seed skipped (catalog stays empty): {e}")
        return 0

Quality_Filters(min_downloads=50, min_likes=5) dataclass

Popularity floor for derived/community models. Deliberately just a downloads/likes threshold — NO content or keyword filtering: the catalog is open to all community models (distilled, RL, uncensored…), and the format tag already guarantees runnability. The floor keeps it from being all of HF, and doubles as a safeguard against a mistagged repo.

Search_Config(search_term, model_type, default_param_size) dataclass

Configuration for derived model search.

__post_init__()

Validate search configuration.

An empty search_term is allowed and means the global pass: search the whole format-tagged space by downloads (no text filter).

Source code in backend/src/database/seed.py
def __post_init__(self) -> None:
    """Validate search configuration.

    An empty ``search_term`` is allowed and means the *global pass*: search the
    whole format-tagged space by downloads (no text filter)."""
    if not self.model_type:
        raise ValueError(f"Invalid search config: {self}")
    if self.default_param_size <= 0:
        raise ValueError(f"Invalid param size: {self.default_param_size}")

Startup_Initializer(db)

Handles initialization of startup state variables.

Initialize startup initializer.

Parameters:

Name Type Description Default
db Session

Active database session.

required
Source code in backend/src/database/seed.py
def __init__(self, db: Session):
    """Initialize startup initializer.

    Args:
        db: Active database session.
    """
    self.db = db

initialize_if_needed()

Initialize startup variables if not already present.

Returns:

Type Description
bool

True if initialization was performed, False if already existed.

Source code in backend/src/database/seed.py
def initialize_if_needed(self) -> bool:
    """Initialize startup variables if not already present.

    Returns:
        True if initialization was performed, False if already existed.
    """
    existing = self.db.query(StartupVariables).first()
    if existing:
        logger.debug("Startup variables already initialized, skipping")
        return False

    variables = StartupVariables(welcome_popup_has_already_displayed=False)
    self.db.add(variables)
    self.db.commit()
    logger.info("Startup variables initialized successfully")
    return True

backfill_wire_tools_startup()

Threadpool entrypoint for the post-ready wire-capability backfill (#298).

Verifying the wire capability loads a tokenizer per unverified model (seconds each, GGUF especially), so it must NOT run inside the awaited boot sequence — the lifespan schedules this AFTER the app is ready, in a threadpool (same rationale as the post-ready catalog resync of #109). Opens and closes its own session; swallows everything: NULL rows simply keep routing systematic until a later boot verifies them.

Source code in backend/src/database/seed.py
def backfill_wire_tools_startup() -> int:
    """Threadpool entrypoint for the post-ready wire-capability backfill (#298).

    Verifying the wire capability loads a tokenizer per unverified model
    (seconds each, GGUF especially), so it must NOT run inside the awaited
    boot sequence — the lifespan schedules this AFTER the app is ready, in a
    threadpool (same rationale as the post-ready catalog resync of #109).
    Opens and closes its own session; swallows everything: NULL rows simply
    keep routing systematic until a later boot verifies them.
    """
    db = None
    try:
        db = SessionLocal()
        return Database_Seeder().backfill_wire_tools(db)
    except Exception as e:
        # Runs after ready in a task nobody awaits: this is its only record.
        logger.warning(f"Wire-capability backfill failed: {e}", exc_info=True)
        return 0
    finally:
        if db is not None:
            db.close()

create_tables() async

Legacy API: Create database tables.

Deprecated: Use Database_Seeder().create_tables() instead.

Source code in backend/src/database/seed.py
async def create_tables() -> None:
    """Legacy API: Create database tables.

    Deprecated: Use Database_Seeder().create_tables() instead.
    """
    seeder = Database_Seeder()
    await seeder.create_tables()

delete_all_data() async

Legacy API: Delete all data.

Deprecated: Use Database_Seeder().delete_all_data() instead.

Source code in backend/src/database/seed.py
async def delete_all_data() -> None:
    """Legacy API: Delete all data.

    Deprecated: Use Database_Seeder().delete_all_data() instead.
    """
    seeder = Database_Seeder()
    await seeder.delete_all_data()

load_base_models_fallback()

Load base models from embedded JSON fallback file.

Used when offline or HuggingFace API is unavailable. Provides minimal model metadata to allow app functionality without internet.

Returns:

Type Description
List[Dict[str, Any]]

List[Dict]: List of base model configurations from JSON file.

Raises:

Type Description
FileSystemException

If fallback JSON file is missing or corrupted.

Note

JSON file located at: src/database/base_models_fallback.json Contains 7 curated base models with essential metadata.

Example

models = load_base_models_fallback() first = models[0] print(first.get("name")) # Gemma-1B

Source code in backend/src/database/seed.py
def load_base_models_fallback() -> List[Dict[str, Any]]:
    """Load base models from embedded JSON fallback file.

    Used when offline or HuggingFace API is unavailable. Provides minimal
    model metadata to allow app functionality without internet.

    Returns:
        List[Dict]: List of base model configurations from JSON file.

    Raises:
        FileSystemException: If fallback JSON file is missing or corrupted.

    Note:
        JSON file located at: src/database/base_models_fallback.json
        Contains 7 curated base models with essential metadata.

    Example:
        >>> models = load_base_models_fallback()
        >>> first = models[0]
        >>> print(first.get("name"))  # Gemma-1B
    """
    fallback_path = config.ROOT_DIR / "src" / "database" / "base_models_fallback.json"

    try:
        with open(fallback_path, "r") as f:
            models = json.load(f)

        logger.info(f"Loaded {len(models)} base models from offline fallback")
        return models

    except FileNotFoundError:
        raise FileSystemException(
            f"Base models fallback file not found: {fallback_path}", trace="FileNotFoundError"
        )
    except json.JSONDecodeError as e:
        raise FileSystemException(f"Failed to parse base models fallback JSON: {e}", trace=str(e))

startup_populate_database() async

Populate startup data and return the result dict.

The catalog is reconciled from the bundled snapshot inside (zero network,

131/#163) — there is nothing left for the caller to schedule.

Source code in backend/src/database/seed.py
async def startup_populate_database() -> Dict[str, Any]:
    """Populate startup data and return the result dict.

    The catalog is reconciled from the bundled snapshot inside (zero network,
    #131/#163) — there is nothing left for the caller to schedule.
    """
    seeder = Database_Seeder()
    return await seeder.populate_startup_data()