Πρώτη Ενσωμάτωση LLM API σε Production
Καλέστε LLM API από τον server με ασφαλές κλειδί, timeout και Zod validation.
Χωρίς πρόσφατο έλεγχο περιεχομένου. Οι εντολές και τα παραδείγματα ενδέχεται να έχουν αλλάξει από τη δημοσίευση.
Καλέστε LLM API από τον server με ασφαλές κλειδί, timeout και Zod validation.
Πρώτη Ενσωμάτωση LLM API σε Production
Η ενσωμάτωση Large Language Models (LLMs) όπως το Claude, το GPT-4o ή το Gemini σε παραγωγικές web εφαρμογές διαφέρει ριζικά από ένα απλό demo script. Στην παραγωγή απαιτείται απόλυτη προστασία API keys, διαχείριση timeouts, εγγύηση δομημένης εξόδου (Structured Outputs) και έλεγχος κόστους.
1. Απαραβίαστη Ασφάλεια Κλειδιών με server-only
Το API Key ενός μοντέλου τεχνητής νοημοσύνης δεν πρέπει ΠΟΤΕ να εκτεθεί στον browser. Ένα εκτεθειμένο κλειδί μπορεί να εξαντλήσει το όριο χρέωσής σας σε λίγα λεπτά:
typescript// lib/ai/client.ts import 'server-only' // Εγγυάται compilation error εάν το αρχείο εισαχθεί σε Client Component! const apiKey = process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY; if (!apiKey) { throw new Error('MISSING_AI_KEY: Παρακαλούμε ορίστε το ANTHROPIC_API_KEY στο περιβάλλον.'); }
2. Διαχείριση Timeouts με AbortController
Τα αιτήματα σε LLM APIs μπορεί να καθυστερήσουν σημαντικά. Χωρίς timeout, ο serverless worker σας θα παραμείνει δεσμευμένος μέχρι το hard execution limit, αυξάνοντας το κόστος υποδομής:
typescriptexport async function callModelWithTimeout(prompt: string, timeoutMs = 15000) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); try { const res = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, }, body: JSON.stringify({ model: 'gpt-4o-mini', messages: [{ role: 'user', content: prompt }], response_format: { type: 'json_object' }, }), signal: controller.signal, }); if (!res.ok) { throw new Error(`LLM API returned status ${res.status}`); } return await res.json(); } catch (err: unknown) { if (err instanceof Error && err.name === 'AbortError') { throw new Error(`Το αίτημα προς το AI μοντέλο έληξε λόγω χρονικού ορίου (${timeoutMs}ms).`); } throw err; } finally { clearTimeout(timer); } }
3. Επικύρωση Δομημένης Εξόδου (Structured Outputs) με Zod
Τα LLMs είναι πιθανοτικά συστήματα (probabilistic) και ενδέχεται να επιστρέψουν μη έγκυρο JSON ή να παραλείψουν πεδία. Η επικύρωση με Zod είναι υποχρεωτική:
typescriptimport { z } from 'zod' // Καθορισμός του αναμενόμενου σχήματος απάντησης const CodeReviewResponseSchema = z.object({ score: z.number().min(0).max(100), summary: z.string().min(10), criticalIssues: z.array( z.object({ file: z.string(), line: z.number().int().positive().optional(), description: z.string(), suggestion: z.string(), }) ), }); export type CodeReviewResult = z.infer<typeof CodeReviewResponseSchema>; export function parseAIReviewResponse(rawJson: unknown): CodeReviewResult { const parsed = CodeReviewResponseSchema.safeParse(rawJson); if (!parsed.success) { console.error('[AI Schema Mismatch]', parsed.error.format()); throw new Error('Η απάντηση του AI μοντέλου δεν συμμορφώνεται με το αναμενόμενο σχήμα δεδομένων.'); } return parsed.data; }
4. Production Checklist για Ενσωμάτωση LLM
| Έλεγχος | Κατάσταση | Σκοπός |
|---|---|---|
| Ασφάλεια Κλειδιού | server-only import | Μηδενική πιθανότητα διαρροής στο client bundle |
| Timeout Protection | AbortController (15s-30s) | Αποτροπή κρεμασμένων Serverless functions |
| Output Validation | Strict Zod Schema validation | Προστασία downstream UI από null pointer errors |
| Fallback Μηχανισμός | Static graceful degradation | Εμφάνιση εναλλακτικής βοήθειας σε περίπτωση API outage |