16 Kasım 2025 Pazar

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

Apple Silicon (ARM64) dizüstüler, bulut tarafında ise yaygın AMD64 sunucular derken, tek bir Docker imajıyla her yerde çalışmak artık bir zorunluluk. Bu yazıda, Docker Buildx kullanarak çok mimarili (multi-arch) imaj oluşturmayı ve GitHub Actions ile her push sonrasında otomatik olarak Docker Hub’a yayınlamayı adım adım anlatıyorum.

Amaç net: Tek bir tag altında linux/amd64 ve linux/arm64 manifest’leri içeren, hafif ve güvenilir bir imaj üretmek. Böylece ister ARM tabanlı bir Raspberry Pi, ister AMD64 bir Kubernetes node’u olsun, aynı etiketi çekip sorunsuz çalıştırabileceksiniz.

Gereksinimler ve Temel Kavramlar

Buildx, Docker’ın gelişmiş build sürücüsüdür. Çok mimarili build, cache yönetimi, manifest listeleri ve daha fazlasını destekler. QEMU ise farklı mimariler için kullanıcı modunda emülasyon sağlayarak tek bir makinede çoklu platform derleme yapmaya imkan verir. Yayınladığınız imajlar tek bir tag altında toplanır; client çektiğinde mimarisine uygun katmanı indirir.

Yerelde Buildx Kurulumu ve Hızlı Test

Önce Buildx’in etkin olduğundan emin olun. Modern Docker Desktop sürümlerinde varsayılan olarak geliyor. CLI ile yeni bir builder yaratıp kullanabilirsiniz:

docker buildx create --name multiarch --use
docker buildx inspect --bootstrap

Basit bir test için iki platforma birden build alıp registry’ye push edelim. Docker Hub’a giriş yapmayı unutmayın:

docker login
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t KULLANICI_ADI/uygulama:deneme \
  --push .

Bu komut, yerel makinenizde emülasyon üzerinden derleyerek manifest listesi içeren bir imaj yayınlar. İndirme sırasında doğru mimari otomatik seçilir.

Dockerfile İçin Pratik İpuçları

Çok mimarili build’lerde Dockerfile’ınızı platform farkındalığı ile yazmak önemlidir. Multi-stage kullanın ve base imajları mümkün olduğunca alpine veya distroless tercih edin. Ayrıca Buildx, bazı değişkenleri otomatik sağlar: TARGETOS, TARGETARCH, TARGETPLATFORM.

Örneğin Go tabanlı bir uygulama için minimal bir Dockerfile şöyle olabilir:

# syntax=docker/dockerfile:1.7
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS builder
ARG TARGETOS TARGETARCH
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /bin/app ./cmd/server

FROM gcr.io/distroless/static:nonroot
COPY --from=builder /bin/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

Burada GOOS/GOARCH değerlerini Buildx sağlıyor. Böylece tek seferde ARM64 ve AMD64 çıktıları üretiliyor. Node.js benzeri yorumlanan dillerde genellikle ekstra işlem gerekmese de, mimariye bağlı paketler (ör. native addon’lar) varsa platforma özel kurulum adımları eklemelisiniz.

GitHub Actions ile Otomatik Yayınlama

Her etiket veya ana dala push sonrası otomatik olarak çok mimarili imaj yayınlamak için aşağıdaki workflow’u kullanabilirsiniz. Repository > Settings > Secrets bölümünde DOCKERHUB_USERNAME ve DOCKERHUB_TOKEN sırlarını oluşturmayı unutmayın.

name: docker-multiarch
on:
  push:
    branches: [ "main" ]
    tags: [ "v*" ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Extract tags and labels
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ secrets.DOCKERHUB_USERNAME }}/uygulama
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=sha

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          provenance: true

Bu iş akışı; QEMU ve Buildx’i hazırlar, Docker Hub’a giriş yapar, branch/semver/commit’e göre etiketler üretir, iki platform için build alır ve imajı push eder. cache-to/cache-from ile katmanlar GitHub’ın cache’inde saklandığı için tekrar derlemeler belirgin şekilde hızlanır.

Yayın Sonrası Doğrulama

Manifest’i kontrol etmek için şu komutu çalıştırın:

docker buildx imagetools inspect KULLANICI_ADI/uygulama:latest

Çıktıda hem linux/amd64 hem de linux/arm64 listeleniyorsa her şey yolunda demektir. Ayrıca bir ARM makinede docker run ile test etmek, gerçek koşulları görmek açısından faydalıdır.

İpuçları ve Sık Görülen Hatalar

- Native bağımlılıklar: OpenSSL, libc farkları gibi platforma duyarlı paketler kullanıyorsanız, base imajlarınızı ve paket yöneticinizi tutarlı seçin. Alpine ile glibc tabanlı dağıtımların farklarını göz önünde bulundurun.

- Boyut optimizasyonu: Çok aşamalı build, .dockerignore ve distroless tabanlarını kullanın. Gerekirse --target ile üretim aşamasını ayrılayın.

- Güvenlik ve tedarik zinciri: provenance: true ile SBOM/attestation üretimini açtınız; ayrıca imajları imzalamak için cosign gibi araçları değerlendirin.

- Versiyonlama: latest etiketine ek olarak semver ile tag’lemek, geriye dönüşleri kolaylaştırır. metadata-action bu süreci oldukça pratik hale getiriyor.

Sonuç olarak, Docker Buildx ve GitHub Actions birlikte kullanıldığında hem geliştirici deneyimini iyileştiriyor hem de kullanıcılarınızın farklı donanımlarda aynı imajı sorunsuzca çalıştırmasını sağlıyor. Kurulumu bir kez yaptıktan sonra, çok mimarili yayın şirketinizin CI/CD zincirinin doğal bir parçası haline gelir.

14 Kasım 2025 Cuma

WebGPU ile Tarayıcıda Yapay Zeka: Transformers.js Kullanarak Yerel Metin Sınıflandırıcı Kurulumu

Özet

Tarayıcıda çalışan yapay zeka uygulamaları, veriyi cihazdan çıkarmadan işlemek ve sunucu maliyetlerini azaltmak için güçlü bir çözüm haline geldi. WebGPU sayesinde artık yalnızca WebAssembly (WASM) ile sınırlı değiliz; modern ekran kartlarının gücünü doğrudan JavaScript ile kullanabiliyoruz. Bu rehberde, Transformers.js kütüphanesi ile tek sayfalık bir uygulama geliştirerek WebGPU üzerinde yerel metin sınıflandırma (pozitif/negatif duygu analizi) kuracağız. Kod, hiçbir sunucu tarafı model barındırma olmadan çalışacak ve tarayıcı, modeli indirip IndexedDB üzerinde önbellekleyecek.

Neden WebGPU?

WebGPU, grafik ve hesaplama iş yüklerinde tarayıcıya modern bir düşük seviye API sunar. WASM ile CPU üzerinde çalışan modeller, bazen yeterli performansı yakalayamazken, WebGPU destekli ONNX Runtime Web ve Transformers.js kombinasyonu, önemli ölçüde hız kazandırır. Sonuç: daha düşük gecikme, daha akıcı kullanıcı deneyimi ve ölçeklenmesi kolay bir mimari.

Önkoşullar

- Güncel bir Chromium tabanlı tarayıcı (Chrome/Edge 113+). Çoğu sistemde WebGPU varsayılan olarak açıktır. Eğer kapalıysa chrome://flags üzerinden “Enable WebGPU” etkinleştirilebilir.

- Modern bir GPU ve güncel sürücüler önerilir. GPU yoksa, uygulama otomatik olarak WASM’e düşer (daha yavaş olabilir).

- Basit bir yerel sunucu. Örnek olarak python -m http.server 8000 veya npx serve . kullanabilirsiniz.

Proje Yapısı ve Temel Sayfa

Bir klasör oluşturun: webgpu-ai-demo/. İçine index.html adında bir dosya ekleyin ve aşağıdaki iskeleti yerleştirin. COOP/COEP başlıkları, çok iş parçacıklı WASM için önerilir; yerel geliştirmede meta etiketleriyle eşdeğeri sağlanabilir. Üretimde ise HTTP yanıt başlıklarını sunucuda ayarlayın.

Aşağıdaki kodu tek bir HTML dosyasında kullanabilirsiniz:

<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>WebGPU ile Metin Sınıflandırma</title>
  <meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin">
  <meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp">
  <style>body{font-family:system-ui, Arial, sans-serif;max-width:800px;margin:40px auto;padding:0 16px}</style>
</head>
<body>
  <h1>WebGPU ile Tarayıcıda Duygu Analizi</h1>
  <textarea id="input" rows="6" style="width:100%" placeholder="Değerlendirilecek metni yazın..."></textarea>
  <br><br>
  <button id="analyze">Analiz Et</button>
  <pre id="log" style="background:#f6f8fa;padding:12px;white-space:pre-wrap">Hazırlanıyor...</pre>
  <script type="module">
    import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers/dist/transformers.min.js';
    // WebGPU varsa kullan, yoksa WASM'e düş.
    const preferGPU = 'gpu' in navigator;  // navigator.gpu modern tarayıcılarda mevcuttur.
    const device = preferGPU ? 'webgpu' : 'wasm';
    // WASM fallback için iş parçacığı sayısı (COOP/COEP ile etkin çoklu iş parçacığı).
    env.backends.onnx.wasm.numThreads = Math.max(1, Math.min(4, (navigator.hardwareConcurrency||4)-1));
    const logEl = document.getElementById('log');
    const btn = document.getElementById('analyze');
    const input = document.getElementById('input');

    log('Model indiriliyor ve hazırlanıyor...');
    const classifier = await pipeline('text-classification', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english', {
      device, quantized: true,
      progress_callback: x => log('İndiriliyor: ' + Math.round((x.progress||0)*100) + '%')
    });
    log('Hazır. Bir metin yazıp "Analiz Et"e basın.');

    btn.addEventListener('click', async () => {
      btn.disabled = true;
      const text = input.value.trim();
      if (!text) { log('Lütfen bir metin girin.'); btn.disabled = false; return; }
      log('Analiz ediliyor...');
      const output = await classifier(text, { topk: 2 });
      log(JSON.stringify(output, null, 2));
      btn.disabled = false;
    });

    function log(msg){ logEl.textContent = msg; }
  </script>
</body>
</html>

Çalıştırma

Proje klasörüne geçip basit bir sunucu açın. Örneğin Python kullanıyorsanız: python -m http.server 8000. Ardından tarayıcıdan http://localhost:8000 adresine gidin. İlk çalıştırmada model ağırlıkları indirileceği için bir miktar bekleme olabilir. Bu dosyalar IndexedDB üzerinde önbelleklenecek; bir sonraki açılışta çok daha hızlı başlayacaktır.

Performans İpuçları

- WebGPU: Kodda device: 'webgpu' geçiliyorsa GPU kullanılacaktır. Tarayıcınız ve ekran kartınız destekliyorsa belirgin hız kazanırsınız.

- Kuantizasyon: quantized: true seçeneğiyle 8-bit ağırlıklar kullanılır; indirme boyutu ve bellek tüketimi düşer, hız genellikle artar.

- Isınma (warm-up): Uygulama açıldığında boş bir metinle hızlı bir “ısınma” çağrısı yapmak, ilk gerçek isteğin gecikmesini azaltır.

- Çok iş parçacığı: WASM’e düşmeniz halinde COOP/COEP etkinse env.backends.onnx.wasm.numThreads ile çekirdek sayınıza göre değer belirleyin.

- Küçük modeller: Tarayıcı için küçük/orta boy modeller tercih edin. Daha büyük LLM’ler (ör. 7B) tarayıcıda pratik olmayabilir; sunucuya veya yerel native uygulamalara yönelin.

Hata Giderme

- “navigator.gpu tanımsız” uyarısı alıyorsanız tarayıcınızı güncelleyin veya WebGPU’yu flags üzerinden etkinleştirin. Bazı kurumsal politikalar WebGPU’yu devre dışı bırakabilir.

- “CORS/COEP/COOP” ile ilgili hatalarda sayfayı mutlaka bir HTTP sunucusundan servis edin. Üretimde, meta etiket yerine gerçek yanıt başlıklarını (COOP/COEP) sunucuda ayarlayın.

- Model indirme yavaşsa farklı bir ağa geçmeyi deneyin. İlk indirme bir kez yapılır; sonraki açılışlarda IndexedDB önbelleği devreye girer.

- Sonuçlar beklediğiniz gibi değilse Türkçe metinler için uygun bir modele geçebilirsiniz; Transformers.js ile Türkçe duygu analizi veya çok dilli modelleri deneyin.

Kısa Değerlendirme

Bu yaklaşım, uçtan uca gizlilik (metin cihazdan çıkmaz), anında ölçeklenebilirlik (sunucu GPU’su gerekmez) ve düşük gecikme gibi avantajlar sunuyor. Chrome ve Edge üzerinde WebGPU ile duyduğum hız artışı belirgin oldu; Safari ve Firefox tarafında ise deneysel destekler hızla olgunlaşıyor. Projenizde basit bir duygu analiziyle başlayıp, soru-cevap ya da özetleme gibi diğer görevler için hafif modellerle devam edebilirsiniz.

Sonuç

WebGPU ve Transformers.js, tarayıcıda çalışan modern yapay zeka uygulamalarını herkes için erişilebilir kılıyor. Bu yazıdaki örneği temel alarak kendi metin moderasyonu, kullanıcı geri bildirimi analizi veya içerik sınıflandırma araçlarınızı birkaç yüz satırlık kodla hayata geçirebilirsiniz. Performansı artırmak için kuantizasyon, uygun model seçimi ve önbellekleme stratejilerinden yararlanmayı unutmayın.

13 Kasım 2025 Perşembe

GitHub Actions ile AWS’e Şifresiz Dağıtım (OIDC) Nasıl Kurulur? Adım Adım Rehber

Modern CI/CD süreçlerinde uzun ömürlü AWS erişim anahtarlarını projelerde saklamak hem riskli hem de yönetimi zahmetli. OpenID Connect (OIDC) sayesinde GitHub Actions, AWS’e şifresiz ve kısa ömürlü kimlik doğrulama ile bağlanabiliyor. Bu yazıda, GitHub Actions’ı kullanarak AWS’e OIDC tabanlı, güvenli ve pratik bir dağıtım hattını nasıl kuracağınızı adım adım anlatıyorum.

Özet: AWS tarafında GitHub’ı güvenilen kimlik sağlayıcısı olarak tanımlayacağız, belirli bir depo/branch için kısıtlı yetkili bir IAM rolü oluşturacağız ve GitHub Actions üzerinde bu rolü geçici olarak üstlenerek dağıtım yapacağız. Anahtar saklamaya gerek yok.

OIDC ile neden şifresiz dağıtım?

Klasik yaklaşımda, GitHub Secrets içine AWS_ACCESS_KEY_ID ve AWS_SECRET_ACCESS_KEY koyarız. Bu yöntem, anahtar sızıntısı, rotasyon zorluğu ve fazladan yetkiler gibi sorunlar yaratır. OIDC ile GitHub, çalıştırdığı iş akışı (workflow) için imzalı bir kimlik belirteci üretir; AWS bu belirteci doğrular ve yalnızca o an, o koşullarda geçerli kısa ömürlü kimlik bilgileri verir. Sonuç: Daha az gizli bilgi, daha sıkı yetkilendirme ve otomatik süre sonu.

Önkoşullar

- Bir AWS hesabı ve IAM üzerinde rol oluşturma yetkisi
- GitHub’da bir depo (public ya da private)
- Dağıtım hedefi: Örneğin S3 statik site, ECR + ECS/Fargate, ya da CloudFormation/SAM ile altyapı

AWS tarafı: IAM rolü ve güven ilişkisi (trust policy)

1) AWS IAM’de Identity providers bölümünden OpenID Connect sağlayıcısı olarak token.actions.githubusercontent.com ekleyin. Audience olarak sts.amazonaws.com kullanın.
2) Yeni bir IAM rolü oluşturun ve “Web identity” seçeneğiyle az önceki sağlayıcıyı seçin.
3) Aşağıdaki gibi bir trust policy tanımlayın. Bu örnek sadece belirli bir repo ve branch için yetki veriyor:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::HESAP_IDNIZ:oidc-provider/token.actions.githubusercontent.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:ORGANIZASYON/DEPO_ADI:ref:refs/heads/main"
}
}
}
]
}

4) Role bağlayacağınız izinleri minimum ilke (least privilege) ile ayarlayın. Örneğin S3’e sadece belirli bir bucket’a yazma yetkisi veya ECR push izinleri. Örnek bir S3 dağıtım politikası (özet):

{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": ["s3:PutObject","s3:DeleteObject"], "Resource": ["arn:aws:s3:::hedef-bucket/*"] },
{ "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::hedef-bucket"] }
]
}

GitHub tarafı: Workflow ile rolü üstlenmek

GitHub Actions, OIDC token’ı otomatik üretir. AWS ile konuşmak için aws-actions/configure-aws-credentials eylemini (action) kullanacağız ve IAM rolümüzü geçici olarak üstleneceğiz. Basit bir S3 dağıtımı örneği:

name: Deploy to S3 (OIDC)
on:
push:
branches: [ "main" ]
permissions:
id-token: write # OIDC token üretimi için şart
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Kodu çek
uses: actions/checkout@v4

- name: AWS kimlik bilgilerini yapılandır
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::HESAP_IDNIZ:role/GITHUB_OIDC_DEPLOY_ROLE
aws-region: eu-central-1

- name: Statik dosyaları derle
run: |
npm ci
npm run build

- name: S3'e senkronize et
run: |
aws s3 sync ./build s3://hedef-bucket --delete

Dikkat edilmesi gereken en kritik kısım permissions altında id-token: write yetkisinin verilmesi. Bu izin olmadan GitHub, OIDC belirteci oluşturmaz ve AWS rolünü üstlenemezsiniz.

Güvenlik ve en iyi uygulamalar

- Least privilege: Role bağlanan politikalar sadece gereken servis ve kaynaklara izin versin. “*” yerine spesifik ARN kullanın.
- Branch kısıtları: Trust policy içinde sub koşulunu belirli branch’lerle sınırlandırın (ör. refs/heads/main ve refs/tags/v*).
- Ortam ayrımı: Prod/staging için farklı rol ve politikalar tanımlayın; workflow’larda çevresel değişkenlerle hedefleri ayırın.
- Geçici kimlik: Varsayılan token süreleri kısadır. Bu, çalınsa bile etkisini sınırlar. Gereksiz session duration artırımı yapmayın.

Sık karşılaşılan hatalar ve çözümü

- AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity: Trust policy’de OIDC provider ARN’i, audience ve subject desenini kontrol edin.
- Invalid identity token: GitHub OIDC domain’i ve thumbprint otomasyonlarını doğru oluşturduğunuzdan emin olun; provider’ı tekrar eklemek çoğu kez sorunu çözer.
- Missing id-token permission: Workflow permissions kısmında id-token: write yoksa ekleyin.
- Bucket veya ECR erişim hataları: IAM rolüne eklediğiniz izin politikasının kaynak ARN’lerini ve region bilgisini doğrulayın.

Gelişmiş kullanım: ECR + ECS/Fargate dağıtımı

S3 yerine konteyner dağıtıyorsanız, aynı rol ile ecr:BatchCheckLayerAvailability, ecr:PutImage, ecr:GetAuthorizationToken gibi izinleri verip Docker imajını ECR’a push edebilir, ardından aws ecs update-service ile hizmeti yeni imaja yönlendirebilirsiniz. Tüm akış yine şifresiz ve OIDC tabanlı kalır.

Sonuç olarak, GitHub Actions + OIDC yaklaşımı, güvenliği artırırken bakım yükünü azaltır. API anahtarlarıyla uğraşmadan, denetlenebilir ve politikalarla sıkı şekilde sınırlandırılmış bir dağıtım boru hattı elde edersiniz. Yeni projelerde varsayılan tercih olarak OIDC’yi değerlendirmenizi öneririm.

12 Kasım 2025 Çarşamba

Tarayıcıda WebGPU ile Makine Öğrenmesi: ONNX Runtime Web ve TensorFlow.js Rehberi

WebGPU, tarayıcıda donanım hızlandırmalı hesaplamayı modern grafik API’lerine (Metal, Direct3D 12, Vulkan) yakın bir modelle sunarak WebGL’in ötesine geçen yeni standart. Bu sayede makine öğrenmesi (ML) çıkarımını doğrudan kullanıcının cihazında, ek sunucu maliyeti olmadan ve gizliliği koruyarak çalıştırmak mümkün oluyor. Bu yazıda, WebGPU ile tarayıcıda ML modelini çalıştırmak için iki pratik yaklaşımı adım adım göstereceğim: ONNX Runtime Web ve TensorFlow.js. İkisini de basit örneklerle kurup, performans ipuçları ve sık karşılaşılan sorunlarla birlikte ele alacağız.

WebGPU hazır mı? Uyum ve kontrol

Güncel Chrome/Edge sürümlerinde WebGPU varsayılan olarak etkin. Safari’de kademeli destek ilerliyor; Firefox cephesinde Nightly kanalıyla deneysel destek mevcut. Hızlı bir kontrol için konsolda if (navigator.gpu) { console.log("WebGPU hazir"); } çalıştırabilirsiniz. Üretimde en sağlıklı deneyimi almak için HTTPS üzerinde barındırma yapın; bazı gelişmiş optimizasyonlar ve çoklu iş parçacığı (WASM tarafı) için COOP/COEP başlıklarını ayarlamak da gerekebilir.

ONNX Runtime Web ile WebGPU: Dönüştür, yükle, çalıştır

ONNX formatı; PyTorch, TensorFlow, scikit-learn ve daha fazlasından dönüştürülebilen evrensel bir model temsili sunar. Tarayıcıda ONNX modellerini çalıştırmak için onnxruntime-web paketinin WebGPU varyantını kullanacağız.

Kurulum (npm):
npm i onnxruntime-web

Basit örnek (WebGPU yüklü sürümle import):
import * as ort from 'onnxruntime-web/webgpu';

// 1) Oturumu aç
const session = await ort.InferenceSession.create('/models/model.onnx');

// 2) Girdi hazırlama (ör. 1x3x224x224 float32 tensör)
const data = new Float32Array(1 * 3 * 224 * 224);
// ... preprocess ile veriyi doldurun
const feeds = {
  'input': new ort.Tensor('float32', data, [1, 3, 224, 224])
};

// 3) Çıkarım
const results = await session.run(feeds);
const output = results['output'] || Object.values(results)[0];
console.log('Çıkış boyutu:', output.dims);

Önemli nokta: webgpu varyantını import ettiğinizde yürütücü bu backend’i tercih eder. WebGPU destekli değilse otomatik olarak WASM’e düşebilir; ancak tutarlı performans için destekli tarayıcı hedefleyin. Büyük modelleri CDN üzerinden getirirken HTTP/2 veya HTTP/3 tercih edin; tek büyük dosya yerine parçalara bölünmüş ağırlıklar ilk etkileşimi hızlandırabilir.

TensorFlow.js + WebGPU: Hızlı başlangıç

TensorFlow ekosisteminde çalışıyorsanız veya TFJS’nin zengin yüksek seviyeli API’lerinden faydalanmak istiyorsanız WebGPU backend’i iyi bir seçenek. Aşağıdaki adımlarla bir GraphModel’i WebGPU üzerinde çalıştırabiliriz.

Kurulum (npm):
npm i @tensorflow/tfjs @tensorflow/tfjs-backend-webgpu

Örnek kullanım:
import * as tf from '@tensorflow/tfjs';
import '@tensorflow/tfjs-backend-webgpu';

await tf.setBackend('webgpu');
await tf.ready();

// Modeli yükle (GraphModel tercih)
const model = await tf.loadGraphModel('/models/model.json');

// Girdi oluştur (NHWC: [1, 224, 224, 3])
const input = tf.randomNormal([1, 224, 224, 3]);
const warmup = model.predict(input);
await warmup.data(); // sıcak başlatma
warmup.dispose();

const output = model.predict(input);
const result = await output.data();
console.log('İlk 5 skor:', Array.from(result).slice(0, 5));
input.dispose();
output.dispose();

TFJS tarafında model.predict zincirindeki tensörleri zamanında dispose() etmek ve tahmin öncesi bir warmup çağrısı yapmak kare sürelerini belirgin biçimde iyileştirir. Özellikle görüntü tabanlı modellerde tf.image.resizeBilinear gibi GPU dostu operasyonları kullanmak CPU-GPU senkronizasyonunu azaltır.

Performans ipuçları: FP16, quantization ve bellek

- FP16 desteği: Cihazınız destekliyse (çoğu modern GPU’da var), FP16 ile bant genişliği ve bellek kullanımını düşürürsünüz. ONNX tarafında dönüştürme sırasında, TFJS tarafında ise uygun model varyantını tercih edin.
- INT8 quantization: Görsel sınıflandırma ve bazı NLP modellerinde int8 kuantizasyon ciddi hız ve boyut kazancı sağlar. Kalibrasyon verisiyle kuantize edilmiş ONNX modelleri WebGPU’da iyi sonuç verir.
- Graf optimizasyonu: ONNX için optimize edilmiş grafik ve sabit katman birleştirme (fusion) seçenekleri; TFJS için GraphModel tercih edin ve gereksiz düğümleri taşımayın.
- Veri aktarımını minimize edin: GPU’dan CPU’ya data() çağrılarını sadece gerekli olduğunda yapın. Akış içinde tensörleri GPU’da tutmak darboğazları azaltır.
- Pipeline hazırlığı: Tek seferlik session ve model nesnelerini uygulama ömrü boyunca yeniden kullanın; her tahminde yeniden oluşturmayın.

Hata ayıklama ve yaygın sorunlar

- navigator.gpu undefined: Tarayıcı desteklemiyor ya da ortam güvenli değil. Güncel sürüm kullanın ve sayfayı HTTPS üzerinde servis edin.
- CORS/COEP/COOP: Büyük modelleri farklı bir origin’den çekiyorsanız CORS başlıkları ve gerekiyorsa COOP/COEP ayarları doğru olmalı. Aksi halde iş parçacığı/optimizasyon kısıtları veya yükleme hataları görebilirsiniz.
- Çıktı isimleri: ONNX modellerinde çıktı adları farklı olabilir. Object.keys(results) ile kontrol edip doğru düğümü okuyun.
- Bellek sızıntısı: TFJS ve ORT’ta tek kullanımlık tensörleri mutlaka dispose() edin. Uzun oturumlarda aksi halde GPU belleği dolar.
- Mobil cihazlar: Termal kısıtlar nedeniyle uzun süreli çıkarımda hız düşebilir. Toplu işler için aralıklı işlem veya daha küçük/kuantize model seçin.

Hangi yolu seçmeli?

- ONNX Runtime Web: Farklı çerçevelerden gelen modelleri tek formatta toplamak, üretim odaklı sabitlenmiş bir çalışma zamanı kullanmak ve WebGPU/WASM arasında esnek geçiş yapmak istediğiniz projeler için ideal.
- TensorFlow.js: TF ekosistemine aşinalığınız varsa, tarayıcıya özel yüksek seviyeli API’lerle hızlı prototipleme ve zengin yardımcı fonksiyonlar arıyorsanız tercih edin.

Sonuç olarak WebGPU, tarayıcı tarafı makine öğrenmesinde yeni bir sayfa açıyor. Doğru model boyutu, kuantizasyon stratejisi ve bellek yönetimiyle, gerçek zamanlı veya etkileşimli deneyimleri tamamen istemci tarafında, gizliliğe saygılı ve düşük gecikmeli şekilde sunmak artık mümkün. Hem ONNX Runtime Web hem de TensorFlow.js, geliştirici deneyimini olgunlaştıracak seviyede; projenizin kökenine ve ekosistem tercihlerinize göre seçim yapıp hızla üretime geçebilirsiniz.

11 Kasım 2025 Salı

Docker Buildx ile Çok Mimarili (Multi-Arch) Konteyner İmajı Oluşturma Rehberi (2025)

Giriş

Farklı mimarilerde (ARM64, AMD64 gibi) çalışan sunucuların ve geliştirici makinelerinin arttığı bir dönemde, tek bir Docker imajını her yerde sorunsuz çalıştırmak kritik hale geldi. Apple Silicon (M1/M2/M3) kullanan geliştiriciler, AMD64 tabanlı üretim sunucularına dağıtım yaparken uyumluluk sorunları yaşayabiliyor. Bu rehberde, Docker Buildx ve BuildKit kullanarak çok mimarili (multi-arch) Docker imajı oluşturmayı, imajı bir container kayıt deposuna itip SBOM/provenance gibi modern güvenlik özelliklerini eklemeyi adım adım anlatıyorum.

Neden Çok Mimarili İmaj?

Çok mimarili imajlar, tek bir etiket altında birden fazla işlemci mimarisini içeren bir manifest listesi barındırır. Böylece docker pull çalıştığında istemcinin mimarisine uygun katmanlar otomatik olarak indirilir. Sonuç: tek etiket, tek dağıtım akışı ve daha az sürpriz. Ayrıca CI/CD hatlarınız basitleşir ve hem ARM64 hem de AMD64 için ayrı imaj yönetme yükünüz azalır.

Gereksinimler ve Kurulum

- Docker 24+ ve Buildx etkin olmalı (Docker Desktop ile varsayılan gelir). Linux sunucularda buildx plugin’inin kurulu olduğundan emin olun.

- Farklı mimariler için yerel derleme yapmıyorsanız, emülasyon için QEMU/binfmt gerekir. Docker Desktop bunu sağlar; çıplak Linux’ta bir defaya mahsus şu komutla etkinleştirebilirsiniz: docker run --privileged --rm tonistiigi/binfmt --install all

- Kayıt deposu erişimi (Docker Hub, GHCR, GitLab Registry vb.) ve push yetkisi.

Adım 1: Buildx Builder Oluşturma

Yeni bir builder örneği, BuildKit özelliklerini (cache, çoklu platform, SBOM) etkin kullanmanızı sağlar. Aşağıdaki komut genel bir başlangıçtır: docker buildx create --name multi --use --bootstrap. Bu, “multi” adında bir builder oluşturur ve aktif hale getirir.

Adım 2: Dockerfile’ı Multi-Arch Uyumlu Yazma

Temel imaj olarak multi-arch sağlayan resmi imajları seçin (örneğin node:20-alpine, python:3.12-slim, golang:1.22-alpine). Derleme sırasında mimari fark yaratabilecek bağımlılıklar (ör. native modüller, OS paketleri) için hedef platforma duyarlı bayrakları düşünün. Multi-stage derleme (builder + runtime) hem boyutu küçültür hem de taşınabilirliği artırır.

Adım 3: Çok Mimarili İmajı İnşa Etme ve Gönderme

Örnek bir komut: docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/kullanici/uygulama:1.0 --push . Bu komut iki mimari için derler ve manifest listesi ile birlikte etikete gönderir. Yerelde test etmek isterseniz --load kullanabilirsiniz; ancak --load tek mimari için çalışır. Multi-arch için en iyi pratik --push kullanmaktır.

Adım 4: SBOM ve Provenance Eklemek

SBOM (Software Bill of Materials) ve provenance, tedarik zinciri güvenliği için giderek zorunlu hale geliyor. BuildKit ile şu bayrakları ekleyebilirsiniz: --sbom=true --provenance=true. Tam örnek: docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/kullanici/uygulama:1.0 --sbom=true --provenance=true --push . Çoğu kayıt deposu bu metadataları saklayıp sonradan denetlenmesine izin verir.

Adım 5: Cache Yapılandırması ile Hız Kazanın

Buildx, uzak kayıt deposu tabanlı cache’i destekler. İlk derlemede --cache-to type=registry,ref=ghcr.io/kullanici/uygulama:buildcache,mode=max; sonraki derlemelerde --cache-from type=registry,ref=ghcr.io/kullanici/uygulama:buildcache kullanın. Bu sayede farklı CI runner’ları arasında katmanlar paylaşılarak derleme süresi ciddi şekilde kısalır.

Gizli Anahtarlar ve Çok Aşamalı Derlemeler

Derleme esnasında gizli anahtar (örneğin NPM_TOKEN) kullanacaksanız, komutta --secret id=NPM_TOKEN,env=NPM_TOKEN bayrağını, Dockerfile içinde de RUN --mount=type=secret,id=NPM_TOKEN kullanın. Bu yaklaşım sırları imaj katmanlarına sızdırmadan bağımlılık yüklemeyi mümkün kılar.

Doğrulama ve Hata Ayıklama

İmajınızın gerçekten çok mimarili olup olmadığını kontrol etmek için docker buildx imagetools inspect ghcr.io/kullanici/uygulama:1.0 çalıştırın. Manifest listesinde linux/amd64 ve linux/arm64 girdiğini görmelisiniz. Yerel test için Apple Silicon’da docker run --platform linux/amd64 ile x86_64 çalıştırıp davranışı karşılaştırabilirsiniz.

CI/CD Entegrasyonu (GitHub Actions Örneği)

GitHub Actions’ta tipik adımlar: QEMU kurulumu, Buildx kurulumu, kayıt deposuna login, cache ayarları, ardından çok mimarili build ve push. Resmi docker/setup-qemu-action ve docker/setup-buildx-action aksiyonlarını kullanın. Workflow’da gizli anahtarları secrets ile yönetin, etiketleri semantik sürümleme veya git SHA ile otomatik üretin.

Performans ve Maliyet İpuçları

- Mümkünse her mimari için yerel runner kullanın; emülasyon (QEMU) doğru ama yavaştır. Büyük derlemelerde süreyi belirgin etkiler.

- Minimal taban imajları (alpine, distroless) boyutu küçültür ve indirme süresini hızlandırır. Ağ maliyeti ve soğuk başlangıç süreleri düşer.

- Çok aşamalı derlemeyle derleme araçlarını final imajdan uzak tutun; güvenlik taramalarında daha az yüzey alanı elde edersiniz.

Sonuç

Docker Buildx ile çok mimarili imaj üretmek, bugün heterojen altyapılarda sürdürülebilir bir dağıtım stratejisinin bel kemiği. Doğru taban imajları, cache ve güvenlik metadatalarıyla desteklendiğinde, tek etiketle tüm platformlara güvenle dağıtım yapabilirsiniz. Üstelik CI/CD hatlarınıza entegre edilmesi kolay ve uzun vadede bakım yükünü ciddi biçimde azaltıyor. Bir kez kurduktan sonra, “nerede çalışacak?” sorusu gündemden düşüyor; geriye sadece uygulamanızın değer üretmesi kalıyor.

10 Kasım 2025 Pazartesi

OpenTelemetry ile Node.js Uygulamasını İzleme: OTLP ve Jaeger ile 15 Dakikada Kurulum

OpenTelemetry nedir ve neden önemli?

Modern mikroservislerin başarısı; gecikme, hata oranı ve bağımlılık zincirini anlık olarak görebilmenize bağlıdır. OpenTelemetry (OTel), kodunuzu satıcı bağımsız bir şekilde enstrümante ederek traces, metrics ve logs toplamanıza izin veren açık bir standarttır. Bu sayede bugün Jaeger kullanırken, yarın Grafana Tempo veya başka bir araca geçmek zorunda kalsanız bile aynı veri modelini korursunuz.

Bu rehberde, Node.js tabanlı bir servisi OTLP (OpenTelemetry Protocol) ile enstrümante edip, yerelde Jaeger All-in-One üzerinde izleri görüntüleyeceğiz. Üretimde Tempo, Honeycomb, Datadog gibi hedeflere geçiş de aynı mantıkla yapılabilir.

Gereksinimler

- Node.js 18+
- Docker (opsiyonel ama tavsiye edilir)
- Terminal ve temel npm bilgisi

Adım 1: Jaeger All-in-One ile hızlı izleme ortamı

Jaeger All-in-One, lokalde hızlı deneme yapmak için idealdir. OTLP alıcısı varsayılan olarak kapalı gelir; bu yüzden aşağıdaki komutta onu açıyoruz:

docker run -d --name jaeger -e COLLECTOR_OTLP_ENABLED=true -p 16686:16686 -p 4317:4317 -p 4318:4318 jaegertracing/all-in-one:1.57

Bu komut ile:
- 16686 portundan Jaeger UI’ya erişirsiniz.
- 4317 (gRPC) ve 4318 (HTTP) portlarından OTLP verisi kabul edilir.
Tarayıcıdan http://localhost:16686 adresine gidip arayüzün geldiğini doğrulayın.

Adım 2: Node.js uygulamasını enstrümante etme

Yeni bir proje oluşturun ve gerekli paketleri kurun:

mkdir otel-node-demo && cd otel-node-demo
npm init -y
npm i express
npm i @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-http

Proje kökünde tracing.js dosyası oluşturun ve aşağıdaki minimal yapılandırmayı ekleyin:

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');

const exporter = new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces' });
const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'otel-node-demo',
  }),
  traceExporter: exporter,
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start().then(() => {
  process.on('SIGTERM', () => sdk.shutdown());
});

Basit bir Express sunucusu için app.js dosyasını ekleyin:

const express = require('express');
const app = express();
app.get('/hello', async (req, res) => {
  await new Promise(r => setTimeout(r, 50)); // Yapay gecikme
  res.json({ ok: true, ts: Date.now() });
});
app.listen(3000, () => console.log('API 3000 portunda'));

Uygulamayı enstrümantasyon ile birlikte çalıştırın:

node -r ./tracing.js app.js

Ardından birkaç istek atın:
curl http://localhost:3000/hello

Adım 3: İzleri Jaeger arayüzünde inceleme

Jaeger UI’da sol üstteki servis listesinden otel-node-demo’yu seçin ve Find Traces butonuna basın. Her HTTP isteği için birer trace oluştuğunu, otomatik enstrümantasyon sayesinde express, http gibi span’ların kendiliğinden toplandığını göreceksiniz. Gecikme (latency) dağılımı ve hatalı isteklerin oranı burada hızla görünür hale gelir.

Tempo mu, Jaeger mi?

Bu rehberde hızlı ilerlemek için Jaeger kullandık. Üretim ortamında Grafana Tempo, özellikle uzun saklama (S3/MinIO) ve Grafana ile sıkı entegrasyon avantajları sağlar. Node.js açısından fark yoktur; uygulama yine OTLP ile veri yollar. Sadece hedef uç nokta değişir. Örneğin Collector veya Agent üzerinden otlp exporter ile Tempo’nun 4317/4318 portlarına gönderebilirsiniz.

İpuçları ve en iyi uygulamalar

- Örnekleme (sampling): Varsayılan olarak oran %100 olabilir. Trafik yüksekse TRACE_SAMPLER=parentbased_traceidratio ve oran ayarlaması ile maliyeti düşürün.
- Dağıtık bağlam: Proksi veya API Gateway kullanıyorsanız traceparent başlıklarının korunduğundan emin olun. Aksi halde zincir kopar.
- Log korelasyonu: Pino/Winston logger’ınıza aktif trace ID’yi ekleyerek sorun giderme hızlanır. @opentelemetry/api içinden trace.getActiveSpan() ile ID alınabilir.
- Güvenlik: OTLP uç noktalarını sadece iç ağda açın ya da mTLS ile koruyun.
- Göç kolaylığı: Bugün Jaeger, yarın Tempo? Uygulama kodu değişmez; sadece uç nokta ve backend değişir. İşte OpenTelemetry’nin gücü budur.

Sonuç

OpenTelemetry ile Node.js servislerinizi dakikalar içinde gözlemlenebilir kılabilirsiniz. OTLP sayesinde backend bağımsız bir mimari kurar, yerelde Jaeger ile hızlıca dener, üretimde ise Tempo ve Grafana ile uçtan uca izlemeyi sürdürebilirsiniz. Bu yatırım, mikroservis karmaşıklığında hataları daha hızlı bulmanızı, performansı ölçmenizi ve son kullanıcı deneyimini iyileştirmenizi sağlar.

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.