v1.19.0 — LLM catalogue DB-source-of-truth
LLM catalogue DB-source-of-truth
Iteration on top of v1.18.1 — admin-facing release. The chat + image LLM catalogue moves from frozen Python constants to the database as source of truth. Administrators can now declare new models and tune their full capability + pricing profile from the admin UI, with no code change, no release, and no redeploy.
📐 Architectural decision: ADR-078
✨ Highlights
- LLM catalogue lives in the database — Three tables replace ~750 lines of frozen Python constants:
llm_models(catalogue withproviderenum + 8 capability flags: max input/output tokens, tools, structured output, strict mode, streaming, vision, reasoning),llm_model_pricingrefactored to FK on the catalogue (composite unique onmodel_id, effective_from), andimage_generation_pricinggains a NOT NULLprovidercolumn. - 14-field admin form for Tarification LLM Texte — A 3-section modal (Modèle / Capacités / Tarification) lets you declare every aspect of a new model in one shot. The Provider is a typed
<Select>, every capability is a<Switch>. The form is the single entry point — no SQL required. - Live propagation across workers — Two singleton in-memory caches (
ModelCapabilitiesCache,ImageOptionsCache) load the catalogue at boot. Every admin write triggers a Redis Pub/Sub message (ADR-063); every API worker reloads in milliseconds. The factory, agent constraints UI, image preferences dropdowns and cost tracker all see the change immediately. - Live propagation across the dashboard — A new React Context (
CatalogueInvalidationProvider) emits typed events after a successful admin write. The LLM Configuration section (per-agent constraints) and the Image Generation Settings page (user preferences) refetch automatically — no page reload needed. - Reasoning-model toggle is finally honored at runtime — Three call sites used to silently bypass the admin's intent via a hardcoded regex (
REASONING_MODELS_PATTERN). All three now consultModelCapabilitiesCache.is_reasoning_model()first and fall back to the regex only for brand-new models not yet in the catalogue. Disablingis_reasoning_modelon a model in the admin UI now disables the reasoning-effort UI on the agents that use it. - Image generation options driven by the live catalogue — User preferences dropdowns (quality, size, format) are rebuilt from
useImageGenerationOptionscalling the newGET /api/v1/image-generation/optionsendpoint. Adding a new image model (or new quality/size combination) is now an admin operation, not a code change.
🛠️ Migration (3-step pattern, ADR-040)
2026_05_05_0001-llm_models_schema.py— creates the new tables and adds nullable columns.2026_05_05_0002-llm_models_backfill.py— backfills 47 known models from a frozenMODELS_DATAlist (preserves capability profiles from the deletedFALLBACK_PROFILESdict).2026_05_05_0003-llm_models_constraints.py— flips backfilled columns to NOT NULL, drops legacyllm_model_pricing.model_name, adds the composite unique constraint.
All three are reversible via standard alembic downgrade -1. Seeds rewritten to match: chat seed inserts 119 catalogue rows then pricing rows via INSERT … SELECT … JOIN; image seed includes provider='openai'::llm_provider_enum on all 27 rows.
🐛 Fixes
- Pricing PUT toast error on existing models —
lazy=\"raise\"onLLMModelPricing.modelwas being invalidated by an unnecessarydb.refresh()afterflush(). Removed three refreshes; defaults are all Python-side and the pre-populated relationship survives flush. UserSkillStatemapper init failure at boot — eager mapper configuration viasa_inspect(LLMModel).mapper.column_attrswas firing before all domain models loaded. Replaced with table-level introspection (LLMModel.__table__.columns.keys()).- Pricing seed
id NOT NULLviolation — the rewritten seed now providesgen_random_uuid()explicitly in theINSERT … SELECT.
🌍 i18n (6 languages)
- 14 new keys for the admin LLM pricing form (provider label + 8 capability labels + 4 pricing labels) + 5 keys for the section headers + buttons.
- 2 new keys for the image options metadata (provider column header + price range tooltip).
🧪 Tests + tooling
- All migrations are revertible and tested via the standard
alembic upgrade head/alembic downgrade -1cycle. - Pre-commit hook (host MyPy + Ruff + Black, host ESLint + tsc, i18n parity check across 4315 keys × 6 languages) green on the full branch.
- All 7400+ unit tests pass.
📚 Documentation
- New ADR-078 — LLM Catalogue DB-Source-of-Truth.
- ADR-026 (LLM Model Selection Strategy) — Evolution header pointing to ADR-078.
- ADR-039 (Cost Optimization & Token Management) — Evolution note on the
MODEL_PROFILES→ DB tables move. - ADR-063 (Cross-Worker Cache Invalidation) —
ModelCapabilitiesCache+ImageOptionsCacheadded to the documented consumer list. - Technical docs aligned: DATABASE_SCHEMA, LLM_PRICING_MANAGEMENT, IMAGE_GENERATION, LLM_PROVIDERS, LLM_PROVIDER_CONSTRAINTS, LLM_CONFIG_ADMIN.
🤖 Released with Claude Code