Varför Edge Functions för AI
Tre anledningar till att Edge Functions är rätt val för AI API-anrop:
1. Säkerhet: Din OpenAI/Anthropic API-nyckel lever som en serversidig hemlighet, aldrig exponerad för klienten. Ingen med din frontendkod kan extrahera nyckeln.
2. Databasåtkomst: Edge Functions körs inuti Supabase infrastruktur och har direkt, låg-latens åtkomst till din PostgreSQL-databas. Du kan hämta användarkontext, lagra resultat och logga användning i samma funktion som anropar AI.
3. Strömningsstöd: Edge Functions stöder Response-strömning, vilket låter dig skicka AI-output till klienten ord för ord, dramatiskt förbättrar upplevd prestanda för långa AI-svar.
För svenska bolag finns ytterligare ett skäl: EU-väst-regionen i Supabase innebär att din Edge Function exekveras i EU, vilket förenklar GDPR-dokumentation och minskar latens för svenska användare.
Grundläggande OpenAI proxy-funktion
Den enklaste Edge Function: ta emot en prompt, anropa OpenAI, returnera svaret.
```typescript
import OpenAI from "npm:openai"
const openai = new OpenAI({ apiKey: Deno.env.get("OPENAI_API_KEY") })
Deno.serve(async (req) => {
const { prompt } = await req.json()
const chat = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: prompt }],
max_tokens: 500
})
return new Response(
JSON.stringify({ result: chat.choices[0].message.content }),
{ headers: { "Content-Type": "application/json" } }
)
})
```
Distribuera med: supabase functions deploy openai-proxy. Ange hemligheten: supabase secrets set OPENAI_API_KEY=sk-....
Enkel men komplett, och säker. Inga API-nycklar i WeWeb eller FlutterFlow-koden.
Lägga till autentisering och hastighetsbegränsning
Varje AI Edge Function bör verifiera att användaren är autentiserad och kontrollera deras användningsgränser.
```typescript
import { createClient } from "npm:@supabase/supabase-js"
Deno.serve(async (req) => {
// Verifiera auth-token
const token = req.headers.get("Authorization")?.replace("Bearer ", "")
const supabase = createClient(Deno.env.get("SUPABASE_URL"), Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"))
const { data: { user }, error } = await supabase.auth.getUser(token)
if (error || !user) return new Response("Unauthorized", { status: 401 })
// Kontrollera hastighetsgräns (max 20 förfrågningar/timme)
const oneHourAgo = new Date(Date.now() - 3600000).toISOString()
const { count } = await supabase
.from("ai_usage_log")
.select("*", { count: "exact" })
.eq("user_id", user.id)
.gte("created_at", oneHourAgo)
if (count >= 20) return new Response("Rate limit exceeded", { status: 429 })
// ... anropa OpenAI och logga användning
})
```
Logga sedan varje lyckad AI-förfrågan till tabellen. Det ger dig inte bara hastighetsbegränsning utan också fullständig revisionslogg, viktigt för GDPR-artikel 5-efterlevnad och för att förstå vilka funktioner som faktiskt används av svenska kunder.
Strömning av svar till WeWeb
Strömning skickar AI-output till klienten progressivt, användare ser text visas ord för ord istället för att vänta på hela svaret.
I Edge Function:
```typescript
const stream = await openai.chat.completions.create({
model: "gpt-4o",
messages,
stream: true
})
const readable = new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || ""
controller.enqueue(new TextEncoder().encode(text))
}
controller.close()
}
})
return new Response(readable, {
headers: { "Content-Type": "text/event-stream" }
})
```
I WeWeb: använd en anpassad JavaScript-åtgärd för att hämta stream-URL:en och uppdatera en sidvariabel tecken för tecken när chunkarna ankommer. Bind en textruta till variabeln för realtidsvisning.
Strömning förbättrar upplevd prestanda dramatiskt. För en svensk B2B-app där yrkesverksamma väntar på AI-svar är skillnaden mellan "väntar 5 sekunder" och "ser text genereras direkt" avgörande för produktacceptans.
Bygga en RAG-pipeline (Retrieval Augmented Generation)
RAG förbättrar AI-svar genom att injicera relevant kunskap i prompten vid förfrågningstid. Arkitektur:
1. Kunskapsinsamling (kör en gång): För varje dokument i din kunskapsbas, anropa OpenAIs embedding-API för att få en 1536-dimensionell vektor. Lagra vektorer i Supabase med pgvector-tillägget.
2. Förfrågningstid: När en användare ställer en fråga, bädda in frågan (samma embedding-API), kör sedan en likhetssökning i Supabase: SELECT content, 1 - (embedding <=> query_embedding) AS similarity FROM documents ORDER BY similarity DESC LIMIT 3.
3. Utökad prompt: Injicera de 3 bäst matchande dokumenten i systemprompten: "Svara enbart med följande kontext: [docs]. Om svaret inte finns i kontexten, säg att du inte vet."
Resultat: AI:n svarar enbart från din dokumentation, utan hallucination om saker du inte dokumenterat. Perfekt för svenska kundtjänstbottar med branschspecifik kunskapsbas.
Kallstart-optimering för Edge Functions
Supabase Edge Functions är Deno-baserade och körs på Deno Deploys globala edge-nätverk. En kallstart, det första anropet av en funktion som inte anropats nyligen, tar vanligtvis 200-500 ms. För AI-funktioner där användare förväntar sig omedelbar återkoppling kan denna kallstartslatens vara märkbar.
Flera optimeringsstrategier minskar effekten av kallstarter. För det första, importera bara det du behöver. En funktion som importerar hela OpenAI SDK:t lägger till mer bundle-vikt än en som bara importerar ChatCompletion-typen. Använd named imports och tree-shaking-vänliga mönster. För det andra, förvärm kritiska funktioner genom att anropa dem enligt ett schema. Ett Supabase cron-jobb som anropar din AI-funktion med en syntetisk förfrågan var 5:e minut håller instansen varm till kostnaden av några få API-anrop per dag.
För det tredje, använd responscachning för deterministiska prompts. Om användare ofta ställer samma typ av fråga (dokumentsammanfattning, kategoriklassificering), cacha resultatet i en Supabase-tabell nyckla på en hash av inputen. Returnera det cachade resultatet omedelbart för upprepade inputs, noll kallstart, noll API-kostnad, svarstid under 10 ms. Detta är särskilt effektivt för klassificeringsuppgifter där mängden möjliga inputs är begränsad.
AI-inferens vid edgen: anropa OpenAI och Anthropic från Edge Functions
Både OpenAI SDK och Anthropic SDK fungerar i Denos körningsmiljö, vilket är det Supabase Edge Functions använder. Du importerar dem via npm:-specifikationer: import OpenAI from 'npm:openai' och import Anthropic from 'npm:@anthropic-ai/sdk'. Båda SDK:erna hanterar HTTPS-anropen, återförsöksslogiken och felhanteringen för sina respektive API:er.
För en AI-funktion i produktion bör du hantera modellval dynamiskt. Lagra modellnamnet som en Supabase Edge Function-hemlighet istället för att hårdkoda det. Det låter dig växla från gpt-4o till gpt-4o-mini (för uppgifter med lägre kostnad) eller från claude-3-5-sonnet till claude-3-haiku utan att omdistribuera funktionen. Du uppdaterar hemligheten och nästa förfrågan använder den nya modellen.
Kostnadshantering är kritiskt för AI-funktioner med öppen användaråtkomst. Logga varje API-anrop med token-antalet som returneras i svaret. Ställ in månatliga utgiftsvarningar i din OpenAI- eller Anthropic-dashboard. För användare på gratisnivå, sätt ett tokenbudgettak per månad och tillämpa det i Edge Function innan API-anropet görs. Vi bygger in det här kostnadsspårningslagret i varje AI-funktion vi levererar, det har förhindrat oväntade räkningar på 3 000 dollar i månaden på mer än ett kundprojekt.
Strömmande svar: Server-Sent Events-mönstret
Server-Sent Events-mönstret (SSE) är det standardsätt att strömma AI-svar från en Supabase Edge Function till en webbläsare. Funktionen sätter Content-Type: text/event-stream och skriver chunkar i formatet data: {text}\n\n allt eftersom de anländer från AI-API:et. Webbläsaren använder det inbyggda EventSource-API:et eller ett fetch med ReadableStream för att konsumera strömmen inkrementellt.
I WeWeb kräver implementering av SSE en anpassad JavaScript-åtgärd eftersom de inbyggda HTTP-förfrågningsåtgärderna väntar på hela svaret innan de fortsätter. Åtgärden öppnar en fetch-förfrågan, läser svarskroppen som en ström med response.body.getReader(), avkodar varje chunk och lägger till den i en sidvariabel. Den här sidvariabeln är bunden till ett textelement på canvasen, så användare ser texten visas tecken för tecken.
Resultatet är en dramatiskt bättre AI-funktions-UX. Ett 300-ords AI-svar från GPT-4o tar ungefär 5 sekunder att slutföra. Utan strömning ser användaren en snurra i 5 sekunder och sedan visas hela texten. Med strömning börjar de läsa svaret inom 300 ms efter att de skickat sin prompt. I användartester rankas strömning konsekvent som mer responsivt och intelligent-kännande, även om den totala genereringstiden är densamma.
Använda Edge Functions som webhook-hanterare
Edge Functions är ett utmärkt val för att hantera webhooks från externa tjänster, Stripe-betalningshändelser, GitHub push-notiser, Twilio SMS, eller vilken tjänst som helst som POST:ar data till en URL. De är alltid tillgängliga (ingen server att starta upp), globalt distribuerade (låg latens från webhook-avsändarens datacenter), och har direkt Supabase-databasåtkomst för att uppdatera poster som svar på händelser.
En Stripe webhook Edge Function validerar webhook-signaturen, tolkar händelsetypen och uppdaterar den relevanta Supabase-posten. För en prenumerationsuppgraderingshändelse: verifiera signaturen med stripe.webhooks.constructEvent() med din webhook-hemlighet, extrahera kund-ID och ny plan, uppdatera subscriptions-tabellen i Supabase, och returnera ett 200-svar inom 5 sekunder (Stripes timeout). Det här är den kompletta betalningslivscykelhanteraren, ingen separat server behövs.
För AI-applikationer används webhooks för asynkron bearbetning. När en användare laddar upp ett dokument för AI-analys låter du dem inte vänta, du köar uppgiften via en Supabase-radinsättning, ett bakgrundsjobb plockar upp den och anropar AI-API:et, och när resultatet är klart skickar en Supabase-trigger en push-notis eller uppdaterar instrumentpanelen via realtid. Edge Functions hanterar både intagswebhooken och den utgående notisen.
Säkerhetsmönster för AI Edge Functions
Den viktigaste säkerhetsåtgärden för alla AI Edge Functions är att verifiera anroparens identitet innan något API-anrop görs. Extrahera alltid JWT:n från Authorization: Bearer-headern, anropa supabase.auth.getUser(token) för att verifiera den, och kontrollera att användaren har rätt roll eller prenumerationsnivå för den begärda åtgärden. En oautentiserad AI-funktion är en direkt väg till obegränsade API-kostnader för vem som helst som upptäcker din endpoint-URL.
Hemlighetshantering i Supabase Edge Functions använder CLI-kommandot supabase secrets set och Deno.env.get() vid körning. Hårdkoda aldrig API-nycklar i funktionens källkod, även i ett privat repository, hemligheter hör hemma i hemlighetslagret, inte i källkodskontroll. Rotera hemligheter omedelbart om ett repository av misstag görs publikt eller om en nyckel loggas i felspår.
Inputvalidering förhindrar prompt injection-attacker, där en illvillig användare skapar en input som ändrar AI:ns beteende. Validera inputlängd, ta bort farliga tecken, och om funktionen använder en systemprompt som innehåller användartillhandahållen data, sanera användarens input före interpolering. En enkel längdkontroll (if (prompt.length > 2000) return error) eliminerar en klass av missbruk där användare skapar extremt långa prompts för att maximera beräkningskostnaden.