Přeskočit na hlavní obsah
PraktickAI
KurzyPro týmySlužbyDokumentaceBlog
KurzyPro týmySlužbyDokumentaceBlog
DomůKurzyAI v produkciIntegrace AI API: OpenAI, Anthropic a lokální modely
Zpět na kurzDalší lekce
Lekce 1 z 740 min

Integrace AI API: OpenAI, Anthropic a lokální modely

Přejít na sekci
  • Tři ekosystémy, jedna architektura
  • Streaming: proč a jak
  • Error handling a retry strategie
  • Lokální modely: kdy a jak
  • Strukturované výstupy a function calling

Tři ekosystémy, jedna architektura

V produkci budete pracovat minimálně se dvěma providery. OpenAI má nejširší ekosystém, Anthropic nejlepší výkon na složitých úlohách, lokální modely (Ollama, vLLM) vám dají kontrolu nad daty a latencí. Klíč je abstrakce — váš kód by neměl být svázaný s jedním providerem.

Základní vzor je jednoduchý: definujte interface pro LLM volání, implementujte ho pro každého providera a přepínejte přes konfiguraci. V TypeScriptu to znamená společný typ ChatMessage a funkci complete(), která vrací AsyncIterable<string> pro streaming.

// Provider-agnostic interface
interface LLMProvider {
  complete(messages: ChatMessage[], opts: CompletionOpts): AsyncIterable<string>;
  countTokens(text: string): Promise<number>;
}

// OpenAI implementation
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const stream = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages,
  stream: true,
});
for await (const chunk of stream) {
  yield chunk.choices[0]?.delta?.content ?? '';
}

Streaming: proč a jak

Bez streamingu uživatel čeká 5-30 sekund na odpověď. Se streamingem vidí první token za 200-500 ms. Pro uživatelský zážitek je to zásadní rozdíl. Ale streaming přidává složitost — musíte řešit partial JSON parsing, backpressure a reconnection.

Anthropic SDK používá Server-Sent Events (SSE) nativně. Pro klienta vystavíte vlastní SSE endpoint nebo použijete ReadableStream v Next.js Route Handleru. Důležité: nikdy neposílejte raw provider stream přímo klientovi — vždy transformujte do vlastního formátu, abyste mohli přepnout providera bez změny frontendu.

// Anthropic streaming with proper error handling
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();
const stream = client.messages.stream({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 4096,
  messages,
});

stream.on('text', (text) => {
  // Transform to your own event format
  res.write(`data: ${JSON.stringify({ type: 'delta', text })}\n\n`);
});
stream.on('error', (err) => {
  res.write(`data: ${JSON.stringify({ type: 'error', code: err.status })}\n\n`);
});

Error handling a retry strategie

Produkční API volání selhávají. Rate limity (429), server errors (500, 503), timeout, síťové chyby. Bez retry logiky váš systém padá při prvním výpadku. S naivním retry (okamžitý opakovaný pokus) zahlcujete providera a dostanete delší ban.

Exponential backoff s jitterem je standard: první retry za 1s, druhý za 2s, třetí za 4s — plus náhodný jitter 0-500ms, aby se requesty od různých klientů nepotkávaly. Pro 429 respektujte header Retry-After. Pro 500/503 retryujte. Pro 400 (bad request) neretryujte — je to bug ve vašem kódu.

async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err: any) {
      if (attempt === maxRetries) throw err;
      if (err.status === 400 || err.status === 401) throw err;
      const base = Math.pow(2, attempt) * 1000;
      const jitter = Math.random() * 500;
      await new Promise(r => setTimeout(r, base + jitter));
    }
  }
  throw new Error('Unreachable');
}

Lokální modely: kdy a jak

Lokální modely (přes Ollama, vLLM nebo TGI) dávají smysl ve třech scénářích: data nesmí opustit vaši infrastrukturu, potřebujete předvídatelnou latenci bez rate limitů, nebo zpracováváte velký objem inference, kde API náklady přesáhnou cenu GPU. Pro prototyp stačí Ollama s OpenAI-kompatibilním endpointem — váš stávající kód funguje beze změny.

// Ollama with OpenAI-compatible endpoint
const localLLM = new OpenAI({
  baseURL: 'http://localhost:11434/v1',
  apiKey: 'ollama', // required but unused
});

const response = await localLLM.chat.completions.create({
  model: 'llama3.1:8b',
  messages,
  stream: true,
});

Strukturované výstupy a function calling

V produkci potřebujete z modelu dostat strukturovaná data — JSON, ne volný text. OpenAI nabízí Structured Outputs s JSON Schema validací. Anthropic má tool_use, kde definujete input schema. Obojí funguje, ale implementace se liší. Váš wrapper by měl tuto diferenci schovat za jednotný interface.

Kritické pravidlo: nikdy neparsujte raw output modelu přímo. Vždy validujte přes Zod nebo podobnou knihovnu. Model může vrátit syntakticky validní JSON, který nesplňuje vaše business pravidla — chybějící pole, špatný typ, hodnota mimo rozsah. Validace na hranici systému je levnější než debug v produkci.

Nikdy nesvazujte aplikační kód s konkrétním providerem. Abstrakce přes interface vám ušetří týdny práce, až budete potřebovat přepnout model — a ten okamžik přijde dřív, než čekáte.

Začněte s jedním providerem a abstrakčním layerem. Druhého přidejte, až ho skutečně potřebujete. Over-engineering na začátku bolí víc než refactoring později.

Build & Deploy AI Apps

Nikdy neposílejte raw provider stream přímo klientovi. Vždy transformujte do vlastního event formátu — budete moci přepnout providera bez změny frontendu.

Multi-provider wrapper

Implementujte LLMProvider interface pro OpenAI a Anthropic. Napište funkci complete(), která přijímá pole zpráv a vrací AsyncIterable<string>. Přidejte retry logiku s exponential backoff. Otestujte přepnutí providera přes environment proměnnou bez změny volajícího kódu.

Nápověda

Použijte factory pattern: createProvider(name: string) vrací správnou implementaci. Pro testy mockujte provider, který vrací předem definované odpovědi.

Hello World s LLM API

Implementujte jednoduchou AI-powered funkci s API: 1) Vyberte si providera (OpenAI, Anthropic, nebo open-source), 2) Nastavte API klíč, 3) Napište funkci, která přijme text a vrátí shrnutí (max 3 věty), 4) Přidejte error handling, 5) Změřte latenci a náklady na 100 requestů. Celé by to mělo trvat max 1 hodinu.

Nápověda

Zdokumentujte svůj postup a výsledky — poslouží jako reference pro budoucí podobné úkoly.

Strukturované výstupy se Zod validací

Implementujte AI funkci, která z textu extrahuje strukturovaná data. 1) Definujte Zod schéma pro výstup (např. ExtractedContact s polemi name, email, phone, company). 2) Napište prompt, který instruuje model vrátit JSON odpovídající schématu. 3) Validujte odpověď modelu přes Zod. 4) Ošetřete případ, kdy model vrátí nevalidní JSON — retry s upřesněným promptem. Otestujte na 10 různých vstupech.

Nápověda

Zod schema funguje jako kontrakt mezi vaším kódem a modelem. Definujte ho nejdřív a z něho odvozujte TypeScript typy — ne naopak.

Klíčové poznatky
  • Abstrahujte LLM volání přes interface — provider lock-in je reálné riziko
  • Streaming zlepšuje UX o řád, ale vyžaduje vlastní event formát
  • Exponential backoff s jitterem je povinný pro produkční retry logiku
  • Vždy validujte strukturované výstupy přes schema — model není databáze
Zpět na kurz
LinkedInX / Twitter
  • Tři ekosystémy, jedna architektura
  • Streaming: proč a jak
  • Error handling a retry strategie
  • Lokální modely: kdy a jak
  • Strukturované výstupy a function calling

PraktickAI

AI školení a konzultace pro technické týmy

KurzyPro týmySlužbyDokumentaceBlog
karel@praktickai.appLinkedIn

© 2026 PraktickAI — SkyVisual s.r.o. Všechna práva vyhrazena. Ochrana soukromí · Obchodní podmínky · Reklamační řád