Node.js ile OpenAI GPT API Entegrasyonu

ChatGPT API'sını kullanarak profesyonel AI uygulamaları geliştirmeyi öğrenin

📅 11 Kasım 2025
⏱️ 15 dakika okuma
🏷️ AI & Machine Learning
👨‍💻 İleri Seviye

🚀 OpenAI GPT API'ya Giriş

OpenAI GPT API, dünyanın en gelişmiş doğal dil işleme modellerinden birine erişim sağlar. Node.js uygulamalarınıza ChatGPT benzeri yapay zeka yetenekleri kazandırmak için bu API'yi nasıl entegre edeceğinizi detaylıyla öğreneceksiniz.

🤖 Chat Completion

GPT-4 ve GPT-3.5-turbo modelleriyle dinamik sohbet uygulamaları geliştirin

🔧 Function Calling

AI'ın harici fonksiyonları çağırabilmesini sağlayarak güçlü entegrasyonlar oluşturun

🎯 Fine-tuning

Özel verilerinizle modeli eğiterek iş süreçlerinize özel AI asistanları yaratın

📊 Embeddings

Metinsel verileri vektörel temsillere dönüştürerek semantik arama sistemleri oluşturun

⚙️ Proje Kurulumu ve Konfigürasyon

OpenAI API'sını Node.js projenize entegre etmek için gerekli paketleri kuralım ve temel konfigürasyonu yapalım.

Gerekli Paketlerin Kurulumu

package.json
{ "name": "openai-integration-app", "version": "1.0.0", "description": "Node.js OpenAI API Integration", "main": "index.js", "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "jest" }, "dependencies": { "openai": "^4.20.1", "express": "^4.18.2", "dotenv": "^16.3.1", "cors": "^2.8.5", "helmet": "^7.1.0", "express-rate-limit": "^7.1.5", "winston": "^3.11.0" }, "devDependencies": { "nodemon": "^3.0.1", "jest": "^29.7.0" } }
Terminal
npm install openai express dotenv cors helmet express-rate-limit winston npm install -D nodemon jest

Çevre Değişkenleri Konfigürasyonu

.env
# OpenAI API Configuration OPENAI_API_KEY=your_openai_api_key_here OPENAI_ORGANIZATION_ID=your_org_id_here # Application Configuration PORT=3000 NODE_ENV=development # Rate Limiting RATE_LIMIT_WINDOW_MS=900000 RATE_LIMIT_MAX_REQUESTS=100 # Logging LOG_LEVEL=info LOG_FILE_PATH=./logs/app.log

⚠️ Güvenlik Uyarısı

API anahtarınızı asla version control sistemine commit etmeyin! .env dosyasını .gitignore'a ekleyin ve production ortamında environment variables kullanın.

🎯 Temel API Kullanımı

OpenAI client'ını kurarak ilk API çağrınızı yapalım ve temel konfigürasyon seçeneklerini inceleyelim.

config/openai.js
const OpenAI = require('openai'); const winston = require('winston'); // Logger konfigürasyonu const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: process.env.LOG_FILE_PATH || './logs/app.log' }) ] }); // OpenAI client konfigürasyonu class OpenAIService { constructor() { this.client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, organization: process.env.OPENAI_ORGANIZATION_ID, timeout: 60000, // 60 saniye timeout maxRetries: 3, // Başarısız istekleri 3 kez tekrarla }); // Desteklenen modeller this.models = { GPT4: 'gpt-4-1106-preview', GPT4_TURBO: 'gpt-4-turbo-preview', GPT35: 'gpt-3.5-turbo-1106', GPT35_16K: 'gpt-3.5-turbo-16k-0613' }; logger.info('OpenAI service initialized successfully'); } // Model listesini getir async getAvailableModels() { try { const response = await this.client.models.list(); return response.data.filter(model => model.id.includes('gpt') ); } catch (error) { logger.error('Failed to fetch models:', error); throw error; } } // Token sayısını hesapla (yaklaşık) estimateTokenCount(text) { // GPT tokenizer'ı tam olarak simüle etmek için tiktoken kullanılabilir // Burada basit bir yaklaşım kullanıyoruz return Math.ceil(text.length / 4); } // Maliyet hesaplama (GPT-4 için) calculateCost(inputTokens, outputTokens, model = 'gpt-4') { const pricing = { 'gpt-4': { input: 0.03, output: 0.06 }, // $0.03/$0.06 per 1K tokens 'gpt-3.5-turbo': { input: 0.001, output: 0.002 } }; const modelPricing = pricing[model] || pricing['gpt-4']; return { inputCost: (inputTokens / 1000) * modelPricing.input, outputCost: (outputTokens / 1000) * modelPricing.output, totalCost: (inputTokens / 1000) * modelPricing.input + (outputTokens / 1000) * modelPricing.output }; } } module.exports = new OpenAIService();

💬 Chat Completion API

En yaygın kullanım senaryosu olan Chat Completion API'sini kullanarak konuşma tabanlı AI uygulamaları geliştirmeyi öğrenelim.

services/chatService.js
const openaiService = require('../config/openai'); const winston = require('winston'); class ChatService { constructor() { this.conversationHistory = new Map(); // Kullanıcı sohbet geçmişi this.logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: './logs/chat.log' }) ] }); } // Temel chat completion async generateResponse(userMessage, options = {}) { try { const { model = openaiService.models.GPT35, temperature = 0.7, maxTokens = 150, systemPrompt = "Sen yardımcı bir AI asistanısın.", userId = 'default' } = options; // Kullanıcı sohbet geçmişini getir veya oluştur let conversation = this.conversationHistory.get(userId) || []; // System message'ı başa ekle (sadece ilk mesajda) if (conversation.length === 0) { conversation.push({ role: 'system', content: systemPrompt }); } // Kullanıcı mesajını ekle conversation.push({ role: 'user', content: userMessage }); // OpenAI API çağrısı const response = await openaiService.client.chat.completions.create({ model: model, messages: conversation, temperature: temperature, max_tokens: maxTokens, top_p: 1, frequency_penalty: 0, presence_penalty: 0, stream: false }); const assistantMessage = response.choices[0].message.content; // Assistant yanıtını sohbet geçmişine ekle conversation.push({ role: 'assistant', content: assistantMessage }); // Sohbet geçmişini sakla (maksimum 20 mesaj) if (conversation.length > 20) { conversation = [conversation[0], ...conversation.slice(-19)]; } this.conversationHistory.set(userId, conversation); // İstatistikleri logla this.logger.info('Chat completion generated', { userId, model, inputTokens: response.usage.prompt_tokens, outputTokens: response.usage.completion_tokens, totalTokens: response.usage.total_tokens }); return { response: assistantMessage, usage: response.usage, model: model, conversationLength: conversation.length }; } catch (error) { this.logger.error('Chat generation failed:', error); throw new Error(`Chat generation failed: ${error.message}`); } } // Streaming response (gerçek zamanlı yanıt) async generateStreamingResponse(userMessage, options = {}, onChunk) { try { const { model = openaiService.models.GPT35, temperature = 0.7, maxTokens = 150, systemPrompt = "Sen yardımcı bir AI asistanısın.", userId = 'default' } = options; let conversation = this.conversationHistory.get(userId) || []; if (conversation.length === 0) { conversation.push({ role: 'system', content: systemPrompt }); } conversation.push({ role: 'user', content: userMessage }); const stream = await openaiService.client.chat.completions.create({ model: model, messages: conversation, temperature: temperature, max_tokens: maxTokens, stream: true }); let fullResponse = ''; for await (const chunk of stream) { const content = chunk.choices[0]?.delta?.content || ''; if (content) { fullResponse += content; onChunk(content); // Chunk'ı callback ile gönder } } // Tam yanıtı sohbet geçmişine ekle conversation.push({ role: 'assistant', content: fullResponse }); if (conversation.length > 20) { conversation = [conversation[0], ...conversation.slice(-19)]; } this.conversationHistory.set(userId, conversation); return fullResponse; } catch (error) { this.logger.error('Streaming chat generation failed:', error); throw error; } } // Sohbet geçmişini temizle clearConversation(userId) { this.conversationHistory.delete(userId); this.logger.info(`Conversation cleared for user: ${userId}`); } // Sohbet geçmişini getir getConversationHistory(userId) { return this.conversationHistory.get(userId) || []; } } module.exports = new ChatService();

🔧 Gelişmiş Özellikler

OpenAI API'nin güçlü özelliklerinden Function Calling ve Embeddings kullanarak daha akıllı AI uygulamaları geliştirmeyi öğrenelim.

Function Calling - AI'ın Fonksiyonları Çağırması

GPT-4 ve GPT-3.5-turbo modelleri, tanımladığınız fonksiyonları çağırabilir. Bu özellik sayesinde AI, veritabanı sorguları yapabilir, API çağrıları gerçekleştirebilir ve dış kaynaklara erişebilir.

services/functionCalling.js
const openaiService = require('../config/openai'); class FunctionCallingService { constructor() { // Kullanılabilir fonksiyonları tanımla this.availableFunctions = { get_weather: this.getWeather, search_database: this.searchDatabase, send_email: this.sendEmail, calculate_math: this.calculateMath }; // Fonksiyon tanımları (OpenAI'a gönderilecek schema) this.functionDefinitions = [ { name: "get_weather", description: "Belirtilen şehir için hava durumu bilgisini getirir", parameters: { type: "object", properties: { city: { type: "string", description: "Hava durumu bilgisi alınacak şehir adı" }, unit: { type: "string", enum: ["celsius", "fahrenheit"], description: "Sıcaklık birimi" } }, required: ["city"] } }, { name: "search_database", description: "Veritabanında ürün araması yapar", parameters: { type: "object", properties: { query: { type: "string", description: "Aranacak ürün adı veya kategorisi" }, limit: { type: "integer", description: "Döndürülecek maksimum sonuç sayısı", default: 10 } }, required: ["query"] } } ]; } // Hava durumu fonksiyonu async getWeather(args) { const { city, unit = "celsius" } = JSON.parse(args); // Gerçek API çağrısı burada yapılabilir return { city: city, temperature: unit === "celsius" ? "22°C" : "72°F", condition: "Güneşli", humidity: "65%" }; } // Veritabanı arama fonksiyonu async searchDatabase(args) { const { query, limit = 10 } = JSON.parse(args); // Gerçek veritabanı sorgusu burada yapılabilir return [ { id: 1, name: `${query} Ürün 1`, price: 299 }, { id: 2, name: `${query} Ürün 2`, price: 399 } ].slice(0, limit); } // Function calling ile chat completion async chatWithFunctions(userMessage, userId = 'default') { try { const messages = [ { role: "system", content: "Sen yardımcı bir AI asistanısın. Kullanıcı isteklerine göre uygun fonksiyonları çağırabilirsin." }, { role: "user", content: userMessage } ]; // İlk API çağrısı - fonksiyon çağrısı gerekli mi? const response = await openaiService.client.chat.completions.create({ model: openaiService.models.GPT4, messages: messages, functions: this.functionDefinitions, function_call: "auto" }); const message = response.choices[0].message; // Eğer AI bir fonksiyon çağırmak istiyorsa if (message.function_call) { const functionName = message.function_call.name; const functionArgs = message.function_call.arguments; // İlgili fonksiyonu çağır if (this.availableFunctions[functionName]) { const functionResult = await this.availableFunctions[functionName].call(this, functionArgs); // Fonksiyon sonucunu mesaj geçmişine ekle messages.push(message); messages.push({ role: "function", name: functionName, content: JSON.stringify(functionResult) }); // Fonksiyon sonucu ile ikinci API çağrısı const secondResponse = await openaiService.client.chat.completions.create({ model: openaiService.models.GPT4, messages: messages }); return { response: secondResponse.choices[0].message.content, functionCalled: functionName, functionResult: functionResult, usage: secondResponse.usage }; } } // Fonksiyon çağrısı gerekli değilse normal yanıt return { response: message.content, functionCalled: null, usage: response.usage }; } catch (error) { console.error('Function calling failed:', error); throw error; } } } module.exports = new FunctionCallingService();

Embeddings - Metinleri Vektörel Temsile Dönüştürme

Embeddings, metinleri sayısal vektörlere dönüştürerek benzerlik analizi, semantik arama ve kümeleme işlemleri yapmanızı sağlar.

services/embeddingService.js
const openaiService = require('../config/openai'); class EmbeddingService { constructor() { this.embeddingModel = 'text-embedding-ada-002'; this.embeddingCache = new Map(); // Embedding önbelleği } // Metin için embedding oluştur async createEmbedding(text) { try { // Önbellekten kontrol et const cacheKey = Buffer.from(text).toString('base64'); if (this.embeddingCache.has(cacheKey)) { return this.embeddingCache.get(cacheKey); } const response = await openaiService.client.embeddings.create({ model: this.embeddingModel, input: text, }); const embedding = response.data[0].embedding; // Önbelleğe kaydet this.embeddingCache.set(cacheKey, embedding); return embedding; } catch (error) { console.error('Embedding creation failed:', error); throw error; } } // Çoklu metinler için embedding oluştur async createBatchEmbeddings(texts) { try { const response = await openaiService.client.embeddings.create({ model: this.embeddingModel, input: texts, }); return response.data.map(item => item.embedding); } catch (error) { console.error('Batch embedding creation failed:', error); throw error; } } // İki embedding arasındaki cosine similarity hesapla calculateSimilarity(embedding1, embedding2) { const dotProduct = embedding1.reduce((sum, a, i) => sum + a * embedding2[i], 0); const magnitude1 = Math.sqrt(embedding1.reduce((sum, a) => sum + a * a, 0)); const magnitude2 = Math.sqrt(embedding2.reduce((sum, a) => sum + a * a, 0)); return dotProduct / (magnitude1 * magnitude2); } // Semantik arama yapı async semanticSearch(query, documents) { try { // Query embedding'ini oluştur const queryEmbedding = await this.createEmbedding(query); // Dokuman embedding'lerini oluştur const docEmbeddings = await this.createBatchEmbeddings(documents); // Benzerlik skorlarını hesapla const similarities = docEmbeddings.map((docEmbedding, index) => ({ document: documents[index], similarity: this.calculateSimilarity(queryEmbedding, docEmbedding), index: index })); // Benzerlik skoruna göre sırala return similarities .sort((a, b) => b.similarity - a.similarity) .slice(0, 5); // En benzer 5 dokümanı döndür } catch (error) { console.error('Semantic search failed:', error); throw error; } } // Metin kümeleme async clusterDocuments(documents, numClusters = 3) { try { // Tüm dokümanlar için embedding oluştur const embeddings = await this.createBatchEmbeddings(documents); // Basit k-means clustering implementasyonu // Gerçek uygulamada scikit-learn benzeri kütüphaneler kullanılabilir const clusters = Array.from({ length: numClusters }, () => []); embeddings.forEach((embedding, index) => { // Rastgele kümelere ata (daha sofistike clustering algoritmaları kullanılabilir) const clusterIndex = index % numClusters; clusters[clusterIndex].push({ document: documents[index], embedding: embedding, index: index }); }); return clusters; } catch (error) { console.error('Document clustering failed:', error); throw error; } } } module.exports = new EmbeddingService();

🤖 AI Chatbot Geliştirme

Express.js kullanarak tam özellikli bir AI chatbot API'si geliştirmeyi ve web arayüzü ile entegre etmeyi öğrenelim.

app.js - Ana Uygulama Dosyası
const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); const winston = require('winston'); require('dotenv').config(); const chatService = require('./services/chatService'); const functionCallingService = require('./services/functionCalling'); const embeddingService = require('./services/embeddingService'); const app = express(); const PORT = process.env.PORT || 3000; // Logger konfigürasyonu const logger = winston.createLogger({ level: 'info', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: './logs/app.log' }) ] }); // Middleware app.use(helmet()); app.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:3001', credentials: true })); app.use(express.json({ limit: '10mb' })); app.use(express.static('public')); // Rate limiting const chatLimiter = rateLimit({ windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000, // 15 dakika max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS) || 50, // Her IP için 50 istek message: { error: 'Çok fazla istek gönderildi. Lütfen daha sonra tekrar deneyin.', retryAfter: Math.ceil((parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 900000) / 1000) }, standardHeaders: true, legacyHeaders: false, }); // Chat endpoint'leri app.post('/api/chat', chatLimiter, async (req, res) => { try { const { message, userId, options = {} } = req.body; if (!message || message.trim().length === 0) { return res.status(400).json({ error: 'Mesaj boş olamaz', code: 'EMPTY_MESSAGE' }); } if (message.length > 2000) { return res.status(400).json({ error: 'Mesaj çok uzun (maksimum 2000 karakter)', code: 'MESSAGE_TOO_LONG' }); } const result = await chatService.generateResponse(message, { ...options, userId: userId || `user_${Date.now()}` }); logger.info('Chat request processed', { userId: userId, messageLength: message.length, responseLength: result.response.length, tokensUsed: result.usage.total_tokens }); res.json({ response: result.response, usage: result.usage, conversationLength: result.conversationLength, timestamp: new Date().toISOString() }); } catch (error) { logger.error('Chat request failed:', error); // OpenAI API hatalarını yakala if (error.message.includes('insufficient_quota')) { return res.status(429).json({ error: 'API kotası doldu. Lütfen daha sonra tekrar deneyin.', code: 'QUOTA_EXCEEDED' }); } if (error.message.includes('rate_limit')) { return res.status(429).json({ error: 'Rate limit aşıldı. Lütfen daha sonra tekrar deneyin.', code: 'RATE_LIMIT_EXCEEDED' }); } res.status(500).json({ error: 'Bir hata oluştu. Lütfen daha sonra tekrar deneyin.', code: 'INTERNAL_SERVER_ERROR' }); } }); // Streaming chat endpoint app.post('/api/chat/stream', chatLimiter, async (req, res) => { try { const { message, userId, options = {} } = req.body; // SSE headers res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Cache-Control' }); // Streaming response handler const handleChunk = (chunk) => { res.write(`data: ${JSON.stringify({ chunk, type: 'content' })}\n\n`); }; const fullResponse = await chatService.generateStreamingResponse( message, { ...options, userId: userId || `user_${Date.now()}` }, handleChunk ); // Stream sonu res.write(`data: ${JSON.stringify({ type: 'done', fullResponse })}\n\n`); res.end(); } catch (error) { logger.error('Streaming chat failed:', error); res.write(`data: ${JSON.stringify({ type: 'error', error: error.message })}\n\n`); res.end(); } }); // Function calling endpoint app.post('/api/chat/functions', chatLimiter, async (req, res) => { try { const { message, userId } = req.body; const result = await functionCallingService.chatWithFunctions( message, userId || `user_${Date.now()}` ); res.json({ response: result.response, functionCalled: result.functionCalled, functionResult: result.functionResult, usage: result.usage, timestamp: new Date().toISOString() }); } catch (error) { logger.error('Function calling failed:', error); res.status(500).json({ error: 'Function calling sırasında hata oluştu', code: 'FUNCTION_CALL_ERROR' }); } }); // Semantik arama endpoint app.post('/api/search', chatLimiter, async (req, res) => { try { const { query, documents } = req.body; if (!query || !documents || !Array.isArray(documents)) { return res.status(400).json({ error: 'Query ve documents gereklidir', code: 'INVALID_INPUT' }); } const results = await embeddingService.semanticSearch(query, documents); res.json({ results: results, query: query, timestamp: new Date().toISOString() }); } catch (error) { logger.error('Semantic search failed:', error); res.status(500).json({ error: 'Semantik arama sırasında hata oluştu', code: 'SEARCH_ERROR' }); } }); // Conversation management endpoints app.delete('/api/chat/clear/:userId', (req, res) => { try { const { userId } = req.params; chatService.clearConversation(userId); res.json({ message: 'Sohbet geçmişi temizlendi', userId: userId }); } catch (error) { logger.error('Clear conversation failed:', error); res.status(500).json({ error: 'Sohbet geçmişi temizlenirken hata oluştu' }); } }); app.get('/api/chat/history/:userId', (req, res) => { try { const { userId } = req.params; const history = chatService.getConversationHistory(userId); res.json({ history: history, userId: userId, count: history.length }); } catch (error) { logger.error('Get conversation history failed:', error); res.status(500).json({ error: 'Sohbet geçmişi alınırken hata oluştu' }); } }); // Health check endpoint app.get('/api/health', (req, res) => { res.json({ status: 'OK', timestamp: new Date().toISOString(), uptime: process.uptime(), memory: process.memoryUsage() }); }); // Error handling middleware app.use((error, req, res, next) => { logger.error('Unhandled error:', error); res.status(500).json({ error: 'Beklenmeyen bir hata oluştu', code: 'INTERNAL_SERVER_ERROR' }); }); // 404 handler app.use('*', (req, res) => { res.status(404).json({ error: 'Endpoint bulunamadı', code: 'NOT_FOUND' }); }); // Server başlat app.listen(PORT, () => { logger.info(`Server ${PORT} portunda başlatıldı`); console.log(`🚀 Server running on http://localhost:${PORT}`); }); module.exports = app;

🔒 Güvenlik ve Best Practices

OpenAI API kullanırken güvenlik önlemlerini alarak güvenli ve ölçeklenebilir uygulamalar geliştirmeyi öğrenelim.

💡 Güvenlik Kontrol Listesi

  • API anahtarlarını environment variables'da saklayın
  • Rate limiting implementasyonu yapın
  • Input validation ve sanitization uygulayın
  • Logging ve monitoring sistemi kurun
  • CORS politikalarını doğru yapılandırın
middleware/security.js
const rateLimit = require('express-rate-limit'); const helmet = require('helmet'); const validator = require('validator'); // Input validation middleware const validateChatInput = (req, res, next) => { const { message, userId, options = {} } = req.body; // Message validation if (!message || typeof message !== 'string') { return res.status(400).json({ error: 'Mesaj gerekli ve string tipinde olmalıdır', code: 'INVALID_MESSAGE' }); } // Message length check if (message.length > 4000) { return res.status(400).json({ error: 'Mesaj çok uzun (maksimum 4000 karakter)', code: 'MESSAGE_TOO_LONG' }); } // Message content filtering if (containsOffensiveContent(message)) { return res.status(400).json({ error: 'Uygunsuz içerik tespit edildi', code: 'OFFENSIVE_CONTENT' }); } // UserID validation if (userId && (!validator.isAlphanumeric(userId.replace(/[_-]/g, '')) || userId.length > 50)) { return res.status(400).json({ error: 'Geçersiz kullanıcı ID', code: 'INVALID_USER_ID' }); } // Sanitize message req.body.message = validator.escape(message.trim()); next(); }; // Uygunsuz içerik kontrolü (basit implementasyon) const containsOffensiveContent = (text) => { const offensiveWords = ['spam', 'hack', 'illegal']; // Genişletilebilir const lowerText = text.toLowerCase(); return offensiveWords.some(word => lowerText.includes(word)); }; // API anahtarı kontrolü const validateApiKey = (req, res, next) => { if (!process.env.OPENAI_API_KEY) { return res.status(500).json({ error: 'API anahtarı yapılandırılmamış', code: 'MISSING_API_KEY' }); } next(); }; // Rate limiting konfigürasyonu const createRateLimiter = (windowMs, max, message) => { return rateLimit({ windowMs, max, message: { error: message, retryAfter: Math.ceil(windowMs / 1000) }, standardHeaders: true, legacyHeaders: false, keyGenerator: (req) => { // IP + User Agent kombinasyonu kullan return `${req.ip}-${Buffer.from(req.get('User-Agent') || '').toString('base64').slice(0, 20)}`; } }); }; // Security middleware factory const securityMiddleware = { // Temel güvenlik basic: [ helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", "data:", "https:"], }, }, }), validateApiKey ], // Chat endpoint'leri için chat: [ createRateLimiter(15 * 60 * 1000, 50, 'Çok fazla mesaj gönderildi'), validateChatInput ], // Admin endpoint'leri için admin: [ createRateLimiter(15 * 60 * 1000, 10, 'Admin işlemleri için rate limit'), (req, res, next) => { // Admin authentication burada yapılabilir const adminKey = req.headers['x-admin-key']; if (adminKey !== process.env.ADMIN_KEY) { return res.status(403).json({ error: 'Yetkisiz erişim', code: 'UNAUTHORIZED' }); } next(); } ] }; module.exports = { securityMiddleware, validateChatInput, validateApiKey, createRateLimiter };

⚡ Performans Optimizasyonu

Uygulamanızın performansını artırmak ve maliyetleri optimize etmek için kullanabileceğiniz teknikler.

🚀 Caching Stratejileri

Sık kullanılan yanıtları ve embedding'leri önbelleğe alarak API çağrılarını azaltın

📊 Token Optimizasyonu

Prompt engineering ile token kullanımını optimize ederek maliyetleri düşürün

⚖️ Load Balancing

Çoklu API anahtarları ile yük dağılımı yaparak rate limit'leri aşın

🔄 Connection Pooling

HTTP connection pooling ile API yanıt sürelerini iyileştirin

utils/performanceOptimizer.js
const NodeCache = require('node-cache'); const crypto = require('crypto'); class PerformanceOptimizer { constructor() { // Cache instances this.responseCache = new NodeCache({ stdTTL: 3600, // 1 saat checkperiod: 600, // 10 dakikada bir temizlik maxKeys: 1000 // Maksimum 1000 cache entry }); this.embeddingCache = new NodeCache({ stdTTL: 86400, // 24 saat checkperiod: 3600, // 1 saatte bir temizlik maxKeys: 5000 }); // Statistics this.stats = { cacheHits: 0, cacheMisses: 0, totalRequests: 0, tokensSaved: 0 }; } // Response cache key oluştur createCacheKey(prompt, options = {}) { const { model, temperature, maxTokens } = options; const keyData = { prompt: prompt.trim().toLowerCase(), model: model || 'default', temperature: temperature || 0.7, maxTokens: maxTokens || 150 }; return crypto .createHash('md5') .update(JSON.stringify(keyData)) .digest('hex'); } // Cached response kontrolü getCachedResponse(prompt, options = {}) { this.stats.totalRequests++; const cacheKey = this.createCacheKey(prompt, options); const cached = this.responseCache.get(cacheKey); if (cached) { this.stats.cacheHits++; this.stats.tokensSaved += cached.usage.total_tokens; return { ...cached, cached: true, cacheHitRate: (this.stats.cacheHits / this.stats.totalRequests * 100).toFixed(2) }; } this.stats.cacheMisses++; return null; } // Response'u cache'le setCachedResponse(prompt, options, response) { const cacheKey = this.createCacheKey(prompt, options); this.responseCache.set(cacheKey, { response: response.response, usage: response.usage, timestamp: new Date().toISOString(), model: response.model }); } // Prompt optimizasyonu optimizePrompt(userMessage, conversationHistory = []) { // Uzun conversation history'yi kısalt let optimizedHistory = conversationHistory; if (conversationHistory.length > 10) { // Son 8 mesaj + system message optimizedHistory = [ conversationHistory[0], // system message ...conversationHistory.slice(-8) ]; } // Gereksiz boşlukları temizle const optimizedMessage = userMessage.trim().replace(/\s+/g, ' '); return { optimizedMessage, optimizedHistory, tokensSaved: this.estimateTokensSaved(conversationHistory, optimizedHistory) }; } // Token tasarrufu tahmini estimateTokensSaved(original, optimized) { const originalLength = JSON.stringify(original).length; const optimizedLength = JSON.stringify(optimized).length; return Math.ceil((originalLength - optimizedLength) / 4); // Yaklaşık token hesabı } // Performans istatistikleri getStats() { return { ...this.stats, cacheHitRate: (this.stats.cacheHits / this.stats.totalRequests * 100).toFixed(2) + '%', cacheSizeResponse: this.responseCache.keys().length, cacheSizeEmbedding: this.embeddingCache.keys().length }; } // Cache temizleme clearCache() { this.responseCache.flushAll(); this.embeddingCache.flushAll(); // Stats sıfırla this.stats = { cacheHits: 0, cacheMisses: 0, totalRequests: 0, tokensSaved: 0 }; } } module.exports = new PerformanceOptimizer();

🛠️ Hata Yönetimi

OpenAI API'si ile çalışırken karşılaşabileceğiniz çeşitli hata durumlarını ele almak ve kullanıcı deneyimini geliştirmek için kapsamlı hata yönetimi stratejileri.

utils/errorHandler.js
const winston = require('winston'); class OpenAIErrorHandler { constructor() { this.logger = winston.createLogger({ level: 'error', format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json() ), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: './logs/errors.log' }) ] }); // Hata türleri ve karşılık gelen kullanıcı mesajları this.errorMessages = { 'insufficient_quota': { message: 'API kotası doldu. Lütfen daha sonra tekrar deneyin.', code: 'QUOTA_EXCEEDED', statusCode: 429, retryable: true }, 'rate_limit_exceeded': { message: 'Çok fazla istek gönderildi. Lütfen daha sonra tekrar deneyin.', code: 'RATE_LIMIT_EXCEEDED', statusCode: 429, retryable: true }, 'invalid_request_error': { message: 'Geçersiz istek. Lütfen giriş verilerinizi kontrol edin.', code: 'INVALID_REQUEST', statusCode: 400, retryable: false }, 'authentication_error': { message: 'API anahtarı geçersiz. Lütfen konfigürasyonunuzu kontrol edin.', code: 'AUTHENTICATION_ERROR', statusCode: 401, retryable: false }, 'permission_error': { message: 'Bu işlem için izniniz yok.', code: 'PERMISSION_ERROR', statusCode: 403, retryable: false }, 'not_found_error': { message: 'İstenen kaynak bulunamadı.', code: 'NOT_FOUND', statusCode: 404, retryable: false }, 'timeout': { message: 'İstek zaman aşımına uğradı. Lütfen tekrar deneyin.', code: 'TIMEOUT', statusCode: 408, retryable: true }, 'server_error': { message: 'Sunucu hatası oluştu. Lütfen daha sonra tekrar deneyin.', code: 'SERVER_ERROR', statusCode: 500, retryable: true } }; } // Ana hata işleme metodu handleError(error, context = {}) { const errorInfo = this.categorizeError(error); // Hata detaylarını logla this.logger.error('OpenAI API Error', { error: error.message, stack: error.stack, type: errorInfo.type, context: context, timestamp: new Date().toISOString() }); return { success: false, error: { message: errorInfo.userMessage, code: errorInfo.code, retryable: errorInfo.retryable, retryAfter: errorInfo.retryAfter }, statusCode: errorInfo.statusCode }; } // Hata türünü belirle categorizeError(error) { const errorMessage = error.message?.toLowerCase() || ''; const errorType = error.type?.toLowerCase() || ''; // OpenAI spesifik hatalar if (errorMessage.includes('insufficient_quota') || errorType === 'insufficient_quota') { return { type: 'insufficient_quota', ...this.errorMessages['insufficient_quota'], userMessage: this.errorMessages['insufficient_quota'].message }; } if (errorMessage.includes('rate_limit') || errorType === 'rate_limit_exceeded') { return { type: 'rate_limit_exceeded', ...this.errorMessages['rate_limit_exceeded'], userMessage: this.errorMessages['rate_limit_exceeded'].message, retryAfter: this.extractRetryAfter(error) }; } if (errorMessage.includes('invalid_request') || errorType === 'invalid_request_error') { return { type: 'invalid_request_error', ...this.errorMessages['invalid_request_error'], userMessage: this.errorMessages['invalid_request_error'].message }; } if (errorMessage.includes('authentication') || errorType === 'authentication_error') { return { type: 'authentication_error', ...this.errorMessages['authentication_error'], userMessage: this.errorMessages['authentication_error'].message }; } // Ağ hataları if (errorMessage.includes('timeout') || error.code === 'ECONNABORTED') { return { type: 'timeout', ...this.errorMessages['timeout'], userMessage: this.errorMessages['timeout'].message }; } // Varsayılan sunucu hatası return { type: 'server_error', ...this.errorMessages['server_error'], userMessage: this.errorMessages['server_error'].message }; } // Retry-After header'ından süreyi çıkar extractRetryAfter(error) { const headers = error.response?.headers; if (headers && headers['retry-after']) { return parseInt(headers['retry-after']); } return 60; // Varsayılan 60 saniye } // Tekrar deneme stratejisi async retryWithBackoff(asyncFunction, maxRetries = 3, baseDelay = 1000) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await asyncFunction(); } catch (error) { const errorInfo = this.categorizeError(error); // Tekrar denenebilir hata değilse direkt fırlat if (!errorInfo.retryable || attempt === maxRetries) { throw error; } // Exponential backoff ile bekle const delay = baseDelay * Math.pow(2, attempt - 1); await this.sleep(delay); this.logger.warn(`Retry attempt ${attempt}/${maxRetries}`, { error: error.message, delay: delay, attempt: attempt }); } } } // Sleep utility sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Circuit breaker pattern implementasyonu createCircuitBreaker(fn, threshold = 5, timeout = 60000) { let failures = 0; let lastFailTime = 0; let state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN return async (...args) => { const now = Date.now(); // Circuit açık ve timeout geçti mi? if (state === 'OPEN' && now - lastFailTime > timeout) { state = 'HALF_OPEN'; failures = 0; } // Circuit açıksa hata fırlat if (state === 'OPEN') { throw new Error('Circuit breaker is OPEN. Service temporarily unavailable.'); } try { const result = await fn(...args); // Başarılı ise circuit'i sıfırla if (state === 'HALF_OPEN') { state = 'CLOSED'; } failures = 0; return result; } catch (error) { failures++; lastFailTime = now; // Threshold'u aştıysak circuit'i aç if (failures >= threshold) { state = 'OPEN'; } throw error; } }; } } module.exports = new OpenAIErrorHandler();

⚠️ Hata Yönetimi Best Practices

  • Her zaman kullanıcı dostu hata mesajları gösterin
  • Teknik detayları loglarda saklayın, kullanıcıya göstermeyin
  • Tekrar denenebilir hatalar için retry mekanizması kullanın
  • Circuit breaker pattern ile sistem stabilitesini koruyun
  • Rate limiting hatalarında kullanıcıyı bilgilendirin

🎯 Sonuç ve İleri Adımlar

OpenAI GPT API entegrasyonunu başarılı bir şekilde tamamladınız! Bu kapsamlı rehberde öğrendiklerinizi özetleyelim ve ileri adımları değerlendirelim.

📚 Öğrendikleriniz

🔧 Temel Entegrasyon

OpenAI API'sini Node.js projelerinize güvenli bir şekilde entegre etmeyi öğrendiniz

💬 Chat Sistemi

Streaming ve normal chat completion ile dinamik sohbet uygulamaları geliştirdiniz

🚀 Gelişmiş Özellikler

Function calling ve embeddings ile AI uygulamalarınıza güçlü yetenekler kazandırdınız

🛡️ Güvenlik & Performans

Production-ready uygulamalar için güvenlik ve performans optimizasyonlarını uyguladınız

🔮 İleri Adımlar

OpenAI API entegrasyonunuzu daha da geliştirmek için aşağıdaki konuları keşfedebilirsiniz:

🎯 Önerilen Sonraki Projeler

  1. Fine-tuning: Kendi verilerinizle özel GPT modelleri eğitin
  2. Multimodal AI: DALL-E ve Whisper API'lerini entegre edin
  3. Vector Database: Pinecone veya Weaviate ile semantic search sistemleri kurun
  4. Real-time Chat: WebSocket ile gerçek zamanlı AI chatbot geliştirin
  5. AI Agents: LangChain ile akıllı AI agent sistemleri oluşturun

📖 Ek Kaynaklar

💡 Son Tavsiyeler

AI teknolojisi hızla gelişiyor. Yeni modeller, özellikler ve best practice'ler için düzenli olarak OpenAI'ın güncellemelerini takip edin. Community forumlarına katılın ve projelerinizi GitHub'da paylaşarak deneyim kazanın.

Bu rehberde öğrendiklerinizi kullanarak güçlü, güvenli ve ölçeklenebilir AI uygulamaları geliştirebilirsiniz. OpenAI GPT API'nin sunduğu sınırsız potansiyeli keşfetmek için bugün kodlamaya başlayın!

OpenAI Dokümantasyon GitHub Repository