En Basit Yapay Zeka Web Uygulaması Nasıl Yapılır

yapay zeka web uygulaması

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:

  1. Kullanıcıların dökümanlarını yükleyebileceği sayfa
  2. 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:

  1. Çoklu Servis Yönetimi: Üç farklı servis ve deployment
  2. Dil Çeşitliliği: JavaScript (frontend) ve Python (AI pipeline)
  3. Veri Senkronizasyonu: MongoDB ile Pinecone arasında tutarlılık
  4. 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

  1. Tek Veritabanı: Dökümanlar ve embeddings aynı yerde
  2. Veri Tutarlılığı: Trigger’lar ile otomatik senkronizasyon
  3. 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ı

  1. Tek Deployment: Tüm kod bir arada
  2. Hızlı Geliştirme: Fonksiyon çağrıları, HTTP yok
  3. Kolay Debug: Tek codebase
  4. 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ı

SeviyeDeploymentGeliştirmeMaintainabilityPerformans
1Çok KarmaşıkYavaşZorOrta
2KarmaşıkOrtaOrtaİyi
3BasitHızlıİyiİyi
4Çok BasitÇok HızlıÇok İyiMü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?

  1. Concurrent Users > 1000: PostgreSQL’e geçiş
  2. Data Size > 100GB: Dedicated vector database
  3. Multiple Services: Microservices mimarisi
  4. 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:

  1. Basit Başla: Karmaşıklığı ancak gerektiğinde ekle
  2. Monolith First: Microservices’e geçiş zamanını doğru seç
  3. SQLite Power: Modern SQLite production-ready
  4. 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.

Yazı gezinmesi

Mobil sürümden çık