RAG etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
RAG etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

4 Şubat 2026 Çarşamba

Docker Compose ile Yerel Bir RAG (Retrieval-Augmented Generation) Ortamı Kurulumu: PostgreSQL + pgvector + API Katmanı

RAG Nedir ve Neden Yerelde Kurulur?

RAG (Retrieval-Augmented Generation), bir dil modelinin cevabı “uydurmak” yerine önce güvenilir bir kaynaktan ilgili içerikleri bulup (retrieval), ardından bu içeriklerle zenginleştirilmiş bir yanıt üretmesi yaklaşımıdır. Son dönemde kurum içi dokümanlarla çalışan asistanlar, teknik arama kutuları ve destek botları RAG ile daha tutarlı sonuçlar verebiliyor. Yerel (local) kurulum ise hem gizlilik hem de maliyet açısından önemli: veriniz üçüncü taraf servislere gitmez, altyapı kontrolü sizde olur ve test/deneme döngüsü hızlanır.

Bu yazıda Docker Compose kullanarak güncel ve pratik bir RAG altyapısının çekirdeğini kuracağız: PostgreSQL üzerinde pgvector eklentisi ile vektör arama, ve bu veritabanına bağlanan örnek bir API katmanı. Amaç; doküman parçalarını (chunk) vektör olarak saklamak, benzerlik araması yapmak ve uygulamalar için tekrar kullanılabilir bir iskelet oluşturmaktır.

Mimari: Hangi Parçalar Var?

Kurulum üç ana parçadan oluşur: (1) PostgreSQL + pgvector: embedding’leri saklar ve benzerlik araması yapar. (2) API: doküman ekleme ve arama uçlarını sunar. (3) İsterseniz ileride LLM entegrasyonu: burada odak veritabanı ve retrieval tarafı olduğu için LLM kısmını opsiyonel bırakıyoruz. Bu iskelet, ister kendi LLM’inizle ister bir harici model API’si ile kolayca genişletilebilir.

Ön Koşullar

Bilgisayarınızda Docker ve Docker Compose kurulu olmalı. Windows’ta Docker Desktop, macOS’ta Docker Desktop, Linux’ta Docker Engine + Compose eklentisi yeterlidir. Ayrıca komut satırı kullanımı ve temel PostgreSQL kavramlarına aşinalık işinizi kolaylaştırır.

1) Docker Compose Dosyasını Hazırlama

Projeniz için bir klasör açın (ör. rag-local) ve içine docker-compose.yml dosyası oluşturun. Aşağıdaki yapı PostgreSQL’i pgvector etkin şekilde başlatır ve örnek bir API servisini ayağa kaldırır. API tarafını kendi projenize göre değiştirebilirsiniz; burada amaç, servislerin bir arada çalıştığı “omurga”yı kurmak.

docker-compose.yml içeriği:

Not: Aşağıdaki bloğu olduğu gibi ekleyebilirsiniz.

YAML:

version: "3.9"
services:
  db:
    image: pgvector/pgvector:pg16
    container_name: rag_db
    environment:
      POSTGRES_USER: rag
      POSTGRES_PASSWORD: ragpass
      POSTGRES_DB: ragdb
    ports:
      - "5432:5432"
    volumes:
      - rag_pgdata:/var/lib/postgresql/data
  api:
    image: node:20-alpine
    container_name: rag_api
    working_dir: /app
    volumes:
      - ./api:/app
    environment:
      DATABASE_URL: postgres://rag:ragpass@db:5432/ragdb
    command: sh -c "npm i && npm run dev"
    depends_on:
      - db
    ports:
      - "3000:3000"
volumes:
  rag_pgdata:

Burada kritik kısım, veritabanı imajının pgvector destekli olmasıdır. Böylece ayrı bir eklenti kurma süreciyle uğraşmadan vektör tiplerini ve indeksleri kullanabilirsiniz. API servisi için Node.js seçtik; ancak aynı yaklaşımı Python/FastAPI ya da Go ile de uygulayabilirsiniz.

2) Veritabanında Tablo ve İndeks Oluşturma

Şimdi PostgreSQL tarafında pgvector’ı etkinleştirelim ve RAG için temel bir tablo kuralım. Terminalden Compose’u başlatın:

Komut: docker compose up -d

Ardından veritabanı kabuğuna girip SQL çalıştırın:

Komut: docker exec -it rag_db psql -U rag -d ragdb

SQL adımları:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE IF NOT EXISTS documents (
  id BIGSERIAL PRIMARY KEY,
  source TEXT NOT NULL,
  chunk TEXT NOT NULL,
  embedding vector(768),
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Benzerlik araması için ivfflat indeks (embedding dolduktan sonra daha verimli olur)
CREATE INDEX IF NOT EXISTS documents_embedding_idx
ON documents USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

Burada vector(768) boyutu örnek bir değerdir. Kullandığınız embedding modeline göre 384, 768, 1024 gibi farklı boyutlar seçebilirsiniz. Boyut ile model çıktısı tutarlı olmak zorunda; aksi halde insert sırasında hata alırsınız.

3) API Katmanını Hızlıca Ayağa Kaldırma

Proje kökünde api adlı klasör oluşturun. İçine basit bir Node.js API koyarak iki uç hazırlayacağız: /ingest (doküman ekleme) ve /search (benzerlik araması). Örnek olması açısından sade tutuldu; prod ortamda doğrulama, rate limit, kuyruk (queue) ve gözlemlenebilirlik eklemek gerekir.

api/package.json:

{
  "name": "rag-api",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "node index.js"
  },
  "dependencies": {
    "express": "^4.19.2",
    "pg": "^8.12.0"
  }
}

api/index.js:

import express from "express";
import pg from "pg";

const app = express();
app.use(express.json({ limit: "2mb" }));

const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });

// ingest: { source, chunk, embedding: [..] }
app.post("/ingest", async (req, res) => {
  const { source, chunk, embedding } = req.body;
  if (!source || !chunk || !Array.isArray(embedding)) {
    return res.status(400).json({ error: "source, chunk ve embedding (array) zorunlu" });
  }
  const emb = `[${embedding.join(",")}]`;
  await pool.query(
    "INSERT INTO documents(source, chunk, embedding) VALUES ($1, $2, $3::vector)",
    [source, chunk, emb]
  );
  res.json({ ok: true });
});

// search: { embedding: [..], topK: 5 }
app.post("/search", async (req, res) => {
  const { embedding, topK = 5 } = req.body;
  if (!Array.isArray(embedding)) {
    return res.status(400).json({ error: "embedding (array) zorunlu" });
  }
  const emb = `[${embedding.join(",")}]`;
  const { rows } = await pool.query(
    `SELECT id, source, chunk,
      1 - (embedding <=> $1::vector) AS score
      FROM documents
      ORDER BY embedding <=> $1::vector
      LIMIT $2`,
    [emb, topK]
  );
  res.json({ results: rows });
});

app.listen(3000, () => console.log("RAG API 3000 portunda çalışıyor"));

Bu API, embedding üretmez; embedding’i dışarıdan bekler. Böylece hangi embedding modelini kullanacağınızı (yerel bir model, bir CLI aracı veya bir bulut servisi) siz belirlersiniz. RAG projelerinde bu ayrım pratik bir avantaj sağlar: depolama/arama altyapısı sabit kalırken model katmanı kolay değişir.

4) Test: Veri Ekleme ve Arama

Servisler ayaktayken basit bir test yapabilirsiniz. Örnek olarak 768 boyut yerine kısa bir vektörle test etmek istiyorsanız tablo boyutunu da ona göre ayarlamanız gerekir. Gerçek kullanımda modelin ürettiği boyutla aynı vektörü göndermelisiniz. Uygulamada tipik akış şudur: (1) dokümanı parçalara böl, (2) her parça için embedding üret, (3) /ingest ile kaydet, (4) kullanıcı sorusu için embedding üret, (5) /search ile en alakalı parçaları çek, (6) bu parçaları LLM’e bağlam olarak ver.

Benzerlik metriklerinde en sık kullanılan seçenekler cosine ve L2’dir. Burada vector_cosine_ops ve <=> operatörü ile cosine mesafesine dayalı sıralama yapıyoruz. Sonuçtaki score alanı basit bir dönüştürme ile “yakınlık” hissi verir; uygulamanızda eşik (threshold) tanımlayarak düşük skorlu sonuçları elemek iyi bir pratik olabilir.

Performans ve Üretim Notları

Yerel RAG ortamı hızlı sonuç verir ama birkaç noktaya dikkat etmek gerekir. ivfflat indeks, veri büyüdükçe anlamlı hale gelir; küçük veri setlerinde tam tarama bazen daha tutarlı sonuç verebilir. Ayrıca ivfflat için ANALYZE çalıştırmak ve “lists” parametresini veri boyutuna göre ayarlamak önemlidir. Daha ileri seviyede hnsw gibi indeks türlerini ve PostgreSQL ayarlarını (work_mem, maintenance_work_mem) incelemek performansı ciddi şekilde artırabilir.

Güvenlik tarafında ise API’ye kimlik doğrulama eklemek, veritabanı şifresini .env dosyasına almak, ağ izolasyonu yapmak ve logları izlemek temel gereksinimlerdir. Bu iskeleti kendi projelerinize uyarlarken en büyük kazanım, retrieval katmanını standardize etmeniz olur; çünkü RAG projelerinde asıl fark genellikle doğru chunking, iyi embedding seçimi ve doğru indeks/parametre kombinasyonunda ortaya çıkar.

29 Ocak 2026 Perşembe

Claude 3, GPT-4o ve Llama 3 ile RAG (Retrieval-Augmented Generation) Kurulumu: Üretim Odaklı Adım Adım Rehber

RAG Nedir ve Neden 2026’da Hâlâ En İyi Yaklaşımlardan Biri?

Büyük dil modelleri (LLM) tek başına güçlü olsa da, her zaman güncel veriye erişemez ve kurumsal dokümanlarınız gibi özel içerikleri “doğrudan” bilemez. RAG (Retrieval-Augmented Generation), modeli harici bir bilgi kaynağıyla besleyerek bu açığı kapatır: Önce doğru doküman parçaları (chunk) aranır, sonra bu parçalar modele bağlam olarak verilerek yanıt ürettirilir. Böylece halüsinasyon riski düşer, cevaplar kaynaklı ve izlenebilir hâle gelir, ayrıca model güncellemeden veri güncellenebilir.

Bu yazıda, ileri seviye ama uygulanabilir bir RAG mimarisini ele alacağız: parça stratejisi, embedding seçimi, vektör veritabanı, filtreleme, yeniden sıralama (reranking) ve üretim tarafında prompt tasarımı. Hedefimiz “demo” değil, üretim ortamına yakın bir kurulum mantığı vermek.

Mimari Genel Bakış: 5 Katmanlı RAG

Sağlam bir RAG sistemi genellikle 5 bileşenden oluşur: (1) Veri hazırlama (temizleme, bölümleme), (2) Embedding (vektörleştirme), (3) Vektör indeks (arama), (4) Yeniden sıralama (en alakalı parçaları seçme), (5) Üretim (LLM ile yanıt oluşturma). Bu yapı, “LLM’ye her şeyi verelim” yaklaşımından daha az maliyetli ve daha tutarlıdır.

1) Veri Hazırlama: Chunk Stratejisi ve Metadata

RAG kalitesi, çoğu zaman modelden önce chunk stratejinizle belirlenir. PDF’lerden, wiki sayfalarından veya ticket kayıtlarından gelen içerik düzensiz olabilir. Pratikte iyi çalışan yaklaşım: 500–900 token arası chunk boyutu ve 70–150 token overlap kullanmaktır. Çok küçük chunk, bağlamı parçalar; çok büyük chunk ise arama isabetini düşürür.

Her chunk’a mutlaka metadata ekleyin: kaynak doküman adı, URL (dahili olabilir), bölüm başlığı, tarih, erişim yetkisi, ürün/servis etiketi gibi alanlar. Üretimde asıl farkı yaratan kısım burasıdır; çünkü sonradan “sadece X ürününe ait, son 6 ayın dokümanlarını tara” gibi filtreleri metadata ile yaparsınız.

2) Embedding Seçimi: Doğru Vektör Doğru Sonuç

Embedding modeli, metni sayısal vektöre dönüştürür ve benzerlik aramasının temelini oluşturur. Türkçe içerikte embedding kalitesi kritiktir. Seçerken şu kriterlere bakın: çok dilli başarı, uzun metin performansı, maliyet ve gecikme. Kurumsal senaryoda aynı anda hem İngilizce hem Türkçe doküman varsa, çok dilli embedding genellikle daha güvenli tercihtir.

Ek bir ipucu: Embedding üretirken metni “ham” basmak yerine, başlık + bölüm + içerik şeklinde birleştirmek arama isabetini artırır. Örneğin: “Başlık: … | Bölüm: … | Metin: …” gibi küçük bir şablon, özellikle benzer kavramların çok geçtiği dokümanlarda yardımcı olur.

3) Vektör Veritabanı ve İndeks Ayarları

Vektör veritabanı seçiminde popüler seçenekler arasında FAISS (self-host), Milvus, Qdrant, Weaviate ve bulut tabanlı servisler bulunur. Üretimde dikkat edilmesi gerekenler: HNSW gibi indeks türleri, filtreli arama performansı, replikasyon/backup ve erişim kontrolüdür.

HNSW tabanlı aramada temel ayar mantığı şöyledir: daha yüksek doğruluk için arama parametreleri yükselir ama gecikme artar. Bu yüzden arama katmanını iki fazlı düşünmek iyi çalışır: önce hızlı bir aday havuzu (ör. top-50) çıkarın, sonra daha pahalı bir reranking ile top-5/top-8’e düşürün.

4) Reranking: “En Yakın” Parça Her Zaman “En Alakalı” Değildir

Embedding benzerliği, semantik yakınlığı yakalar ama her zaman kullanıcı sorusuna en alakalı parçayı seçmeyebilir. Özellikle teknik dokümanlarda aynı terimler farklı bağlamlarda geçebilir. Burada reranker devreye girer: Soru ile aday chunk’ları daha “dikkatli” karşılaştırıp yeniden sıralar.

Üretimde yaygın ve etkili bir desen: top-50 vektör araması → top-10 rerank → top-4 bağlam. Reranking maliyetli olabilir; bu yüzden sadece gerekli olduğunda açmak için basit bir eşik kullanabilirsiniz (örneğin, en iyi sonucun benzerlik skoru düşükse rerank uygula).

5) Üretim (LLM) Katmanı: Prompt Tasarımı ve Kaynak Gösterme

RAG’in “G” kısmı, yani generation tarafı, çoğu zaman yanlış anlaşılır: LLM’den mucize beklemek yerine ona disiplin kazandırmak gerekir. İyi çalışan prompt ilkeleri: (1) Modeli sadece verilen bağlamla cevap vermeye zorlamak, (2) Yetersiz bağlam varsa “bilmiyorum” demesini istemek, (3) Cevabı madde madde ve adım adım ürettirmek, (4) Mümkünse kaynak chunk referansı döndürmek.

Kısa bir örnek yönerge mantığı: “Aşağıdaki bağlam parçalarını kullan. Bağlam dışında tahmin yürütme. Yanıtın sonunda ‘Kullanılan Kaynaklar’ altında parça kimliklerini yaz.” Bu yaklaşım, özellikle denetim ve uyumluluk isteyen ekiplerde RAG’i güvenilir kılar.

Kalite Ölçümü: RAG’i “Hissetmek” Yerine Test Etmek

RAG sistemleri, “birkaç soru sorup iyi gibi” diyerek üretime alınmamalı. Basit ama etkili bir yöntem: 30–100 adet gerçek kullanıcı sorusunu toplayın, her soru için “beklenen kaynak doküman” düşünün ve şu metrikleri izleyin: retrieval recall (doğru kaynak top-k içinde mi), answer faithfulness (cevap bağlamla tutarlı mı), latency (uçtan uca gecikme) ve maliyet. Bu ölçümlerle chunk boyutu, top-k, reranking aç/kapa ve prompt ayarlarını kontrollü biçimde optimize edebilirsiniz.

Üretim İçin Pratik İpuçları (Sık Yapılan Hatalar)

1) Yetkilendirme yok sayılmasın: Kullanıcının görmemesi gereken dokümanı retrieval katmanında filtrelemezseniz, LLM yanlışlıkla sızdırabilir. Metadata’ya erişim seviyeleri ekleyin ve arama sorgusuna mutlaka uygulayın.

2) “Tek indeks her şeye yeter” yanılgısı: Destek kayıtları, teknik kılavuzlar ve release notları aynı dilde olsa bile farklı karakterdedir. Bazen iki ayrı koleksiyon/indeks, tek dev koleksiyondan daha iyi sonuç verir.

3) Güncelleme akışı planlayın: Dokümanlar değiştikçe embedding’lerin güncellenmesi gerekir. En azından günlük incremental indeksleme ve silinen içerik için “tombstone” mantığı kurun.

4) Caching kullanın: Sık sorulan sorular ve popüler retrieval sonuçları için cache, maliyeti ciddi düşürür. Ayrıca aynı sorunun farklı yazımları için basit bir normalizasyon (küçük harf, noktalama temizliği) bile kazanç sağlar.

Sonuç: RAG’i Bir “Özellik” Değil, Bir Sistem Olarak Kurun

RAG, doğru kurgulandığında LLM’leri kurumsal bilgiyle güvenli şekilde birleştirmenin en pratik yoludur. Başarı; modelden çok, chunk stratejisi, metadata disiplini, filtreleme, reranking ve ölçüm altyapısının birlikte çalışmasına bağlıdır. Bu yazıdaki adımları temel alıp kendi verinize göre ayarladığınızda, hem daha doğru yanıtlar alır hem de maliyeti ve gecikmeyi kontrol edebilirsiniz.

16 Aralık 2025 Salı

Yerelde RAG Asistanı Kurulumu: Python, FAISS ve FastAPI ile Adım Adım

RAG nedir ve neden yerelde kurmalısınız?

RAG (Retrieval-Augmented Generation), bir büyük dil modelinin (LLM) yanıt üretmeden önce kendi veritabanınızdan veya belgeliklerinizden ilgili parçaları çekmesini sağlayan bir yaklaşım. Böylece model, güncel ve doğrulanabilir bilgiye dayanarak cevap verir, halüsinasyon oranı düşer ve alanınıza özgü bir asistan elde edersiniz. Bu yazıda, internete kapalı bir ortamda, Python, FAISS ve FastAPI kullanarak hızlı ve hafif bir RAG asistanını nasıl kurabileceğinizi adım adım anlatıyorum.

Mimari bileşenler ve gereksinimler

Minimal bir RAG sistemi dört temel bileşenden oluşur: metin ön işleme ve parçalara ayırma, embedding üretimi, vektör dizin (FAISS) ve yanıt üretici (LLM). Yerel kurulum için Python 3.10+ bir ortam, sentence-transformers ile çok dilli bir embedding modeli, faiss-cpu dizini ve HTTP üzerinden istek alıp yanıtlamak için FastAPI yeterli. İsterseniz yanıt üretici olarak Ollama üzerinden Llama 3 ailesi gibi bir yerel modeli kullanabilir, ya da sisteminize uygun bir başka LLM’i bağlayabilirsiniz.

Kurulum adımları: ortam, paketler ve veri hazırlığı

Önce izole bir Python sanal ortamı oluşturun ve temel paketleri kurun. Gerekli çekirdek paketler tipik olarak fastapi, uvicorn, faiss-cpu, sentence-transformers, pydantic ve metin işleme için regex/unidecode gibi küçük yardımcılar olur. Eğer yerel bir model kullanacaksanız Ollama’yı yükleyip örneğin “llama3” veya “mistral” gibi bir modeli indirin. Belgelerinizi tek bir klasörde toplayın; PDF, DOCX ve düz metinleri mümkünse metne dönüştürüp temizleyin. Tekrarlayan başlıklar, sayfa dipnotları ve tablolar metni kirlettiği için önceden sadeleştirme yapmak ileride kaliteyi ciddi biçimde artırır.

Embedding üretimi ve FAISS ile dizinleme

RAG’in çekirdeği, metni anlam uzayına taşıyan embedding’lerdir. Türkçe ağırlıklı bir kurulum için çok dilli bir model seçmek pratik olur. intfloat/multilingual-e5-base veya sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 iyi başlangıç seçenekleridir. Belgeleri 500–800 karakter aralığında, 50–100 karakter örtüşmeli parçalara bölerseniz hem hatırlama oranı hem bağlam bütünlüğü dengelenir. Her parçayı embedding modelinden geçirip bir vektör matrisi üretin; ardından FAISS’te IndexFlatIP (cosine benzeri iç çarpım) veya daha büyük veri için HNSW/IVF tabanlı bir dizin kurun. Dizin ve meta verileri (ör. belge kimliği, başlık, sayfa numarası) disk üzerinde saklayarak soğuk başlatma sürelerini azaltabilirsiniz.

Sorgu işleme hattı: geri getirme, yeniden sıralama ve yanıt üretimi

İstemci bir soru sorduğunda önce soruyu embedding modellerinden geçirip FAISS’e benzerlik araması yapın. İlk aşamada genellikle top-k=5–8 yeterlidir. Sonuçları kalite için hafif bir yeniden sıralama (re-rank) aşamasından geçirmek özellikle uzun ve benzer parçalarda fark yaratır; isterseniz küçük bir cross-encoder veya basit bir skor birleştirme (benzerlik + anahtar kelime çakışması) yaklaşımı kullanın. Son olarak en iyi 3–5 parçayı bir prompt şablonunda LLM’e vererek yanıt üretin. İyi bir şablon, modele “yalnızca verilen bağlama dayanması”, “kaynakları listelemesi” ve “emin olmadığı noktalarda netçe belirtmesi” yönünde talimatlar içerir. Bu aşamada streaming yanıt (chunk bazlı) hem his olarak daha hızlıdır hem de istemci tarafında kullanıcı deneyimini iyileştirir.

FastAPI ile uç noktalar ve basit bir API tasarımı

Sunucu tarafında iki temel uç nokta yeterlidir: /index ve /query. İlk uç nokta yeni belge eklemeyi, embedding ve dizine yazmayı üstlenir. İkincisi kullanıcı sorusunu alır, geri getirme ve yeniden sıralama yapar, LLM’den gelen yanıtı döndürür. Yanıta kaynak parçaların kimliklerini ve güven puanlarını dahil ederseniz istemci tarafında “bu cevabın kanıtı” şeritleri gösterebilirsiniz. Üretim ortamında CORS ayarlarını, basit bir oran sınırlama (rate limit) ve temel kimlik doğrulamayı eklemeyi unutmayın.

Performans, kalite ve bakım ipuçları

İlk indekslemeyi hızlandırmak için toplu gömme (batch) boyutunu donanımınıza göre ayarlayın; CPU’da 16–64 arası genelde güvenlidir. Dizin aramasında hız/kalite dengesini sağlamak üzere IVF ya da HNSW gibi yaklaşık yakın komşu (ANN) yapılarını deneyin ve geri getirme anında efSearch benzeri parametreleri kademeli artırın. Kalite için chunk boyutu ve örtüşmesini alanınıza göre yeniden ayarlayın; teknik dökümanlarda daha uzun, SSS türü içerikte ise daha kısa parçalar daha iyi sonuç verir. Ayrıca yinelenen metinleri, versiyonlanmış kopyaları ve tarih geçmişlerini indeks dışında tutmak, cevapların tekrara düşmesini engeller.

Düzenli bir değerlendirme seti oluşturun: 30–50 soruluk, doğru cevap ve kaynak eşleşmesi içeren bir küçük benchmark ile sürümler arasında regresyon olup olmadığını görebilirsiniz. Ölçüt olarak geri getirme için recall@k, cevap üretimi için ise doğruluk, faydalılık ve kaynak isabetini manuel etiketleme ile kontrol etmek etkilidir. Basit bir geri bildirim mekanizması (kullanıcı oylaması, “yanlıştı/düzelt” düğmesi) gerçek kullanımda iyileştirme fırsatlarını hızla ortaya çıkarır.

Güvenlik, gizlilik ve dağıtım

Yerel RAG sistemleri çoğu zaman hassas verilerle çalışır. Bu nedenle PII tespiti ve maskeleme, uçtan uca TLS, erişim loglarının minimal ve anonim tutulması önemlidir. Küçük bir ek katman olarak belirli sorgulara kural tabanlı filtre uygulayabilir, gizli etiketli içerikleri yanıt bağlamına girmeden önce temizleyebilirsiniz. Dağıtım için hafif bir konteyner imajı, tek bir health-check uç noktası ve kalıcı depolama bağlanmış bir FAISS dizini çoğu ekip için yeterli, ölçeklenebilir ve sürdürülebilir bir başlangıç sunar.

Sonuç

Python, FAISS ve FastAPI ile yerelde çalışan bir RAG asistanı kurmak sanıldığından daha erişilebilir. Doğru embedding modeli, düzenli bir parçalara ayırma stratejisi ve iyi tasarlanmış bir prompt ile, alanınıza özel, hızlı ve güvenilir bir bilgi asistanına sahip olursunuz. İlk sürümü basit tutun, kullanım verisi geldikçe yeniden sıralama ve değerlendirme mekanizmasını güçlendirin; böylece hem maliyeti hem karmaşıklığı kontrol altında tutarken yüksek kaliteli cevaplar üreten bir sistem inşa edebilirsiniz.

10 Aralık 2025 Çarşamba

Ollama, LangChain ve ChromaDB ile Yerel RAG Chatbotu Kurulum Rehberi

Özet

Bu rehberde, internet bağlantısına ihtiyaç duymadan çalışan bir RAG (Retrieval-Augmented Generation) chatbotunu yerelde nasıl kurabileceğinizi adım adım anlatıyorum. Kullandığımız bileşenler: Ollama (yerel LLM çalıştırma), LangChain (zincirleme ve orkestrasyon), ChromaDB (vektör veritabanı) ve yerel gömlemeler. Amaç; PDF, teknik doküman veya notlarınızı indeksleyip, LLM modeline belgelerden alıntı yaparak daha doğru yanıtlar ürettirmek.

Neden Yerel RAG?

RAG yaklaşımı, dil modelinin yanıtlarını belgelerinizle zenginleştirerek halüsinasyonları azaltır ve güncel bilgi sağlar. İşin “yerel” tarafı ise verinin bilgisayarınızdan çıkmaması, maliyetin düşük ve sistemin offline çalışabilmesi demek. Özellikle kurumsal dokümanlar, Ar-Ge notları veya gizli veriler için bu yaklaşım idealdir.

Gereksinimler

- 16 GB RAM önerilir (8 GB ile küçük modeller çalışabilir).
- macOS, Linux veya Windows (WSL destekli).
- Python 3.10+.
- Temel terminal bilgisi.
- Bazı modellerde GPU varsa hız artar (Metal/CUDA desteği).

Adım 1: Ollama ve Modelleri Kurma

Ollama, LLM modellerini tek komutla indirip yerelde çalıştırmanızı sağlar. Sisteminizde kurulu değilse resmi talimatları izleyerek kurun. Linux için tipik kurulum şu şekildedir:

curl -fsSL https://ollama.com/install.sh | sh
# Servisi başlat (Linux)
ollama serve

Şimdi bir sohbet modeli ve bir gömleme modeli çekelim. Küçük ve hızlı bir sohbet modeli için Llama 3.1 8B iyi bir başlangıçtır. Gömlemeler için “nomic-embed-text” yaygın ve hızlıdır:

ollama pull llama3.1:8b
ollama pull nomic-embed-text

Model adlarını ihtiyacınıza göre değiştirebilirsiniz (örn. mistral veya phi-3). Büyük modeller daha iyi kalite, daha fazla RAM/GPU kullanımı demektir. İlk denemelerde 7B–8B aralığı pratik bir seçimdir.

Adım 2: Python Ortamını Hazırlama

Proje klasörünüzü oluşturup sanal ortam açın ve gerekli paketleri yükleyin. LangChain ile Ollama’nın entegrasyonu için “langchain-ollama” paketini kullanalım. Vektör veritabanı için Chroma’yı ekleyelim.

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install langchain langchain-community langchain-ollama chromadb pydantic

Basit metin dosyalarıyla başlayacağız. PDF’ler için ekstra dönüştürücüler (örn. pypdf, unstructured) ekleyebilirsiniz.

Adım 3: Belgeleri İndeksleme ve RAG Zinciri

Aşağıdaki örnekte, “docs/” klasöründeki metin dosyalarını parçalara ayırıp Chroma’ya yükleyeceğiz. Ardından bir sorgu geldiğinde ilgili parçaları geri çağırıp modelin bağlamıyla birlikte yanıtlamasını sağlayacağız.

# rag_app.py
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain.prompts import PromptTemplate
from langchain.schema import Document

# 1) Belgeleri yükle
loader = DirectoryLoader("docs", glob="**/*.txt", loader_cls=TextLoader, show_progress=True, use_multithreading=True)
docs = loader.load()

# 2) Parçala
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=120)
chunks = splitter.split_documents(docs)

# 3) Gömleme ve vektör veritabanı
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectordb = Chroma.from_documents(chunks, embedding=embeddings, collection_name="yerel_rag")

# 4) Retriever ve LLM
retriever = vectordb.as_retriever(search_kwargs={"k": 4})
llm = ChatOllama(model="llama3.1:8b", temperature=0.2)

# 5) İstem şablonu
template = """Aşağıdaki bağlamı KESİNLİKLE dikkate alarak soruyu yanıtla.
Bağlam:
{context}

Soru: {question}
Cevap: """
prompt = PromptTemplate.from_template(template)

def ask(question: str):
    # İlgili parçaları getir
    rel_docs = retriever.get_relevant_documents(question)
    context = "\n\n".join([d.page_content for d in rel_docs])
    # İstemi oluştur ve yanıtı al
    final_prompt = prompt.format(context=context, question=question)
    return llm.invoke(final_prompt).content

if __name__ == "__main__":
    print(ask("Bu belgelerde performans optimizasyonu için öneriler neler?"))

Uygulamayı çalıştırmadan önce “docs/” klasörüne örnek metinler koymayı unutmayın. Eğer PDF kullanacaksanız “pypdf” ile yükleyebilir veya metne dönüştürüp aynı adımları uygulayabilirsiniz.

Performans ve Kalite İpuçları

Gömleme modeli seçimi: “nomic-embed-text” hızlı ve yeterli doğruluk sağlıyor. Çok dilli dokümanlarda “bge-m3” gibi çok dilli gömlemelere bakabilirsiniz.

Parça boyutu ve örtüşme: chunk_size=600–1200, chunk_overlap=80–200 aralığı pratik. Metin türüne göre ayarlayın. Uzun form teknik belgelerde daha büyük parçalar, soru-cevap notlarında daha küçük parçalar işe yarar.

Arama türü: Chroma varsayılan kosinüs benzerliği ile iyi çalışır. Farklı “k” değerlerini deneyin. Çok sayıda belge olduğunda metadata filtreleri eklemek doğruluğu artırır.

İstem mühendisliği: Şablona “Cevabın sonunda kaynak alıntısı ver” gibi kurallar eklemek kullanıcı güvenini artırır. Yanıt formatını (madde işaretleri, kısa özet + detaylar) açıkça belirtin.

Model ve nicemleme: Ollama üzerinde “:q4_0” gibi nicemlenmiş sürümler daha az RAM kullanır ve hızlanır; kalite az da olsa düşebilir. GPU mevcutsa GPU kullanımını etkinleştirmek büyük fark yaratır.

Güvenlik ve Gizlilik

Yerel RAG’in en önemli avantajı verilerin cihazınızda kalmasıdır. Ancak indeks dizininizi şifreli disk üzerinde tutmak, yedekleri güvenli almak ve işletim sistemi düzeyinde erişim izinlerini doğru ayarlamak gerekir. Paylaşılan makinelerde servis portlarını dışa açmayın.

Sorun Giderme

- “Connection refused”: Ollama servisi çalışmıyor olabilir. “ollama serve” komutunu kontrol edin.
- “CUDA/Metal hataları”: Sürücü/güncelleme gerekli olabilir. Geçici olarak CPU ile deneyin.
- “Bellek yetersiz”: Daha küçük model deneyin (ör. 3B–7B) veya nicemlenmiş varyant çekin.
- “Cevaplar ilgisiz”: chunk_size ve k değerlerini ayarlayın, gömleme modelini değiştirin, istemi netleştirin.

Sonuç

Bu kurulumla, Ollama + LangChain + Chroma üçlüsü sayesinde tamamen yerel çalışan bir RAG chatbotu elde ettiniz. Küçük boyutlu bir modelle bile belgeye dayalı arama ve yanıt üretiminde tatmin edici sonuçlar alabilirsiniz. Zamanla daha iyi gömlemeler, gelişmiş istem şablonları ve daha hızlı modellerle doğruluğu ve hızı artırabilirsiniz. Sonraki adım olarak bir REST API ekleyip (ör. FastAPI) web arayüzü veya Slack/Teams entegrasyonu kurmayı düşünebilirsiniz.

29 Kasım 2025 Cumartesi

pgvector ile RAG Uygulaması: Docker Compose ile PostgreSQL 16 ve Basit Semantik Arama API’si

RAG (Retrieval-Augmented Generation), büyük dil modellerinin (LLM) güncel ve alanınıza özgü verilerle daha doğru yanıtlar üretmesini sağlar. Bu yaklaşımda, soruyu bir vektöre dönüştürür, vektör veritabanından benzer içerikleri geri çağırır ve modeli bu bağlamla beslersiniz. Özel bir vektör veritabanına ihtiyaç duymadan, PostgreSQL 16 + pgvector ile etkili bir semantik arama katmanı kurmak mümkündür. Bu yazıda, Docker Compose ile PostgreSQL’i ayağa kaldıracak, pgvector eklentisini etkinleştirecek ve basit bir API üzerinden semantik arama yapabileceğiz.

Neden PostgreSQL + pgvector? PostgreSQL hâlihazırda üretim ortamlarında yaygın, güvenilir ve güçlü bir ilişkisel veritabanıdır. pgvector eklentisi, vektör tipini, benzerlik metriklerini (cosine, L2, inner product) ve ivfflat/HNSW benzeri indeksleme stratejilerini destekler. Küçük ve orta ölçekli RAG projeleri için tek bir veritabanı üzerinde hem ilişkisel hem de vektörel sorgular yürütmek operasyonel anlamda sade ve maliyet-etkindir.

Önkoşullar: Makinenizde Docker ve Docker Compose kurulu olmalı. Embedding üretimi için OpenAI hesabı (veya yerelde Ollama gibi bir çözüm) işinizi kolaylaştırır. Örneklerde OpenAI’nin “text-embedding-3-small” (1536 boyut) modelini referans vereceğiz; yerel seçenek kullanacaksanız embedding boyutunu ona göre ayarlamalısınız.

Adım 1: Docker Compose ile PostgreSQL 16 ve pgvector
Basit bir docker-compose.yml dosyası oluşturun ve şu servisi tanımlayın:
version: "3.9"
services:
  db:
    image: pgvector/pgvector:pg16
    environment:
      - POSTGRES_USER=rag
      - POSTGRES_PASSWORD=ragpass
      - POSTGRES_DB=ragdb
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
Dosyayı kaydedip docker compose up -d komutunu çalıştırın. Bu imaj, pgvector eklentisi ile birlikte gelir.

Adım 2: pgvector’ü etkinleştirmek ve şema hazırlığı
Veritabanına bağlanın: psql -h localhost -U rag -d ragdb ve şu komutları çalıştırın:
CREATE EXTENSION IF NOT EXISTS vector;
OpenAI’nin “text-embedding-3-small” boyutuna uygun bir tablo oluşturun:
CREATE TABLE docs (
  id BIGSERIAL PRIMARY KEY,
  content TEXT NOT NULL,
  embedding vector(1536)
);
Arama performansı için ivfflat indeksini kurun (cosine metrik popüler bir tercih):
CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
İndeksin etkili çalışması için tabloyu analiz edin: ANALYZE docs;

Adım 3: Embedding üretimi ve veri ekleme
Örnek içerikler ekleyelim: ürün açıklamaları, SSS, teknik notlar vs. Python ile kısa bir betik yazabilirsiniz. OpenAI için mantık şu şekildedir:
- Metni al, client.embeddings.create(model="text-embedding-3-small", input=metin) ile vektörü üret.
- Vektörü PostgreSQL’e parametreli bir sorgu ile yaz: INSERT INTO docs(content, embedding) VALUES ($1, $2).
Yerel alternatif isterseniz, Ollama’da ollama pull nomic-embed-text diyerek bir embedding modeli çekebilir, http://localhost:11434/api/embeddings üzerinden benzer bir akış kurabilirsiniz. Dikkat: embedding boyutunu (ör. 768) tablo şemanızla tutarlı yapın.

Adım 4: Semantik arama sorgusu
Kullanıcı sorgusunu da embedding’e çevirin ve ORDER BY embedding <=> $1 ifadesiyle benzerliğe göre sıralayın. Örnek bir SQL:
WITH q AS (SELECT $1::vector AS v)
SELECT id, content
FROM docs, q
ORDER BY docs.embedding <=> q.v
LIMIT 5;
Burada <=>, pgvector’ün benzerlik operatörüdür (cosine için mesafe). Bu sonuçları LLM’e bağlam olarak verip RAG yanıtı oluşturabilirsiniz.

Adım 5: Basit bir API ile uçtan uca akış
Hızlı bir prototip için Python FastAPI idealdir. Akış şöyledir:
1) POST /search: query alır, embedding üretir, PostgreSQL’den top-k döner.
2) POST /ask: query ve top-k bağlamı alır, seçtiğiniz LLM (OpenAI veya yerel) ile yanıt üretir.
Üretimde, sonuçları önbelleğe almak (ör. Redis), indeks lists değerini veri büyüklüğüne göre artırmak ve maintenance_work_mem, shared_buffers gibi PostgreSQL ayarlarını optimize etmek önemlidir.

İleri seviye ipuçları
- HNSW: pgvector 0.7+ sürümlerinde HNSW desteği bulunur; okuma gecikmesini düşürür, ancak indexleme süresi ve bellek kullanımı artar. Benchmark yapmadan geçiş yapmayın.
- Normalize embedding: Cosine benzerliğinde vektörleri normalize etmek sonuç tutarlılığını artırabilir.
- Chunking ve metadata: Belgeleri 300–800 token aralığında parçalara bölün. Kaynak, tarih, başlık gibi metadata alanlarını tabloya ekleyin ve sonuçlarda gösterin.
- Güncelleme stratejisi: Sık değişen veriler için upsert akışı oluşturun; embedding’i yalnızca içerik değiştiğinde güncelleyin.
- Güvenlik: Üretimde veritabanını dışarıya kapatın, SSL kullanın, sıkı rol ve politika tanımları yapın.

Sonuç
PostgreSQL 16 ve pgvector ile, ek bir servis karmaşıklığına girmeden güçlü bir semantik arama ve RAG katmanı kurabilirsiniz. Docker Compose yapılandırması hızlı kurulum sağlar; embedding üretimi için OpenAI veya yerel modelleri kullanabilirsiniz. Üzerine basit bir API ekleyerek hem prototip hem de üretim öncesi pilot projelerinizi hızla hayata geçirmeniz mümkün. Doğru indeks, boyut ve ayarlarla, pgvector küçük-orta ölçekli prodüksiyon yüklerini rahatlıkla karşılayacaktır.

28 Kasım 2025 Cuma

RAG ile Türkçe Soru-Cevap Sistemi Kurma: Vektör Veritabanı, Yeniden Sıralama ve Prompt Tasarımı

RAG (Retrieval-Augmented Generation), büyük dil modellerinin (LLM) güncel ve alanınıza özel bilgilerle desteklenmesini sağlayan, üretken yapay zekâ projelerinde giderek standarda dönüşen bir yaklaşımdır. Bu yazıda, Türkçe odaklı bir doküman arama ve soru-cevap sistemini RAG mimarisiyle nasıl kurabileceğinizi; veri hazırlığından vektör veritabanına, yeniden sıralamadan (re-ranking) prompt tasarımına kadar adım adım anlatıyorum.

Amaç, kullanıcı sorusuna dayanarak şirket içi PDF’ler, politika metinleri, ürün katalogları veya destek dökümanları içinden ilgili pasajları bulmak ve LLM’nin yalnızca bu pasajları referans alarak doğru, denetlenebilir cevaplar üretmesini sağlamaktır. Böylece hem halüsinasyonları azaltır hem de cevaplara kaynak gösterebilirsiniz.

Mimari Özeti: RAG iki parçadan oluşur. Birincisi bilgi erişimi (retrieval): Belgeleri parçalayıp (chunking), vektörlerine dönüştürerek bir vektör veritabanına koyar ve sorguya en yakın aday pasajları getirir. İkincisi jenerasyon (generation): LLM, gelen pasajları bağlam olarak kullanıp nihai cevabı üretir. İsteğe bağlı üçüncü bir katman olan yeniden sıralama (re-ranking) ile en iyi adayları üst sıralara taşıyarak doğruluğu yükseltirsiniz.

1) Veri Toplama ve Temizleme: PDF, HTML, Word veya düz metin kaynaklarınızı tek bir havuzda toplayın. Başlık, bölüm, tarih ve izin seviyesi gibi meta verileri koruyun. OCR gerekiyorsa hatalı karakterleri düzeltin, tabloları metne uygun biçimde dönüştürün. Aynı belgenin eski sürümlerini işaretleyerek sürüm çakışmalarını engelleyin.

2) Parçalama (Chunking): Türkçe dilinde bağlamı korumak için paragraf temelli veya cümle temelli parçalama tercih edin. 400–800 token aralığı pratikte iyi sonuç verir; çok küçük parçalarda bağlam kaybolur, aşırı büyük parçalarda ise arama isabeti düşer. Kayma penceresi (overlap) 50–100 token aralığında seçildiğinde cümle bütünlüğü ve referanslar daha sağlam kalır.

3) Gömme (Embeddings) Seçimi: Çok dilli Sentence Transformers tabanlı modeller veya Türkçe uyumlu modern embedding modelleri tercih edin. Türkçe morfolojisi nedeniyle kök/ek varyasyonlarını iyi yakalayan çok dilli modeller pratikte güçlüdür. Vektörleri L2 normla normalize etmeniz kozinüs benzerliği için istikrar sağlar. Boyut (dimensionality) arttıkça isabet artsa da depolama ve gecikme maliyeti yükselir; üretim için 384–1024 aralığı dengelidir.

4) İndeksleme ve Vektör Veritabanı: FAISS ile lokal hızlı prototipleme yapabilir, üretimde Qdrant, Weaviate, Pinecone ya da Elasticsearch’ün yoğun vektör (dense) alanlarını kullanabilirsiniz. HNSW veya IVF-PQ gibi yaklaşık en yakın komşu (ANN) indeksleri gecikmeyi düşürür. Meta veri filtreleme (ör. dil, departman, tarih) ile hassas eşleşme yaparak alakasız sonuçları erkenden eleyin.

5) Hibrit Arama: Tek başına vektör benzerliği bazen anahtar kelime ağırlıklı soruları ıskalayabilir. BM25 + vektör aramayı birleştirerek iki dünyanın en iyisini alabilirsiniz. RRF (Reciprocal Rank Fusion) veya ağırlıklı skor birleştirme ile son aday listesini oluşturun. MMR (Maximal Marginal Relevance) kullanarak çeşitliliği artırın; böylece benzer pasajlar yerine farklı açılardan destekleyen pasajlar üst sıralara gelir.

6) Yeniden Sıralama (Re-ranking): İlk 50–200 adayı, küçük ama hassas bir çapraz-enkoder re-ranker modeliyle yeniden puanlayın. Re-ranker, sorgu ile pasaj arasındaki anlam ilişkisini derinlikli değerlendirir ve isabeti gözle görülür şekilde artırır. Özellikle Türkçe sorgularda, re-ranker kullanımı yanlış pozitifleri ciddi biçimde azaltır.

7) Prompt Tasarımı: Sistem talimatına “Sadece sağlanan bağlamdan yararlan, kaynak yoksa ‘yeterli bilgi yok’ de” gibi net kısıtlar ekleyin. Kullanıcı sorusu, seçilen pasajlar ve gerekirse kısa bir özet talimatı tek bir prompt içinde verilebilir. Her pasajın yanında kaynak kimliği (belge adı, sayfa, bölüm) tutarak yanıta otomatik kaynakça ekleyin; bu, güven ve denetlenebilirlik sağlar.

8) Cevap Üretimi ve Biçimlendirme: Uzun cevaplar için madde işaretleri, kısa cevaplar için net tek paragraf formatı tercih edin. Modelin “uydurma” eğilimini azaltmak için bağlam penceresini verimli kullanın; gerekirse soruyu alt-sorulara bölüp her alt-soru için mini retrieval akışı kurgulayın (multi-step RAG). Hassas alanlarda (hukuk, finans, sağlık) kesinlik dilini yumuşatın ve gerekiyorsa uyarı notu ekleyin.

9) Değerlendirme ve İzleme: Recall@k, MRR, nDCG gibi arama metrikleri ile konteks isabetini ölçün. Yanıt kalitesi için bağlam kapsamı, doğruluk ve kaynak tutarlılığına bakın. Üretim ortamında RAG değerlendirme çerçeveleri (ör. otomatik değerlendirme ve örneklem tabanlı insan denetimi) kurarak sürekli iyileştirme döngüsü oluşturun. Yanlış eşleşen pasajları etiketleyip yeniden eğitime dahil ederek sistematik hataları azaltın.

10) Performans, Maliyet ve Bakıma Dair İpuçları: Sorgu tarafında embedding önbelleği, sonuç tarafında yanıt önbelleği (semantic cache) maliyeti düşürür. ANN indeks parametrelerini (efSearch, nprobe vb.) gecikme/hedef isabet dengesine göre ayarlayın. Kenar cihazlarda veya düşük bütçede 4-bit/8-bit quantized LLM’ler iş görür. Büyük kurumsal koleksiyonlarda artımlı indeks güncellemeleri ve arka plan yeniden inşa stratejisi planlayın.

11) Güvenlik ve Uyumluluk: Kurumsal RAG’da erişim kontrolünü indeks katmanında uygulayın; kullanıcının yetkisi olmayan belgeler retrieval aşamasına hiç girmesin. PII maskeleme ve günlükleme (audit) politikalarını belirleyin. Oran sınırlama (rate limiting) ve anomali tespiti ile kötüye kullanımı engelleyin.

Sık Yapılan Hatalar: Çok büyük chunk boyutları kullanmak, yalnızca vektör aramaya güvenmek, re-ranker atlamak, prompt’ta kaynak gösterimi istememek ve üretim izleme metriklerini kurmamak. Ayrıca embed modeli ile arama dili uyumsuz olduğunda isabet hızla düşer; çok dilli kullanımda model seçimini A/B testleriyle doğrulayın.

Sonuç: RAG, Türkçe belgelerle çalışan soru-cevap sistemleri için pratik, ölçeklenebilir ve denetlenebilir bir çözüm sunar. Doğru chunking, iyi seçilmiş embedding, hibrit arama ve re-ranking üçlüsü; üzerine titizlikle kurgulanmış prompt ve değerlendirme yönergeleri ile birleştiğinde, hem doğruluk hem de kullanıcı güveni açısından sınıf atlatır. Küçük bir pilot ile başlayıp metrikler ışığında iteratif optimize ederek kısa sürede üretime hazır, kaynaklı ve güvenilir bir RAG çözümü elde edebilirsiniz.

9 Kasım 2025 Pazar

Docker ile PostgreSQL + pgvector Kurulumu ve Semantik Arama Rehberi (2025)

pgvector nedir ve neden önemlidir?

Semantik arama, metnin anlamını kavrayarak benzer içerikleri bulmayı hedefleyen modern bir yaklaşım. Bu yaklaşımın kalbinde ise metinleri yüksek boyutlu sayısal vektörlere dönüştürmek ve bu vektörler arasında en benzer olanları hızlıca bulmak yer alır. pgvector, PostgreSQL üzerinde vektör veri tipini ve benzerlik aramalarını destekleyen bir eklenti olarak, ek bir vektör veritabanı yönetmek zorunda kalmadan güçlü semantik arama çözümleri geliştirmenize imkan tanır.

Bu rehberde, Docker kullanarak PostgreSQL 16 + pgvector kurulumunu gerçekleştirecek, örnek bir şema ile HNSW veya IVFFlat indeksleri üzerinden hızlı arama yapacak ve üretim ortamı için ayar önerileri sunacağız. RAG (Retrieval Augmented Generation) gibi yapay zekâ uygulamalarında performanslı ve ölçeklenebilir bir temel oluşturmayı hedefliyoruz.

Önkoşullar

- Docker ve Docker Compose yüklü bir makine (Linux, macOS veya Windows).

- Terminal/komut satırına erişim ve temel PostgreSQL bilgisi.

- Embedding üretmek için bir model (ör. Sentence-Transformers veya bir LLM sağlayıcısı). Bu rehberde örnek olarak sabit vektörlerle ilerleyeceğiz; gerçek projede modelden gelen boyutlarla eşleşecek şekilde tabloyu kurmalısınız.

Kurulum: Docker ile PostgreSQL + pgvector

Hızlı başlamak için resmi pgvector imajını kullanacağız. Aşağıdaki komut PostgreSQL 16 ve pgvector eklentisini içeren bir konteyneri ayağa kaldırır:

docker run --name pgvector -e POSTGRES_PASSWORD=secret -p 5432:5432 -d pgvector/pgvector:pg16

Veritabanına bağlanmak için psql kullanabilirsiniz:

psql -h localhost -U postgres

Bağlandıktan sonra eklentiyi etkinleştirin:

CREATE EXTENSION IF NOT EXISTS vector;

Şema tasarımı ve örnek veri

Gerçekte embedding boyutunuz seçtiğiniz modele göre değişir (ör. 384, 768, 1024). Anlatımı basitleştirmek adına burada 3 boyutlu bir örnek kullanacağız; siz kendi projelerinizde doğru boyutu tablo tanımında belirtin.

CREATE TABLE docs (id BIGSERIAL PRIMARY KEY, title TEXT, content TEXT, embedding VECTOR(3));

Benzerlik aramalarını hızlandırmak için iki popüler indeks tipinden birini ekleyebilirsiniz. HNSW genel olarak yüksek doğruluk ve iyi performans sunarken, IVFFlat kurulum ve ayar açısından daha basittir.

-- HNSW + Kosinüs uzaklığı

CREATE INDEX docs_embedding_hnsw ON docs USING hnsw (embedding vector_cosine_ops);

Örnek verileri ekleyelim:

INSERT INTO docs (title, content, embedding) VALUES

('PostgreSQL Rehberi', 'Indeks, performans ve yedekleme ipuçları.', '[0.10, 0.85, 0.20]'),

('Vektör Veritabanları', 'pgvector, HNSW ve benzerlik metrikleri.', '[0.12, 0.80, 0.25]'),

('Docker ile Kurulum', 'Kapsayıcı tabanlı veritabanı dağıtımı.', '[0.60, 0.10, 0.30]');

Semantik arama sorguları

Kullanacağınız benzerlik ölçütü projeye göre değişir. Çoğu metin embedding’inde kosinüs uzaklığı iyi sonuç verir. Kosinüs mesafesi için pgvector’da <=> operatörü kullanılır; mesafe ne kadar düşükse benzerlik o kadar yüksektir. Dilerseniz skor olarak benzerliği görmek için 1 - mesafe hesaplayabilirsiniz.

-- Sorgu vektörü örnek: '[0.12, 0.88, 0.33]'

SELECT id, title, 1 - (embedding <=> '[0.12, 0.88, 0.33]') AS cosine_similarity

FROM docs

ORDER BY embedding <=> '[0.12, 0.88, 0.33]'

LIMIT 5;

IVFFlat indeksi tercih edecekseniz, eğitim gerektirir ve arama-doğruluk dengesi için probes parametresi önemlidir:

CREATE INDEX docs_embedding_ivf ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

SET ivfflat.probes = 10;

Üretim için en iyi uygulamalar

- Boyut tutarlılığı: Tablo tanımındaki vektör boyutu embedding modeli ile birebir aynı olmalı. Modeli değiştirirseniz yeni bir alan veya tablo kullanın.

- Normalizasyon: Kosinüs benzerliği kullanırken embedding’leri uygulama katmanında birim uzunluğa normalize etmek sonuçların tutarlılığını artırır.

- Toplu yüklemeler: Büyük veri yüklerken indeksleri en son oluşturun ve synchronous_commit = off ile yüklemeyi hızlandırmayı değerlendirin (kritik verilerde dikkatli olun).

- Bakım: Veri dağılımı değiştikçe ANALYZE ve gerekirse REINDEX yapın. IVFFlat için doğru lists ve probes değerlerini veri setinizde deneyerek belirleyin.

- Bellek ve önbellek: PostgreSQL yapılandırmasında genel öneriler: shared_buffers RAM’in %25’i civarı, effective_cache_size %50–75, indeks oluştururken maintenance_work_mem’i yüksek tutun, sorgu başına work_mem değerini gözlemleyerek ayarlayın.

- Yedekleme ve göç: Şema değişiklikleri ve büyük indeksler söz konusu olduğunda pg_dump ve pg_restore stratejinizi test edin; depolama IOPS kapasitesini göz önünde bulundurun.

RAG ve uygulama entegrasyonu

RAG mimarisinde tipik akış, sorgu metnini embedding’e çevirip PostgreSQL’de en benzer içerikleri bulmak ve bu içerikleri LLM’e bağlam olarak sunmaktır. Uygulamada sıklıkla yapılan optimizasyon, hem title hem de content alanlarını birleştirip tek embedding üretmek ya da çok alanlı senaryoda iki ayrı embedding sütunu ile ağırlıklı birleştirme yapmaktır. İhtiyaçlarınıza göre HNSW ile yüksek doğrulukta, IVFFlat ile daha düşük gecikmede cevaplar elde edebilirsiniz.

Sonuç olarak, pgvector ile PostgreSQL’i bir vektör veritabanına dönüştürmek hem yönetim yükünü azaltır hem de üretim tecrübesi kanıtlanmış bir ekosistemden yararlanmanızı sağlar. Doğru indeks, metrik ve donanım ayarlarıyla semantik arama ve RAG uygulamalarınızı güvenle ölçekleyebilirsiniz.

3 Kasım 2025 Pazartesi

Laptopta Yerel LLM Çalıştırma Rehberi: Ollama ile GPU Hızlandırmalı RAG Kurulumu (2025)

Giriş

Üretken yapay zekâ servislerini bulut yerine kendi bilgisayarınızda çalıştırmak hem gizliliği artırıyor hem de maliyeti düşürüyor. Son aylarda adını sıkça duyduğumuz Ollama, yerel LLM çalıştırmayı son derece pratik hâle getiriyor. Bu rehberde, laptop veya masaüstünüzde GPU hızlandırmalı bir kurulum yapacak, ardından basit bir RAG (Retrieval Augmented Generation) akışı kurgulayarak kendi belgeleriniz üzerinde akıllı arama ve soru-cevap deneyimi oluşturacağız. Tüm adımlar sade ve SEO dostu bir “how-to” olarak planlandı.

Sistem Gereksinimleri ve Model Seçimi

Modern bir CPU ve en az 16 GB RAM önerilir. GPU tarafında NVIDIA (CUDA) veya Apple Silicon (Metal) destekleri performansı ciddi biçimde artırır. Disk alanınızın en az 10–20 GB boş olması faydalıdır. Model seçerken boyut-kalite dengesine dikkat edin: llama3:8b veya mistral:7b gibi 7–8B modeller, 4-bit kuantizasyonla çoğu senaryoda iyi sonuç verir. Daha ciddi analizler için 13B üstü modellere yönelebilirsiniz, ancak VRAM ve RAM kullanımınız artacaktır.

Ollama Kurulumu

macOS üzerinde brew install ollama ile kurulumu tamamlayabilirsiniz. Windows için resmi yükleyiciyi tercih edin (Ollama sitesinden .exe indirerek). Linux’ta ise curl -fsSL https://ollama.com/install.sh | sh komutu işinizi görecektir. Kurulumdan sonra servisi başlatmak için ollama serve komutunu çalıştırın; arka planda http://localhost:11434 adresinde bir API sunucusu açılır.

İlk Modeli İndirme ve Çalıştırma

Örnek olarak Llama 3’ün 8B sürümünü indirelim: ollama pull llama3:8b. Ardından hızlı bir test için ollama run llama3:8b komutunu çalıştırın. Komut satırında modele doğrudan soru sorabilirsiniz. Türkçe anlama ve yanıt üretimi konusunda tatmin edici sonuçlar için sistem talimatını kısa bir bağlamla başlatmanız iyi olur; örneğin “Türkçe, kısa ve teknik yanıt ver” gibi bir içerikle diyaloğu yönlendirin.

GPU Hızlandırma İpuçları

Apple Silicon (M1/M2/M3) cihazlarda Metal desteği otomatik devreye girer. NVIDIA tarafında en iyi sonuç için güncel CUDA ve cuDNN sürümlerini kurun, ardından ortam değişkenleriyle ince ayar yapın. Örneğin, OLLAMA_NUM_GPU=1 ile kaç GPU kullanılacağını sınırlandırabilir, OLLAMA_MAX_LOADED_MODELS=1 ile aynı anda yüklenen model sayısını azaltarak VRAM taşmalarını önleyebilirsiniz. Ayrıca 4-bit kuantize sürümler (Q4_K_M benzeri) daha az bellek tüketir; ilk denemelerde bunları tercih etmek stabilite sağlar.

RAG Nedir ve Neden Gerekli?

RAG, modelin kendi parametrelerinde olmayan güncel veya özel bilgiyi, harici bir bilgi tabanından anlık olarak alıp yanıtları zenginleştirmesini sağlar. Örneğin, şirket içi dokümanlarınızı veya notlarınızı vektör dizinine (vector store) dönüştürür, sorgu anında en uygun parçaları çekip modele “bağlam” olarak verirsiniz. Böylece hallucination azalır, doğruluk artar.

Basit RAG Akışı: Adım Adım

1) Belgeleri Hazırla: PDF, Markdown veya düz metin dosyalarınızı tek bir klasörde toplayın. Büyük dosyaları ~500–1000 token’lık parçalara bölmek arama kalitesini artırır.

2) Embedding Modelini Çek: Ollama içinden bir gömme modeli indirin: ollama pull nomic-embed-text veya çok dilli kullanım için all-minilm benzeri alternatifleri deneyin.

3) Vektör Üret: Hızlı bir test için Ollama’nın HTTP API’sini kullanabilirsiniz. Örnek bir istek: curl -s http://localhost:11434/api/embeddings -d '{"model":"nomic-embed-text","input":"Merhaba dünya"}'. Script ile belgelerinizi satır satır embed ederek bir JSONL çıktısı oluşturabilirsiniz.

4) Vektör Dizini Kur: Hafif bir çözüme ihtiyaç varsa Chroma veya FAISS gibi kütüphaneleri tercih edin. Python tarafında pip install chromadb ile başlayabilir, vektörleri ve metin parçalarını koleksiyonlara ekleyebilirsiniz. Alternatif olarak SQLite tabanlı vektör eklentileri (ör. sqlite-vss) yerel, dosya tabanlı bir yaklaşım sunar.

5) Sorgu ve Geri Getirme: Kullanıcı sorgusunu aynı embedding modeliyle vektöre çevirin, en benzer N doküman parçasını bulun ve bu parçaları model istemine (prompt) “bağlam” olarak ekleyin. Ardından curl -s http://localhost:11434/api/generate veya ollama run llama3:8b üzerinden, oluşturduğunuz bağlamı içeren bir istemle yanıt üretin.

Performans ve Doğruluk İçin İnce Ayar

- Daha hızlı yanıt için kısa bağlam ve az sayıda parça ile deneyin; gerekirse N değerini 3–5 aralığında tutun. Uzun bağlamlar, özellikle küçük modellerde kaliteyi bazen düşürebilir.

- Top-k ve top-p örnekleme ayarları ile yaratıcılık/kararlılık dengesini kurun. Kritik teknik metinlerde deterministikliğe yakın ayarlar tercih edin.

- Kaynak parçaları yanıtın sonunda listeler veya dipnotlar olarak ekletin. Bu hem şeffaflık sağlar hem de güveni artırır. İstemde “Kaynaklardan alıntı yap ve bağlantı ver” gibi net talimatlar verin.

Güvenlik ve Gizlilik

Yerel kurulumun en büyük artısı verilerin bilgisayarı terk etmemesidir. Yine de hassas belgelerle çalışırken disk şifrelemesi, güçlü oturum açma yöntemleri ve düzenli yedekleme kullanın. Eğer API’nizi ağ üzerinden açacaksanız bir ters proxy arkasında kimlik doğrulama ekleyin. Model ve embedding versiyonlarını not edin; üretim senaryosunda değişikliklerin etkisini takip etmek için versiyonlama kritiktir.

Sonuç

Ollama ile yerel LLM kurmak, düşündüğünüzden daha hızlı ve verimli. Küçük bir embedding modeli ve hafif bir vektör diziniyle kuracağınız RAG katmanı, kişisel notlarınızdan teknik dokümanlara kadar geniş bir bilgi tabanını akıllıca sorgulamanıza imkân tanır. Donanımınıza göre doğru model ve kuantizasyonu seçip GPU hızlandırmayı aktifleştirdiğinizde, bulut bağımlılığını azaltan, düşük gecikmeli ve gizlilik dostu bir üretken yapay zekâ deneyimi elde edersiniz. İlk POC’yi başarıyla tamamladıktan sonra; bir REST arayüzü ekleyip arka planda planlanmış yeniden indeksleme görevleri ve log analiziyle yapınızı olgunlaştırabilirsiniz.

28 Ekim 2025 Salı

PostgreSQL + pgvector ile Semantik Arama ve RAG: Kurulum, İndeks ve Performans Rehberi

Giriş

Semantik arama ve RAG (Retrieval-Augmented Generation) uygulamaları, yalnızca bir metnin kelimelerine değil, anlamına göre sonuç döndürerek daha isabetli yanıtlar verebiliyor. Bu yaklaşımı uygulamak için vektör veritabanı şart. Pek çok ekip, halihazırda kullandıkları PostgreSQL üzerinde pgvector eklentisiyle bu ihtiyacı karşılıyor. Bu yazıda, PostgreSQL + pgvector kombinasyonuyla semantik arama altyapısını nasıl kuracağınızı, indekslemeyi nasıl yapacağınızı ve performansı nasıl optimize edeceğinizi adım adım anlatıyorum.

Neden pgvector?

Pgvector, PostgreSQL’e vektör veri tipi (vector) ve benzerlik aramaları (cosine, L2, inner product) kazandırır. Ayrı bir veritabanı yönetmek yerine tek bir Postgres kümesi üzerinde hem ilişkisel verilerinizi hem de embedding’lerinizi saklayabilirsiniz. Bu, devops maliyetini azaltırken güçlü ACID garantileri ve yedekleme stratejilerinden de yararlanmanızı sağlar.

Önkoşullar

PostgreSQL 14+ önerilir; performans ve özellikler için 15/16 daha iyi. Sunucuda en az 4 CPU, 8 GB RAM başlamak için konfor sağlar. Ayrıca embedding üretmek için bir model (örneğin OpenAI text-embedding-3-small, Instructor, E5-large veya yerel bir model) gereklidir.

Kurulum (Docker ve Yerel)

Docker ile hızlı kurulum: Resmi Postgres imajı yerine pgvector içeren bir imaj kullanabilirsiniz. Örnek:

docker run -d --name pg -e POSTGRES_PASSWORD=secret -p 5432:5432 ankane/pgvector

Yerel kurulum (Ubuntu/Debian): Paket yöneticinizde pgvector olmayabilir. Kaynaktan kurulum tipik akış:

sudo apt-get update && sudo apt-get install -y postgresql postgresql-server-dev-all git make gcc

git clone https://github.com/pgvector/pgvector.git && cd pgvector && make && sudo make install

Veritabanını Hazırlama

Postgres’e bağlandıktan sonra eklentiyi etkinleştirin ve şemanızı oluşturun:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (id bigserial PRIMARY KEY, title text, body text, embedding vector(1536));

Burada vector(1536) embedding boyutunu temsil ediyor. Kullanacağınız modele göre bu değeri değiştirin (örn. 768, 1024, 1536).

Embedding Üretme ve Veri Ekleme

Embedding’leri uygulama katmanında üretip Postgres’e yazmak en yaygın yaklaşım. Basit akış: metni temizle, cümlelere/segmentlere böl, embedding modeline gönder, sonuç vektörünü tabloya ekle.

Örnek bir ekleme akışı:

INSERT INTO documents (title, body, embedding) VALUES ('KVKK Özeti', 'Kişisel verilerin korunması...', '[0.012, -0.034, ...]');

Not: pgvector, köşeli parantezle vektör alır. Uygulama dilinizde (Python/Node/Go) embedding dizisini string’e çevirip eklemek pratik bir yöntemdir.

Benzerlik İndeksleri: IVFFlat ve HNSW

Büyük veri kümelerinde ham tarama yavaştır. Bu nedenle IVFFlat veya HNSW indeksleri kullanılır. IVFFlat için önce tabloyu kabaca küme merkezlerine göre “eğitmek” gerekir.

-- Koşul: önce yeterince satır eklenmiş olmalı

CREATE INDEX ON documents USING ivfflat (embedding vector_cosine) WITH (lists = 100);

HNSW, eğitime gerek duymaz ve bazı veri setlerinde daha iyi gecikme/kalite dengesi sunabilir:

CREATE INDEX ON documents USING hnsw (embedding vector_cosine) WITH (m = 16, ef_construction = 128);

Metrik seçimi kritiktir: embedding modeliniz cosine ile eğitildiyse vector_cosine seçin. Performans için lists (IVFFlat) ve ef_search (HNSW) değerlerini iş yükünüze göre ayarlayın.

Semantik Arama Sorguları

Arama anında, sorgu metnini embedding’e çevirin ve en yakın komşuları çekin:

-- sorgu_embedding uygulama katmanından parametre olarak gelir

SELECT id, title, body FROM documents ORDER BY embedding <#> :sorgu_embedding LIMIT 5;

<#> operatörü cosine distance’dır. En iyi sonuçları almak için LIMIT’i ve filtre koşullarını (ör. kategori, tarih aralığı) birlikte kullanın.

RAG İçin Basit Bir Akış

- Kullanıcı sorusunu alın ve embedding’e dönüştürün.

- PostgreSQL’den en alakalı 5–10 dokümanı semantik aramayla çekin.

- Cevaplayıcı LLM’e, bu parçaları bağlamsal ek metin (context) olarak verin.

- Kaynakları (title ve id) cevapla birlikte kullanıcıya gösterin. Bu yaklaşım, halüsinasyonları azaltır ve izlenebilirlik sağlar.

Performans ve Ölçek İpuçları

1) İndeks ısınması: Sık aranan sorgu türleri için sistem başladığında birkaç “ısınma” araması yapın. Bu, sayfa önbelleğini doldurur.

2) Paralelleştirme: Toplu embedding üretiminde çoklu iş parçacığı ya da job queue kullanın. Veritabanına batch insert (ör. 100–1000 satır) performans sağlar.

3) Tablo tasarımı: Metin gövdeleri büyükse, embedding’leri ayrı bir tabloda (documents_vec) tutup body’yi object storage’a koymayı değerlendirin; Postgres’te sadece referans saklayın.

4) Bakım: Yoğun yazma/indeks güncellemelerinde VACUUM (ANALYZE) planlayın. Autovacuum ayarlarını (naptime, cost_limit) iş yükünüze göre iyileştirin.

5) IVFFlat ayarları: lists değerini veri büyüklüğüne göre artırmak hatırlama oranını iyileştirir; sorgu anında SET ivfflat.probes = X; ile daha fazla liste tarayıp isabet oranını yükseltebilirsiniz (gecikme artar).

6) HNSW ayarları: SET hnsw.ef_search = 64/128/256 gibi değerlerle kalite/gecikmeyi dengeleyin. Daha yüksek ef_search, daha iyi sonuç ama daha fazla CPU demektir.

7) Sharding/Partitioning: Konu veya müşteri bazlı PARTITION BY LIST ile arama alanını daraltmak ciddi kazanç sağlar.

Güvenlik ve Versiyonlama

Embedding uzayı model güncellemeleriyle değişebilir. Model versiyonunu tabloda saklayın (örn. model_version text) ve farklı versiyonlar için ayrı indeks tutun. Erişim tarafında Row Level Security (RLS) ile müşteri/veri bölümlendirmesini zorunlu kılın.

Hata Ayıklama ve Sık Karşılaşılan Sorunlar

- ERROR: type "vector" does not exist: CREATE EXTENSION vector; komutunun ilgili veritabanında çalıştığından ve eklentinin kurulu olduğundan emin olun.

- IVFFlat “not enough tuples”: İndeksi kurmadan önce yeterli sayıda satır eklenmiş olmalı; aksi halde eğitim yapılamaz.

- Yüksek gecikme: İndeks kullanılmıyor olabilir; EXPLAIN (ANALYZE, BUFFERS) ile planı inceleyin. probes veya ef_search değerlerini ayarlayın.

Sonuç

Pgvector, PostgreSQL’i güçlü bir vektör arama motoruna dönüştürüyor. Doğru indeks ve ayarlarla milyonlarca embedding üzerinde milisaniyeler içinde semantik arama yapılabiliyor. RAG senaryolarında ise hem kaynak yönetimini sadeleştiriyor hem de mevcut Postgres ekosisteminin güvenilirliğinden yararlanmanızı sağlıyor. Küçük bir POC ile başlayıp indeks parametrelerini kademeli ayarlayarak en iyi maliyet/performans noktasını yakalayabilirsiniz.

24 Ekim 2025 Cuma

Yerel LLM ile RAG: Ollama + LangChain + ChromaDB ile Türkçe Soru-Cevap Sistemi Kurulumu (2025 Rehberi)

RAG nedir, neden yerel?

RAG (Retrieval-Augmented Generation), büyük dil modellerini (LLM) kendi verinizle güçlendirmenin en pratik yollarından biridir. Model, önce vektör veritabanından ilgili pasajları arar (retrieval), ardından yanıtı bu pasajları referans alarak üretir (generation). Bu yaklaşım, hem doğruluk hem de güncellik sağlar. Yerel (on-prem/edge) kurulum ise hassas veriyi dışarı çıkarmadan çalıştığı için KVKK uyumu, gecikme ve maliyet açısından avantajlıdır.

Mimari genel bakış

Ollama yerel LLM’i (ör. Qwen2.5 7B) çalıştırır, LangChain iş akışını yönetir, ChromaDB vektör veritabanı olarak belgeleri tutar, Sentence-Transformers ise Türkçe uyumlu gömme (embedding) üretir. Sorgu akışı: Kullanıcı sorusu → Embedding → Chroma’dan benzer parçaların bulunması → Seçilmiş LLM ile bağlamsal yanıt.

Gereksinimler ve ortam

- İşletim sistemi: macOS, Linux veya WSL2’li Windows
- Python 3.10+
- 16 GB RAM önerilir (8 GB ile quantize modeller çalışır).
- GPU hızlandırma varsa avantajlı; yoksa 4-bit quantize modelleri tercih edin.

Kurulum adımları

1) Ollama’yı kurun ve modeli çekin:
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen2.5:7b
Qwen2.5 çok dilli yapısıyla Türkçe’de başarılıdır. Daha hafif bir seçenek gerekiyorsa qwen2.5:3b veya llama3.1:8b-instruct da tercih edilebilir.

2) Python ortamını hazırlayın:
python -m venv .venv && source .venv/bin/activate
pip install langchain langchain-community chromadb sentence-transformers pypdf fastapi uvicorn
Embedding için Türkçe’de güçlü bir seçenek: intfloat/multilingual-e5-base veya sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2.

Veri hazırlama ve indeksleme

Belgelerinizi data/ klasörüne koyun (PDF, TXT, MD). PDF’ler için pypdf ile metin çıkarabilirsiniz. Amaç, büyük belgeleri 500–1000 karakterlik, 50–100 karakter örtüşmeli parçalara ayırmaktır. Bu sayede arama daha isabetli olur ve bağlam penceresini verimli kullanırsınız.

Örnek akış (özet):
- Belgeleri yükle: PDF/TXT okuma
- Parçala: 800 karakter, 120 örtüşme
- Embedding üret: multilingual-e5-base
- ChromaDB’ye yaz: kalıcı (persist) bir dizinde tut

Basit bir betik iskeleti:
from langchain_community.document_loaders import PyPDFLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings

loader = PyPDFLoader("data/rapor.pdf")
docs = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=120)
chunks = splitter.split_documents(docs)

emb = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-base")
vect = Chroma.from_documents(chunks, emb, persist_directory="chroma_store")
vect.persist()

Arama + üretim zinciri

LangChain ile basit bir RAG zinciri kurabilirsiniz. Retriever’ı Chroma’dan oluşturun, Ollama LLM’i bağlayın ve istem (prompt) şablonu ile bağlamı enjekte edin. MMR (Maximal Marginal Relevance) ve top_k gibi ayarlarla oynayarak tekrar eden içerikleri azaltın ve çeşitliliği artırın.

Örnek sorgulama iskeleti:
from langchain_community.llms import Ollama
from langchain.prompts import PromptTemplate

vect = Chroma(persist_directory="chroma_store", embedding_function=emb)
retriever = vect.as_retriever(search_type="mmr", search_kwargs={"k": 5, "fetch_k": 20})

llm = Ollama(model="qwen2.5:7b", temperature=0.2)
template = ("Aşağıdaki bağlama dayanarak Türkçe, kaynaklara sadık ve kısa bir yanıt ver. "
"Bağlam:\n{context}\n\nSoru: {question}\nYanıt:")
prompt = PromptTemplate.from_template(template)

docs = retriever.get_relevant_documents("2024 finansal özet nedir?")
context = "\n\n".join([d.page_content for d in docs])
print(llm.invoke(prompt.format(context=context, question="2024 finansal özet nedir?")))

Doğruluk ve optimizasyon

- Chunk boyutu: 600–1000 karakter arası pratik. Daha küçük parça daha hassas arama, daha fazla parçayı LLM’e göndermek demektir. Bağlam penceresiyle dengeleme yapın.
- Reranker: GPU’nuz varsa bge-reranker-large gibi çapraz-encoder modeller ekleyerek bağlam kalitesini artırın.
- Top-k: 3–8 arası iyi bir başlangıç. Soru karmaşıksa artırın.
- Sıcaklık (temperature): 0.1–0.3 arası daha tutarlı, kaynaklara sadık yanıt sağlar.
- GYS/Değerlendirme: Küçük bir altın veri kümesi ile doğruluk ölçün. RAGAS gibi metriklerle bağlamsal doğruluğu takip edin.

Üretimde çalıştırma

Basit bir API için FastAPI idealdir. İsteğe göre streaming açarak ilk token’ı daha hızlı iletebilirsiniz. Chroma’yı kalıcı dizinle (persist_directory) başlatın ve yalnızca “okuma” modunda koşturun. Döküman güncellemeleri için zamanlanmış yeniden indeksleme (ör. günlük) stratejisi belirleyin.

Örnek uç nokta iskeleti:
from fastapi import FastAPI
app = FastAPI()

@app.get("/ask")
def ask(q: str):
  docs = retriever.get_relevant_documents(q)
  ctx = "\n\n".join(d.page_content for d in docs)
  ans = llm.invoke(prompt.format(context=ctx, question=q))
  return {"answer": ans}

uvicorn main:app --reload

Güvenlik, maliyet ve lisans notları

- Veri gizliliği: PII içeren alanları maskeleyin; loglarda ham sorgu ve belgeleri tutmayın. Diskte Chroma klasörünü şifreli bir birimde saklayın.
- Lisans: Kullandığınız model ve embedding lisansını kontrol edin; ticarî kullanımlarda kısıtlar olabilir.
- Maliyet: Yerel kurulum bulut token maliyetini düşürür, ancak donanım kaynağına ihtiyaç duyar. 4-bit quantize modeller düşük RAM’de dengeli performans sağlar.

Sorun giderme

- Yavaş yanıt: Embedding modelini daha hafife çekin (MiniLM), top_k’yı düşürün, quantize LLM kullanın.
- Alakasız bağlam: Chunk boyutunu artırın, MMR’ı açın, gerekirse reranker ekleyin.
- Bozuk indeks: chroma_store klasörünü temizleyip yeniden indeksleyin; gömme modelini değiştirdiyseniz indeksin de değişmesi gerekir.
- Hallüsinasyon: Prompt’a “Kaynak verilmeyen bilgiyi üretme” kuralını ekleyin, temperature’ı düşürün ve bağlamı zenginleştirin.

Sonuç

Bu rehberde Ollama + LangChain + ChromaDB ve çok dilli embedding’lerle yerel bir Türkçe RAG sistemi kurmanın hızlı yolunu gördünüz. Doğru chunking, iyi bir retriever ve tutarlı istem tasarımıyla, Türkçe dokümanlarınıza dayalı güvenilir bir soru-cevap deneyimi sağlayabilirsiniz. İhtiyaca göre model boyutunu, indeks ayarlarını ve dağıtım mimarisini optimize ederek sistemi üretim kalitesine taşıyın.

21 Ekim 2025 Salı

Yerel LLM Kurulumu: Ollama ve Open WebUI ile Hızlı ve Güvenli Yapılandırma Rehberi

Giriş: Neden Yerel LLM?

Gizlilik, düşük gecikme ve maliyet kontrolü, büyük dil modellerini (LLM) yerelde çalıştırmanın en önemli avantajları. Bu rehberde, açık kaynak ekosistemde hızla popülerleşen Ollama ile modelleri nasıl indireceğinizi ve Open WebUI üzerinden nasıl yöneteceğinizi adım adım göstereceğim. Amaç, teknik bariyeri düşük tutarak pratik bir kurulum sağlamak ve GPU hızlandırma, belge tabanlı arama (RAG) gibi ileri kullanım senaryolarına hızlıca geçebilmek.

Ön Koşullar ve Mimari

Ollama; macOS’ta Metal, Linux’ta CUDA/ROCm, Windows’ta DirectML/CUDA (uyum durumuna göre) ile çalışır. Open WebUI, Ollama’nın sunduğu yerel API’ye (varsayılan http://localhost:11434) bağlanarak tarayıcı tabanlı bir arayüz sunar. İkisini tek makinede koşturabilir, Docker ile izole edebilir veya sunucuya taşıyabilirsiniz.

Kurulum: Ollama

macOS: Homebrew ile brew install ollama komutunu çalıştırın. Ardından ollama serve ile servisi başlatın. Apple Silicon’da GPU hızlandırma otomatik devreye girer.

Linux: Terminalde curl -fsSL https://ollama.com/install.sh | sh komutunu çalıştırın. NVIDIA GPU için sürücü ve CUDA kurulumu yaptığınızdan emin olun. Servisi systemctl enable --now ollama ile kalıcılaştırabilirsiniz.

Windows: Resmi .msi yükleyicisiyle kurulum yapın. Ollama Tray ile servis başlatılabilir. GPU hızlandırma için güncel sürücüler ve desteklenen backend gereklidir.

İlk Modeli İndirme ve Çalıştırma

Popüler ve hızlı bir başlangıç için ollama pull llama3:8b veya ollama pull mistral:7b komutlarını kullanın. Ardından ollama run llama3:8b diyerek etkileşime geçin. Soruları terminalden yazabilir veya REST API ile programatik çağrılar yapabilirsiniz.

API örneği: curl http://localhost:11434/api/generate -d '{"model":"llama3:8b","prompt":"Merhaba, bugünün tarihi?"}'. Yanıtlarda gecikme görürseniz daha düşük quantizasyon (ör. q4_K_M) indirmeyi değerlendirin.

Open WebUI ile Grafik Arayüz

Open WebUI, sohbet geçmişi, çoklu model, belge ekleme ve RAG gibi özellikleri tek ekranda sunar. Docker ile hızlı kurulum için iki konteyner yeterlidir.

Ollama (Docker): docker run -d --name ollama -p 11434:11434 --gpus all -v ollama:/root/.ollama ollama/ollama

Open WebUI: Linux’ta Ollama’ya erişim için host gateway ekleyin: docker run -d --name open-webui -p 3000:8080 --add-host=host.docker.internal:host-gateway -e OLLAMA_API_BASE_URL=http://host.docker.internal:11434 -v open-webui:/app/backend/data open-webui/open-webui:latest

Windows/macOS’ta genellikle host.docker.internal otomatik çalışır. Tarayıcıdan http://localhost:3000 adresine giderek arayüze ulaşabilirsiniz.

RAG: Belgelerle Akıllı Yanıtlar

Open WebUI içinde “Knowledge” veya “Documents” bölümünden PDF, Markdown, TXT gibi belgeleri ekleyebilir ve indeksleyebilirsiniz. Ardından sohbet penceresinde ilgili bilgi tabanını seçtiğinizde model, cevaplarını bu içeriklere dayandırır. Küçük veri kümelerinde arama oldukça hızlıdır; büyük koleksiyonlarda bellek yükünü azaltmak için daha düşük boyutlu modeller ve hafif embedding’ler tercih edin.

Performans ve İnce Ayar

- Quantization: q4 varyantları RAM ve VRAM kullanımını düşürür; kalite/akıcılık dengesi için q5 veya q6 deneyin.
- İş Parçacığı: OLLAMA_NUM_PARALLEL ile eşzamanlı istek sayısını, --num-ctx ile bağlam penceresini ayarlayın.
- GPU Paylaşımı: Birden fazla model kullanıyorsanız aynı anda çalıştırmak yerine sıraya almayı tercih edin. GPU belleği dolarsa CPU’ya düşerek performans keskin biçimde azalabilir.
- Model Seçimi: Kod tamamlama için “Coder” varyantları; uzun bağlam gerektiren işlerde “Instruct” ve geniş context pencereli sürümler daha verimlidir.

Güvenlik ve Ağ Erişimi

Ollama’nın API’sini dış dünyaya açacaksanız bir ters vekil (ör. Caddy, Nginx) arkasında temel kimlik doğrulama uygulayın. Ev ağı senaryosunda sadece localhost’a bağlayın ve 11434 portunu yönlendirmeyin. Open WebUI kullanıcı hesapları oluşturmanıza izin verir; rol tabanlı erişimle modellerin kimler tarafından kullanılabileceğini sınırlayın.

Sorun Giderme

- Yavaş yanıt: Daha küçük modeli veya düşük quantizasyonu deneyin; CPU moduna düşmediğinizden emin olun.
- GPU tanınmıyor: Sürücü/CUDA güncellemelerini kontrol edin. Docker’da --gpus all bayrağı ve NVIDIA Container Toolkit gereklidir.
- Bağlantı hatası: Open WebUI’de OLLAMA_API_BASE_URL değerini ve ağ köprüsünü doğrulayın; Linux’ta --add-host parametresini eklemeyi unutmayın.
- Disk doluyor: Kullanmadığınız modelleri ollama rm model-adı ile kaldırın; hacim boyutlarını düzenli izleyin.

Sonuç

Ollama + Open WebUI ikilisiyle yerel LLM deneyimi, hem bireysel üretkenlik hem de kurumsal prototipleme için güçlü bir zemin sunuyor. Kurulum basit, yönetim pratik ve maliyet öngörülebilir. Başlangıçta hafif bir modelle ilerleyip ihtiyaçlara göre ölçeklendirmek, GPU kaynaklarını dikkatle planlamak ve güvenlik katmanlarını erken eklemek uzun vadede en sağlıklı yaklaşım olacaktır.

6 Ekim 2025 Pazartesi

Yerel LLM Rehberi: Ollama ile Llama 3.1’i Bilgisayarınızda Çalıştırma, GPU Hızlandırma ve RAG

Yerelde LLM çalıştırmanın avantajları

Büyük dil modellerini (LLM) bulut yerine kendi bilgisayarınızda çalıştırmak; gizliliği artırır, gecikmeyi düşürür ve yoğun denemelerde maliyeti kontrol altına alır. Son dönemde popülerleşen Ollama, Llama 3.1, Qwen, Mistral gibi açık modelleri tek komutla indirip çalıştırmanızı sağlayan hafif ve pratik bir platformdur. Bu yazıda, Llama 3.1’i Ollama ile yerelde kurmayı, GPU hızlandırmayı devreye almayı ve RAG (Retrieval-Augmented Generation) mimarisine giden kısa bir yol haritasını adım adım anlatıyorum.

Gereksinimler ve model seçimi

LLM’lerin RAM ve VRAM iştahı, model boyutuna ve sıkıştırma (quantization) düzeyine göre değişir. 8B (8 milyar parametre) sınıfı modeller güncel tüketici bilgisayarlarda iyi bir denge sunar. 16 GB RAM ve tercihen en az 8 GB VRAM, akıcı kullanım için idealdir. Daha büyük 13B veya 70B modeller daha yüksek kalite verse de donanım talebi ciddi artar. Ollama, modelleri quantized (ör. 4-bit) olarak sunabildiği için daha düşük bellekle de tatmin edici performans elde edilebilir. Kural basit: RAM/VRAM yetmiyorsa daha küçük model veya daha agresif sıkıştırma seçin.

Kurulum: macOS, Windows ve Linux

macOS: Apple Silicon için Metal hızlandırma desteği hazır gelir. Homebrew ile kurabilirsiniz: “brew install ollama”. Kurulum sonrası menü çubuğundaki Ollama simgesinden servis durumunu kontrol edebilirsiniz.

Windows: Ollama’nın resmi kurulum paketini indirip çalıştırın. Kurulumla birlikte Ollama servisi otomatik başlatılır. PowerShell veya Komut İstemi üzerinden komutları çalıştırabilirsiniz.

Linux: Resmi kurulum betiği pratik bir yoldur: “curl -fsSL https://ollama.com/install.sh | sh”. NVIDIA GPU kullanacaksanız sistemde güncel CUDA sürümü yüklü olmalı (sürücü ve CUDA 12.x tavsiye edilir).

İlk model: Llama 3.1’i indirme ve çalıştırma

Kurulumdan sonra ilk test için komut satırında şu komutu verin: “ollama run llama3.1:8b”. İlk çağrıda model otomatik indirilecektir. Ardından terminalde bir istem (prompt) göreceksiniz; bir soru yazıp Enter’a basın. Çıkmak için Ctrl+C kullanabilirsiniz. Modeli önceden indirmek isterseniz “ollama pull llama3.1:8b” komutunu çalıştırmanız yeterli.

Performans/kalite dengesini değiştirmek için farklı varyantları deneyin. Daha küçük bellekli sistemlerde 8B sınıfı daha rahat çalışırken, güçlü GPU’larda 13B ve üzeri modeller daha iyi sonuç verebilir. Türkçe performansı sizin için kritikse, Qwen veya Mistral ailesinin Türkçe kapsama oranı yüksek sürümlerini de test etmeyi düşünebilirsiniz.

GPU hızlandırma: CUDA, Metal ve ROCm

Ollama, uygun GPU’yu otomatik algılar. Apple Silicon’da Metal, NVIDIA’da CUDA, Linux’ta bazı AMD kartlarda ROCm ile ivme kazanırsınız. GPU’nun gerçekten kullanıldığını doğrulamak için macOS’ta Etkinlik İzleyici’de, Linux’ta “nvidia-smi” çıktısında veya Windows’ta Görev Yöneticisi’nde GPU kullanımını kontrol edebilirsiniz. Eğer sistem otomatik olarak CPU’ya düşüyorsa sürücü/kitaplık sürümlerinizi güncelleyin ve yeniden deneyin.

Bellek hataları alırsanız, daha küçük bir model seçin veya sıkıştırma derecesini yükseltin. Uzun bağlam (context) isteyen uygulamalarda context penceresi büyüdükçe hem RAM hem VRAM tüketimi artar; bu durumda promptunuzu kısaltın veya daha geniş VRAM’e sahip bir GPU kullanın.

Modelfile ile özelleştirme

Ollama, Modelfile ile model davranışını özelleştirmenize izin verir. Klasörünüzde “Modelfile” adlı bir dosya oluşturup aşağıdaki gibi sade bir yapı yazabilirsiniz:

FROM llama3.1:8b
PARAMETER temperature 0.2
SYSTEM Şirket içi belge asistanısın. Kısa ve net yanıtlar ver.

Ardından “ollama create kurumsal-asistan -f Modelfile” komutuyla yeni bir yerel model varyantı oluşturun ve “ollama run kurumsal-asistan” ile çalıştırın. Bu yöntemle sıcaklık, sistem mesajı, durdurma token’ları gibi ayarları kalıcı hâle getirebilirsiniz.

HTTP API ile entegrasyon

Ollama, varsayılan olarak “http://localhost:11434” üzerinde bir API sunar. Basit bir metin üretimi için “/api/generate” uç noktasına şu gövdede bir POST isteği gönderebilirsiniz: { "model": "llama3.1:8b", "prompt": "Merhaba, bugün hava nasıl?" }. Akışlı (stream) yanıtları desteklediği için gerçek zamanlı token üretimini arayüzünüze yansıtabilirsiniz. Benzer şekilde “/api/embeddings” uç noktasıyla yerel embedding üretip vektör veri tabanlarına yazmanız mümkündür.

RAG (Retrieval-Augmented Generation) hızlı başlangıç

Yerel kurulumun en güçlü senaryolarından biri, belgelerinizle konuşan bir asistan oluşturmaktır. Özet adımlar şöyle: (1) Belgelerinizi parçalara ayırın (chunking), (2) Her parça için embeddings üretin (“/api/embeddings” veya LangChain/LlamaIndex ile Ollama backend), (3) Embedding’leri bir vektör veritabanına (Chroma, FAISS, Milvus vb.) kaydedin, (4) Kullanıcı sorusunu embed edip en yakın parçaları bulun ve (5) Bu parçaları prompt’un “context” bölümüne enjekte ederek modelden yanıt isteyin. Böylece modelin parametre içi bilgisini güncellemeden, belgenize dayalı güncel ve kaynaklı cevaplar üretirsiniz.

İpuçları ve sorun giderme

- Uzun süreli oturumlar için keep-alive süresini artırarak modelin bellekte kalmasını sağlayın; yükleme gecikmesi azalır. Sunucu yeniden başlarken otomatik model yüklenmesini istemiyorsanız keep-alive’ı düşürebilirsiniz.
- Yanıt kalitesi dalgalanıyorsa temperature’ı düşürüp (0.2–0.5) deterministikliği artırın; yaratıcılık istiyorsanız 0.7+ deneyin.
- Türkçe çıktı kalitesi, sistem mesajınız ve örneklerle (few-shot) ciddi iyileşir. Kısa, görev odaklı bir SYSTEM ve birkaç örnek diyaloğu eklemeyi deneyin.
- Performans sınırına yaklaştığınızda bağlam penceresini (ör. 4K yerine 2K token) küçültmek, hız ve kararlılığı belirgin artırır.
- Yeni sürümlerle birlikte çekirdek hızlandırmalar (FlashAttention benzeri optimizasyonlar) ve bellek kullanımı iyileşiyor; Ollama’yı ve sürücüleri güncel tutun.

Sonuç

Ollama, yerelde LLM çalıştırmayı herkes için erişilebilir kılıyor. Llama 3.1’in 8B sınıfı, günlük asistan görevlerinden hızlı prototiplemeye kadar pek çok kullanımda tatmin edici sonuç veriyor. GPU hızlandırma ve RAG ile birleştirildiğinde, şirket içi gizli verilerle çalışan, düşük gecikmeli ve kontrol edilebilir üretken yapay zekâ deneyimleri inşa etmek mümkün. Küçük başlayın, donanım ve kullanım senaryonuza göre modeli ve ayarları kademeli olarak büyütün; elde edeceğiniz verim, bulut tabanlı çözümlerle rahatlıkla yarışacaktır.

29 Eylül 2025 Pazartesi

Ollama ve ChromaDB ile RAG: Kendi Verinizle Yerel Yapay Zekâ Sohbet Botu Nasıl Kurulur?

RAG nedir ve neden önemli?

Retrieval-Augmented Generation (RAG), bir dil modelinin cevap üretmeden önce bir vektör veritabanından ilgili parçaları geri çağırdığı, bu sayede daha doğru ve kaynaklı yanıtlar ürettiği bir yaklaşımdır. Güncel kurumsal ihtiyaçlarda gizlilik, maliyet kontrolü ve özelleştirme kritik hale geldiği için RAG, özellikle şirket içi dokümanlar, bilgi tabanları ve politikalar üzerinde çalışan sohbet botları için en verimli yöntemlerden biri olarak öne çıkıyor.

Bu rehberde, tamamen yerel çalışan bir kurulumla Ollama (yerel LLM çalıştırma), ChromaDB (vektör veritabanı) ve Python kullanarak adım adım bir RAG sistemi kurulumu yapacağız. Amaç, Türkçe metinlerle yüksek doğrulukta, düşük gecikmeli ve veri gizliliği korunan bir sohbet deneyimi sunmak.

Gerekenler ve mimari

Bileşenler: Ollama (Llama 3 veya benzeri açık kaynak model), ChromaDB (kalıcı vektör deposu), bir gömme (embedding) modeli (örn. intfloat/multilingual-e5-base), Python 3.10+, LangChain veya minimal kendi kodunuz. İsteğe bağlı olarak PDF/Word dosyaları için pypdf veya docx desteği ekleyebilirsiniz.

Akış: Dokümanları parçalara ayır → Embedding ile vektörleştir → ChromaDB’de indeksle → Soru geldiğinde benzer parçaları getir → Model için talimat şablonuna (prompt) enjekte et → Yanıtı oluştur ve kaynakları göster.

Kurulum adımları

1) Ollama’yı kurun. Resmi site üzerinden işletim sisteminize uygun paketi indirin. Model indirmek için komut satırında şu adımı uygulayın:
ollama pull llama3
Ardından test amaçlı kısa bir deneme yapabilirsiniz:
ollama run llama3

2) Python ortamını hazırlayın. Ayrı bir sanal ortam tercih edin:
python -m venv .venv && source .venv/bin/activate (Windows için .venv\Scripts\activate)
pip install chromadb sentence-transformers langchain langchain-community pypdf

Veri hazırlığı: parçalama ve temizleme

İyi bir RAG’in temeli, doğru parça boyutları ve temiz veridir. Türkçe belgelerde 300–500 token’lık parçalar pratikte iyi sonuç verir. Parçaları ayırırken başlık bilgilerini ve içerik konusunu korumaya çalışın. Örneğin bir politika belgesinde bölüm başlığını her parçaya meta veri olarak ekleyin. Bu, hem geri çağırmayı hem de kaynakları kullanıcıya göstermeyi kolaylaştırır.

Temizlik aşamasında gereksiz boşlukları, tekrar eden sayfa altbilgilerini ve tablo görsellerinden gelen çöp metinleri temizleyin. PDF okuyucu olarak pypdf kullanabilir, Markdown veya HTML dokümanlarını doğrudan metne dönüştürebilirsiniz.

ChromaDB ile vektör indeksleme

Embedding için çok dilli ve Türkçe performansı yüksek bir model seçin. “intfloat/multilingual-e5-base”, hız/doğruluk dengesiyle güvenilir bir tercih. Basit bir akış şöyle olabilir: Belgeleri oku → Böl → Her parça için embedding hesapla → ChromaDB’ye “persist_directory” ile kalıcı olarak yaz. Bu sayede uygulama yeniden başladığında indeksi tekrar oluşturmadan kullanabilirsiniz.

Koleksiyonlarınızı konuya göre ayırın (örn. “insan_kaynaklari”, “urun_dokumantasyonu”). Meta veriye kaynak adı, sayfa numarası, bölüm ve tarih gibi alanlar eklemek, yanıtların izlenebilirliğini artırır.

Sorgulama: RAG adım adım

Kullanıcıdan gelen soruyu önce bir sorgu embedding’ine dönüştürün, ardından ChromaDB’den en ilgili 3–5 parçayı çekin. Bu parçaları modelinize şu yapıda verin: kısa bir talimat + kullanıcı sorusu + “bağlam” bölümü (geri çağrılan parçalar). Örnek şablon yaklaşımı: “Aşağıdaki bağlamdan faydalanarak soruya kısa ve kaynaklı bir yanıt ver. Bağlamda yoksa tahmin yürütme.”

Ollama tarafında llama3 modelini çağırırken sıcaklık (temperature) düşük (0.1–0.3) tutulduğunda halüsinasyon azalır. Yanıtın sonuna “Kaynaklar” başlığı ile geri çağrılan parçaların referanslarını eklemek, güven inşa eder ve SEO açısından “uzman” hissiyatı yaratır.

İyileştirme: yeniden sıralama ve çoklu sorgu

Bazı senaryolarda temel benzerlik araması yeterli olmaz. Açık kaynak yeniden sıralayıcılar (örn. bge-reranker-large) ile ilk 20 sonucu alıp en iyi 5’ini rerank ederek doğruluğu yükseltebilirsiniz. Ayrıca multi-query tekniği ile kullanıcı sorusunu farklı biçimlerde genişletip (eş anlamlılar, farklı bağlamlar) birleştirilmiş sonuçlar elde etmek de hatırlamayı artırır.

Soru ön-işleme katmanında yazım hatalarını düzeltmek, alan terimlerini sözlükten normalleştirmek ve tarih-sayı gibi varlıkları standart forma getirmek, özellikle kurumsal dokümanlarda fark yaratır. Halüsinasyonları azaltmak için “sadece bağlamdan yanıt ver, bağlam yoksa ‘yok’ de” gibi net kurallar koyun.

Performans, güvenlik ve üretime alma

CPU ile başlayıp gerekirse GPU’ya geçin. Düşük bellekli sistemlerde quantized (örneğin Q4_0) model varyantları iyi sonuç verir. ChromaDB tarafında kalıcı dizin SSD üzerinde olmalı ve düzenli olarak koleksiyon boyutu ile gecikmeyi izleyin. Top_k değerini 3–8 arasında test ederek doğruluk/performans dengesini bulun.

Üretim ortamında bir FastAPI uç noktası ile sorgulama zincirinizi sunabilirsiniz. Yanıtları ve kullanılan kaynakları log’layarak kalite ölçümü yapın. Kişisel veriler içeren dokümanlarda yerel çalışmanın avantajı büyüktür; ağ dışına veri çıkarmadan kurumsal uyumluluk hedeflerine yaklaşabilirsiniz.

Sonuç

Ollama + ChromaDB ile kurulan yerel RAG yığını, maliyeti düşük, gizliliği yüksek ve yönetilebilir bir yapay zekâ çözümü sunar. Doğru parça boyutu, iyi bir embedding modeli ve dikkatli şablonlama ile Türkçe içerikte dahi oldukça isabetli yanıtlar elde edebilirsiniz. Bu rehberi temel alarak önce küçük bir pilot oluşturun, ardından veri kapsamını ve değerlendirme metriklerini (doğruluk, geri çağırma, MRR) aşamalı olarak genişletin. Böylece güncel ve ileri seviye bir deneyimi, tamamen kendi verinizle kontrol ederek hayata geçirebilirsiniz.

9 Eylül 2025 Salı

Ollama ve ChromaDB ile Yerel RAG Sistemi Kurulumu: Adım Adım Geliştirici Rehberi (2025)

RAG nedir ve neden yerelde kurmalısınız?

Retrieval-Augmented Generation (RAG), büyük dil modellerinin (LLM) kurumsal veya özel verilerle beslendiğinde daha güncel, doğru ve izlenebilir cevaplar üretmesini sağlayan bir yaklaşım. Kısaca, önce vektör veritabanı üzerinden ilgili doküman parçalarını buluyor, sonra bu parçaları modelin istemine ekleyerek yanıt oluşturuyoruz. Yerel RAG ise verinizin cihazınızda kalmasına, maliyetin düşmesine ve düşük gecikme ile çalışmanıza olanak tanır. Bu yazıda Ollama, ChromaDB ve açık kaynak modellerle tamamen yerel bir RAG sistemi kuracağız.

Mimari ve gereksinimler

Mimari: (1) Gömme (embedding) modeli ile dokümanları vektörleştir, (2) ChromaDB’ye kaydet, (3) Soru geldiğinde en alakalı parçaları geri getir (retrieve), (4) LLM’e bu bağlamı vererek cevabı üret.

Gereksinimler: 8 GB+ RAM (tercihen 16 GB), modern CPU; GPU varsa daha iyi. macOS, Linux veya Windows üzerinde çalışabilir. Python 3.10+, ve terminal erişimi gerekir.

Kurulum: Ollama, model ve ChromaDB

1) Ollama kurulum
macOS: brew install ollama
Linux: curl -fsSL https://ollama.com/install.sh | sh
Windows: Resmi MSI kurulum paketini indirip çalıştırın
Ardından servis: ollama serve

2) Modelleri indir
ollama pull llama3.1:8b-instruct
ollama pull nomic-embed-text
Not: Kaynaklar kısıtlıysa daha ufak bir model (ör. llama3.2:3b-instruct) seçebilirsiniz. Embed modeli olarak mxbai-embed-large da iyi sonuç verir.

3) Python bağımlılıkları
python -m venv .venv && source .venv/bin/activate
pip install chromadb fastapi uvicorn pydantic
İsteğe bağlı: yeniden sıralama (re-ranking) için pip install sentence-transformers

Veri yükleme ve vektörleştirme

Dokümanlarınızı data/ klasörüne (PDF, TXT, MD) yerleştirdiğinizi varsayalım. Basitlik için düz metin örnekliyoruz. Üretim ortamında PDF parçalama (chunking) ve OCR katmanı düşünebilirsiniz.

Basit Python ingestor
import os, requests, uuid
import chromadb
from chromadb.utils import embedding_functions

OLLAMA_URL = "http://localhost:11434/api/embeddings"
EMBED_MODEL = "nomic-embed-text"

def embed_texts(texts):
  vecs = []
  for t in texts:
    r = requests.post(OLLAMA_URL, json={"model": EMBED_MODEL, "input": t})
    r.raise_for_status()
    vecs.append(r.json()["embedding"])
  return vecs

client = chromadb.PersistentClient(path="chroma_store")
collection = client.get_or_create_collection(name="docs", embedding_function=embed_texts)

def chunk(text, size=700, overlap=120):
  out=[]; i=0
  while i < len(text):
    out.append(text[i:i+size])
    i += size - overlap
  return out

docs_dir = "data"
for fname in os.listdir(docs_dir):
  path = os.path.join(docs_dir, fname)
  if not os.path.isfile(path): continue
  text = open(path, "r", encoding="utf-8").read()
  chunks = chunk(text)
  ids = [str(uuid.uuid4()) for _ in chunks]
  metas = [{"source": fname} for _ in chunks]
  collection.add(documents=chunks, metadatas=metas, ids=ids)
print("Indeksleme tamam.")

Sorgulama ve yanıt üretimi

Sorguda, ChromaDB’den en alakalı parçaları çekip bunları LLM istemine ekleyeceğiz. Ollama’nın üretim API’sini kullanacağız.

Basit sorgu/cevap
import requests
GEN_URL = "http://localhost:11434/api/generate"

def ask(query, k=4):
  res = collection.query(query_texts=[query], n_results=k)
  contexts = [d for d in res["documents"][0]]
  sources = [m["source"] for m in res["metadatas"][0]]
  context_block = "\\n\\n".join([f"[{i+1}] {c}" for i,c in enumerate(contexts)])
  prompt = f"Kontekstten yararlanarak yanıtla. Bilgiyi uydurma. Kaynak numaralarını belirt.\\nKontekst:\\n{context_block}\\n\\nSoru: {query}\\nCevap:"
  r = requests.post(GEN_URL, json={"model":"llama3.1:8b-instruct","prompt":prompt,"stream":False,"options":{"temperature":0.2}})
  r.raise_for_status()
  answer = r.json()["response"]
  return answer, list(set(sources))

print(ask("Şirketimizin yedekleme politikası nedir?"))

FastAPI ile basit REST API

Uygulamanızı diğer servislerin kullanabilmesi için REST olarak sunabilirsiniz.

from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()

class Q(BaseModel):
  query: str

@app.post("/ask")
def api_ask(q: Q):
  answer, sources = ask(q.query)
  return {"answer": answer, "sources": sources}

# Çalıştır: uvicorn app:app --reload --port 8000

Doğrulama, kalite ve ölçüm

- Halüsinasyonları azaltmak için sıcaklığı 0.0–0.3 aralığında tutun, prompt’a “bilgiyi uydurma, bilmiyorsan söyle” ifadesini ekleyin.
- Geri getirilen parça sayısını (k) 3–8 arası deneyin; çok yüksek k, gürültü katar.
- Parça boyutu (chunk size) 500–1000 arası genelde iyi sonuç verir, 10–15% örtüşme koruyun.
- Yeniden sıralama: Sentence-Transformers ile cross-encoder/ms-marco-MiniLM-L-6-v2 gibi bir re-ranker, isabeti belirgin artırabilir.
- Değerlendirme: Küçük bir altın soru-cevap seti hazırlayın; doğru kaynağa referans verilip verilmediğini ölçün.

Performans ve maliyet ipuçları

- Kantizasyon: Ollama’da llama3.1:8b-instruct-q4_K_M gibi kantize varyantlar RAM tüketimini düşürür.
- Önbellek: Sorgu → bağlam → cevap üçlüsünü dosya veya Redis ile önbelleğe alın. Yinelenen sorularda gecikme dramatik düşer.
- GPU: Metal (macOS) veya CUDA (Linux/Windows) desteği varsa model çıkarımı hızlanır.
- İndeks: ChromaDB’de kalıcı depolama (PersistentClient) ile büyük koleksiyonlarda yeniden başlatma maliyeti azalır.

Güvenlik ve uyumluluk

Yerel RAG’in en büyük artısı veri egemenliği. Yine de şu tedbirleri alın: hassas alanları maskeyle; kaynak metaverileri log’layın; modeli “yanlış kullanım” prompt’larına karşı kıstırın; uç noktalara (FastAPI) kimlik doğrulama ekleyin; yedekleri şifreleyin.

Hata ayıklama ve sık görülen problemler

- Bağlantı hatası: Ollama servisinin 11434 portunda çalıştığını doğrulayın (curl localhost:11434).
- Out-of-memory: Daha küçük/quantize model çekin; eşzamanlı istekleri düşürün.
- Alakasız sonuçlar: Farklı embedding modeli deneyin; chunk’ları daha iyi bölün; re-ranker ekleyin.
- Dil karışması: Prompt’u Türkçe olarak sabitleyin ve cevabı Türkçe isteyin.

Sonuç

Bu rehberle, Ollama ve ChromaDB kullanarak tamamen yerelde çalışan, ölçeklenebilir ve gizlilik dostu bir RAG sistemi kurdunuz. Temeller oturduktan sonra re-ranking, çoklu koleksiyon, rol tabanlı erişim ve kullanım analitiği gibi katmanları ekleyerek üretim kalitesine taşıyabilirsiniz. Küçük bir dizüstü bilgisayarda bile tatmin edici yanıtlar alınabildiğini görmek, RAG’in 2025’te neden “uygulamaya dönük yapay zekânın” omurgası olduğunu net biçimde gösteriyor.