feat(backend): add idempotent LLM catalog importer and bundled catalog - #13607
feat(backend): add idempotent LLM catalog importer and bundled catalog#13607ntindle wants to merge 1 commit into
Conversation
Part 3 of 9 of the LLM registry restack. Replaces the original stack's one-shot 287-line seed SQL migration with an importer that runs on every startup: - catalog_model.py: CatalogPayload schema (v1) — model facts only; costs, credentials, routing cells, and non-GA models are never in a catalog - importer.py: upsert-by-slug with source tracking. LOCAL (admin-owned) rows are never updated or disabled, enforced via `source != LOCAL` inside every UPDATE WHERE clause (row-atomic against concurrent admin writes). Removals disable + stamp catalogRemovedAt, never delete. sha256 content-hash fast-path makes steady-state boots one SELECT. All writes in one transaction, then refresh_runtime_caches() - registry.refresh_runtime_caches(): the single write-path choke point (clear Redis L2 -> rebuild L1 -> pub/sub fan-out) - export.py: regenerate catalog.json from a populated DB (poetry run python -m backend.data.llm_registry.export) - catalog.json: 85 models / 8 providers / 17 creators generated from the current MODEL_METADATA (not the stale March seed data); gpt-5.2 marked recommended to mirror DEFAULT_LLM_MODEL - lifespan: import_bundled_catalog() before the registry refresh, fail-soft Tests: real-DB integration tests for every merge rule + catalog schema validation + a forever-guard that catalog.json parses with unique slugs. Co-authored-by: Bentlybro <Github@bentlybro.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/llm-registry-v2-core #13607 +/- ##
==========================================================
Coverage 76.01% 76.01%
==========================================================
Files 2688 2688
Lines 204280 204280
Branches 19654 19654
==========================================================
+ Hits 155278 155281 +3
+ Misses 44662 44657 -5
- Partials 4340 4342 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
After a post-build design review we pivoted from the DB-registry to catalog-as-code: one canonical, schema-validated catalog file is the source of truth (models + costs + copilot routing), updated by PR (catalog-only diffs may ride hotfix→master; the /review bot covers the lane), propagated by CD, with LaunchDarkly demoted to optional cohort experiments and git history as the audit log. Rationale: the admin machinery mostly bought instant-mutation and non-engineer authoring we don't need, and LD is too unreliable to be the load-bearing control layer. Replaced by #13622 — catalog.py is promoted from seed data to the database itself; the importer/merge semantics have no second writer to exist for. |
Why
Part 3 of 9 of the LLM registry restack (#13605 → #13606 → this). The original stack seeded the registry with a one-shot SQL migration — frozen at install time, no way to update self-hosted installs, and no protection for admin edits. This PR replaces seeding with an idempotent importer that runs on every startup, which is the foundation the remote-sync mechanism (part 5) builds on.
What
catalog_model.py—CatalogPayloadschema v1: the single source of truth for the bundled file, the public endpoint (part 4), and sync validation (part 5). Facts only: no costs, no credentials, no routing cells, no non-GA models. Slug patterns, bounds, and a 2000-model cap.importer.py— merge rules: upsert-by-slug;source=LOCAL(admin-owned) rows never updated or disabled, enforced inside every UPDATE's WHERE clause so a concurrent admin claim wins the race; absent models are disabled +catalogRemovedAt-stamped, never deleted;LlmModelCostnever touched; sha256 content-hash fast-path (steady-state boot = one SELECT); one transaction, then cache refresh + cross-pod fan-out.export.py— regeneratescatalog.jsonfrom a populated DB (python -m backend.data.llm_registry.export); GA-visibility models only.catalog.json— 85 models / 8 providers / 17 creators, generated from today'sMODEL_METADATA(deliberately not the March-era seed data);gpt-5.2recommended, mirroringDEFAULT_LLM_MODEL.Verification
catalog.jsonparses with unique slugs and sound referencespoetry run format+poetry run lintcleanChecklist
data/*.pychanges: registry tables are global config, no user-scoped rows — no user ID checks applicable