Cette page t'a-t-elle aidé ?

Cette page t'a-t-elle aidé ?
Concepts
Gilbert ne hardcode jamais un nom de modèle. Chaque appel LLM déclare un tier abstrait, le provider du workspace fait la traduction concrète.
Dernière mise à jour : 28 mai 2026
Deux raisons concrètes, l'une produit, l'autre maintenance.
Portabilité BYOLLM. Chaque workspace choisit son provider LLM (voir Workspaces). Si un call site écrivait claude-sonnet-4-5en dur, il casserait silencieusement pour les workspaces sur Google Gemini ou OpenAI : leur clé ne reconnaît pas le modèle Anthropic, et soit on planterait, soit on devrait bypasser leur config pour appeler notre clé centrale. Inacceptable côté privacy et facturation.
Provider drift. Les noms de modèles changent tous les 3-6 mois (Sonnet 4.5 → 4.6 → 4.7, Gemini 2.5 → 3.0, gpt-4o → gpt-5). Sans abstraction, chaque release oblige à patcher 14 call sites en parallèle. Avec MODEL_BY_TIER, on bump une seule constante et tous les call sites suivent. C'est aussi pour ça que la règle #8 de CLAUDE.md interdit les noms de modèle hardcodés dans le code applicatif : tout passe par getLLMClient(supabase, workspaceId, { tier }).
// Mauvais — hardcode un nom de modèle Anthropic
const result = streamText({
model: anthropic("claude-sonnet-4-5"),
messages,
});
// Bon — déclare l'intent, laisse le workspace décider du provider
const client = await getLLMClient(supabase, workspaceId, {
tier: "smart",
});
const result = streamText({
model: client.model,
messages,
});Trois niveaux, choisis pour couvrir les usages réels sans combinatoire inutile. La table ci-dessous est la source de vérité (MODEL_BY_TIER dans src/lib/gilbert/llmClient.ts).
| Tier | Usage typique | Anthropic | OpenAI | |
|---|---|---|---|---|
| fast | Classification, extraction structurée, parse JSON, génération de titre, condensation. Latence basse, coût minimum. | claude-haiku-4-5 | gemini-2.5-flash-lite | gpt-4o-mini |
| smart | Chat multi-tool, briefing matinal, polish de drafts mail, raisonnement post-tool. Le bon défaut quand le call site n'a pas d'avis tranché. | claude-sonnet-4-5 | gemini-2.5-flash | gpt-4o |
| premium | Analyse de document long, code review hebdo, agent autonome long-horizon, raisonnement edge case. Plus cher, plus lent, réservé aux tâches qui le méritent. | claude-opus-4-7 | gemini-2.5-pro | gpt-4o* |
*OpenAI n'a pas aujourd'hui de tier premium distinct compatible avec notre stack tool-use (o1/o3 ont des contraintes incompatibles). Le tier premium est aligné sur smarten attendant un GPT-5 tool-use-friendly. Si ton workspace est sur OpenAI et qu'une routine demande premium, elle tourne sur gpt-4o sans erreur.
Default tier quand un call site n'en précise pas : smart. C'est fail-safe (modèle capable) sans gâcher (pas premium). Les call sites économes (gen de titre de chat, extraction mémoire) doivent passer explicitement fast.
Trois acteurs peuvent fixer le tier d'un appel :
model_tier (default smart) configurable depuis le Console : c'est l'admin qui décide qu'un briefing matinal mérite smart et qu'une revue de code hebdo mérite premium.create_scheduled_draft accepte un argument tier). Le modèle peut choisir d'escalader la qualité pour une sous-tâche difficile, ou descendre sur fast pour générer 20 brouillons rapidement.BYOLLM (Bring Your Own LLM) et ModelTier sont les deux faces de la même pièce. BYOLLM répond à la question « chez quion appelle ? » ; ModelTier répond à « quelle puissanceon appelle ? ». Les deux sont orthogonaux et se combinent dans getLLMClient :
getLLMClient(supabase, workspaceId, { tier }).gilbert.workspace_llm_config et déchiffre la clé API stockée (AES-256-GCM).anthropic, google, ou openai) sert d'index dans MODEL_BY_TIER[provider][tier]pour obtenir l'identifiant de modèle concret.LanguageModel prêt à passer à streamText ou generateText.Si le workspace n'a pas de clé configurée, le comportement dépend du toggle allow_central_fallback du workspace. Activé (default mode trial) → Gilbert utilise sa clé Anthropic centrale en respectant le tier demandé. Désactivé (privacy strict) → getLLMClient throw une WorkspaceProviderNotConfiguredError, à catch côté UI pour afficher un CTA « configurer la clé ».
ACME Immo configure son workspace sur Google Gemini (ils ont déjà un contrat Google Cloud, ils préfèrent rester chez eux). Trois routines sont actives :
gmail-morning-briefing — tier smart. Tourne sur gemini-2.5-flash tous les matins à 8h. Lit les 30 derniers mails non lus, écrit un brief de 200 mots.weekly-code-review — tier premium. Tourne sur gemini-2.5-prole vendredi soir. Analyse les commits de la semaine, sort un rapport d'auditabilité.classify-incoming-leads — tier fast. Tourne sur gemini-2.5-flash-lite à chaque mail entrant. Classifie le lead (qualifié / non qualifié / spam) en ~300ms.Demain, l'équipe décide de migrer vers Anthropic. Le seul changement à faire : mettre à jour la config LLM du workspace dans le Console. Les trois routines continuent de tourner sans modification — elles passent automatiquement sur Sonnet, Opus et Haiku respectivement, parce qu'elles ne déclarent que leur tier, jamais un nom de modèle.
-- Une routine porte son propre tier (default 'smart')
-- Le worker cron lit ce champ et le passe à getLLMClient.
SELECT id, name, model_tier
FROM gilbert.routines
WHERE workspace_id = '<workspace-uuid>';
-- Bump un briefing matinal sur premium si le compte-rendu mérite Opus
UPDATE gilbert.routines
SET model_tier = 'premium'
WHERE id = '<routine-uuid>';ModelTier est une abstraction utile mais simple — voilà ce qu'elle ne fait pasaujourd'hui :
MODEL_BY_TIERest une constante du bundle. Quand un nouveau modèle sort (ex : Haiku 5), il faut bump la constante et redéployer. Pas de hot-swap config-driven. C'est volontaire (le contrôle qualité reste avec l'équipe Gilbert), mais ça veut dire que tu ne peux pas bypasser un modèle cassé sans nous attendre.gilbert.llm_usage_daily) trace les tokens par provider et par pipeline, mais pas par tier. Si tu veux savoir « combien me coûte mon usage premium ce mois », il faut cross-référencer manuellement. Roadmap V2.model_tier par routine planifiée.