AI pracowników: modele wnioskowania i wizji LLM bezpośrednio na krawędzi
Workers AI odnotowało wzrost liczby żądań wnioskowania o 4000% rok do roku do I kwartału 2026 r. Dowiedz się, jak bezpośrednio uruchamiać modele tekstu, wizji i mowy w komputerach roboczych bez dedykowanego procesora graficznego, z opóźnieniem poniżej 200 ms.
Wnioskowanie AI przeniesione na krawędź
Do 2023 r. prowadzenie modelu wielkojęzykowego było niemal obowiązkowe komunikować się z zewnętrznym API (OpenAI, Anthropic, Google) lub wdrażać drogie procesory graficzne na dedykowanej infrastrukturze. Opóźnienie sieci dla tych scentralizowanych punktów końcowych dodawał 200–800 ms do każdego żądania, a koszty procesora graficznego były zaporowe aplikacje o małej objętości.
AI pracowników zmienił ten scenariusz. Cloudflare został rozprowadzony Sprzęt do wnioskowania AI (wyspecjalizowane procesory graficzne) w dziesiątkach centrów danych na całym świecie. Modele działają na tym samym sprzęcie, na którym działa Twój Robotnik, co eliminuje objazd sieci do dostawców zewnętrznych. Rezultatem jest wnioskowanie o opóźnieniu obniżone, rozliczane według zużycia bez zarządzania infrastrukturą.
Czego się nauczysz
- Szablony dostępne w Workers AI: LLM, wizja, mowa, osadzanie
- Generowanie tekstu za pomocą Lamy 3.1 i przesyłanie strumieniowe odpowiedzi
- Modele widzenia: analiza obrazu za pomocą LLaVA
- Zamiana mowy na tekst za pomocą funkcji Whisper
- Osadzanie tekstu na potrzeby wyszukiwania semantycznego
- AI Gateway: buforowanie, ograniczanie szybkości i obserwowalność żądań AI
- Limity, koszty i strategie optymalizacji
Przegląd dostępnych modeli
Workers AI oferuje wybór modeli typu open source zoptymalizowanych pod kątem wnioskowania
na sprzęcie Cloudflare. Modele są oznaczone przedrostkiem
@cf/ o @hf/ (gospodarz „Przytulona twarz”):
| Kategoria | Główne modele | Użyj przypadku |
|---|---|---|
| Generacja tekstu | @cf/meta/llama-3.1-8b-instruct, @cf/mistral/mistral-7b-instruct-v0.2 | Chatbot, podsumowanie, pytania i odpowiedzi, generowanie kodu |
| Generowanie tekstu (duże) | @cf/meta/llama-3.3-70b-instruct-fp8-fast | Złożone rozumowanie, zaawansowana analiza |
| Wizja | @cf/llava-hf/llava-1.5-7b-hf, @cf/unum/uform-gen2-qwen-500m | Podpisy do zdjęć, wizualne pytania i odpowiedzi |
| Zamiana mowy na tekst | @cf/openai/whisper, @cf/openai/whisper-large-v3-turbo | Transkrypcja dźwięku |
| Osadzanie tekstu | @cf/baai/bge-base-en-v1.5, @cf/baai/bge-large-en-v1.5 | Wyszukiwanie semantyczne, podobieństwo, RAG |
| Klasyfikacja obrazu | @cf/microsoft/resnet-50 | Klasyfikacja obrazu |
| Tłumaczenie | @cf/meta/m2m100-1.2b | Tłumaczenie na ponad 100 języków |
| Generowanie obrazu | @cf/stabilityai/stable-diffusion-xl-base-1.0 | Tekst do obrazu |
Konfiguracja: Powiązanie AI w pliku wrangler.toml
Aby korzystać z Workers AI, po prostu dodaj powiązanie [ai] w konfiguracji:
# wrangler.toml
name = "ai-worker"
main = "src/worker.ts"
compatibility_date = "2024-09-23"
# Binding per Workers AI
[ai]
binding = "AI"
Typ powiązania TypeScript musi być zadeklarowany w interfejsie Env:
// types.ts - dichiarazione del binding AI
interface Env {
AI: Ai; // Tipo fornito da @cloudflare/workers-types
}
Generowanie tekstu za pomocą Lamy 3.1
Najczęstszym przypadkiem użycia jest generowanie tekstu za pomocą szablonu instrukcja-odpowiedź. Zobaczmy, jak zaimplementować punkt końcowy czatu:
// 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;
}
Bardziej kompletny przykład implementujący asystenta podpowiedzi systemowych i solidna obsługa błędów:
// 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;
}
Modele wizji: analiza obrazu
Modele wizyjne pozwalają na analizę obrazów wejściowych wraz z pytaniem tekstowy. Jest to przydatne do moderowania treści i wydobywania informacji ze zeskanowanych dokumentów i funkcji ułatwień dostępu:
// 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;
}
Zamiana mowy na tekst za pomocą szeptu
Workers AI zawiera Whisper do transkrypcji dźwięku. Model akceptuje dźwięk
w formacie ArrayBuffer i zwraca transkrypcję ze znacznikiem czasu
opcjonalnie:
// 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;
}
Osadzanie tekstu w wyszukiwaniu semantycznym
Osadzenia to wektory numeryczne reprezentujące znaczenie semantyczne tekstu. Workers AI obejmuje modele BGE zoptymalizowane pod kątem wyszukiwania semantycznego. W połączeniu z Vectorize (baza danych wektorów Cloudflare) umożliwiają budowanie Rurociąg RAG całkowicie na krawędzi:
// 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;
}
Brama AI: obserwowalność i buforowanie
Brama Cloudflare AI jest to przejrzyste potwierdzenie, że tak pozycje przed wezwaniami AI (zarówno Workers AI, jak i dostawcy zewnętrzni, tacy jak OpenAI). Dodaje buforowanie semantyczne, ograniczanie szybkości, rejestrowanie i automatyczne przywracanie:
// 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;
}
Alternatywnie możesz skonfigurować bramkę bezpośrednio w powiązaniu AI pliku wrangler.toml:
# wrangler.toml con AI Gateway
[ai]
binding = "AI"
# Il gateway viene usato automaticamente per tutte le chiamate
# Configurato nella dashboard Cloudflare
Ograniczenia i względy kosztowe
| Model | Bezpłatnie (jednostki neuronowe) | Płatne ($ za 1 tys. neuronów) | Typowe opóźnienie |
|---|---|---|---|
| Lama 3.1 8B | 10 tys. NU/dzień za darmo | 0,011 USD / 1 tys. NU | ~500ms-2s (w zależności od tokenów) |
| Lama 3.3 70B FP8 | Zawarte w płatnym planie | 0,050 USD / 1 tys. NU | ~1-5 s |
| Szept | 10 tys. NU/dzień za darmo | 0,011 USD / 1 tys. NU | ~1-3 s na minutę dźwięku |
| Osadzenia BGE | 10 tys. NU/dzień za darmo | 0,011 USD / 1 tys. NU | ~50-200ms |
| Stabilna dyfuzja XL | 10 tys. NU/dzień za darmo | 0,020 USD / obraz | ~3-10 s |
Limity czasu i limity procesora
Workers AI działa poza normalnym budżetem procesora pracownika (płatny plan 30s). Jednak w przypadku dużych modeli, takich jak Llama 70B, może to zająć 5–15 sekund odpowiedzieć. W takich przypadkach pamiętaj o użyciu przesyłanie strumieniowe aby zwracać tokeny na bieżąco i nie przekraczać limitu czasu HTTP klienta. W przypadku długich wniosków rozważ użycie kolejki (kolejki robocze) i powiadom klienta po zakończeniu.
Schemat produkcji: RAG na krawędzi
Coraz powszechniejszym wzorem jest tzw RAG (generacja wspomagana odzyskiwaniem) całkowicie na krawędzi: wektoryzacja do pobierania, Workers AI do osadzania i generowania.
// 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;
}
Wnioski i dalsze kroki
Sztuczna inteligencja pracowników reprezentuje zmianę paradygmatu w dostępie do wnioskowań AI: brak procesora graficznego do zarządzania, brak zewnętrznych dostawców do integracji i rozliczenia do spożycia z hojnym bezpłatnym poziomem. Odzwierciedla to wzrost o 4000% r/r do I kwartału 2026 r szybkie przyjęcie przez programistów poszukujących prostszej ścieżki w stronę sztucznej inteligencji w swoich produktach.
Kombinacja Workers AI + Vectorize + Trwałe obiekty (do zarządzania historia rozmów) pozwala w całości zbudować kompletnych asystentów AI na platformie Cloudflare, bez zewnętrznych zależności.
Następne artykuły z serii
- Artykuł 6: Vercel Edge Runtime — zaawansowane oprogramowanie pośredniczące, Geolokalizacja i testy A/B: jak Vercel wykorzystuje środowisko wykonawcze Edge w Next.js do dostosowywania i flag funkcyjnych.
- Artykuł 7: Trasowanie geograficzne na krawędzi — personalizacja Treść i zgodność z RODO: Twórz logikę opartą na danych geograficznych bez dotykania głównego serwera.
- Artykuł 8: Cache API i strategie unieważniania w Cloudflare Pracownicy: programowalny CDN z TTL, funkcją sprawdzania stanu aktualnego podczas ponownej weryfikacji i czyszczeniem poszczególnych kluczy.







