← Resources
TUTORIAL · 2026-03-26
Migrer du Vercel AI SDK vers une pile BYOK auto-hébergeable
Le Vercel AI SDK convient jusqu'au moment où vous avez besoin de clés portables, de routage personnalisé ou d'un déploiement ailleurs que sur Vercel. Ce guide mappe chaque primitive vers une pile BYOK auto-hébergeable et propose une bascule dual-write d'une semaine.
Pourquoi les équipes dépassent le Vercel AI Gateway
L'AI SDK livre vite : `streamText`, `generateText` et `generateObject` couvrent la plupart des besoins production avec une seule surface TypeScript. La friction apparaît plus tard, en général à trois endroits.
D'abord, le runtime est orienté Vercel. Particularités du runtime Edge, primitives de streaming taillées pour Next.js, et l'AI Gateway en routeur recommandé : tout suppose que la production tourne sur Vercel.
Ensuite, l'AI Gateway reste dans le chemin de requête même en BYOK. Selon la tarification publique de l'AI Gateway de Vercel en mai 2026, le BYOK tourne à 0 % de marge sur les tokens, mais votre équipe doit garder en permanence des crédits AI Gateway financés, parce que les requêtes BYOK échouées sont retentées avec les identifiants système de Vercel. Ce couplage compte dès que la conformité ou le routage VPC entre en jeu.
Enfin, la politique par tenant vit dans le code de l'app. Il n'existe pas de concept natif de tenant, de whitelist de modèle ou de plafond de budget dans le SDK. Les équipes SaaS multi-locataires finissent par écrire un second mini-gateway au-dessus du premier.
Mapper les primitives Vercel vers une pile BYOK
La bonne nouvelle : la surface publique de l'AI SDK est petite. La plupart des appels se résument à trois fonctions et un objet provider. Mappage :
- `streamText` et `generateText` mappent directement vers `chat.completions.create` du SDK OpenAI avec `stream: true` ou `false`. N'importe quel endpoint OpenAI-compatible sert de `baseURL`, ce qui veut dire llama.cpp, vLLM, LiteLLM, ou un fournisseur hébergé derrière un proxy conscient des tenants.
- `generateObject` mappe vers `response_format: { type: 'json_schema' }` sur les serveurs OpenAI-compatibles, ou vers un adaptateur de structured-output pour les fournisseurs qui utilisent un autre schéma (tools Anthropic, mode JSON de Gemini).
- Les objets provider (`openai('gpt-4o')`, `anthropic('claude-...')`) deviennent un client unique pointé vers votre gateway, avec l'id du modèle passé en string. Le routage se fait côté serveur au lieu d'être figé dans l'import.
Gardez vos hooks React existants. `useChat` et `useCompletion` n'ont besoin que d'une route renvoyant un flux Server-Sent Events au même format.
Streaming, tool calls et structured outputs sans lock-in
Les trois fonctionnalités survivent à la migration si vous choisissez un gateway OpenAI-compatible. Voici le même appel avant et après.
Avant, avec le Vercel AI SDK :
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await streamText({
model: openai('gpt-4o'),
messages,
tools: { search: searchTool },
});
return result.toDataStreamResponse();
```
Après, avec le SDK OpenAI pointé sur votre propre gateway :
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: process.env.GATEWAY_URL, apiKey: tenantKey });
const stream = await client.chat.completions.create({
model: 'gpt-4o',
messages,
tools: [searchToolSchema],
stream: true,
});
```
Les tool calls arrivent dans `delta.tool_calls`. Les structured outputs utilisent `response_format`. Les deux sont des champs standards OpenAI-spec que LiteLLM, vLLM et la plupart des fournisseurs managés honorent.
Clés, quotas et routage par tenant
C'est là qu'un SDK fin paie. Dès que les requêtes passent par un endpoint OpenAI-compatible que vous contrôlez, toutes les préoccupations transverses quittent le code applicatif.
Un gateway auto-hébergé comme LiteLLM permet d'émettre des clés virtuelles par tenant, de fixer des plafonds RPM et TPM, d'attacher des budgets et de router par alias de modèle. Une requête sur `model: 'fast'` peut se résoudre vers Groq Llama pour un tenant et vers un serveur llama.cpp local pour un autre, sans changement de code dans l'app Next.js.
osFoundry adopte la même posture BYOK pure-passthrough et ajoute règles de routage par tenant, streaming, tool calls et structured outputs dans un runtime que vous pouvez auto-héberger. À mentionner : LiteLLM est la baseline open source évidente et le bon choix pour beaucoup d'équipes ; retenez ce qui correspond à votre modèle ops.
La décision porteuse est de faire posséder clés et quotas par le gateway, pas par l'app. Tout le reste, y compris les swaps de modèles, devient un changement de config.
Auto-héberger ou hybride : coût et ops
Trois formes de déploiement couvrent la plupart des équipes.
1. Entièrement auto-hébergé. Gateway dans votre VPC, BYOK vers les fournisseurs, modèles locaux optionnels sur une machine GPU. Zéro marge, audit complet, vous portez l'astreinte. Idéal quand la conformité ou la résidence des données pilote le choix.
2. Hybride. Gateway auto-hébergé pour le routage et la politique, fournisseurs managés pour l'inférence, modèles locaux uniquement pour les charges bon marché ou privées. C'est l'état stable courant.
3. Gateway managé, vos clés. Utilisez un proxy OpenAI-compatible hébergé qui supporte le passthrough BYOK. Vous cédez un peu de contrôle sur le chemin de requête ; vous évitez de faire tourner un service de plus.
Le coût ops de l'option 1 est réel : un petit conteneur, un Postgres pour clés et dépense, du log shipping et une cadence de mise à niveau. Pour la plupart des équipes sous quelques centaines de millions de tokens par mois, l'économie face à un gateway à marge est inférieure au temps passé à en débattre. Choisissez sur le contrôle, pas sur les centimes.
Script de bascule : dual-write pendant une semaine
Ne basculez pas l'import dans une seule PR. Faites du dual-write pendant sept jours, comparez, puis coupez.
Jour 0 : ajoutez le nouveau client gateway derrière un feature flag. Pour chaque requête, lancez en parallèle l'ancien chemin `streamText` et le nouvel appel `chat.completions` avec les mêmes messages. Jetez la seconde réponse mais consignez latence, comptage de tokens, finish reason et toute divergence de forme sur les tool calls.
Jours 1-3 : shadow 100 % du trafic. Comparez les structured outputs et le JSON des arguments de tool calls. La plupart des régressions sont liées au schéma : Anthropic renvoie des stop reasons légèrement différents, Gemini wrappe le JSON différemment. Corrigez dans le gateway, pas dans l'app.
Jours 4-6 : basculez 10 %, puis 50 %, puis 100 % des routes en lecture (chat, résumé). Gardez les routes en écriture ou agentiques sur l'ancien chemin tant que le diff n'est pas clean sur 24 h.
Jour 7 : supprimez les paquets `ai` et `@ai-sdk/*`, supprimez les env vars AI Gateway et archivez le flag.
Après la migration : cache, observabilité, évals
Posséder le chemin de requête débloque trois choses peu commodes au sein du SDK.
Cache : un gateway peut hasher sur `(model, messages, tools, response_format)` et servir les requêtes identiques depuis Redis. Pour le RAG et les boucles agentiques avec system prompts répétés, le cache de préfixe au niveau fournisseur (Anthropic, OpenAI) se superpose. Câblez les deux ; les hits cache se voient immédiatement sur la latence p50.
Observabilité : émettez un log structuré par requête avec id du tenant, modèle, tokens de prompt, tokens de complétion, nombre de tool calls, finish reason et latence upstream. Expédiez vers ce que vous utilisez déjà. Plus besoin d'une intégration de tracing spécifique au fournisseur pour voir ce qu'a fait le modèle.
Évals : avec tout le trafic dans un seul endpoint, échantillonner pour un jeu d'éval est une requête SQL. Rejouez contre de nouveaux modèles en changeant le champ `model`. C'est la raison long terme de posséder le gateway : le choix de modèle devient une expérimentation hebdomadaire, pas une migration trimestrielle.
Frequently asked questions
- Abandonner le Vercel AI SDK signifie-t-il perdre useChat et les hooks React de streaming ?
- Non. Les hooks sont découplés du runtime serveur tant que votre route API renvoie un flux Server-Sent Events au format attendu par le hook. Vous pouvez garder `useChat` et `useCompletion` du paquet `ai` et les pointer vers une route qui proxie une réponse OpenAI-compatible en streaming. Beaucoup d'équipes laissent intact le côté React le premier mois de la migration et ne swap que le handler serveur. Si vous souhaitez ensuite supprimer entièrement la dépendance `ai`, un parser SSE fin tient en une trentaine de lignes de TypeScript.
- LiteLLM est-il une vraie alternative ou un palliatif ?
- C'est une vraie alternative, largement déployée en production. LiteLLM est un proxy OpenAI-compatible open source qui couvre plus de 140 fournisseurs, supporte les clés virtuelles, les budgets par clé, les limites RPM et TPM, et le load balancing. Il tourne en un seul conteneur Docker avec Postgres. Le compromis face à un runtime d'orchestration plus complet porte surtout sur les boucles agentiques, la normalisation des structured outputs entre fournisseurs et la politique tenant-scopée au-delà des clés et budgets. Pour un cas d'usage routage et BYOK pur, LiteLLM suffit souvent à lui seul.
- Comment garder les structured outputs fonctionnels entre fournisseurs après migration ?
- Normalisez au gateway, pas dans l'app. OpenAI et les serveurs OpenAI-compatibles acceptent `response_format: { type: 'json_schema', json_schema: {...} }`. Anthropic utilise un pattern tool-call pour imposer les schémas. Gemini propose `responseMimeType` plus `responseSchema`. Une petite couche d'adaptation dans le gateway traduit une seule forme canonique vers le fournisseur ciblé et valide le JSON renvoyé avant réponse. Votre code applicatif continue d'appeler une fonction unique et vous pouvez swap les modèles sans toucher à la logique de schéma.
- Et la latence ? Ajouter un gateway auto-hébergé ressemble à un saut de plus.
- En pratique, la latence ajoutée est de l'ordre de quelques millisecondes si le gateway est dans la même région que votre app, ce qui est noyé par l'inférence modèle (de centaines de ms à des secondes). Le vrai gain de latence est côté cache : un gateway peut servir les prompts répétés depuis Redis en moins de 5 ms, ce qui est impossible si chaque requête part directement chez un fournisseur. Mesurez p50 et p95 avant/après ; les équipes constatent en général des nombres neutres ou améliorés une fois le cache activé.
Sources