Almacenar en caché solicitudes de inferencia repetidas

CloudflareBeginner
Practicar Ahora

Introducción

Normalmente, un modelo de IA genera una respuesta nueva cada vez que una aplicación lo consulta. Este trabajo requiere tiempo y consume uso del modelo incluso cuando la solicitud es exactamente igual a otra que el modelo acaba de responder. Una caché conserva una respuesta reutilizable durante un tiempo limitado para que una solicitud idéntica pueda recibirla sin realizar otra llamada al modelo.

La caché solo resulta útil cuando la reutilización es segura. Una pregunta frecuente pública y fija es una buena candidata, porque todos los usuarios pueden recibir la misma respuesta. No ocurre lo mismo con una instrucción de soporte personalizada: dos clientes nunca deben agruparse bajo una clave de caché compartida solo para mejorar la velocidad. La clave de caché predeterminada de AI Gateway protege este laboratorio porque incluye el proveedor, el endpoint, el modelo, la credencial del proveedor y el cuerpo completo de la solicitud. Cualquier cambio en el cuerpo crea una entrada diferente.

Creará un gateway autenticado y desechable con una duración de caché de cinco minutos. Enviará una pregunta pública pequeña a Workers AI y observará un MISS de caché; repetirá la solicitud exacta para demostrar un HIT; después cambiará la pregunta y verá otro MISS. Por último, omitirá la respuesta almacenada cuando necesite contenido actualizado y confirmará mediante los registros del gateway que la solicitud llegó al modelo.

Si accedió directamente a este curso, complete primero Conectar LabEx a su cuenta de Cloudflare. Este laboratorio enseña a utilizar el terminal de la máquina virtual de LabEx, la autorización del dispositivo de Wrangler, la confirmación de la cuenta de aprendizaje y los identificadores de cuenta explícitos. Complete también primero Enrutar la inferencia a través de un gateway, porque este laboratorio reutiliza sus límites independientes de gateway y autorización ascendente.

El laboratorio utiliza el modelo alojado en Cloudflare @cf/meta/llama-3.3-70b-instruct-fp8-fast con la facturación Standard de Workers AI. No necesita Workers Paid, Unified Billing ni una cuenta de proveedor externo. Solo tres solicitudes deben llegar al modelo; la repetición exacta debe provenir de la caché. Si la asignación diaria compartida de Workers AI no está disponible, deténgase en lugar de reintentar repetidamente.

La configuración instala Node.js 22.22.0 y Wrangler 4.132.0 local del proyecto en /home/labex/project/ai-gateway-cache. Prepara evaluaciones independientes de solo lectura, pero no autoriza Wrangler, no crea recursos en la nube ni envía tráfico al modelo. LabEx destruye la máquina virtual temporal cuando termina el laboratorio; aun así, deberá eliminar el gateway y el token antes de cerrar la sesión, porque la destrucción de la máquina virtual por sí sola no puede eliminar recursos de la nube.

Autorice la máquina virtual y asigne un nombre al experimento de caché

En este paso, conectará la máquina virtual nueva a su cuenta de aprendizaje y generará los nombres de un gateway y un token desechables.

La caché es una infraestructura compartida, por lo que debe definir cuidadosamente su alcance. Este laboratorio utiliza un gateway con un nombre único y únicamente preguntas públicas sintéticas. El sufijo aleatorio evita que su experimento entre en conflicto con otro gateway de la misma cuenta de aprendizaje.

Acceda al proyecto preparado, confirme la CLI fijada y autorice esta máquina virtual:

cd /home/labex/project/ai-gateway-cache
npx wrangler --version
npx wrangler login --device --browser=false --scopes account:read user:read ai:write

Abra el enlace mostrado, introduzca el código y autorice la cuenta de aprendizaje correcta. Confirme la identidad estructurada:

npx wrangler whoami --json

Deberá ver Wrangler 4.132.0 y loggedIn: true. Sustituya YOUR_ACCOUNT_ID a continuación por el ID real de 32 caracteres que se muestra para la cuenta correcta:

GATEWAY_ID="labex-c09-g03-$(openssl rand -hex 6)"
TOKEN_NAME="$GATEWAY_ID-token"
cat > .labex/state.json <<JSON
{
  "accountId": "YOUR_ACCOUNT_ID",
  "gatewayId": "$GATEWAY_ID",
  "tokenName": "$TOKEN_NAME"
}
JSON
cat .labex/state.json

Estos identificadores no secretos se guardan en un inventario local para que todas las lecturas, verificaciones y operaciones de limpieza posteriores se dirijan únicamente a los recursos de este laboratorio.

Cree un gateway autenticado con una caché breve

En este paso, creará el gateway y asignará a las respuestas almacenadas un tiempo de vida, o TTL, de cinco minutos. Un TTL es el tiempo máximo durante el que se puede reutilizar una entrada antes de que quede obsoleta y deba actualizarse desde el modelo.

Abra Cloudflare Dashboard y seleccione AI → AI Gateway → Create gateway → Custom gateway. Use el gatewayId guardado como nombre del gateway. Mantenga activados el registro de solicitudes y la autenticación del gateway, active Cache responses y establezca su TTL exactamente en 300 segundos. Mantenga desactivados los límites de frecuencia, los límites de gasto y los reintentos, y mantenga la facturación de Workers AI en Standard.

La configuración del gateway muestra la autenticación, el registro y una caché de respuestas de 300 segundos

Después de crear el gateway, confirme su ID único en la ruta de navegación. El TTL breve permite repetir este experimento, pero evita que la respuesta de ejemplo permanezca almacenada innecesariamente.

Seleccione Create an AI Gateway authentication token. Use el tokenName guardado, incluya únicamente la cuenta de aprendizaje correcta y establezca exactamente estos permisos:

  • AI Gateway — Run para acceder al gateway autenticado;
  • AI Gateway — Edit para leer las evidencias de caché y eliminar este gateway desechable.

No añada el permiso de Workers AI. Wrangler proporciona la credencial ascendente independiente y de corta duración. Cree el token después de revisar la cuenta y los permisos; después, guarde su valor de un solo uso sin mostrarlo en pantalla:

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
'

Verifique la configuración exacta de la caché mediante la API de administración autenticada:

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" \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s),g=b.result||{};console.log(JSON.stringify({success:b.success,id:g.id,collect_logs:g.collect_logs,authentication:g.authentication,cache_ttl:g.cache_ttl},null,2))})'
unset GATEWAY_TOKEN

Deberá ver el ID guardado, collect_logs: true, authentication: true y cache_ttl: 300.

Envíe la primera solicitud pública de preguntas frecuentes

En este paso, enviará una pregunta pública pequeña que cualquier participante puede reutilizar de forma segura. La primera solicitud apta no puede tener todavía una entrada en este gateway nuevo, por lo que debería producir un MISS de caché. Un miss significa que AI Gateway reenvía la solicitud a Workers AI y después almacena la respuesta correcta.

La clave de caché predeterminada incluye la credencial del proveedor ascendente. Guarde de forma privada la credencial actual de Wrangler de esta máquina virtual para que las cuatro solicitudes utilicen una misma clave controlada. Este es un archivo temporal del laboratorio, no un patrón recomendado para secretos en producción:

umask 077
npx wrangler auth token --json \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))' \
  > .labex/upstream-token
chmod 600 .labex/upstream-token

Envíe la primera solicitud y guarde los encabezados de respuesta, el cuerpo y el estado HTTP sin imprimir ninguna de las dos credenciales:

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')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
METADATA='{"lab":"g03-cache","case":"public-faq","synthetic":true}'
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
STATUS=$(curl --http1.1 -sS -D .labex/first-headers.txt \
  -o .labex/first-response.json -w '%{http_code}' \
  -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
  -H "Authorization: Bearer $UPSTREAM_TOKEN" \
  -H "cf-aig-metadata: $METADATA" \
  -H 'Content-Type: application/json' \
  --data '{"prompt":"In one short sentence, what does an AI gateway do?","max_tokens":32}' \
  "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/first-status.txt
awk 'BEGIN{IGNORECASE=1} /^cf-aig-cache-status:/ {gsub("\r","",$2); print toupper($2)}' .labex/first-headers.txt \
  | tail -1 | tee .labex/first-cache-status.txt
node -e 'const b=require("./.labex/first-response.json"); console.log(b.result?.response ?? b.result)'

Deberá obtener HTTP 200, estado de caché MISS y una respuesta breve generada. El cuerpo de la solicitud no contiene datos de clientes, por lo que reutilizar temporalmente esta respuesta es seguro.

Repita la solicitud exacta y demuestre un acierto de caché

En este paso, enviará exactamente el mismo proveedor, endpoint, modelo, credencial y cuerpo de solicitud. Por tanto, AI Gateway puede reutilizar la entrada creada en el paso anterior. Un HIT de caché significa que la respuesta provino de la caché del gateway sin generar una respuesta nueva en el modelo.

El almacenamiento en caché es asíncrono, por lo que debe esperar unos segundos después de la primera respuesta correcta antes de repetirla:

sleep 5
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
METADATA='{"lab":"g03-cache","case":"public-faq","synthetic":true}'
STATUS=$(curl --http1.1 -sS -D .labex/repeat-headers.txt \
  -o .labex/repeat-response.json -w '%{http_code}' \
  -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
  -H "Authorization: Bearer $UPSTREAM_TOKEN" \
  -H "cf-aig-metadata: $METADATA" \
  -H 'Content-Type: application/json' \
  --data '{"prompt":"In one short sentence, what does an AI gateway do?","max_tokens":32}' \
  "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/repeat-status.txt
awk 'BEGIN{IGNORECASE=1} /^cf-aig-cache-status:/ {gsub("\r","",$2); print toupper($2)}' .labex/repeat-headers.txt \
  | tail -1 | tee .labex/repeat-cache-status.txt
cmp -s .labex/first-response.json .labex/repeat-response.json \
  && echo 'response bytes match the cached source'

Deberá obtener HTTP 200 y HIT. Que los bytes coincidan es una observación adicional útil, pero el encabezado de respuesta HIT y el registro almacenado en el Dashboard son las evidencias autorizadas. El almacenamiento en caché de AI Gateway es asíncrono y volátil, por lo que no envíe las dos solicitudes simultáneamente. Si la repetición secuencial todavía produce un miss, espere unos segundos y ejecute una vez más este bloque exacto.

Abra la vista Logs del gateway en el Dashboard. Busque las dos solicitudes public-faq y compare sus indicadores de caché, duraciones y uso de tokens. Una fila debería mostrar el miss atendido por el modelo y la otra, el hit atendido desde la caché.

Los registros del gateway muestran el primer miss de preguntas frecuentes junto al hit de la repetición exacta

Cambie la pregunta y observe un nuevo miss

En este paso, cambiará únicamente la instrucción. El cuerpo completo de la solicitud participa en la clave de caché predeterminada, por lo que esta pregunta nueva no debe recibir la respuesta anterior.

GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
METADATA='{"lab":"g03-cache","case":"changed-question","synthetic":true}'
STATUS=$(curl --http1.1 -sS -D .labex/changed-headers.txt \
  -o .labex/changed-response.json -w '%{http_code}' \
  -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
  -H "Authorization: Bearer $UPSTREAM_TOKEN" \
  -H "cf-aig-metadata: $METADATA" \
  -H 'Content-Type: application/json' \
  --data '{"prompt":"In one short sentence, name one benefit of an AI gateway.","max_tokens":32}' \
  "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/changed-status.txt
awk 'BEGIN{IGNORECASE=1} /^cf-aig-cache-status:/ {gsub("\r","",$2); print toupper($2)}' .labex/changed-headers.txt \
  | tail -1 | tee .labex/changed-cache-status.txt
node -e 'const b=require("./.labex/changed-response.json"); console.log(b.result?.response ?? b.result)'

Deberá obtener HTTP 200 y MISS. Este comportamiento de coincidencia exacta es deliberadamente más restrictivo que la similitud semántica: dos preguntas que parecen relacionadas siguen teniendo cuerpos diferentes y entradas de caché diferentes.

No sustituya la clave predeterminada por una clave compartida como support-answer para instrucciones personalizadas. Una clave personalizada solo es segura cuando cada solicitud agrupada bajo ella está autorizada a recibir la misma respuesta.

Omita la caché cuando necesite una respuesta actualizada

En este paso, volverá a la pregunta original, pero omitirá explícitamente su respuesta almacenada. Bypass significa «consultar ahora al proveedor», incluso si existe una entrada de caché válida. Esto resulta útil cuando una aplicación necesita contenido actualizado para una solicitud concreta.

El encabezado cf-aig-skip-cache: true controla únicamente esta solicitud. No desactiva la caché del gateway para los demás usuarios:

GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
METADATA='{"lab":"g03-cache","case":"fresh-bypass","synthetic":true}'
STATUS=$(curl --http1.1 -sS -D .labex/bypass-headers.txt \
  -o .labex/bypass-response.json -w '%{http_code}' \
  -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
  -H "Authorization: Bearer $UPSTREAM_TOKEN" \
  -H "cf-aig-metadata: $METADATA" \
  -H 'cf-aig-skip-cache: true' \
  -H 'Content-Type: application/json' \
  --data '{"prompt":"In one short sentence, what does an AI gateway do?","max_tokens":32}' \
  "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/bypass-status.txt
awk 'BEGIN{IGNORECASE=1} /^cf-aig-cache-status:/ {gsub("\r","",$2); print toupper($2)}' .labex/bypass-headers.txt \
  | tail -1 | tee .labex/bypass-cache-status.txt
node -e 'const b=require("./.labex/bypass-response.json"); console.log(b.result?.response ?? b.result)'

Deberá obtener HTTP 200 y ningún HIT. Según la respuesta actual del gateway, el encabezado puede describir una omisión o simplemente permanecer en un estado distinto de hit; el registro autorizado del gateway debe mostrar cached: false para fresh-bypass.

Vuelva a Logs en el Dashboard y abra la solicitud fresh-bypass. Compárela con la fila almacenada en caché de public-faq. La misma pregunta llegó a Workers AI porque la omisión aplicada a esta solicitud prevaleció sobre la configuración predeterminada del gateway.

El detalle de fresh-bypass muestra la duración del modelo y el uso de tokens para la pregunta original

Elimine el gateway desechable

En este paso, eliminará el gateway mientras la credencial de administración todavía puede demostrar que ya no existe. Al eliminar este gateway que le pertenece también se eliminan su espacio de nombres de caché de corta duración y sus registros.

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 -X DELETE \
  -H "Authorization: Bearer $GATEWAY_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s);if(!b.success)process.exit(1);console.log("gateway deletion accepted")})'
unset GATEWAY_TOKEN

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
node -e 'const b=require("./.labex/gateways-after-delete.json"),id=process.argv[1],found=(b.result||[]).some(g=>g.id===id);console.log("gateway absent:",!found);if(found)process.exit(1)' "$GATEWAY_ID"

Deberá obtener gateway absent: true. Este inventario autenticado distingue una eliminación real de una página que no se muestra debido al cierre de sesión o a un fallo de red.

Elimine el token y cierre la sesión

En este paso, revocará la credencial de nube restante, eliminará las dos copias temporales del token y desconectará la máquina virtual.

En Cloudflare Dashboard, abra My Profile → API Tokens. Busque el tokenName guardado, abra Actions, seleccione Delete, revise la confirmación y elimine únicamente ese token. Ahora es seguro revocarlo porque la eliminación del gateway ya está comprobada.

Elimine los archivos de tokens del gateway y ascendentes, y después finalice la autorización independiente de Wrangler:

shred -u .labex/gateway-token .labex/upstream-token
npx wrangler logout
npx wrangler whoami --json || true
test ! -e .labex/gateway-token -a ! -e .labex/upstream-token \
  && echo "local token files removed"

Deberá obtener loggedIn: false y local token files removed. La sesión del Dashboard es independiente y permanecerá abierta. Cuando termine el laboratorio, LabEx destruirá esta máquina virtual temporal en lugar de guardarla.

Resumen

Configuró una caché breve de respuestas de AI Gateway para una pregunta pública segura. La primera solicitud produjo un MISS, la repetición exacta se convirtió en un HIT y la entrada modificada creó una entrada independiente. Después utilizó una omisión por solicitud cuando necesitó una respuesta actualizada y confirmó mediante los registros que la solicitud fue atendida por el modelo, no por la copia almacenada.

El próximo laboratorio añadirá controles de tráfico. Aprenderá la diferencia entre limitar la frecuencia con la que llegan las solicitudes y limitar cuánto uso del modelo puede consumir un gateway, manteniendo deliberadamente pequeño el volumen de pruebas y el coste.