Workers AI: LLM-inferentie- en visiemodellen direct aan de rand
Workers AI zag een groei van 4000% op jaarbasis in het aantal gevolgtrekkingsverzoeken tot Q1 2026. Leer hoe u tekst-, beeld- en spraakmodellen rechtstreeks kunt uitvoeren in uw werknemers zonder speciale GPU, met een latentie van minder dan 200 ms.
AI-inferentie verplaatst naar de rand
Tot 2023 was het hanteren van een Large Language Model bijna verplicht communiceer met een externe API (OpenAI, Anthropic, Google) of zet dure GPU's in op speciale infrastructuur. De netwerklatentie naar deze gecentraliseerde eindpunten het voegde 200-800 ms toe aan elk verzoek, en de GPU-kosten waren onbetaalbaar toepassingen met laag volume.
Werknemers AI heeft dit scenario veranderd. Cloudflare heeft verspreid AI-inferentiehardware (gespecialiseerde GPU's) in tientallen datacenters over de hele wereld. Modellen draaien op dezelfde hardware waarop uw Worker draait, waardoor u geen problemen meer heeft de netwerkretour naar externe providers. Het resultaat is latentie-inferentie verlaagd, gefactureerd op basis van verbruik zonder infrastructuurbeheer.
Wat je gaat leren
- Sjablonen beschikbaar in Workers AI: LLM, visie, spraak, inbedding
- Tekstgeneratie met Llama 3.1 en antwoordstreaming
- Visiemodellen: beeldanalyse met LLaVA
- Spraak-naar-tekst met fluisteren
- Tekstinsluitingen voor semantisch zoeken
- AI Gateway: caching, snelheidsbeperking en waarneembaarheid van AI-verzoeken
- Limieten, kosten en optimalisatiestrategieën
Overzicht van beschikbare modellen
Workers AI biedt een selectie open-sourcemodellen die zijn geoptimaliseerd voor gevolgtrekking
op Cloudflare-hardware. De modellen worden aangegeven met het voorvoegsel
@cf/ o @hf/ (Knuffelgezicht gehost):
| Categorie | Belangrijkste modellen | Gebruiksgeval |
|---|---|---|
| Tekst genereren | @cf/meta/llama-3.1-8b-instruct, @cf/mistral/mistral-7b-instruct-v0.2 | Chatbot, samenvatting, vraag en antwoord, code genereren |
| Tekst genereren (groot) | @cf/meta/llama-3.3-70b-instruct-fp8-fast | Complexe redenering, geavanceerde analyse |
| Visie | @cf/llava-hf/llava-1.5-7b-hf, @cf/unum/uform-gen2-qwen-500m | Ondertiteling van afbeeldingen, visuele vragen en antwoorden |
| Spraak-naar-tekst | @cf/openai/whisper, @cf/openai/whisper-large-v3-turbo | Audiotranscriptie |
| Tekstinsluitingen | @cf/baai/bge-base-en-v1.5, @cf/baai/bge-large-en-v1.5 | Semantisch zoeken, gelijkenis, RAG |
| Beeldclassificatie | @cf/microsoft/resnet-50 | Beeldclassificatie |
| Vertaling | @cf/meta/m2m100-1.2b | Vertaling 100+ talen |
| Beeld genereren | @cf/stabilityai/stable-diffusion-xl-base-1.0 | Tekst-naar-afbeelding |
Configuratie: AI-binding in wrangler.toml
Om Workers AI te gebruiken, hoeft u alleen maar de binding toe te voegen [ai] in de configuratie:
# wrangler.toml
name = "ai-worker"
main = "src/worker.ts"
compatibility_date = "2024-09-23"
# Binding per Workers AI
[ai]
binding = "AI"
Het TypeScript-type van de binding moet in de interface worden aangegeven Env:
// types.ts - dichiarazione del binding AI
interface Env {
AI: Ai; // Tipo fornito da @cloudflare/workers-types
}
Tekstgeneratie met lama 3.1
Het meest voorkomende gebruiksscenario is het genereren van tekst met een sjabloon instructie-antwoord. Laten we eens kijken hoe we een chateindpunt kunnen implementeren:
// src/worker.ts - endpoint di chat con Llama 3.1
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST' || new URL(request.url).pathname !== '/chat') {
return new Response('POST /chat required', { status: 400 });
}
const { messages, stream = false } = await request.json<ChatRequest>();
// Valida l'input
if (!Array.isArray(messages) || messages.length === 0) {
return Response.json({ error: 'messages array required' }, { status: 400 });
}
if (stream) {
// Streaming response: il modello restituisce token man mano
const aiStream = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages,
stream: true,
max_tokens: 1024,
temperature: 0.7,
});
// Trasforma lo stream AI in Server-Sent Events
return new Response(aiStream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
}
// Risposta sincrona: attende il completion completo
const result = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages,
max_tokens: 1024,
temperature: 0.7,
});
return Response.json({
response: (result as AiTextGenerationOutput).response,
usage: {
// Workers AI non espone ancora i token counts nella risposta base
model: '@cf/meta/llama-3.1-8b-instruct',
},
});
},
};
interface ChatRequest {
messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>;
stream?: boolean;
}
interface Env {
AI: Ai;
}
Een completer voorbeeld dat een systeempromptassistent implementeert en robuuste foutafhandeling:
// src/assistant-worker.ts
const SYSTEM_PROMPT = `Sei un assistente tecnico esperto in cloud computing e edge computing.
Rispondi in modo conciso e tecnico. Se non conosci la risposta, dillo chiaramente.
Non inventare informazioni. Rispondi sempre in italiano a meno che l'utente non scriva in un'altra lingua.`;
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return new Response('Method Not Allowed', { status: 405 });
}
let body: AssistantRequest;
try {
body = await request.json<AssistantRequest>();
} catch {
return Response.json({ error: 'Invalid JSON body' }, { status: 400 });
}
if (!body.question?.trim()) {
return Response.json({ error: 'question field is required' }, { status: 400 });
}
try {
const result = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: body.question },
],
max_tokens: 2048,
temperature: 0.3, // Bassa temperatura per risposte piu deterministiche
}) as AiTextGenerationOutput;
return Response.json({
answer: result.response,
model: '@cf/meta/llama-3.1-8b-instruct',
timestamp: new Date().toISOString(),
});
} catch (err) {
console.error('AI inference error:', err);
return Response.json(
{ error: 'AI inference failed', details: (err as Error).message },
{ status: 500 }
);
}
},
};
interface AssistantRequest {
question: string;
}
interface Env {
AI: Ai;
}
Visiemodellen: beeldanalyse
Met visiemodellen analyseert u invoerbeelden samen met een vraag tekstueel. Dit is handig voor het modereren van inhoud en het extraheren van informatie van gescande documenten en toegankelijkheidsfuncties:
// src/vision-worker.ts - analisi immagini con LLaVA
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return new Response('Method Not Allowed', { status: 405 });
}
// Accetta immagine come Base64 o URL
const body = await request.json<VisionRequest>();
let imageData: number[];
if (body.imageUrl) {
// Scarica l'immagine e converti in array di byte
const imgResponse = await fetch(body.imageUrl);
if (!imgResponse.ok) {
return Response.json({ error: 'Failed to fetch image' }, { status: 400 });
}
const buffer = await imgResponse.arrayBuffer();
imageData = Array.from(new Uint8Array(buffer));
} else if (body.imageBase64) {
// Decodifica Base64
const binaryString = atob(body.imageBase64);
imageData = Array.from({ length: binaryString.length }, (_, i) =>
binaryString.charCodeAt(i)
);
} else {
return Response.json({ error: 'imageUrl or imageBase64 required' }, { status: 400 });
}
const prompt = body.prompt ?? 'Descrivi questa immagine in dettaglio in italiano.';
const result = await env.AI.run('@cf/llava-hf/llava-1.5-7b-hf', {
image: imageData,
prompt,
max_tokens: 512,
}) as AiTextGenerationOutput;
return Response.json({
description: result.response,
prompt,
model: '@cf/llava-hf/llava-1.5-7b-hf',
});
},
};
interface VisionRequest {
imageUrl?: string;
imageBase64?: string;
prompt?: string;
}
interface Env {
AI: Ai;
}
Spraak-naar-tekst met fluisteren
Workers AI bevat Whisper voor audiotranscriptie. Het model accepteert audio
qua formaat ArrayBuffer en retourneert het transcript met tijdstempel
optioneel:
// src/transcribe-worker.ts - Speech-to-text con Whisper
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return new Response('Method Not Allowed', { status: 405 });
}
const contentType = request.headers.get('Content-Type') ?? '';
// Accetta audio come multipart/form-data o application/octet-stream
let audioBuffer: ArrayBuffer;
if (contentType.includes('multipart/form-data')) {
const formData = await request.formData();
const audioFile = formData.get('audio') as File | null;
if (!audioFile) {
return Response.json({ error: 'audio field required in form data' }, { status: 400 });
}
audioBuffer = await audioFile.arrayBuffer();
} else {
// Raw binary audio
audioBuffer = await request.arrayBuffer();
}
if (audioBuffer.byteLength === 0) {
return Response.json({ error: 'Empty audio data' }, { status: 400 });
}
// Limita a 25MB (limite Whisper)
if (audioBuffer.byteLength > 25 * 1024 * 1024) {
return Response.json({ error: 'Audio file too large (max 25MB)' }, { status: 413 });
}
const result = await env.AI.run('@cf/openai/whisper', {
audio: Array.from(new Uint8Array(audioBuffer)),
}) as AiSpeechRecognitionOutput;
return Response.json({
text: result.text,
wordCount: result.text.split(/\s+/).filter(Boolean).length,
model: '@cf/openai/whisper',
});
},
};
interface Env {
AI: Ai;
}
Tekstinsluitingen voor semantisch zoeken
Inbedding zijn numerieke vectoren die de semantische betekenis vertegenwoordigen van een tekst. Workers AI bevat BGE-modellen die zijn geoptimaliseerd voor semantisch zoeken. Gecombineerd met Vectorize (de vectordatabase van Cloudflare) kunt u bouwen RAG-leiding volledig aan de rand:
// src/embedding-worker.ts - generazione embeddings + ricerca semantica
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/embed' && request.method === 'POST') {
const { texts } = await request.json<EmbedRequest>();
if (!Array.isArray(texts) || texts.length === 0) {
return Response.json({ error: 'texts array required' }, { status: 400 });
}
// BGE genera embedding di 768 dimensioni (base) o 1024 (large)
const result = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: texts,
}) as AiTextEmbeddingsOutput;
return Response.json({
embeddings: result.data,
dimensions: result.data[0]?.length ?? 0,
count: result.data.length,
model: '@cf/baai/bge-base-en-v1.5',
});
}
if (url.pathname === '/search' && request.method === 'POST') {
const { query, topK = 5 } = await request.json<SearchRequest>();
// 1. Genera l'embedding per la query
const queryEmbed = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: [query],
}) as AiTextEmbeddingsOutput;
// 2. Ricerca semantica su Vectorize
const results = await env.VECTORIZE.query(queryEmbed.data[0], {
topK,
returnMetadata: 'all',
});
return Response.json({
query,
results: results.matches.map((match) => ({
id: match.id,
score: match.score,
metadata: match.metadata,
})),
});
}
return new Response('Not Found', { status: 404 });
},
};
interface EmbedRequest {
texts: string[];
}
interface SearchRequest {
query: string;
topK?: number;
}
interface Env {
AI: Ai;
VECTORIZE: VectorizeIndex;
}
AI Gateway: waarneembaarheid en caching
Cloudflare AI-gateway het is een transparante proxy die ja is posities vóór AI-oproepen (zowel Workers AI als externe providers zoals OpenAI). Voegt semantische caching, snelheidsbeperking, logboekregistratie en automatische terugval toe:
// src/worker-with-gateway.ts - Workers AI via AI Gateway
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { prompt } = await request.json<{ prompt: string }>();
// Usa il gateway invece del binding diretto
// Il gateway aggiunge: caching, retry, logging, rate limiting
const response = await fetch(
`https://gateway.ai.cloudflare.com/v1/${env.CF_ACCOUNT_ID}/${env.AI_GATEWAY_ID}/workers-ai/@cf/meta/llama-3.1-8b-instruct`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${env.CF_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [{ role: 'user', content: prompt }],
max_tokens: 512,
}),
}
);
if (!response.ok) {
const error = await response.text();
return Response.json({ error }, { status: response.status });
}
const result = await response.json();
return Response.json(result);
},
};
interface Env {
AI: Ai;
CF_ACCOUNT_ID: string;
CF_API_TOKEN: string;
AI_GATEWAY_ID: string;
}
Als alternatief kunt u de gateway rechtstreeks in de AI-binding van wrangler.toml configureren:
# wrangler.toml con AI Gateway
[ai]
binding = "AI"
# Il gateway viene usato automaticamente per tutte le chiamate
# Configurato nella dashboard Cloudflare
Beperkingen en kostenoverwegingen
| Model | Vrij (neuroneenheden) | Betaald ($per 1K neuronen) | Typische latentie |
|---|---|---|---|
| Lama 3.1 8B | 10K NU/dag gratis | $ 0,011 / 1K NU | ~500 ms-2s (afhankelijk van tokens) |
| Lama 3.3 70B FP8 | Inbegrepen in het betaalde abonnement | $ 0,050 / 1K NU | ~1-5s |
| Fluisteren | 10K NU/dag gratis | $ 0,011 / 1K NU | ~1-3s per minuut audio |
| BGE-inbedding | 10K NU/dag gratis | $ 0,011 / 1K NU | ~50-200 ms |
| Stabiele diffusie XL | 10K NU/dag gratis | $ 0,020 / afbeelding | ~3-10s |
Time-outs en CPU-limieten
Workers AI werkt buiten het normale CPU-budget van de Worker (betaald abonnement voor de jaren 30). Bij grote modellen zoals de Llama 70B kan het echter 5-15 seconden duren reageren. Zorg er in deze gevallen voor dat u de streamen om tokens te retourneren terwijl u bezig bent en de HTTP-time-out van de client niet te overschrijden. Voor lange gevolgtrekkingen kunt u overwegen een wachtrij (Workers Queues) te gebruiken en hiervan op de hoogte te stellen de cliënt als hij klaar is.
Productiepatroon: RAG at the Edge
Een steeds vaker voorkomend patroon is de RAG (Retrieval-Augmented Generation) helemaal aan de rand: vectoriseren voor ophalen, Workers AI voor insluiten en genereren.
// src/rag-worker.ts - RAG completo all'edge
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') return new Response('POST only', { status: 405 });
const { question } = await request.json<{ question: string }>();
// Step 1: Genera l'embedding della domanda
const queryEmbedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: [question],
}) as AiTextEmbeddingsOutput;
// Step 2: Recupera i chunk rilevanti dal vector store
const relevant = await env.DOCS.query(queryEmbedding.data[0], {
topK: 3,
returnMetadata: 'all',
});
// Step 3: Costruisce il contesto dai chunk recuperati
const context = relevant.matches
.map((m) => m.metadata?.['text'] as string ?? '')
.filter(Boolean)
.join('\n\n---\n\n');
// Step 4: Genera la risposta con il contesto
const answer = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{
role: 'system',
content: `Rispondi alla domanda basandoti SOLO sul contesto fornito.
Se il contesto non contiene informazioni sufficienti, dillo esplicitamente.
Contesto:
${context}`,
},
{ role: 'user', content: question },
],
max_tokens: 1024,
temperature: 0.1,
}) as AiTextGenerationOutput;
return Response.json({
question,
answer: answer.response,
sources: relevant.matches.map((m) => ({
id: m.id,
score: m.score,
title: m.metadata?.['title'],
})),
});
},
};
interface Env {
AI: Ai;
DOCS: VectorizeIndex;
}
Conclusies en volgende stappen
Workers AI vertegenwoordigt een paradigmaverschuiving in de toegang tot AI-gevolgtrekkingen: geen GPU om te beheren, geen externe providers om te integreren, facturering voor consumptie met royale gratis laag. Een groei van 4000% op jaarbasis tot het eerste kwartaal van 2026 weerspiegelt dit snelle acceptatie door ontwikkelaars die op zoek zijn naar een eenvoudiger pad richting AI in hun producten.
De combinatie Workers AI + Vectorize + Sustainable Objects (voor het beheren van de gespreksgeschiedenis) kunt u volledige AI-assistenten bouwen op het Cloudflare-platform, zonder externe afhankelijkheden.
Volgende artikelen in de serie
- Artikel 6: Vercel Edge Runtime — Geavanceerde middleware, Geolocatie en A/B-testen: hoe Vercel de edge-runtime gebruikt met Next.js voor maatwerk en functievlaggen.
- Artikel 7: Geografische routing aan de rand: personalisatie AVG-inhoud en naleving: bouw geogebaseerde logica zonder de hoofdserver aan te raken.
- Artikel 8: Cache-API en invalidatiestrategieën in Cloudflare Werknemers: programmeerbaar CDN met TTL, verouderd tijdens opnieuw valideren en opschonen per sleutel.







