Bu makalede, yapay zeka entegrasyonlu web uygulamalarının nasıl geliştirileceği konusunda kapsamlı bir düşünce deneyi yapacağız. Temel sorumuz şu:
Yapay zeka entegrasyonlu bir web uygulamasını ne kadar basit hale getirebiliriz?
Web uygulaması geliştirmede basitlik, anlaşılabilirlik, hızlı geliştirme ve sürdürülebilirlik açısından kritik öneme sahiptir. Bu rehberde, tipik bir AI entegrasyonuna sahip bir web uygulaması RAG (Retrieval-Augmented Generation) uygulamasını dört farklı seviyede inceleyeceğiz. En karmaşık yapıdan başlayarak, adım adım basitleştirme işlemini gerçekleştireceğiz.
Seviye 1: Karmaşıklığın Zirvesi
MERN Stack ile Başlangıç
Bir müşteri sizden RAG uygulaması geliştirmenizi istediğini varsayalım. Bu uygulama iki temel sayfaya sahip olacak:
- Kullanıcıların dökümanlarını yükleyebileceği sayfa
- Dökümanlarla RAG kullanarak sohbet edebilecekleri sayfa
En popüler web teknolojilerini kullanarak, MERN stack (MongoDB, Express.js, React, Node.js) tercih ediyorsunuz.
RAG Pipeline Mimarisi
RAG işlem hatları için şu teknolojileri seçiyorsunuz:
- LangChain: Doküman işleme, chunking, embedding ve retrieval
- FastAPI: Deployment için
- Pinecone: Vector database olarak
Bu mimari şu şekilde görünür:
┌─────────────────────────┐
│ Pinecone Vector DB │
│ (Cloud Service) │
└─────────────────────────┘
↕ HTTP
┌─────────────────────────┐
│ LangChain + FastAPI │
│ (RAG Pipelines) │
└─────────────────────────┘
↕ HTTP
┌─────────────────────────┐
│ MERN Stack + MongoDB │
│ (Web Application) │
└─────────────────────────┘
Karmaşıklık Sorunları
Yapay Zeka Web Uygulaması , Bu mimaride karşılaştığımız temel sorunlar:
- Çoklu Servis Yönetimi: Üç farklı servis ve deployment
- Dil Çeşitliliği: JavaScript (frontend) ve Python (AI pipeline)
- Veri Senkronizasyonu: MongoDB ile Pinecone arasında tutarlılık
- HTTP Overhead: Servisler arası iletişim gecikmesi
Kod Örneği: FastAPI Endpoint
from fastapi import FastAPI
from langchain.embeddings import OpenAIEmbeddings
import pinecone
app = FastAPI()
@app.post("/index")
async def index_document(document: dict):
# Doküman işleme
chunks = process_document(document)
# Embedding oluşturma
embeddings = OpenAIEmbeddings()
vectors = embeddings.embed_documents(chunks)
# Pinecone'a kaydetme
pinecone.upsert(vectors)
return {"status": "indexed"}
@app.post("/query")
async def query_documents(query: str):
# Vector arama
results = pinecone.query(query_vector)
# LLM ile yanıt oluşturma
response = generate_response(results, query)
return {"response": response}
Seviye 2: Cloud Bağımlılığından Kurtulma
PostgreSQL + pgvector Geçişi
Pinecone yerine PostgreSQL ve pgvector extension kullanarak basitleştirme yapabiliriz:
-- PostgreSQL'de vector column ekleme
ALTER TABLE documents
ADD COLUMN embedding vector(1536);
-- Trigger ile otomatik embedding
CREATE OR REPLACE FUNCTION update_embedding()
RETURNS TRIGGER AS $$
BEGIN
NEW.embedding = generate_embedding(NEW.content);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER embedding_trigger
BEFORE INSERT OR UPDATE ON documents
FOR EACH ROW EXECUTE FUNCTION update_embedding();
Avantajlar
- Tek Veritabanı: Dökümanlar ve embeddings aynı yerde
- Veri Tutarlılığı: Trigger’lar ile otomatik senkronizasyon
- Maliyet Azalması: Cloud vector database maliyeti yok
Seviye 3: Microservices’den Monolith’e
Django ile Birleşik Mimari
Microservices karmaşıklığından kurtulmak için Django kullanarak monolith yapıya geçiş:
# Django views.py
from django.shortcuts import render
from django.http import JsonResponse
from .utils.rag_pipeline import index_document, query_pipeline
def upload_document(request):
if request.method == 'POST':
document = request.FILES['document']
# Direkt fonksiyon çağrısı (HTTP yok)
result = index_document(document)
return JsonResponse({'status': 'success'})
return render(request, 'upload.html')
def chat(request):
if request.method == 'POST':
query = request.POST.get('query')
# Direkt fonksiyon çağrısı
response = query_pipeline(query)
return JsonResponse({'response': response})
return render(request, 'chat.html')
Basitleştirme Kazançları
- Tek Deployment: Tüm kod bir arada
- Hızlı Geliştirme: Fonksiyon çağrıları, HTTP yok
- Kolay Debug: Tek codebase
- Düşük Latency: Network hop’ları yok
Seviye 4: SQLite ile Nihai Basitlik
SQLite + sqlite-vec Implementasyonu
En basit seviyede SQLite ve sqlite-vec kullanımı:
import sqlite3
import sqlite_vec
# SQLite bağlantısı
conn = sqlite3.connect('app.db')
conn.enable_load_extension(True)
conn.load_extension("sqlite_vec")
# Vector tablosu oluşturma
conn.execute('''
CREATE TABLE IF NOT EXISTS documents (
id INTEGER PRIMARY KEY,
content TEXT,
embedding BLOB
)
''')
def add_document(content):
embedding = generate_embedding(content)
conn.execute(
"INSERT INTO documents (content, embedding) VALUES (?, ?)",
(content, embedding)
)
conn.commit()
def search_documents(query):
query_embedding = generate_embedding(query)
results = conn.execute('''
SELECT content, vec_distance_cosine(embedding, ?) as distance
FROM documents
ORDER BY distance
LIMIT 5
''', (query_embedding,)).fetchall()
return results
Django ile Entegrasyon
# models.py
from django.db import models
import sqlite3
class Document(models.Model):
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# SQLite vector store'a kaydet
add_to_vector_store(self.content, self.id)
def delete(self, *args, **kwargs):
# Vector store'dan sil
remove_from_vector_store(self.id)
super().delete(*args, **kwargs)
Nihai Mimari
┌─────────────────────────────────────┐
│ Django Web App │
│ ┌─────────────────────────────┐ │
│ │ RAG Functions │ │
│ │ (LangChain Modules) │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ SQLite + sqlite-vec │ │
│ │ (app.db file) │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
Performans Karşılaştırması
Seviye | Deployment | Geliştirme | Maintainability | Performans |
---|---|---|---|---|
1 | Çok Karmaşık | Yavaş | Zor | Orta |
2 | Karmaşık | Orta | Orta | İyi |
3 | Basit | Hızlı | İyi | İyi |
4 | Çok Basit | Çok Hızlı | Çok İyi | Mükemmel |
Production Hazırlığı
SQLite Production Konfigürasyonu
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
'OPTIONS': {
'init_command': '''
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA cache_size=1000000;
PRAGMA temp_store=MEMORY;
PRAGMA mmap_size=268435456;
'''
}
}
}
Backup Stratejisi
# Litestream ile otomatik backup
litestream replicate db.sqlite3 s3://my-bucket/db
# Cron job ile düzenli backup
0 2 * * * /usr/local/bin/litestream replicate db.sqlite3 s3://backup-bucket/
Ölçekleme Stratejileri
Ne Zaman Karmaşıklık Eklemeli?
- Concurrent Users > 1000: PostgreSQL’e geçiş
- Data Size > 100GB: Dedicated vector database
- Multiple Services: Microservices mimarisi
- High Availability: Load balancer + multiple instances
Migration Path
# Basit migration script
def migrate_to_postgres():
# SQLite'dan veri okuma
sqlite_conn = sqlite3.connect('app.db')
documents = sqlite_conn.execute("SELECT * FROM documents").fetchall()
# PostgreSQL'e yazma
pg_conn = psycopg2.connect(DATABASE_URL)
for doc in documents:
pg_conn.execute(
"INSERT INTO documents (content, embedding) VALUES (%s, %s)",
(doc[1], doc[2])
)
pg_conn.commit()
Sonuç ve Öneriler
Bu rehberde, yapay zeka entegrasyonlu web uygulamalarının nasıl basitleştirilebileceğini dört seviyede inceledik. Temel prensiplerimiz:
- Basit Başla: Karmaşıklığı ancak gerektiğinde ekle
- Monolith First: Microservices’e geçiş zamanını doğru seç
- SQLite Power: Modern SQLite production-ready
- Erken Optimizasyon Tuzağı: Ölçekleme sorunlarını önceden varsayma
Teknoloji Seçim Rehberi
Başlangıç Seviyesi (0-1000 kullanıcı):
- Django/Rails + SQLite + sqlite-vec
- Tek deployment, maksimum hız
Büyüme Seviyesi (1000-10000 kullanıcı):
- PostgreSQL + pgvector
- Redis cache ekleme
- Load balancer
Ölçek Seviyesi (10000+ kullanıcı):
- Microservices architecture
- Dedicated vector database
- Container orchestration
Bu yaklaşım ile hem hızlı prototipleme hem de ölçeklenebilir uygulamalar geliştirebilirsiniz.
Ek Kaynaklar
Bu makale, yapay zeka entegrasyonlu web uygulaması geliştirme sürecinde basitlikten karmaşıklığa doğru giden yolculuğu detaylandırmaktadır. Teknoloji seçimlerinizde bu rehberi referans alabilirsiniz.