Skip to content

v1.19.0 — LLM catalogue DB-source-of-truth

Choose a tag to compare

@jgouviergmail jgouviergmail released this 05 May 18:05

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 with provider enum + 8 capability flags: max input/output tokens, tools, structured output, strict mode, streaming, vision, reasoning), llm_model_pricing refactored to FK on the catalogue (composite unique on model_id, effective_from), and image_generation_pricing gains a NOT NULL provider column.
  • 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 consult ModelCapabilitiesCache.is_reasoning_model() first and fall back to the regex only for brand-new models not yet in the catalogue. Disabling is_reasoning_model on 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 useImageGenerationOptions calling the new GET /api/v1/image-generation/options endpoint. 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 frozen MODELS_DATA list (preserves capability profiles from the deleted FALLBACK_PROFILES dict).
  • 2026_05_05_0003-llm_models_constraints.py — flips backfilled columns to NOT NULL, drops legacy llm_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 modelslazy=\"raise\" on LLMModelPricing.model was being invalidated by an unnecessary db.refresh() after flush(). Removed three refreshes; defaults are all Python-side and the pre-populated relationship survives flush.
  • UserSkillState mapper init failure at boot — eager mapper configuration via sa_inspect(LLMModel).mapper.column_attrs was firing before all domain models loaded. Replaced with table-level introspection (LLMModel.__table__.columns.keys()).
  • Pricing seed id NOT NULL violation — the rewritten seed now provides gen_random_uuid() explicitly in the INSERT … 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 -1 cycle.
  • 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 + ImageOptionsCache added 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