ChatGPT API - Integracja AI w aplikacjach webowych
ChatGPT API Integracja
ai-mlChatGPT API - Integracja AI w aplikacjach webowych
OpenAI API to jedno z najpotezniejszych narzedzi dostepnych dla deweloperow, ktorzy chca wzbogacic swoje aplikacje o mozliwosci sztucznej inteligencji. Od generowania tekstu, przez analize dokumentow, po budowe zaawansowanych chatbotow - ChatGPT API otwiera drzwi do nowej generacji aplikacji webowych. W tym przewodniku omowimy wszystkie kluczowe aspekty integracji, od podstaw po zaawansowane techniki optymalizacji.
Przeglad OpenAI API#
OpenAI udostepnia RESTful API, ktore pozwala na interakcje z modelami jezykowymi z poziomu dowolnego jezyka programowania. Kluczowe elementy ekosystemu to:
- Chat Completions API - glowny endpoint do konwersacji i generowania tekstu
- Embeddings API - generowanie wektorowych reprezentacji tekstu
- Moderation API - filtrowanie tresci pod katem bezpieczenstwa
- Assistants API - zaawansowane asystenty z pamiecia i narzedziami
- Images API (DALL-E) - generowanie i edycja obrazow
- Audio API (Whisper, TTS) - transkrypcja mowy i synteza glosu
Instalacja i konfiguracja#
Zacznijmy od instalacji oficjalnego SDK dla Node.js:
npm install openai
Konfiguracja klienta:
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
Klucz API uzyskasz w panelu platform.openai.com. Nigdy nie umieszczaj klucza bezposrednio w kodzie - zawsze korzystaj ze zmiennych srodowiskowych.
Modele GPT-4 i GPT-3.5#
OpenAI oferuje kilka modeli rozniących sie mozliwosciami, szybkoscia i kosztem:
GPT-4 Turbo (gpt-4-turbo)#
- Najnowsza wersja GPT-4 z oknem kontekstowym 128K tokenow
- Wiedza do kwietnia 2024
- Doskonaly do zlozonych zadan: analiza kodu, rozumowanie wieloetapowe, generowanie dlugich tekstow
- Koszt: ~$10/1M tokenow wejsciowych, ~$30/1M tokenow wyjsciowych
GPT-4o (gpt-4o)#
- Zoptymalizowana wersja GPT-4 - szybsza i tansza
- Multimodalna - obsluguje tekst, obrazy i audio
- Okno kontekstowe 128K tokenow
- Koszt: ~$2.50/1M tokenow wejsciowych, ~$10/1M tokenow wyjsciowych
GPT-3.5 Turbo (gpt-3.5-turbo)#
- Szybki i ekonomiczny model do prostszych zadan
- Okno kontekstowe 16K tokenow
- Idealny do: klasyfikacji, podsumowań, prostych chatbotow
- Koszt: ~$0.50/1M tokenow wejsciowych, ~$1.50/1M tokenow wyjsciowych
// Wybor modelu w zaleznosci od zadania
const model = taskComplexity === "high"
? "gpt-4-turbo"
: taskComplexity === "medium"
? "gpt-4o"
: "gpt-3.5-turbo";
Chat Completions API - podstawy#
Chat Completions API to glowny endpoint do interakcji z modelami GPT. Komunikacja odbywa sie za pomoca tablicy wiadomosci z rolami:
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function chatCompletion() {
const response = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{
role: "system",
content:
"Jestes ekspertem ds. programowania webowego. " +
"Odpowiadasz zwiezle i podajesz przyklady kodu.",
},
{
role: "user",
content: "Jak zaimplementowac middleware w Next.js?",
},
],
temperature: 0.7,
max_tokens: 1000,
});
return response.choices[0].message.content;
}
Role w konwersacji#
- system - instrukcje definiujace zachowanie modelu (persona, styl, ograniczenia)
- user - wiadomosci od uzytkownika
- assistant - odpowiedzi modelu (wykorzystywane do kontynuacji konwersacji)
Kluczowe parametry#
| Parametr | Opis | Zakres |
|----------|------|--------|
| temperature | Kreatywnosc odpowiedzi | 0.0 - 2.0 |
| max_tokens | Maksymalna dlugosc odpowiedzi | 1 - limit modelu |
| top_p | Nucleus sampling | 0.0 - 1.0 |
| frequency_penalty | Kara za powtarzanie slow | -2.0 - 2.0 |
| presence_penalty | Kara za powtarzanie tematow | -2.0 - 2.0 |
| stop | Sekwencje zatrzymania | string[] |
Streaming - odpowiedzi w czasie rzeczywistym#
Streaming pozwala na wyswietlanie odpowiedzi token po tokenie, co znacznie poprawia UX:
async function streamChat(userMessage: string) {
const stream = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{ role: "system", content: "Jestes pomocnym asystentem." },
{ role: "user", content: userMessage },
],
stream: true,
});
let fullResponse = "";
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || "";
fullResponse += content;
process.stdout.write(content); // Wyswietlanie w czasie rzeczywistym
}
return fullResponse;
}
Streaming w Next.js z Server-Sent Events#
// app/api/chat/route.ts
import { NextRequest } from "next/server";
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export async function POST(req: NextRequest) {
const { messages } = await req.json();
const stream = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages,
stream: true,
});
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || "";
if (content) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ content })}\n\n`)
);
}
}
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
controller.close();
},
});
return new Response(readable, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
Function Calling i Tool Use#
Function calling pozwala modelowi na wywolywanie zdefiniowanych przez dewelopera funkcji, co umozliwia integracje z zewnetrznymi API i bazami danych:
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// Definicja narzedzi
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
{
type: "function",
function: {
name: "get_weather",
description: "Pobiera aktualną pogode dla podanego miasta",
parameters: {
type: "object",
properties: {
city: {
type: "string",
description: "Nazwa miasta, np. Warszawa",
},
unit: {
type: "string",
enum: ["celsius", "fahrenheit"],
description: "Jednostka temperatury",
},
},
required: ["city"],
},
},
},
{
type: "function",
function: {
name: "search_products",
description:
"Wyszukuje produkty w bazie danych na podstawie zapytania",
parameters: {
type: "object",
properties: {
query: { type: "string", description: "Fraza wyszukiwania" },
category: { type: "string", description: "Kategoria produktu" },
maxPrice: { type: "number", description: "Maksymalna cena" },
},
required: ["query"],
},
},
},
];
// Implementacje funkcji
async function getWeather(city: string, unit = "celsius") {
// Wywolanie zewnetrznego API pogodowego
const response = await fetch(
`https://api.weather.example/current?city=${city}&unit=${unit}`
);
return response.json();
}
async function searchProducts(
query: string,
category?: string,
maxPrice?: number
) {
// Zapytanie do bazy danych
return db.products.findMany({
where: {
name: { contains: query },
...(category && { category }),
...(maxPrice && { price: { lte: maxPrice } }),
},
});
}
// Obsluga function calling
async function handleToolCalls(userMessage: string) {
const response = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [{ role: "user", content: userMessage }],
tools,
tool_choice: "auto",
});
const message = response.choices[0].message;
if (message.tool_calls) {
const toolResults = await Promise.all(
message.tool_calls.map(async (toolCall) => {
const args = JSON.parse(toolCall.function.arguments);
let result;
switch (toolCall.function.name) {
case "get_weather":
result = await getWeather(args.city, args.unit);
break;
case "search_products":
result = await searchProducts(
args.query,
args.category,
args.maxPrice
);
break;
default:
result = { error: "Nieznana funkcja" };
}
return {
role: "tool" as const,
tool_call_id: toolCall.id,
content: JSON.stringify(result),
};
})
);
// Drugie wywolanie z wynikami narzedzi
const finalResponse = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{ role: "user", content: userMessage },
message,
...toolResults,
],
});
return finalResponse.choices[0].message.content;
}
return message.content;
}
Embeddingi - wektorowe reprezentacje tekstu#
Embeddingi to numeryczne reprezentacje tekstu w przestrzeni wektorowej. Pozwalaja na wyszukiwanie semantyczne, klasteryzacje i porownywanie tresci:
// Generowanie embeddingu
async function generateEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: "text-embedding-3-small",
input: text,
dimensions: 1536,
});
return response.data[0].embedding;
}
// Obliczanie podobienstwa kosinusowego
function cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, ai, i) => sum + ai * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, ai) => sum + ai * ai, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, bi) => sum + bi * bi, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
// Wyszukiwanie semantyczne
async function semanticSearch(
query: string,
documents: { id: string; text: string; embedding: number[] }[]
) {
const queryEmbedding = await generateEmbedding(query);
const results = documents
.map((doc) => ({
...doc,
similarity: cosineSimilarity(queryEmbedding, doc.embedding),
}))
.sort((a, b) => b.similarity - a.similarity)
.slice(0, 5);
return results;
}
Modele embeddingowe#
| Model | Wymiary | Koszt/1M tokenow |
|-------|---------|-------------------|
| text-embedding-3-small | 512-1536 | ~$0.02 |
| text-embedding-3-large | 256-3072 | ~$0.13 |
| text-embedding-ada-002 | 1536 | ~$0.10 |
Zarzadzanie tokenami#
Tokeny to podstawowa jednostka rozliczeniowa w OpenAI API. Efektywne zarzadzanie tokenami jest kluczowe dla kontroli kosztow:
import { encoding_for_model } from "tiktoken";
// Liczenie tokenow
function countTokens(text: string, model = "gpt-4-turbo"): number {
const enc = encoding_for_model(model as any);
const tokens = enc.encode(text);
enc.free();
return tokens.length;
}
// Przycinanie kontekstu do limitu tokenow
function trimMessages(
messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[],
maxTokens: number
): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {
const systemMessage = messages.find((m) => m.role === "system");
const conversationMessages = messages.filter((m) => m.role !== "system");
let totalTokens = systemMessage
? countTokens(systemMessage.content as string)
: 0;
const trimmed: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [];
// Iteracja od najnowszych wiadomosci
for (let i = conversationMessages.length - 1; i >= 0; i--) {
const msgTokens = countTokens(
conversationMessages[i].content as string
);
if (totalTokens + msgTokens > maxTokens) break;
totalTokens += msgTokens;
trimmed.unshift(conversationMessages[i]);
}
if (systemMessage) trimmed.unshift(systemMessage);
return trimmed;
}
Rate Limiting i obsluga bledow#
OpenAI stosuje limity zapytan (RPM - requests per minute) i tokenow (TPM - tokens per minute). Oto strategia obslugi:
import OpenAI from "openai";
// Klasa z retry i exponential backoff
class OpenAIClient {
private client: OpenAI;
private maxRetries: number;
constructor(apiKey: string, maxRetries = 3) {
this.client = new OpenAI({ apiKey });
this.maxRetries = maxRetries;
}
async chatCompletion(
params: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
) {
let lastError: Error | null = null;
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
try {
return await this.client.chat.completions.create(params);
} catch (error) {
lastError = error as Error;
if (error instanceof OpenAI.RateLimitError) {
const waitTime = Math.pow(2, attempt) * 1000;
console.warn(
`Rate limit - czekam ${waitTime}ms (proba ${attempt + 1})`
);
await new Promise((resolve) => setTimeout(resolve, waitTime));
continue;
}
if (error instanceof OpenAI.APIError) {
if (error.status && error.status >= 500) {
const waitTime = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, waitTime));
continue;
}
}
throw error;
}
}
throw lastError;
}
}
Optymalizacja kosztow#
Koszty API moga szybko rosnac. Oto sprawdzone strategie optymalizacji:
1. Wybor odpowiedniego modelu#
function selectModel(task: string): string {
const simpleTaskPatterns = [
/klasyfikacja|kategoria/i,
/podsumowanie|streszczenie/i,
/tlumaczenie|przetlumacz/i,
/formatowanie|format/i,
];
const isSimple = simpleTaskPatterns.some((p) => p.test(task));
return isSimple ? "gpt-3.5-turbo" : "gpt-4o";
}
2. Cache odpowiedzi#
import { Redis } from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
async function cachedCompletion(
messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[],
model: string
) {
const cacheKey = `openai:${model}:${JSON.stringify(messages)}`;
const cached = await redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const response = await openai.chat.completions.create({
model,
messages,
});
await redis.setex(cacheKey, 3600, JSON.stringify(response));
return response;
}
3. Kompresja promptow#
// Zamiast dlugich instrukcji, uzyj zwiezlych promptow
// ZLE:
const verbosePrompt =
"Chcialabym, zebys przeanalizowal ponizszy tekst i wygenerowal " +
"krotkie podsumowanie, ktore bedzie zawierac najwazniejsze informacje...";
// DOBRZE:
const concisePrompt =
"Podsumuj tekst w 2-3 zdaniach, zachowujac kluczowe fakty:";
4. Batching zapytan#
async function batchProcess(items: string[], batchSize = 5) {
const results: string[] = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const promises = batch.map((item) =>
openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: `Przetworz: ${item}` }],
})
);
const batchResults = await Promise.all(promises);
results.push(
...batchResults.map(
(r) => r.choices[0].message.content || ""
)
);
}
return results;
}
Prompt Engineering - najlepsze praktyki#
Jakość odpowiedzi modelu zalezy w duzej mierze od jakosci promptu. Oto kluczowe techniki:
Few-shot prompting#
const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
{
role: "system",
content: "Klasyfikujesz opinie klientow jako: pozytywna, negatywna, neutralna.",
},
{
role: "user",
content: "Swietny produkt, polecam kazdemu!",
},
{
role: "assistant",
content: "pozytywna",
},
{
role: "user",
content: "Produkt okej, nic specjalnego.",
},
{
role: "assistant",
content: "neutralna",
},
{
role: "user",
content: "Fatalna jakosc, nigdy wiecej.",
},
];
Chain-of-Thought#
const systemPrompt = `Jestes ekspertem od analizy danych.
Gdy odpowiadasz:
1. Zidentyfikuj kluczowe dane wejsciowe
2. Opisz swoj tok rozumowania krok po kroku
3. Podaj wnioski z uzasadnieniem
4. Zakoncz konkretna rekomendacja
Mysli poczatkowe oznacz tagiem <thinking>, a finalna odpowiedz tagiem <answer>.`;
Structured Output#
const response = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{
role: "system",
content:
"Zwracaj odpowiedzi wylacznie w formacie JSON. " +
"Schemat: { summary: string, keywords: string[], sentiment: string, score: number }",
},
{
role: "user",
content: `Przeanalizuj opinie: "${reviewText}"`,
},
],
response_format: { type: "json_object" },
});
Budowanie chatbota konwersacyjnego#
Kompletna implementacja chatbota z pamiecia konwersacji:
import OpenAI from "openai";
interface ConversationMessage {
role: "system" | "user" | "assistant";
content: string;
}
class Chatbot {
private openai: OpenAI;
private conversations: Map<string, ConversationMessage[]>;
private systemPrompt: string;
private maxMessages: number;
constructor(systemPrompt: string, maxMessages = 20) {
this.openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
this.conversations = new Map();
this.systemPrompt = systemPrompt;
this.maxMessages = maxMessages;
}
private getConversation(sessionId: string): ConversationMessage[] {
if (!this.conversations.has(sessionId)) {
this.conversations.set(sessionId, [
{ role: "system", content: this.systemPrompt },
]);
}
return this.conversations.get(sessionId)!;
}
async sendMessage(
sessionId: string,
userMessage: string
): Promise<string> {
const conversation = this.getConversation(sessionId);
conversation.push({ role: "user", content: userMessage });
// Przycinanie do limitu wiadomosci
if (conversation.length > this.maxMessages + 1) {
const system = conversation[0];
const recent = conversation.slice(-this.maxMessages);
conversation.length = 0;
conversation.push(system, ...recent);
}
const response = await this.openai.chat.completions.create({
model: "gpt-4o",
messages: conversation,
temperature: 0.7,
max_tokens: 800,
});
const assistantMessage =
response.choices[0].message.content || "";
conversation.push({ role: "assistant", content: assistantMessage });
return assistantMessage;
}
clearConversation(sessionId: string): void {
this.conversations.delete(sessionId);
}
}
// Uzycie
const supportBot = new Chatbot(
"Jestes asystentem obslugi klienta firmy TechShop. " +
"Pomagasz w sprawach zamowien, zwrotow i informacji o produktach. " +
"Odpowiadasz uprzejmie i zwiezle po polsku."
);
Integracja RAG (Retrieval-Augmented Generation)#
RAG pozwala modelowi odpowiadac na pytania na podstawie wlasnych danych, eliminujac halucynacje:
import OpenAI from "openai";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// Wyszukiwanie relevantnych dokumentow
async function findRelevantDocs(
query: string,
limit = 5
): Promise<{ content: string; source: string; similarity: number }[]> {
const queryEmbedding = await generateEmbedding(query);
const result = await pool.query(
`SELECT content, source,
1 - (embedding <=> $1::vector) as similarity
FROM documents
WHERE 1 - (embedding <=> $1::vector) > 0.7
ORDER BY embedding <=> $1::vector
LIMIT $2`,
[JSON.stringify(queryEmbedding), limit]
);
return result.rows;
}
// RAG pipeline
async function ragQuery(userQuestion: string): Promise<string> {
// 1. Wyszukaj relevantne dokumenty
const docs = await findRelevantDocs(userQuestion);
// 2. Zbuduj kontekst
const context = docs
.map((d) => `[Zrodlo: ${d.source}]\n${d.content}`)
.join("\n\n---\n\n");
// 3. Wygeneruj odpowiedz
const response = await openai.chat.completions.create({
model: "gpt-4-turbo",
messages: [
{
role: "system",
content:
"Odpowiadaj na pytania wylacznie na podstawie podanego kontekstu. " +
"Jesli kontekst nie zawiera odpowiedzi, powiedz o tym wprost. " +
"Cytuj zrodla w odpowiedzi.",
},
{
role: "user",
content: `Kontekst:\n${context}\n\nPytanie: ${userQuestion}`,
},
],
temperature: 0.3,
});
return response.choices[0].message.content || "";
}
Bezpieczenstwo i moderacja tresci#
OpenAI udostepnia Moderation API do filtrowania niebezpiecznych tresci:
// Moderacja tresci
async function moderateContent(
text: string
): Promise<{ flagged: boolean; categories: string[] }> {
const response = await openai.moderations.create({ input: text });
const result = response.results[0];
const flaggedCategories = Object.entries(result.categories)
.filter(([, flagged]) => flagged)
.map(([category]) => category);
return {
flagged: result.flagged,
categories: flaggedCategories,
};
}
// Middleware moderacji dla chatbota
async function safeChatMiddleware(
userMessage: string,
handler: (msg: string) => Promise<string>
): Promise<string> {
// Sprawdz wiadomosc uzytkownika
const inputModeration = await moderateContent(userMessage);
if (inputModeration.flagged) {
console.warn("Zablokowano wiadomosc:", inputModeration.categories);
return "Przepraszam, ale nie moge przetworzyc tej wiadomosci.";
}
// Wygeneruj odpowiedz
const response = await handler(userMessage);
// Sprawdz odpowiedz modelu
const outputModeration = await moderateContent(response);
if (outputModeration.flagged) {
console.warn("Zablokowano odpowiedz:", outputModeration.categories);
return "Przepraszam, nie jestem w stanie udzielić odpowiedzi na to pytanie.";
}
return response;
}
Najlepsze praktyki bezpieczenstwa#
- Walidacja wejscia - sprawdzaj dlugosc i zawartosc wiadomosci uzytkownikow
- Rate limiting - ogranicz liczbe zapytan na uzytkownika
- Prompt injection protection - oddzielaj instrukcje systemowe od danych uzytkownika
- Logowanie - monitoruj uzycie API i podejrzane wzorce
- Koszty - ustaw limity budzetowe w panelu OpenAI
Integracja z Next.js - kompletny przyklad API Route#
Pelna implementacja endpointu chatowego w Next.js App Router:
// app/api/chat/route.ts
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { Redis } from "ioredis";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const redis = new Redis(process.env.REDIS_URL!);
// Rate limiting
async function checkRateLimit(ip: string): Promise<boolean> {
const key = `ratelimit:chat:${ip}`;
const requests = await redis.incr(key);
if (requests === 1) await redis.expire(key, 60);
return requests <= 10; // max 10 req/min
}
// Walidacja wejscia
function validateInput(body: unknown): {
valid: boolean;
messages?: OpenAI.Chat.Completions.ChatCompletionMessageParam[];
error?: string;
} {
if (!body || typeof body !== "object") {
return { valid: false, error: "Nieprawidlowe dane wejsciowe" };
}
const { messages } = body as { messages: unknown };
if (!Array.isArray(messages) || messages.length === 0) {
return { valid: false, error: "Brak wiadomosci" };
}
if (messages.length > 50) {
return { valid: false, error: "Za wiele wiadomosci" };
}
return { valid: true, messages };
}
export async function POST(req: NextRequest) {
try {
// Rate limiting
const ip = req.headers.get("x-forwarded-for") || "unknown";
const allowed = await checkRateLimit(ip);
if (!allowed) {
return NextResponse.json(
{ error: "Zbyt wiele zapytan. Sprobuj ponownie za minute." },
{ status: 429 }
);
}
// Walidacja
const body = await req.json();
const validation = validateInput(body);
if (!validation.valid) {
return NextResponse.json(
{ error: validation.error },
{ status: 400 }
);
}
// Moderacja ostatniej wiadomosci
const lastMessage = validation.messages![
validation.messages!.length - 1
];
if (lastMessage.role === "user") {
const moderation = await openai.moderations.create({
input: lastMessage.content as string,
});
if (moderation.results[0].flagged) {
return NextResponse.json(
{ error: "Wiadomosc narusza zasady uzytkowania." },
{ status: 400 }
);
}
}
// Streaming response
const stream = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "system",
content:
"Jestes pomocnym asystentem. " +
"Odpowiadasz po polsku, zwiezle i merytorycznie.",
},
...validation.messages!,
],
stream: true,
temperature: 0.7,
max_tokens: 1000,
});
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
try {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ content })}\n\n`)
);
}
}
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
} catch (err) {
controller.error(err);
} finally {
controller.close();
}
},
});
return new Response(readable, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
} catch (error) {
console.error("Chat API error:", error);
return NextResponse.json(
{ error: "Wewnetrzny blad serwera" },
{ status: 500 }
);
}
}
Porownanie z Claude API i Gemini API#
Wybierajac dostawce AI API, warto porownac kluczowe roznice:
| Cecha | OpenAI (GPT-4) | Anthropic (Claude 3) | Google (Gemini Pro) | |-------|-----------------|---------------------|---------------------| | Okno kontekstowe | 128K | 200K | 1M+ | | Function calling | Tak | Tak (tool use) | Tak | | Streaming | Tak | Tak | Tak | | Multimodal | Tak (vision, audio) | Tak (vision) | Tak (vision, audio, video) | | Structured output | JSON mode | JSON z XML | JSON mode | | Cena (input/1M) | od $2.50 | od $3 | od $1.25 | | Cena (output/1M) | od $10 | od $15 | od $5 |
Kiedy wybrac OpenAI?#
- Najszerszy ekosystem - Assistants API, fine-tuning, DALL-E, Whisper
- Function calling - najbardziej dojrzala implementacja
- Spolecznosc - najwieksza baza wiedzy i przykladow
- Fine-tuning - mozliwosc dostosowania modeli do wlasnych danych
Kiedy rozwazyc alternatywy?#
- Claude - dlugi kontekst (200K), lepsza zgodnosc z instrukcjami, bezpieczenstwo
- Gemini - milionowe okno kontekstowe, integracja z Google Cloud, nizsza cena
- Lokalne modele (Ollama/Llama) - pelna prywatnosc danych, brak kosztow API
Ujednolicona warstwa abstrakcji#
// Wspolny interfejs dla roznych dostawcow AI
interface AIProvider {
chat(messages: Message[], options?: ChatOptions): Promise<string>;
stream(
messages: Message[],
options?: ChatOptions
): AsyncIterable<string>;
embed(text: string): Promise<number[]>;
}
class OpenAIProvider implements AIProvider {
async chat(messages: Message[], options?: ChatOptions) {
const response = await openai.chat.completions.create({
model: options?.model || "gpt-4o",
messages: messages as any,
});
return response.choices[0].message.content || "";
}
async *stream(messages: Message[], options?: ChatOptions) {
const stream = await openai.chat.completions.create({
model: options?.model || "gpt-4o",
messages: messages as any,
stream: true,
});
for await (const chunk of stream) {
yield chunk.choices[0]?.delta?.content || "";
}
}
async embed(text: string) {
const response = await openai.embeddings.create({
model: "text-embedding-3-small",
input: text,
});
return response.data[0].embedding;
}
}
Podsumowanie#
ChatGPT API to potezne narzedzie, ktore otwiera ogromne mozliwosci dla deweloperow aplikacji webowych. Kluczowe wnioski:
- Wybieraj model swiadomie - GPT-4 do zlozonych zadan, GPT-3.5 do prostych operacji
- Implementuj streaming - znacznie poprawia doswiadczenie uzytkownika
- Korzystaj z function calling - integruje AI z logika biznesowa aplikacji
- Stosuj RAG - eliminuje halucynacje i pozwala korzystac z wlasnych danych
- Optymalizuj koszty - cache, odpowiedni model, kompresja promptow
- Dbaj o bezpieczenstwo - moderacja, rate limiting, walidacja wejscia
Potrzebujesz integracji AI w swojej aplikacji?#
MDS Software Solutions Group specjalizuje sie w integracji rozwiazan AI z aplikacjami webowymi. Budujemy inteligentne chatboty, systemy RAG, wyszukiwarki semantyczne i narzedzia automatyzacji oparte na OpenAI API, Claude i innych modelach LLM.
Skontaktuj sie z nami, aby omowic, jak sztuczna inteligencja moze usprawnić Twoj biznes i dac Ci przewage konkurencyjna. Oferujemy konsultacje, projektowanie architektury AI oraz pelna implementacje - od prototypu po produkcje.
Zespół ekspertów programistycznych specjalizujących się w nowoczesnych technologiach webowych.