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
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
|
|
required |
Returns:
| Type | Description |
|---|---|
Engine
|
The live engine (also published as |
Source code in backend/src/database/core.py
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
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
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
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
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
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
1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 | |
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
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
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
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
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
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
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).
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
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
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
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | |
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
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | |
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
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
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
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
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
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
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
create_tables()
async
¶
Legacy API: Create database tables.
Deprecated: Use Database_Seeder().create_tables() instead.
delete_all_data()
async
¶
Legacy API: Delete all data.
Deprecated: Use Database_Seeder().delete_all_data() instead.
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
startup_populate_database()
async
¶
Populate startup data and return the result dict.
The catalog is reconciled from the bundled snapshot inside (zero network,