Introduction
Un modèle d’IA peut être temporairement indisponible, surchargé ou recevoir des données qu’il ne peut pas comprendre. Un modèle de secours fournit à l’application une alternative prévue au lieu de retourner immédiatement une erreur. Un mécanisme de secours utile reste limité : il utilise une courte liste ordonnée et possède un point d’arrêt clair. Il ne doit pas réessayer indéfiniment ni appeler tous les modèles après la première réussite.
Vous allez déployer un petit Cloudflare Worker avec deux parcours. Le parcours de secours envoie volontairement des données au format conversationnel à un modèle d’embeddings, intercepte cette incompatibilité prévisible, puis appelle un modèle conversationnel. Le parcours sain appelle un modèle conversationnel principal compatible et s’arrête. Toutes les tentatives passent par la même AI Gateway ; ses journaux indiquent donc quel modèle a échoué et quel modèle a traité la requête.
Si vous avez accédé directement à ce cours, commencez par Connect LabEx to Your Cloudflare Account. Vous y apprendrez à utiliser le terminal LabEx, l’autorisation de l’appareil Wrangler, la sélection du compte et l’identifiant du compte. Terminez également Route Inference Through a Gateway avant ce laboratoire, car celui-ci s’appuie sur ses concepts de passerelle et de Workers AI.
Ce laboratoire utilise les modèles Workers AI hébergés par Cloudflare ainsi que la liaison Workers AI. Il ne nécessite ni Workers Paid, ni clé d’un fournisseur externe, ni Universal Endpoint obsolète. La tentative contrôlée échoue avant l’inférence, et chaque parcours réussi génère uniquement une réponse courte. Si l’allocation quotidienne partagée de Workers AI est indisponible, arrêtez-vous au lieu de réessayer de manière répétée.
La configuration installe Node.js 22.22.0 et Wrangler 4.132.0, installé localement dans le projet /home/labex/project/ai-gateway-fallback. Elle prépare des vérifications indépendantes, mais n’autorise pas Wrangler, ne crée pas de ressources cloud, ne déploie pas de Worker et n’envoie pas de trafic aux modèles. LabEx détruit la machine virtuelle à la fin du laboratoire ; vous devez toutefois supprimer le Worker distant, la passerelle et le jeton d’API, car la destruction d’une machine virtuelle ne supprime pas les ressources cloud.
Autoriser la machine virtuelle et nommer le parcours de récupération
Chaque laboratoire commence dans une nouvelle machine virtuelle. Dans cette étape, vous allez autoriser Wrangler à utiliser votre compte d’apprentissage et enregistrer des noms uniques pour une passerelle, un Worker et un jeton temporaire.
cd /home/labex/project/ai-gateway-fallback
npx wrangler --version
npx wrangler login --device --browser=false
Ouvrez le lien affiché, saisissez le code et autorisez le compte d’apprentissage voulu. Wrangler demande les autorisations de déploiement de Worker et de Workers AI nécessaires plus tard dans ce laboratoire ; vérifiez le compte affiché avant d’approuver. Inspectez ensuite les informations d’identité structurées :
npx wrangler whoami --json
Vous devez obtenir Wrangler 4.132.0 et loggedIn: true. Remplacez YOUR_ACCOUNT_ID par l’identifiant réel de 32 caractères affiché pour le compte voulu :
GATEWAY_ID="labex-c09-g05-$(openssl rand -hex 6)"
WORKER_NAME="${GATEWAY_ID/g05/g05-worker}"
TOKEN_NAME="$GATEWAY_ID-token"
cat > .labex/state.json <<JSON
{
"accountId": "YOUR_ACCOUNT_ID",
"gatewayId": "$GATEWAY_ID",
"workerName": "$WORKER_NAME",
"tokenName": "$TOKEN_NAME"
}
JSON
cat .labex/state.json
Ces identifiants ne sont pas des secrets. Leur enregistrement permet de limiter les vérifications et le nettoyage ultérieurs aux ressources de ce laboratoire.
Créer une AI Gateway observable
Dans cette étape, vous allez créer le point de contrôle partagé qui enregistrera les deux routes de modèle.
Une AI Gateway est un point de contrôle nommé entre une application et les appels aux modèles. Elle centralise les journaux et les métadonnées de plusieurs tentatives, même lorsque l’application change de modèle.
Ouvrez le tableau de bord Cloudflare et choisissez AI → AI Gateway → Create a custom gateway. Utilisez la valeur enregistrée pour gatewayId. Laissez Collect Logs et Authenticated Gateway activés. Laissez la mise en cache, les limites de débit, les nouvelles tentatives et les limites de dépenses désactivées, et conservez la facturation Workers AI sur Standard. Créez ensuite la passerelle.

Ouvrez My Profile → API Tokens, choisissez Create Token → Create Custom Token et utilisez la valeur enregistrée pour tokenName. Ajoutez les autorisations de compte AI Gateway — Edit et AI Gateway — Run, limitées au compte d’apprentissage voulu. Ce jeton temporaire permet au laboratoire de lire puis de supprimer uniquement sa passerelle ; la liaison AI du Worker déployé ne l’intègre pas.
Après avoir créé le jeton, copiez uniquement la valeur située après Bearer dans la commande de vérification à usage unique de Cloudflare et enregistrez-la avec une saisie masquée :
bash -c '
while :; do
read -ersp "Paste the AI Gateway token: " GATEWAY_TOKEN
printf "\n"
[ -n "$GATEWAY_TOKEN" ] && break
printf "Token cannot be empty; paste it again.\n" >&2
done
umask 077
printf "%s" "$GATEWAY_TOKEN" > .labex/gateway-token
unset GATEWAY_TOKEN
chmod 600 .labex/gateway-token
'
Relisez uniquement les paramètres importants qui ne sont pas secrets :
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
> .labex/gateway.json
unset GATEWAY_TOKEN
node -e 'const g=require("./.labex/gateway.json").result; console.log({id:g.id,collect_logs:g.collect_logs,authentication:g.authentication})'
Vous devez voir l’identifiant de la passerelle enregistrée, avec les deux valeurs définies sur true.
Définir un Worker à deux tentatives
Dans cette étape, vous allez écrire la stratégie de récupération dans du code Worker classique. Elle comporte deux appels explicites au lieu d’une boucle ; son coût et sa latence maximaux sont donc faciles à déterminer.
Le premier appel du parcours de secours utilise un modèle d’embeddings. Les modèles d’embeddings transforment le texte en vecteurs numériques ; ils n’acceptent pas de messages conversationnels. L’envoi de données au format conversationnel crée une incompatibilité sûre et déterministe avant l’inférence. Le bloc catch enregistre cet échec et effectue un appel à un modèle conversationnel compatible.
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
WORKER_NAME=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).workerName')
cat > wrangler.jsonc <<JSON
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-09-17",
"ai": { "binding": "AI" }
}
JSON
cat > src/index.js <<JS
export default {
async fetch(request, env) {
const healthy = new URL(request.url).pathname === "/healthy";
const attempts = [];
const gateway = {
gateway: {
id: "$GATEWAY_ID",
metadata: {
lab: "g05-fallback",
mode: healthy ? "healthy" : "fallback",
synthetic: true
}
}
};
if (!healthy) {
try {
await env.AI.run(
"@cf/baai/bge-small-en-v1.5",
{ messages: [{ role: "user", content: "Reply with ROUTE OK" }] },
gateway
);
attempts.push({ model: "@cf/baai/bge-small-en-v1.5", status: "unexpected-success" });
} catch (error) {
attempts.push({
model: "@cf/baai/bge-small-en-v1.5",
status: "failed",
reason: String(error).slice(0, 180)
});
}
}
const selectedModel = healthy
? "@cf/meta/llama-3.3-70b-instruct-fp8-fast"
: "@cf/meta/llama-3.2-3b-instruct";
const result = await env.AI.run(
selectedModel,
{ prompt: "Reply with exactly: ROUTE OK", max_tokens: 12 },
gateway
);
attempts.push({ model: selectedModel, status: "succeeded" });
return Response.json({
mode: healthy ? "healthy-primary" : "fallback-recovery",
usedFallback: !healthy,
selectedModel,
attempts,
response: result.response
});
}
};
JS
npx wrangler deploy --dry-run
La liaison AI fournit au Worker un accès direct à Workers AI. L’option gateway fait passer chaque appel par la passerelle enregistrée et lui associe uniquement des métadonnées synthétiques — jamais de prompt, d’identifiant d’accès ou d’identifiant personnel.
Déployer et tester le parcours de secours
Dans cette étape, vous allez déployer le Worker et déclencher une fois le cas de récupération contrôlé.
Déployez le Worker et enregistrez la sortie de Wrangler afin que le test utilise l’URL exacte attribuée à votre compte :
npx wrangler deploy 2>&1 | tee .labex/deploy-output.txt
WORKER_URL=$(grep -Eo 'https://[^ ]+\.workers\.dev' .labex/deploy-output.txt | tail -1)
printf '%s\n' "$WORKER_URL" | tee .labex/worker-url.txt
La route workers.dev peut mettre quelques secondes à se propager après un déploiement réussi. Interrogez l’URL sans générer de trafic supplémentaire vers les modèles : une réponse 404 indique seulement que la route en périphérie n’est pas encore prête, et la boucle s’arrête à la première réponse 200.
WORKER_URL=$(cat .labex/worker-url.txt)
for attempt in $(seq 1 12); do
STATUS=$(curl --http1.1 -sS -o .labex/fallback-response.json -w '%{http_code}' "$WORKER_URL/fallback")
printf 'attempt %s: HTTP %s\n' "$attempt" "$STATUS"
[ "$STATUS" = 200 ] && break
[ "$attempt" -eq 12 ] && exit 1
sleep 5
done
python3 -m json.tool < .labex/fallback-response.json
Vous devez obtenir usedFallback: true, deux tentatives, le modèle d’embeddings marqué failed et @cf/meta/llama-3.2-3b-instruct marqué succeeded. La formulation générée n’est pas évaluée au mot près ; c’est la décision de routage qui compte.
Prouver qu’un modèle principal sain s’arrête immédiatement
Dans cette étape, vous allez montrer qu’un modèle principal qui réussit empêche un appel de secours inutile.
Un mécanisme de secours n’est correct que s’il reste inactif lorsque le parcours principal fonctionne. Le parcours /healthy commence par un modèle conversationnel compatible ; il doit donc produire une seule tentative, puis s’arrêter.
WORKER_URL=$(cat .labex/worker-url.txt)
curl --http1.1 -fsS "$WORKER_URL/healthy" \
| tee .labex/healthy-response.json \
| python3 -m json.tool
Vous devez obtenir usedFallback: false, @cf/meta/llama-3.3-70b-instruct-fp8-fast comme selectedModel et exactement une tentative réussie. C’est le comportement de court-circuit : la réussite termine immédiatement le parcours.
Lire le parcours dans les journaux de la passerelle
Dans cette étape, vous allez relier les résultats JSON du Worker à des éléments de preuve indépendants provenant d’AI Gateway.
La réponse du Worker décrit le comportement de l’application. Les journaux d’AI Gateway fournissent une preuve indépendante du côté du fournisseur. Les journaux peuvent mettre quelques secondes à apparaître ; attendez brièvement, puis affichez uniquement les champs utiles au routage :
sleep 8
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID/logs?per_page=50" \
> .labex/logs.json
unset GATEWAY_TOKEN
node - <<'NODE'
const rows=require('./.labex/logs.json').result||[];
const meta=row=>{try{return typeof row.metadata==='string'?JSON.parse(row.metadata):(row.metadata||{})}catch{return {}}};
console.table(rows.filter(row=>meta(row).lab==='g05-fallback').map(row=>({
mode:meta(row).mode, model:row.model, success:row.success, status:row.status_code
})));
NODE
Ouvrez la page Logs de la passerelle dans le tableau de bord. Le groupe de secours doit contenir une ligne échouée pour le modèle d’embeddings et une ligne réussie pour le modèle de secours. Le groupe sain doit contenir uniquement la ligne réussie du modèle conversationnel principal.


Les métadonnées mode relient les lignes sans inclure de prompt ni de secret. Le modèle, la réussite et le statut expliquent le parcours ; le texte généré ne suffit pas à lui seul.
Examiner le contrat de récupération limité
Dans cette étape, vous allez comparer les deux parcours et déterminer le nombre maximal de tentatives de modèle.
Vous disposez maintenant de trois formes concordantes de preuve :
- le code source contient deux appels explicites à
env.AI.run()et aucune boucle de nouvelle tentative ; /fallbacksignale un échec suivi d’une réussite ;/healthysignale une réussite et s’arrête.
Affichez une comparaison concise à partir des réponses enregistrées :
node - <<'NODE'
for (const name of ['fallback','healthy']) {
const body=require(`./.labex/${name}-response.json`);
console.log(name, {
usedFallback: body.usedFallback,
selectedModel: body.selectedModel,
attemptCount: body.attempts.length,
statuses: body.attempts.map(item=>item.status)
});
}
NODE
Le maximum est de deux tentatives. Si le modèle de secours échoue lui aussi, le Worker retourne une erreur au lieu de redémarrer le parcours. Dans une application de production, vous pourriez ajouter un délai d’expiration, un disjoncteur ou une erreur compréhensible pour l’utilisateur, mais chaque mécanisme de récupération supplémentaire doit rester limité et observable indépendamment.
Supprimer les ressources temporaires
Dans cette étape, vous allez supprimer toutes les ressources distantes appartenant à ce laboratoire et retirer l’autorisation locale.
Supprimez d’abord le Worker afin qu’il ne puisse plus générer de trafic vers la passerelle. Supprimez ensuite uniquement la passerelle enregistrée dans state.json :
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
WORKER_NAME=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).workerName')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
npx wrangler delete --name "$WORKER_NAME" --force
curl --http1.1 -fsS -X DELETE \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
> .labex/delete-gateway.json
unset GATEWAY_TOKEN
node -p 'require("./.labex/delete-gateway.json").success'
Vous devez obtenir true. Tant que les deux autorisations temporaires existent encore dans cette machine virtuelle, enregistrez une preuve indépendante de l’absence du Worker et de la passerelle :
set +e
npx wrangler deployments list --name "$WORKER_NAME" --json \
> .labex/worker-after-delete.json 2> .labex/worker-absent.err
printf '%s\n' "$?" > .labex/worker-absent-status.txt
set -e
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways" \
> .labex/gateways-after-delete.json
unset GATEWAY_TOKEN
GATEWAY_ID="$GATEWAY_ID" node - <<'NODE'
const rows=require('./.labex/gateways-after-delete.json').result||[];
console.log('gateway absent:', !rows.some(row=>row.id===process.env.GATEWAY_ID));
NODE
grep -Ei '10090|10007|script_not_found|does not exist' .labex/worker-absent.err
Vous devez obtenir gateway absent: true et une réponse indiquant l’absence du Worker, telle que script_not_found, le code 10090, le code 10007 ou does not exist. Wrangler peut utiliser différentes formes d’erreur pour un même script absent ; les erreurs réseau et d’authentification ne prouvent pas la suppression.
Ouvrez maintenant My Profile → API Tokens et supprimez le tokenName enregistré exact. Supprimez enfin sa copie dans la machine virtuelle et déconnectez-vous :
shred -u .labex/gateway-token
npx wrangler logout
npx wrangler whoami --json
Vous devez obtenir loggedIn: false. La suppression ultérieure de la machine virtuelle supprime les fichiers locaux, mais seules ces commandes suppriment les ressources distantes et révoquent l’autorisation.
Résumé
Vous avez construit un parcours de récupération limité utilisant deux modèles hébergés par Cloudflare. Une tentative principale contrôlée et incompatible a échoué, un modèle de secours a traité la requête, et un modèle principal sain s’est arrêté après un seul appel. Les journaux d’AI Gateway ont relié les décisions de l’application aux preuves côté fournisseur concernant le modèle et le statut. Vous avez également compris pourquoi des limites explicites de tentatives, des métadonnées sûres et un nettoyage vérifié sont essentiels à une conception fiable de mécanisme de secours.



