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.

9 Aralık 2025 Salı

İnca Gaming Klavye Fabrika Ayarlarına Döndürme

 Bir süredir klavyemin tüm ışıkları gitmişti ve nasıl geri getirebileceğimi merak ediyordum. FN + ESC tuş kombinasyonuna birkaç saniye basılı tuttuktan sonra ışıklar yeniden açılmaya başladı ve renk modlarını istediğim gibi değiştirmeye başladım. Bu harika bir haber benim için, teşekkürler :)

Docker Buildx ile Çok Mimarili Container İmajı Oluşturma ve GitHub Actions ile Yayınlama

Giriş

Docker Buildx, aynı Dockerfile’dan tek komutla AMD64 ve ARM64 gibi birden fazla mimari için imaj üretebilen güçlü bir eklentidir. Özellikle Apple Silicon (M1/M2) makinelere geçiş, edge cihazları ve farklı donanımlara sahip Kubernetes kümeleri göz önüne alındığında, çok mimarili (multi-arch) imaj oluşturmak hem performans hem de dağıtım kolaylığı açısından kritik hale geldi. Bu yazıda, Docker Buildx ile çok mimarili container imajı nasıl oluşturulacağını ve GitHub Actions kullanarak Docker Hub’a otomatik olarak nasıl yayınlanacağını adım adım anlatıyorum.

Neden Çok Mimarili İmaj?

Tek mimariye göre paketlenmiş bir imaj, farklı donanımlarda çalıştırılmak istendiğinde "no matching manifest for linux/arm64" gibi hatalara yol açar. Çok mimarili bir imaj ise manifest listesi sayesinde doğru platformu otomatik seçer. Bu sayede aynı etiketi (ör. latest veya 1.2.0) hem AMD64 sunucularda hem de ARM64 tabanlı cihazlarda sorunsuz kullanabilirsiniz. Sonuç: daha az bakım yükü, daha az sürpriz ve daha yüksek taşınabilirlik.

Önkoşullar

Gereksinimler: Docker 20.10+ (tercihen güncel), Buildx etkin, registry hesabı (Docker Hub veya GHCR). Apple Silicon kullanıyorsanız, emülasyon için QEMU desteği faydalıdır. Buildx çoğu modern Docker kurulumunda hazır gelse de aşağıdaki komutlarla kontrol edebilirsiniz.
docker buildx version
docker buildx ls

Yerelde Buildx ile Başlangıç

Önce bir builder oluşturup onu aktif kullanıma alalım. QEMU emülasyonunu mümkün kılmak için binfmt kurulumunu da yapabiliriz (Linux ortamlarında gerekebilir).
docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx create --use --name multiarch-builder
docker buildx inspect --bootstrap
Builder hazır olduğunda, tek komutla AMD64 ve ARM64 için imaj inşa edip registry’ye push edebiliriz.

Örnek Dockerfile ve Build Komutu

Aşağıdaki Node.js tabanlı örnek Dockerfile, BUILDPLATFORM/TARGETPLATFORM değişkenleriyle platforma duyarlı, küçük ve üretime uygun bir imaj üretir.
# syntax=docker/dockerfile:1.6
FROM --platform=$BUILDPLATFORM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM --platform=$TARGETPLATFORM node:20-alpine
WORKDIR /app
COPY --from=build /app /app
EXPOSE 3000
CMD ["node", "dist/index.js"]

İmajı çok mimarili olarak inşa edip push etmek için:
docker login
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t KULLANICI_ADI/uygulama:1.0.0 \
-t KULLANICI_ADI/uygulama:latest \
--push .

Önbellek ve SBOM/Provenance

Build sürelerini kısaltmak için registry tabanlı önbellek kullanabilirsiniz. Ayrıca tedarik zinciri güvenliği bağlamında SBOM ve provenance meta verileri üretmek iyi bir pratiktir.
docker buildx build \
--platform linux/amd64,linux/arm64 \
--cache-to=type=registry,ref=KULLANICI_ADI/uygulama:buildcache,mode=max \
--cache-from=type=registry,ref=KULLANICI_ADI/uygulama:buildcache \
--sbom=true --provenance=true \
-t KULLANICI_ADI/uygulama:1.0.0 \
--push .

GitHub Actions ile Otomasyon

CI/CD hattında her push veya tag için otomatik çok mimarili build almak için GitHub Actions iş akışı aşağıdaki gibi olabilir. Docker Hub kullanıcı adı ve token’ınızı repo Secrets bölümüne DOCKERHUB_USERNAME ve DOCKERHUB_TOKEN olarak eklemeyi unutmayın.
name: build-and-push
on:
push:
tags: ["v*"]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ secrets.DOCKERHUB_USERNAME }}/uygulama:latest
cache-from: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/uygulama:buildcache
cache-to: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/uygulama:buildcache,mode=max

Etiketleme ve Sürümleme Stratejisi

Semantik versiyonlama (örn. 1.2.3) ile birlikte major, minor ve latest etiketlerini birlikte yayınlamak yaygın bir pratik. Örneğin v1.2.3 için şu

8 Aralık 2025 Pazartesi

Kubernetes Gateway API ile Ingress’ten Modern Trafik Yönetimine Geçiş (Adım Adım Rehber)

Kubernetes üzerinde uygulama trafiğini yönetirken yıllardır Ingress nesnelerine güvendik. Ancak mikro servisler büyüdükçe, L7/L4 kombinasyonları, çok kiracılı mimariler ve gelişmiş yönlendirme ihtiyaçları için Ingress’in sınırları daha görünür hale geldi. Gateway API, bu boşluğu kapatmak için tasarlanmış, açık standartlara dayanan ve birden fazla sağlayıcı tarafından desteklenen modern bir trafik yönetim modelidir. Bu yazıda, Gateway API’nin ne sunduğunu, nasıl kurulacağını ve Ingress’ten geçişi adım adım anlatıyorum.

Gateway API nedir? Kısa ve net

Gateway API; GatewayClass, Gateway, HTTPRoute, GRPCRoute, TCPRoute gibi özelleştirilmiş kaynak türleri (CRD) sunar. İki ana fark öne çıkar: Birincisi, rollerin ayrımı. Platform ekibi Gateway’leri tanımlayıp kimin kullanacağını belirlerken, uygulama ekipleri yalnızca Route nesneleriyle trafik kurallarını yönetir. İkincisi, zengin eşleşme ve filtre seti sayesinde başlık, yol, hostname, mTLS, oran sınırlama ve header manipülasyonu gibi gelişmiş senaryolar standartlaştırılmıştır.

Önkoşullar ve kurulum

Başlamadan önce Kubernetes 1.25+ sürümünde bir kümeniz ve bir Gateway API uygulaması (NGINX, Istio, Traefik, Cilium vb.) kurulu olmalı. CRD’leri yüklemek için yönetilen küme kullanıyorsanız çoğu sağlayıcıda ön tanımlı gelebilir; değilse CRD’leri kendiniz uygulayabilirsiniz. Örnek: kubectl apply -k "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.1.0". Ardından seçtiğiniz kontrolcünün Gateway API desteğini etkinleştirin; örneğin NGINX için GatewayClass genelde nginx veya nginx-experimental olarak gelir, Istio’da istio adıyla görünür.

Adım 1: GatewayClass ve Gateway oluşturma

GatewayClass, kümede hangi kontrolcünün dinleyici oluşturacağını belirler. Platform ekibi tek bir GatewayClass atayıp çoklu Gateway’lere hizmet verebilir. Basitçe söylemek gerekirse, Ingress’teki ingressClassName’in yerini daha güçlü bir kavram alıyor. Gateway ise yük dengeleyicinizin gerçekte nasıl dışa açılacağını tanımlar: portlar, TLS, SNI, HTTP/2, hatta (destek varsa) HTTP/3. Örnek bir yaklaşım: gatewayclass.name: nginx olan bir prod-gateway’i 80 ve 443 portlarında dinleyecek şekilde oluşturun ve AllowedRoutes politikasıyla yalnızca belirli isim alanlarından route kabul edin.

Adım 2: HTTPRoute ile trafiği yönlendirme

Uygulama ekipleri için asıl iş HTTPRoute’ta başlar. Burada hostnames, path eşleşmeleri ve header filtreleriyle kuralları tanımlarsınız. Örneğin api.ornek.com alan adındaki /v1/* yollarını demo-svc:80 servisine yönlendirin, X-Canary: true başlığı geldiğinde trafiğin %10’unu canary sürümüne gönderin. Ek olarak RequestHeaderModifier filtresi ile giden isteklere bir X-Trace-Id eklemek mümkün. Bu tür politikalar, Ingress anotasyonlarına bağımlı olmanıza gerek kalmadan, standart ve taşınabilir bir şekilde tanımlanır.

Adım 3: TLS sonlandırma ve güvenlik

TLS sonlandırmayı Gateway nesnesi üzerinde yönetmek daha tutarlı bir model sunar. certificateRefs ile bir Secret referansı vererek SNI üzerinden birden fazla alan adı için sertifika tanımlayabilirsiniz. mTLS gerekiyorsa, destekleyen uygulamalarda TLSMode: Terminate yerine TLSMode: Passthrough veya karşılıklı TLS doğrulaması yapılandırılabilir. Güvenlik tarafında iki güçlü özellik daha var: AllowedRoutes ile hangi isim alanlarının Gateway’e bağlanabileceği, ReferencePolicy ile hangi kaynakların birbirini görebileceği belirlenir. Böylece çok kiracılı ortamlarda izolasyon korunur.

Ingress’ten Gateway API’ye geçiş

Geçiş için basit bir eşleştirme stratejisi işe yarar: Ingress’teki ingressClassName → GatewayClass, rules.host ve paths → HTTPRoute.rules, tls → Gateway.listeners.tls. İlk aşamada mevcut Ingress’i koruyup paralelde bir Gateway + Route tanımı oluşturun. ExternalDNS kullanıyorsanız, yeni yük dengeleyicinin dış IP’si oluşunca DNS’i aşamalı olarak Gateway’e yönlendirin. Canlı geçişte hata oranını düşürmek için HTTPRoute üzerinde ağırlıklandırılmış backend’lerle kademeli trafik geçişi (canary) uygulayın. Son adımda Ingress’i kapatıp gereksiz anotasyonları temizleyebilirsiniz.

Gözlem ve hata giderme

Gateway API, durum ve koşul (conditions) alanlarını zenginleştirerek sorunları teşhis etmeyi kolaylaştırır. kubectl get gatewayclass ile sınıfın Accepted olup olmadığını, kubectl describe gateway ile Programmed ve atanan Addresses değerini kontrol edin. kubectl describe httproute çıktısında Accepted ve ResolvedRefs koşullarını görün; bir kural kabul edilmediyse nedenini burada bulursunuz (ör. izin verilmeyen hostname veya eşleşen Gateway yok). Olaylar (events) sıklıkla eksik Secret, yanlış referans veya port çakışmalarını ele verir.

Performans, uyumluluk ve farklar

Gateway API standarttır fakat her uygulamanın destek seviyesi farklı olabilir. Üretime çıkmadan önce seçtiğiniz kontrolcünün Conformance matrisini inceleyin. HTTP/2 ve (destek varsa) HTTP/3 kullanımında bağlantı ömrü ve yeniden deneme politikalarını gözden geçirin. Varsayılan timeout ve retry davranışları uygulamadan uygulamaya değişebilir; uzun süreli akışlar (streaming) için uygun ayarları HTTPRoute üzerindeki timeouts ve filtrelerle netleştirin. Ayrıca, L4 trafiği için TCPRoute/UDPRoute kullanarak veritabanı veya özel protokoller için aynı yönetişim modelinden faydalanabilirsiniz.

Yaygın hatalar ve pratik ipuçları

En yaygın hatalardan biri, Route’ların Gateway’e bağlanmasına izin vermeyi unutmak. Gateway üzerinde AllowedRoutes.namespaces ayarını netleştirin. İkinci hata, eski Ingress anotasyonlarının aynısını Gateway API’de aramak; çoğu senaryo artık filters ile standartlaştırıldı. Eğer dışa açık bir LoadBalancer bekliyorsanız ancak adres gelmiyorsa, kontrolcünün bulut sağlayıcısı entegrasyonunu ve servis tiplerini doğrulayın. Son olarak, üretim öncesi bir staging Gateway’inde tüm host ve TLS kombinasyonlarını duman testi (smoke test) ile deneyin; SNI yanlışlıkları genelde burada yakalanır.

Sonuç

Gateway API, Kubernetes’te trafik yönetimini bir üst seviyeye taşıyor: net rol ayrımı, güçlü politika dili ve çok sağlayıcılı ekosistem. Ingress’ten görece zahmetsiz bir geçişle başlamak ve ilk kazanımları (daha iyi görünürlük, canary, header bazlı yönlendirme) kısa sürede görmek mümkün. Kümenizde standart, taşınabilir ve güvenli bir ağ katmanı istiyorsanız, Gateway API’yi denemenin tam zamanı.

7 Aralık 2025 Pazar

Kubernetes’te Horizontal Pod Autoscaler (HPA) ile Otomatik Ölçeklendirme: Adım Adım Kurulum ve İpuçları

Giriş

Kubernetes üzerinde çalışan uygulamalarınızın trafiğe göre otomatik ölçeklenmesi, maliyet ve performans dengesini korumak için kritik öneme sahiptir. Horizontal Pod Autoscaler (HPA), pod sayısını metriklere göre dinamik olarak artırıp azaltarak bu dengeyi sağlar. Bu rehberde, Kubernetes’te HPA’yı adım adım nasıl kuracağınızı, doğru metrikleri nasıl seçeceğinizi ve üretim ortamlarında dikkat edilmesi gereken noktaları paylaşacağım.

Neden HPA?

HPA, belirli bir hedefe (örneğin CPU kullanımının %70’te kalması) göre pod sayısını yatayda (horizontal) değiştirir. Ani trafik artışlarında hızlıca ölçeklenmek, düşük trafik saatlerinde ise maliyeti kısmak için idealdir. Üstelik Kubernetes 1.26+ sürümlerinde autoscaling/v2 API’si ile birden fazla metriği aynı anda değerlendirerek daha akıllı kararlar verebilir.

Önkoşullar

HPA’nın doğru çalışması için kümenizde bazı bileşenlerin hazır olması gerekir. En kritik bağımlılık metrics-server’dır. Bu bileşen, CPU ve bellek gibi kaynak metriklerini Kubernetes API üzerinden ulaşılabilir kılar.

Ayrıca Deployment’ınızdaki container’ların resource requests/limits alanlarının tanımlı olması gerekir. Aksi hâlde HPA CPU/Bellek bazlı hedefleri doğru hesaplayamaz.

Metrics Server Kurulumu (Örnek)

Çoğu yönetilen Kubernetes hizmeti (GKE, AKS, EKS) metrics-server’ı hazır getirir. Kendi kümenizde kurmanız gerekiyorsa, resmi manifest veya Helm chart kullanabilirsiniz.

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl get apiservices | grep metrics
kubectl top nodes
kubectl top pods -A

Yukarıdaki komutlar hatasız çalışıyorsa, metrik akışı sağlanmıştır ve HPA için hazırsınız.

Örnek Uygulama ve HPA Tanımı

Aşağıdaki örnekte CPU hedefi %70 olan bir HPA tanımı bulunuyor. API sürümü olarak autoscaling/v2 kullanıyoruz. Bu sürüm, ölçeklendirme davranışını (behavior) detaylı kontrol etmeye izin verir.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-api-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-api
  minReplicas: 2
  maxReplicas: 15
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
        - type: Percent
          value: 100
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 20
          periodSeconds: 60
      selectPolicy: Min

Bu yapılandırma, ihtiyaç durumunda pod sayısını hızlı artırırken (burst trafiği yakalama), azaltma işlemlerinde daha konservatif davranır (ani düşüşlerde dalgalanmayı engelleme).

Gelişmiş Metrikler: CPU, Bellek, Özel ve Harici

HPA, birden fazla metrikle çalışabilir ve ölçeklendirme kararını en baskın sinyale göre verir:

CPU/Bellek (Resource): averageUtilization ile yüzdesel hedefler verilir. CPU için genellikle %60–70, bellek için uygulama karakteristiğine göre %60–80 yaygındır.

Object/Pods: Uygulama seviyesinde RPS (request per second) gibi metrikleri pod başına normalize ederek ölçeklenebilir. Örneğin Nginx Ingress üzerinden istek sayısı.

External: Prometheus Adapter gibi bir adaptörle gecikme süresi, kuyruk uzunluğu, Kafka lag gibi harici metriklere göre ölçeklendirme yapılabilir.

Test: Yük Üreterek Doğrulama

HPA’nın doğru tepki verip vermediğini anlamak için kısa süreli bir yük testi yapabilirsiniz. Örneğin hey veya k6 ile endpoint’lerinize istek gönderebilir, ardından aşağıdaki komutla HPA durumunu izleyebilirsiniz:

kubectl describe hpa web-api-hpa
kubectl get hpa
kubectl top pods -n default

Çıkışta “Current” ve “Target” metrikleri ile “Desired Replicas” alanının beklenen şekilde değiştiğini gözlemlemelisiniz.

En İyi Pratikler

1) Doğru resource requests/limits: “request” değerlerini gerçekçi belirleyin. Çok düşük değerler HPA’yı gereğinden fazla tetikler; çok yüksek değerler ise ölçeklenmeyi geciktirir.

2) Stabilizasyon pencereleri: behavior.scaleDown altında 300–600 saniye aralığı çoğu web uygulaması için uygundur. Bu, titremeyi (flapping) azaltır.

3) Çoklu metrik kullanın: CPU’ya ek olarak RPS veya kuyruk uzunluğu gibi iş metrikleri eklemek daha doğru ölçeklendirme sağlar. Baskın metrik prensibini unutmayın: en yüksek gereksinimi işaret eden metrik kazanır.

4) Soğuk başlangıç sürelerini hesaba katın: Container başlatma süresi uzunsa scaleUp politikalarını daha agresif yapın; ör. Percent 100 veya Pods 4 gibi.

5) Pod Disruption Budget (PDB) ve Readiness: HPA ile birlikte PDB ve readinessProbe ayarlarını gözden geçirerek ölçeklenme ve dağıtım sırasında kesinti riskini azaltın.

6) VPA ve HPA birlikte kullanım: HPA yatay, VPA dikey ölçekleme yapar. Aynı kaynağı aynı anda hedeflememek için VPA’yı “recommendation” modunda çalıştırmayı değerlendirin.

Sık Karşılaşılan Hatalar ve Çözümler

Hata: HPA metrik okuyamıyor. Çözüm: metrics-server’ın sağlıklı çalıştığını doğrulayın; API erişim hatalarını ve TLS ayarlarını kontrol edin.

Hata: Pod sayısı artmıyor. Çözüm: Deployment’ın replicas alanı başka bir kontrolcü tarafından sabitlenmiş olabilir. Ayrıca node kapasitesi yetersizse Cluster Autoscaler gerekebilir.

Hata: Ölçeklendirme çok agresif veya çok yavaş. Çözüm: behavior.policies ve stabilizationWindowSeconds değerlerini gözden geçirin; metrik hedeflerini (averageUtilization) gerçek yük profiline göre ayarlayın.

Sonuç

Doğru yapılandırılmış bir HPA, Kubernetes ortamınızda esneklik ve maliyet verimliliği sağlar. Metrics-server, isabetli resource ayarları ve davranış politikaları ile desteklendiğinde, yük dalgalanmalarına hızla uyum sağlayan, istikrarlı ve performanslı bir mimari kurabilirsiniz. Üretime geçmeden önce küçük bir yük testiyle ayarları doğrulamak, canlıya çıktıktan sonra ise metrikleri izleyip ince ayar yapmak en sağlıklı yaklaşımdır.

6 Aralık 2025 Cumartesi

WebGPU ile Tarayıcıda Gerçek Zamanlı Makine Öğrenmesi: TensorFlow.js ile Adım Adım

WebGPU neden önemli?

Tarayıcıda makine öğrenmesi denildiğinde yıllardır WebGL ve WebAssembly (WASM) üzerinden çalışan çözümler öne çıkıyordu. Ancak bu yaklaşımlar, genel amaçlı hesaplama tarafında ciddi kısıtlar içeriyordu. WebGPU, modern grafik API’lerinin (Vulkan/Metal/Direct3D 12) üzerine inşa edilmiş, düşük gecikmeli ve yüksek verimli bir standarda dayanır. Bu sayede tensör işlemleri, matris çarpımları ve konvolüsyon gibi ML çekirdekleri doğrudan GPU üzerinde, daha az ara kopya ve daha iyi paralellik ile çalışır. Kısacası WebGPU, tarayıcıda gerçek zamanlı çıkarım (inference) yapmayı pratik hale getirir ve mobil dahil geniş bir cihaz yelpazesinde daha istikrarlı performans sağlar.

Tarayıcı desteği ve gereksinimler

WebGPU bugün Chrome 113+ ve Edge 113+ sürümlerinde varsayılan olarak kullanılabilir. Safari tarafında macOS ve iOS’in yeni sürümlerinde destek giderek olgunlaşıyor; Firefox içinse Nightly üzerinde bayrak ile etkinleştirme gerekebiliyor. Projenizi yayına almayı düşünüyorsanız, özellik tespiti (feature detection) yaparak WebGPU desteklenmiyorsa WASM veya WebGL’e otomatik düşüş sağlamanız kritik. Kullanıcı tarafında ekstra bir eklenti gerekmiyor; tek koşul güncel bir tarayıcı ve yeterli GPU/driver desteği.

TensorFlow.js ile WebGPU backend’i etkinleştirme

TensorFlow.js, WebGPU için resmi bir backend sunuyor. Uygulama başlangıcında WebGPU özelliğini tespit edip uygun backend’i seçmeniz en sağlıklı yaklaşım. Genel akış şudur: WebGPU destekleniyorsa TF.js’i webgpu backend ile başlatın, aksi durumda wasm veya webgl’e geri dönün. Başlangıçta bir “ısınma” (warm-up) adımı uygulamak da önemlidir; bir sahte giriş (dummy input) ile modeli bir kez çalıştırarak shader derlemelerinin tamamlanmasına izin verirsiniz. Bu sayede ilk gerçek tahmin sırasında yaşanabilecek ani gecikme önemli ölçüde azalır.

Model seçimi: boyut, hassasiyet ve gecikme dengesi

Gerçek zamanlı çıkarım hedefliyorsanız model seçimi kadar nicemleme (quantization) stratejisi de önemlidir. MobilNet tabanlı sınıflandırıcılar, BlazeFace veya MediaPipe tabanlı hafif yüz/eldeneyim modelleri ve COCO-SSD gibi optimize edilmiş nesne tespit ağları tarayıcı için uygundur. FP16 veya INT8 nicemleme ile model boyutu azalırken bellek kullanımınız düşer ve GPU bant genişliği tasarrufu sağlanır. Ancak nicemleme ile birlikte doğruluk payında ufak düşüşler olabilir; hedef senaryonuza göre tatlı noktayı bulmak için A/B testleri yapın.

Veri yolu ve gecikme: Kamera, Canvas ve sıfır kopya stratejileri

Gerçek zamanlı senaryolarda darboğaz genellikle GPU hesaplama gücünden ziyade veri aktarımıdır. Kamera akışını almak için getUserMedia kullanıyor, görüntüyü bir canvas’a çiziyor ve ardından tensöre dönüştürüyorsanız, gereksiz kopyalardan kaçınmalısınız. Modern tarayıcılarda OffscreenCanvas ve WebCodecs ile birlikte “zero-copy”a yakın akışlar kurulabiliyor; ancak API’ler platforma göre farklı olgunlukta. Her adımda gereksiz yeniden boyutlandırma ve renk uzayı dönüşümlerinden kaçınmak, çerçeve başına gecikmeyi düşürür. Ayrıca requestAnimationFrame ile çıkarımı ekran yenileme döngüsüne bağlamak yerine, sabit bir çıkarım frekansı belirleyip sonuçları görsel katmana asenkron taşımak çoğu zaman daha kararlı FPS verir.

Performans ipuçları

- Tek seferlik tensör tahsisleri yapın, tekrar kullanılan tensörleri yeniden yaratmak yerine cache’leyin. Bu yaklaşım hem GC baskısını hem de GPU bellek fragmentasyonunu azaltır.

- Batched çıkarım (ör. birden fazla çerçeveyi tek seferde işlemek) her zaman yararlı olmayabilir; gecikme duyarlı uygulamalarda mikro-batch yerine tekil çerçeve akışı daha iyi tepki süresi verir.

- Modeli hedef cihaza göre değiştirmek için koşullu yükleme yapın. Masaüstünde daha büyük bir model, mobilde hafif bir varyant seçmek kullanıcı deneyimini dengeler.

- WebGPU sürücülerindeki farklılıklardan etkilenmemek için düzenli olarak Chrome, Edge ve Safari üzerinde duman testleri (smoke test) koşturun.

Hata ayıklama ve ölçüm

Performansı yönetemediğiniz şeyi optimize edemezsiniz. Tarayıcının Performance paneli ile kare zaman çizelgesini (timeline) inceleyerek GPU tarafında beklenmedik duraklamaları tespit edin. TensorFlow.js, çıkarım sırasında bellek kullanımını ve kernel sürelerini profil etmeye yardımcı olacak yardımcı işlevler sunar; bu sayede hangi adımın darboğaz olduğunu netleştirirsiniz. Ayrıca FPS, gecikme (p95/p99) ve tahmin doğruluğunu aynı anda izleyebileceğiniz hafif bir telemetri katmanı kurmak, üretimde sorunları hızla yakalamanıza yardım eder.

Uyumluluk ve erişilebilirlik

Bazı kurumsal cihazlarda GPU erişimi kısıtlı olabilir veya kullanıcılar enerji tasarrufu modunda çalışıyor olabilir. Uygulamada “Gelişmiş hızlandırmayı aç/kapat” seçeneği sunarak WebGPU’yu kullanıcı tercihine bırakın. Erişilebilirlik açısından, çıkarım sonuçlarını yalnızca görsel olarak göstermek yerine metin çıktısı ve ARIA canlı bölgeleri üzerinden ekran okuyuculara iletmek, ML özelliklerini daha geniş kullanıcı kitlesine ulaştırır.

Güvenlik ve gizlilik

WebGPU, sitenin izni olmadan cihaz verilerine erişim sağlamaz; ancak yine de uzun süreli yoğun GPU kullanımı pil tüketimini artırabilir ve cihaz sıcaklığını yükseltebilir. Gerçek zamanlı uygulamalarda etkinlik algılama (ör. sekme arka plana geçince frekansı düşürme) ve otomatik duraklatma mekanizmaları ekleyin. Gizlilik açısından, modeli istemci tarafında çalıştırmak veriyi sunucuya göndermeden işleme imkânı sunduğu için hassas senaryolarda güçlü bir artıdır.

Sonuç

WebGPU, tarayıcıda makine öğrenmesini hobi projesi seviyesinden üretim kalitesine taşıyan bir dönüm noktası. TensorFlow.js ile birleştiğinde, kamera tabanlı gerçek zamanlı analitikten etkileşimli multimedya deneyimlerine kadar geniş bir yelpazede düşük gecikme ve yüksek kare hızına ulaşmak artık mümkün. Doğru model seçimi, dengeli nicemleme, dikkatli veri yolu tasarımı ve kapsamlı profil ile bugün dahi pek çok cihazda akıcı bir kullanıcı deneyimi sunabilirsiniz. WebGPU desteklenmeyen ortamlara zarifçe düşüş sağlamayı da unutmayın; böylece tüm kullanıcılar için çalışır bir çözüm elde edersiniz.

5 Aralık 2025 Cuma

WebGPU ile Tarayıcıda Makine Öğrenimi: ONNX Runtime Web ile Görsel Sınıflandırma (Adım Adım)

Giriş

WebGPU, modern tarayıcılarda GPU gücünden standart ve güvenli bir şekilde yararlanmayı sağlayan yeni bir web standardı. Bu yazıda, ONNX Runtime Web ve WebGPU kullanarak tarayıcı içinde tamamen istemci tarafında çalışan bir görsel sınıflandırma uygulamasını adım adım kuracağız. Sunucuya veri göndermeden, gizliliğe saygılı ve düşük gecikmeli bir makine öğrenimi deneyimi elde edeceğiz. Bu yaklaşım, SEO açısından da kıymetli; zira “tarayıcıda makine öğrenimi”, “WebGPU”, “ONNX Runtime Web”, “görsel sınıflandırma” gibi anahtar kelimelerle teknik kitlelere doğrudan hitap ediyor.

Ön Koşullar

- Güncel bir tarayıcı: Chrome 113+ sürümlerinde WebGPU masaüstünde varsayılan olarak açıktır. Safari’de ve Firefox’ta destek durumu değişebilir; deneysel bayraklar gerekebilir. Mobilde destek kısmi durumdadır.

- Node.js 18+ (geliştirme sunucusu ve paket yönetimi için)

- Temel HTML/JS bilgisi

Proje Kurulumu

1) Vite ile boş bir proje oluşturun:

npm create vite@latest webgpu-ml -- --template vanilla
cd webgpu-ml
npm install

2) ONNX Runtime Web paketini ekleyin:

npm i onnxruntime-web

3) Basit bir dosya yapısı hazırlayın: index.html, main.js ve bir models/ klasörü. Örnek olarak mobilenetv2.onnx gibi 224x224 giriş alan bir sınıflandırma modelini models/ altına yerleştirin. ONNX model arşivlerinden (örn. ResNet, MobileNet) hafif bir model tercih edin.

index.html İskeleti

Aşağıdaki minimal HTML, bir görsel yükleme alanı ve sonuçları göstermek için basit bir arayüz içerir.

<!doctype html>
<html lang="tr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>WebGPU ile Görsel Sınıflandırma</title>
  </head>
  <body>
    <h1>WebGPU + ONNX Runtime Web</h1>
    <input type="file" id="file" accept="image/*" />
    <button id="predict">Sınıflandır</button>
    <div id="status">Hazır</div>
    <div id="result"></div>
    <canvas id="canvas" width="224" height="224" style="display:none"></canvas>
    <script type="module" src="/main.js"></script>
  </body>
</html>

WebGPU ve ONNX Runtime Web ile Çalıştırma

Aşağıdaki kodda, tarayıcıda WebGPU desteği kontrol edilir, ONNX modeli yüklenir, görsel 224x224 boyutuna ölçeklenir ve ImageNet ortalama/standart sapma değerleri ile normalize edilerek tensöre dönüştürülür. Ardından model çıkarımı yapılır ve en yüksek olasılıklı sınıf ekrana yazdırılır.

// main.js
import * as ort from 'onnxruntime-web/webgpu';

const statusEl = document.getElementById('status');
const resultEl = document.getElementById('result');
const fileInput = document.getElementById('file');
const predictBtn = document.getElementById('predict');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let session;

// WebGPU desteğini kontrol edin
if (!('gpu' in navigator)) {
  statusEl.textContent = 'WebGPU desteklenmiyor. Varsayılan WASM ile deneyin.';
}

// Modeli başlat
async function initModel() {
  statusEl.textContent = 'Model yükleniyor...';
  // Fallback ile: önce WebGPU, olmazsa WASM
  session = await ort.InferenceSession.create('/models/mobilenetv2.onnx', {
    executionProviders: ['webgpu', 'wasm']
  });
  statusEl.textContent = 'Model yüklendi.';
}

function imageToTensor(img) {
  const size = 224;
  ctx.clearRect(0, 0, size, size);
  // Görseli 224x224'e çiz
  ctx.drawImage(img, 0, 0, size, size);
  const { data } = ctx.getImageData(0, 0, size, size);

  // NHWC(RGBA) -> NCHW, normalize [0,1], ImageNet mean/std
  const mean = [0.485, 0.456, 0.406];
  const std = [0.229, 0.224, 0.225];

  const input = new Float32Array(1 * 3 * size * size);
  let idx = 0;
  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      const i = (y * size + x) * 4;
      const r = data[i] / 255;
      const g = data[i + 1] / 255;
      const b = data[i + 2] / 255;
      // Kanal sırası: [R plane][G plane][B plane]
      input[0 * size * size + idx] = (r - mean[0]) / std[0];
      input[1 * size * size + idx] = (g - mean[1]) / std[1];
      input[2 * size * size + idx] = (b - mean[2]) / std[2];
      idx++;
    }
  }
  return new ort.Tensor('float32', input, [1, 3, size, size]);
}

function softmax(arr) {
  const max = Math.max(...arr);
  const exps = arr.map(v => Math.exp(v - max));
  const sum = exps.reduce((a, b) => a + b, 0);
  return exps.map(v => v / sum);
}

async function runInference(img) {
  if (!session) await initModel();

  statusEl.textContent = 'Çıkarım yapılıyor...';
  const tensor = imageToTensor(img);

  const inputName = session.inputNames[0];
  const output = await session.run({ [inputName]: tensor });

  const outputName = session.outputNames[0];
  const logits = Array.from(output[outputName].data);
  const probs = softmax(logits);

  // En yüksek olasılıklı sınıfı bul
  let bestIdx = 0;
  for (let i = 1; i < probs.length; i++) {
    if (probs[i] > probs[bestIdx]) bestIdx = i;
  }

  // Label dosyanız varsa fetch edip eşleyebilirsiniz (örn. imagenet-labels.txt)
  resultEl.textContent = `Tahmin sınıf index: ${bestIdx}, olasılık: ${(probs[bestIdx] * 100).toFixed(2)}%`;
  statusEl.textContent = 'Bitti';
}

// Görsel seç ve çıkarım başlat
predictBtn.addEventListener('click', async () => {
  const file = fileInput.files?.[0];
  if (!file) {
    alert('Lütfen bir görsel seçin.');
    return;
  }
  const img = new Image();
  img.onload = () => runInference(img);
  img.src = URL.createObjectURL(file);
});

// Sayfa yüklenince modeli hazırlayın (isteğe bağlı)
initModel().catch(err => {
  console.error(err);
  statusEl.textContent = 'Model yüklenirken hata oluştu.';
});

Performans İpuçları

- WebGPU genellikle WASM/WASM SIMD’e göre daha yüksek paralellik ve throughput sunar. Ancak küçük modellerde fark az olabilir. Model boyutu ve katman türleri sonucu etkiler.

- Modeli mümkün olduğunca küçük seçin (MobileNet, EfficientNet-Lite gibi). Büyük modeller hem ağdan indirmede hem de bellek kullanımında sorun çıkarabilir.

- İlk çıkarım (warm-up) genellikle daha yavaştır. Gerçek kullanıcı deneyimi için ikinci/üçüncü çıkarımı da ölçün.

- Vite yerine üretime alırken kodu küçültün ve model dosyasını CDN veya HTTP/2 ile hızlı sunun. Cache-Control başlıklarını doğru ayarlayın.

Sorun Giderme

- “WebGPU desteklenmiyor”: Tarayıcınızı güncelleyin veya chrome://flags içinde WebGPU ile ilgili bayrakları kontrol edin. Kurumsal politikalar GPU erişimini kısıtlayabilir.

- “Model giriş/çıkış adı uyuşmuyor” hatası: session.inputNames ve session.outputNames üzerinden gerçek isimleri alın, manuel isim yazmayın.

- Görselin renkleri veya sonuçlar beklenenden farklıysa, normalize adımlarını (mean/std) ve kanal sırasını (NCHW vs NHWC) model dokümantasyonuna göre doğrulayın.

- Bazı platformlarda WebGPU var ama belirli doku formatları kısıtlı olabilir. Fallback olarak WASM sağlayıcısını eklediğinizden emin olun.

Sonuç

WebGPU ve ONNX Runtime Web ile tarayıcıda makine öğrenimi artık gerçek bir seçenek. İstemci tarafında görsel sınıflandırma gibi görevlerde gizlilik, düşük gecikme ve çevrimdışı çalışma avantajları sunar. Bu rehberle temel bir iskelet kurdunuz; bundan sonra model çeşitliliğini artırabilir, etiket dosyaları ile daha anlaşılır sonuçlar gösterebilir, hatta Web Workers kullanarak arayüzü bloklamadan çoklu çıkarım senaryolarını deneyebilirsiniz. Kısacası, WebGPU sayesinde modern web uygulamaları, yapay zeka kabiliyetlerini kullanıcıya en yakın yerde, doğrudan tarayıcıda sunabiliyor.