14 Eylül 2025 Pazar

WebGPU ile Tarayıcıda Yapay Zeka: ONNX Runtime Web ile Hızlı Görüntü Sınıflandırma Rehberi

Giriş

Tarayıcıda yapay zeka çalıştırmak artık bir deney olmaktan çıktı; WebGPU ve ONNX Runtime Web gibi teknolojiler sayesinde ciddi performans elde etmek mümkün. Bu rehberde, WebGPU hızlandırmasıyla bir ONNX görüntü sınıflandırma modelini tamamen tarayıcı içinde, ek bir sunucu tarafı altyapı olmadan nasıl koşturabileceğinizi adım adım anlatıyorum. Hedefimiz düşük gecikme, daha iyi gizlilik (veri cihazı terk etmez) ve çevrimdışı çalışma imkânı.

Neden WebGPU?

WebGPU, WebGL’in ötesine geçen, modern GPU mimarilerinden doğrudan faydalanmayı kolaylaştıran bir tarayıcı API’sidir. Hesaplama (compute) kabiliyetleri, daha düşük sürücü ek yükü ve daha öngörülebilir performans sunar. ONNX Runtime Web de bu yeteneklerden yararlanarak modeli GPU üzerinde çalıştırabilir; GPU desteklenmiyorsa otomatik olarak WASM (CPU) yoluna düşer.

Önkoşullar ve Ortam

• Tarayıcı: Chrome/Edge 113+ sürümlerinde WebGPU varsayılan olarak açıktır. Safari’de kısmi, Firefox’ta Nightly ve bayrak ile destek var. En güncel Chrome önerilir.
• Temel JS/HTML bilgisi ve statik bir sunucu (ör. npx serve veya Vite).
• Model dosyası: ONNX Model Zoo’dan MobileNetV2-7 küçük ve hızlı bir başlangıçtır. Alternatif olarak SqueezeNet veya EfficientNet-Lite tercih edilebilir.

Proje İskeleti

Basit bir index.html dosyasıyla başlayın. Aşağıdaki minimal iskelet, bir dosya girişi, bir tuş ve sonucu göstermek için alan içerir:

<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>WASM + WebGPU Sınıflandırma</title>
</head>
<body>
  <input id="file" type="file" accept="image/*">
  <button id="run">Çalıştır</button>
  <canvas id="canvas" width="224" height="224"></canvas>
  <div id="out"></div>
  <script type="module" src="./app.js"></script>
</body>
</html>

ONNX Runtime Web’i Entegre Etme

CDN üzerinden ORT’yi kullanabilirsiniz. app.js dosyasında ORT’yi içe alın ve WebGPU’yu tercih eden bir oturum oluşturun. WASM fallback’i yedekte kalsın:

import * as ort from "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js";

// WASM dosyalarının yolu (CDN veya yerel) - doğru ayarlayın
ort.env.wasm.wasmPaths = "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/";
// Daha yüksek performans için çoklu iş parçacığı (COOP/COEP gerektirebilir)
// ort.env.wasm.numThreads = navigator.hardwareConcurrency || 4;

const preferGPU = !!navigator.gpu;
const session = await ort.InferenceSession.create("./models/mobilenetv2-7.onnx", {
  executionProviders: preferGPU ? ["webgpu", "wasm"] : ["wasm"],
  graphOptimizationLevel: "all"
});

Ön İşleme: Görseli Tensore Dönüştürme

MobileNet türü modeller genelde 224x224 giriş, RGB kanal sırası ve kanal başta (NCHW) düzeni bekler. Pixel değerlerini 0-1 aralığına getirip normalize etmek gerekir. Örnek bir dönüştürme:

async function imageToTensor(file) {
  const img = new Image();
  img.src = URL.createObjectURL(file);
  await img.decode();
  const canvas = document.getElementById("canvas");
  const ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0, 224, 224);
  const { data } = ctx.getImageData(0, 0, 224, 224);
  const chw = new Float32Array(1 * 3 * 224 * 224);
  const mean = [0.485, 0.456, 0.406];
  const std = [0.229, 0.224, 0.225];
  let p = 0;
  for (let y = 0; y < 224; y++) {
    for (let x = 0; x < 224; x++) {
      const i = (y * 224 + x) * 4;
      const r = data[i] / 255;
      const g = data[i + 1] / 255;
      const b = data[i + 2] / 255;
      // NCHW: önce tüm R, sonra G, sonra B kanalı
      chw[0 * 224 * 224 + p] = (r - mean[0]) / std[0];
      chw[1 * 224 * 224 + p] = (g - mean[1]) / std[1];
      chw[2 * 224 * 224 + p] = (b - mean[2]) / std[2];
      p++;
    }
  }
  return new ort.Tensor("float32", chw, [1, 3, 224, 224]);
}

Çalıştırma ve Sonuçları Yorumlama

Girdi tensörünü oluşturduktan sonra oturumu çalıştırın. Çoğu sınıflandırma modelinde çıktı tek bir tensördür; en büyük olasılığı seçip etikete dönüştürürsünüz. ImageNet etiketlerini küçük bir JSON dosyası olarak projeye ekleyebilirsiniz:

import labels from "./labels-imagenet.json" assert { type: "json" };

document.getElementById("run").addEventListener("click", async () => {
  const file = document.getElementById("file").files[0];
  if (!file) return;
  const input = await imageToTensor(file);
  const feeds = { input: input }; // Modelin gerçek girdi ismini kontrol edin
  const out = await session.run(feeds);
  const outputName = session.outputNames[0];
  const data = out[outputName].data;
  let idx = 0, max = -Infinity;
  for (let i = 0; i < data.length; i++) { if (data[i] > max) { max = data[i]; idx = i; } }
  document.getElementById("out").textContent = labels[idx] + " (" + max.toFixed(3) + ")";
});

Performans İpuçları

• İlk yüklemede bir “ısındırma” (warm-up) çağrısı yapın; modelin derlenmesi ve GPU kaynaklarının hazırlanması süre alabilir.
• WebGPU aktifleştirilmişse IOBinding ile giriş/çıkışları GPU üzerinde tutmak ek hız kazandırır (ileri kullanım).
• Modellerin quantized (INT8) sürümlerini tercih ederek dosya boyutunu ve gecikmeyi azaltın.
• Model dosyasını Brotli/Gzip ile sıkıştırıp uygun cache header’ları ayarlayın; tarayıcı önbelleğini ve Service Worker ile Cache Storage’ı kullanın.
• Görüntü ön işlemesini OffscreenCanvas veya Web Worker içinde yaparak ana iş parçacığını serbest bırakın.

Güvenlik ve Uyumluluk Notları

WASM tarafında çoklu iş parçacığı ve SharedArrayBuffer kullanmak istiyorsanız COOP/COEP başlıklarını etkinleştirmeniz gerekir. Bu mümkün değilse tek iş parçacığı da gayet iş görür; WebGPU varsa GPU hızlandırması zaten ciddi bir fark yaratır. Tarayıcı uyumluluğunda problem yaşıyorsanız, geçici olarak executionProviders: ["wasm"] ile çalışmaya devam edebilirsiniz.

Sonuç

Bu rehberle, yalnızca statik dosyalardan oluşan basit bir web projesinde ONNX Runtime Web ve WebGPU kullanarak gerçek zamanlıya yakın görüntü sınıflandırma kurdunuz. Avantajları açık: düşük gecikme, veri gizliliği ve dağıtım kolaylığı. Bir sonraki adım olarak kamera akışı (getUserMedia) ile canlı sınıflandırma, farklı model mimarileri (ResNet, EfficientNet, ViT), otomatik etiketleme veya yerleşik önbellekle çevrimdışı kullanım gibi özellikleri ekleyebilirsiniz. WebGPU ekosistemi hızla olgunlaşıyor; bugün attığınız adımlar, yarının tarayıcı tabanlı yapay zeka uygulamalarının temelini oluşturacak.

3.

13 Eylül 2025 Cumartesi

Passkey (WebAuthn) ile Şifresiz Giriş Entegrasyonu: Adım Adım Rehber

Passkey nedir ve neden önemli?

Geleneksel parolalar hem kullanıcı deneyimi açısından sorunlu hem de güvenlik zaafları nedeniyle verimsizdir. Passkey, FIDO2 ve WebAuthn standartlarına dayalı, phishing’e dayanıklı ve cihaz tabanlı bir kimlik doğrulama yöntemidir. Kullanıcılar artık “123456” gibi zayıf parolalarla uğraşmak yerine, platformlarının (iOS, Android, Windows, macOS) yerleşik biyometrik doğrulamasını veya donanım anahtarını kullanır. Bu yazıda, modern bir web uygulamasına passkey ile şifresiz girişin nasıl ekleneceğini, mimari prensipleri ve dikkat edilmesi gereken güvenlik detaylarını anlatıyorum.

Temel mimari ve kavramlar

WebAuthn iki temel akıştan oluşur: Kayıt (Registration) ve Giriş (Authentication). Kayıt sırasında tarayıcı bir anahtar çifti üretir ve sunucuya sadece public key ve credentialId gibi meta veriler iletilir. Girişte, sunucu tarafından üretilen tek kullanımlık challenge imzalanarak doğrulama yapılır.

Önemli alanlar: rpId (Relying Party ID, genellikle alan adınız), origin (tam köken, ör. https://app.siteniz.com), userHandle (kullanıcının uygulama içi benzersiz kimliği), signCount (anti-rollback sayacı). Her doğrulamada challenge rastgele üretilir ve tek seferliktir.

Önkoşullar ve teknoloji seçimi

Üretimde HTTPS zorunludur. Geliştirme için localhost istisnası vardır. Sunucu tarafında doğrulama için hazır kütüphaneler tercih edin: Node.js için SimpleWebAuthn, Go için duo-labs/webauthn, Java için WebAuthn4J, Python için webauthn. İstemci tarafında tarayıcı API’si navigator.credentials üzerinden erişilir. Veritabanında her kullanıcı için birden fazla credential saklamaya hazır olun (cihaz kaybı senaryosu).

Kayıt (Registration) akışı

1. Sunucu hazırlığı: Kullanıcı hesabı oluşturulduğunda veya “Passkey ekle” tıklandığında sunucu bir PublicKeyCredentialCreationOptions üretir. İçerik: rp (name, id), user (id, name, displayName), challenge (kriptopratik rastgele dizi), pubKeyCredParams (genelde -7 ES256), authenticatorSelection (ör. residentKey: "preferred", userVerification: "required"), attestation ("none" çoğu senaryo için yeterli).

2. İstemci isteği: Tarayıcıda navigator.credentials.create({ publicKey: options }) çağrılır. Kullanıcı, biyometrik veya PIN ile onaylar. Tarayıcı size attestation yanıtını döner.

3. Sunucu doğrulaması: İstemciden dönen cevabı sunucuda kütüphane ile doğrulayın. Origin ve rpId eşleşmeli, challenge doğru olmalı. Başarılıysa şu verileri saklayın: credentialId (base64url), publicKey, signCount, transports (ör. "internal", "usb", "ble"), userId. attestation politikanıza göre sertifika zinciri doğrulamasını atlayabilir veya sıkı modda açabilirsiniz.

Giriş (Authentication) akışı

1. Sunucu challenge üretimi: Giriş sayfasında kullanıcı e-posta veya kullanıcı adını girince sunucu PublicKeyCredentialRequestOptions döner: challenge, rpId, allowCredentials (ilgili credentialId listesi) ve userVerification ("required" önerilir).

2. İstemci doğrulaması: navigator.credentials.get({ publicKey: options }) çağrılır. Tarayıcı kullanıcıdan biyometrik onay ister ve assertion döner.

3. Sunucu doğrulaması: İmza ve authenticatorData kontrol edilir; rpIdHash ve origin eşleşmeli. signCount daha büyükse güncellenir, geriye düşüyorsa potansiyel klon/hatalı cihaz işareti olarak reddedilir. Başarılıysa güvenli bir session veya token üretin.

Kullanıcı deneyimi: Conditional UI ve otomatik doldurma

Conditional UI (Chromium) ile kullanıcı adını sormadan doğrudan mediation: "conditional" parametresiyle passkey önerisini tarayıcıda tetikleyebilirsiniz. iOS ve Safari tarafında sistem otomatik doldurma panelindeki “Anahtarlar” akışı devreye girer. Parola yerine “Devam etmek için cihazınızı doğrulayın” gibi net, güven veren metinler kullanın ve OTP/eposta doğrulamayı sadece kurtarma senaryosu olarak bırakın.

Güvenlik ve en iyi uygulamalar

- HTTPS zorunlu; Secure, HttpOnly, SameSite cookie bayraklarını doğru ayarlayın. CSRF için same-site veya token stratejisi uygulayın.

- rpId alan adınızla birebir ilişkili olmalı. Üretimde app.example.com kullanıyorsanız origin tam olarak bu olmalı; ters proxy kullanıyorsanız X-Forwarded-Proto/Host başlıklarını doğru iletin.

- Discoverable credentials (resident keys) açıldığında kullanıcı adı girmeden giriş mümkün olur. Ancak veritabanında kullanıcı başına çoklu credential yönetimini kurgulayın.

- Cihaz kaybı ve kurtarma: Kullanıcının birden fazla passkey ekleyebilmesini sağlayın (telefon, laptop, güvenlik anahtarı). Eski credential’ları listeden kaldırma (revoke) imkanı verin.

- Hata yönetimi: Timeout, NotAllowedError, InvalidStateError gibi hataları kullanıcı dostu mesajlarla ele alın. Geri dönüş yolunda asla parola istemeyin; kurtarma akışını ayrı doğrulamalarla çalıştırın.

Test, uyumluluk ve dağıtım

Geliştirme sırasında Chrome DevTools’taki Virtual Authenticator Environment ile farklı platformları simüle edin. iOS 17+, Android 14+, Windows Hello ve macOS/iCloud Keychain ile pratik testler yapın. Google Password Manager ve iCloud senkronizasyon farklarını (cihazlar arası passkey paylaşımı) göz önünde bulundurun.

Üretime geçerken alan adı stratejinizi belirleyin: rpId olarak kök alan adını (example.com) seçip alt alanlarda tutarlılık sağlayın. CDN ve WAF arkasında origin doğru raporlanıyor mu kontrol edin. İzleme için kayıt/giriş başarı oranı, kullanıcı başına credential sayısı, hataya düşen challenge sayısı gibi metrikler tutun.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, hem güvenliği yükselten hem de kullanıcı deneyimini sadeleştiren bir yaklaşım. Doğru rpId/origin eşlemesi, sıkı challenge doğrulaması ve sağlam bir oturum yönetimiyle phishing’e dirençli bir kimlik doğrulama katmanı elde edersiniz. Üstelik conditional UI ve discoverable credentials sayesinde “parola” kavramını kullanıcıdan tamamen gizleyerek tek dokunuşla giriş deneyimi sunabilirsiniz. Küçük bir POC ile başlayıp, çoklu credential ve kurtarma senaryolarını da kapsayacak şekilde adım adım genellemek en pragmatik yol olacaktır.

12 Eylül 2025 Cuma

Next.js 14’te Server Actions ile Güvenli Form ve Dosya Yükleme: Adım Adım Rehber

Next.js 14 ile birlikte gelen Server Actions, form gönderimlerini sunucu tarafında güvenle işlemek ve istemci kodunu sadeleştirmek için güçlü bir seçenek sunar. Bu rehberde, e-posta alanı içeren basit bir formu ve güvenli dosya yükleme akışını, Zod ile doğrulama yaparak adım adım kuracağız. Hedefimiz, gereksiz API katmanları oluşturmadan, tek bir action ile temiz ve ölçeklenebilir bir çözüm elde etmek.

Server Actions yaklaşımı; XHR/fetch kodlarını azaltır, React Server Components ile uyumlu çalışır ve SSR/ISR stratejilerine zarar vermeden form iş akışlarını basitleştirir. Dosya işlemlerinde ise tür ve boyut kontrolüyle güvenlik yüzeyini daraltır. Vercel gibi platformlarda çalışırken /tmp gibi geçici dizinlerin kullanımı mümkündür; kalıcı depolama için S3 benzeri servisler önerilir.

Gereksinimler

- Node.js 18+ ve Next.js 14+

- Paket yöneticisi (pnpm, npm veya yarn)

- (İsteğe bağlı) Zod ile şema tabanlı doğrulama

Kurulum ve Hazırlık

Yeni bir proje başlatalım:

npx create-next-app@latest next14-server-actions
cd next14-server-actions
pnpm add zod

Server Actions Next.js 14’te varsayılan olarak desteklenir. Projenizde gerekirse aşağıdaki gibi bir yapılandırma ile istek boyutunu kontrol edebilirsiniz (opsiyonel):

// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverActions: {
      bodySizeLimit: '6mb' // FormData sınırı (opsiyonel)
    }
  }
};
export default nextConfig;

Server Action: Doğrulama ve Yükleme

Aşağıdaki action, e-postayı Zod ile doğrular, dosya türünü ve boyutunu kontrol eder, ardından dosyayı bir hedef dizine yazar. Geliştirme ve Vercel üzerinde test için varsayılan olarak /tmp kullanılabilir.

// app/actions.ts
'use server';

import { z } from 'zod';
import { writeFile } from 'fs/promises';
import path from 'path';
import crypto from 'crypto';

const schema = z.object({
  email: z.string().email()
});

// Node.js API'larına ihtiyacımız olduğundan runtime'ı Node olarak zorlayalım (opsiyonel).
export const runtime = 'nodejs';

export async function uploadFile(formData: FormData) {
  const email = String(formData.get('email') || '');
  const file = formData.get('file');

  const parsed = schema.safeParse({ email });
  if (!parsed.success) {
    return { ok: false, error: 'Geçersiz e-posta adresi.' };
  }

  if (!(file instanceof File)) {
    return { ok: false, error: 'Dosya bulunamadı.' };
  }

  const allowed = ['image/png', 'image/jpeg', 'application/pdf'];
  if (!allowed.includes(file.type)) {
    return { ok: false, error: 'İzin verilmeyen dosya türü.' };
  }

  const MAX = 5 * 1024 * 1024; // 5MB
  if (file.size > MAX) {
    return { ok: false, error: 'Dosya boyutu 5MB sınırını aşıyor.' };
  }

  const arrayBuffer = await file.arrayBuffer();
  const buffer = Buffer.from(arrayBuffer);

  const filename =
    crypto.randomBytes(8).toString('hex') + '-' + (file.name || 'upload');
  const destDir = process.env.UPLOAD_DIR || '/tmp';
  const destPath = path.join(destDir, filename);

  await writeFile(destPath, buffer);

  return { ok: true, path: destPath };
}

Form Bileşeni ve Kullanım

Formun action özelliğine doğrudan server action’ı vererek kolayca bağlayabiliriz. Bu sayede client tarafında ekstra fetch mantığına gerek kalmaz.

// app/page.tsx
import { uploadFile } from './actions';

export default function Page() {
  return (
    <main style={{ maxWidth: 560, margin: '40px auto', fontFamily: 'sans-serif' }}>
      <h1>Dosya Yükleme Formu</h1>
      <form action={uploadFile}>
        <label>E-posta</label>
        <input type="email" name="email" required placeholder="[email protected]" />

        <label style={{ display: 'block', marginTop: 12 }}>Dosya (PNG/JPEG/PDF)</label>
        <input type="file" name="file" accept="image/png,image/jpeg,application/pdf" required />

        <button type="submit" style={{ marginTop: 16 }}>Gönder</button>
      </form>
      <p style={{ fontSize: 12, color: '#666', marginTop: 12 }}>
        Not: Demo amaçlı yüklemeler geçici dizine kaydedilir.
      </p>
    </main>
  );
}

İsterseniz kullanıcı deneyimini iyileştirmek için Client bileşeninde submit durumunu gösterebilir, form sonucunu Server Action’dan dönen nesneye göre ekrana yazdırabilirsiniz. Daha gelişmiş bir deneyim için useFormStatus ve useFormState yardımcılarını değerlendirebilirsiniz.

Güvenlik ve En İyi Uygulamalar

- Dosya türlerini beyaz listeyle sınırlandırın (PNG, JPEG, PDF gibi). Gerekirse MIME kontrolüne ek olarak sihirli bayt (magic bytes) kontrolü uygulayın.

- Boyut limiti belirleyin ve Next.js yapılandırmasında body limiti ile eşleştirin.

- Kalıcı depolama için S3 veya benzeri bir objeler deposu kullanın; dosya adlarını çakışmaları önlemek için hashleyin.

- İşlem süresi ve ortam kısıtları için Node.js runtime tercih edin; kenar (Edge) iş yüklerinde dosya manipülasyonu yerine imzalı URL yaklaşımı kullanın.

Çalıştırma ve Dağıtım

Geliştirme ortamında başlatmak için:

pnpm dev

Vercel’e dağıtırken ek bir API katmanına ihtiyaç duymadan aynı kod çalışır. Yalnızca kalıcı depolama kullanacaksanız ilgili servis kimlik bilgilerini çevresel değişkenlerle (ör. S3_ACCESS_KEY, S3_BUCKET) eklemeyi unutmayın.

Sonuç olarak, Next.js 14’te Server Actions ile güvenli ve performanslı bir dosya yükleme akışını, sade bir mimariyle hayata geçirebilirsiniz. Zod tabanlı doğrulama, sınırlı dosya türleri ve boyut kontrolleri ile riskleri minimize ederken, kullanıcıya yalın bir deneyim sunarsınız.

11 Eylül 2025 Perşembe

Passkey (WebAuthn) ile Şifresiz Giriş: Node.js Üzerinden Adım Adım Kurulum ve İpuçları

Passkey (WebAuthn) nedir? Neden şimdi?

Passkey, FIDO2 ve WebAuthn standartlarını temel alan, phishing’e dayanıklı ve kullanıcı dostu bir şifresiz kimlik doğrulama yöntemidir. Tarayıcılar ve işletim sistemleri 2024 itibarıyla passkey’leri yerel olarak destekler hale geldi; 2025’te ise iCloud Anahtar Zinciri, Google Password Manager ve üçüncü parti yöneticiler ile çok cihazlı senkronizasyon yaygınlaştı. Sonuç: Kullanıcılar tek dokunuşla (parmak izi, Face ID, Windows Hello) giriş yapabiliyor, geliştiriciler ise veri ihlallerine açık parola depolama yükünden kurtuluyor.

SEO açısından bakarsak, “şifresiz giriş”, “WebAuthn”, “FIDO2” ve “passkey” gibi terimler özellikle güvenlik ve kullanıcı deneyimi odaklı aramalarda öne çıkıyor. Bu rehberde Node.js ile sıfırdan bir passkey akışını nasıl kurabileceğinizi, istemci ve sunucu tarafındaki kritik ayarları ve üretim ortamında karşılaşabileceğiniz hataları ele alacağım.

Temel mimari ve akış

Kayıt (Registration): Sunucu bir “challenge” üretir, istemci WebAuthn API üzerinden biyometrik/PIN ile bir anahtar çifti oluşturur ve attestation ile sunucuya döner. Sunucu bu veriyi doğrulayıp kullanıcının public key’ini kalıcı olarak kaydeder.

Giriş (Authentication): Sunucu yine bir challenge üretir, istemci kayıtlı credential’ı kullanarak imza (assertion) üretir ve döndürür. Sunucu imzayı public key ile doğrular; eşleşirse oturum açılır.

Hazırlık: Alan, HTTPS ve kütüphaneler

WebAuthn üretimde yalnızca HTTPS üzerinde çalışır (localhost hariç). Relying Party ID (rpId), tarayıcının algıladığı etkin alanla uyuşmalıdır. Örneğin site adresiniz “app.ornek.com” ise rpId “ornek.com” ya da “app.ornek.com” olabilir. Node.js tarafında @simplewebauthn/server veya fido2-lib gibi kütüphaneler doğrulama işini büyük ölçüde kolaylaştırır.

Node.js ile uçtan uca akış (özet)

1) Kayıt için challenge üretin: Kullanıcının henüz passkey’i yoksa sunucu tarafında bir kayıt endpoint’i (ör. /webauthn/registration/options) oluşturun. rp.name, rp.id, user.id (rastgele GUID), user.name ve authenticatorSelection (residentKey: “preferred” veya “required”, userVerification: “preferred”) gibi alanları belirleyin. Challenge’ı sunucu oturumunda saklayın.

2) İstemci tarafında create() çağırın: Tarayıcıda navigator.credentials.create({ publicKey: options }) ile kullanıcıdan biyometrik/PIN onayı alın. Dönüşte attestationObject ve clientDataJSON gelecektir. Bu verileri JSON olarak sunucuya gönderin.

3) Attestation doğrulaması: Sunucuda gelen attestation verisini kütüphaneyle doğrulayın. Başarılıysa credentialId, publicKey (COSE veya JWK), signCount ve AAGUID gibi alanları kullanıcıya bağlı olarak veritabanına kaydedin. Aynı kullanıcıya birden fazla credential tanımlanabilir.

4) Giriş için challenge üretin: /webauthn/authentication/options ile kayıtlı credentialId’leri referans alarak yeni bir challenge üretin. userVerification: “preferred” veya “required” ile MFA benzeri güvenlik seviyesi sağlayabilirsiniz.

5) İstemci tarafında get() çağırın: navigator.credentials.get({ publicKey: requestOptions }) ile kullanıcıdan onay alın. Dönüşte authenticatorData, signature ve clientDataJSON gelir; sunucuya gönderin.

6) Assertion doğrulaması ve oturum: İmza doğrulanırsa oturumu başlatın. JWT veya HttpOnly, Secure, SameSite=strict bir çerezle oturumu yönetin. Replay saldırılarını önlemek için challenge tek kullanımlık olmalı ve kısa süreli (örn. 60 sn) geçerli tutulmalıdır.

Veri modeli: Ne saklamalı?

- Kullanıcı: userId (UUID), email/username, oluşturulma tarihi.

- Credential: userId, credentialId (base64url), publicKey (COSE/JWK), signCount, transports (usb, nfc, ble, internal), aaguid, createdAt.

- Güvenlik: Her doğrulamada signCount karşılaştırması yaparak kopyalanmış authenticator tespitine yardımcı olun (bazı platformlarda sabit kalabilir; kütüphanenin notlarını okuyun).

Üretim ipuçları (Güvenlik ve UX)

- Tam HTTPS: Şifreli bağlantı zorunludur. HSTS etkinleştirilebilir.

- Origin ve rpId uyumu: Hata mesajlarının çoğu burada çıkar. Subdomain değişikliklerinde dikkatli olun.

- Discoverable credentials: Kullanıcı adı öncesi doğrudan passkey ile giriş için residentKey’i “required” yapabilirsiniz. Bu, “şifresiz ve kullanıcı adısız” akış sağlar.

- Conditional UI (Chrome/Safari): Giriş formunuzda kullanıcı adı alanı göstermeden passkey istemek için conditional UI kullanın; özellikle mobilde dönüşüm oranını artırır.

- Oturum yönetimi: HttpOnly + Secure çerez kullanın, SameSite=strict iyidir. Token tabanlı sistemlerde kısa ömürlü access token ve yenileyici mekanizma kurun.

- FallBack ve hesap kurtarma: Yedek kodlar, e-posta linki veya TOTP gibi alternatifleri dengeli biçimde sunun. Amaç passkey’e öncelik verip erişilebilirliği korumaktır.

- Attestation politikası: Çoğu tüketici uygulaması “none” kullanır. Kurumsal gereksinimlerde belirli üreticilere kısıtlama getirmek için attestation “direct” değerlendirilebilir.

- Rate limit ve anti-automation: Kayıt ve giriş uç noktalarınızı hız sınırlayın, bot koruması ekleyin.

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

“The relying party ID is not a registrable domain suffix...” rpId alan adınızla uyuşmuyor olabilir. Geliştirmede localhost kullanın; üretimde tam alan adıyla test edin.

“NotAllowedError” Kullanıcı işlemi iptal etmiş olabilir veya conditional UI tetiklenmemiştir. get()/create() çağrısını kullanıcı etkileşimi (click) bağlamında başlatın.

Attestation doğrulama başarısız Sertifika zinciri veya format hatası olabilir. @simplewebauthn gibi kütüphanelerin güncel sürümünü kullanın; ham binary verileri doğru base64url kodladığınızdan emin olun.

Safari farklılıkları iOS’ta üçüncü parti iframe içinde WebAuthn kısıtlı olabilir. Mümkünse üst alan üzerinde akışı çalıştırın.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, güvenliği artırırken kullanıcı deneyimini sadeleştirir. Node.js tarafında doğru rpId/origin ayarları, tek kullanımlık challenge’lar, güvenli oturum yönetimi ve iyi bir veri modeli ile üretim seviyesinde sağlam bir akış kurabilirsiniz. 2025 itibarıyla tarayıcı ve işletim sistemi desteği olgunlaştığı için, yeni projelerde parolayı varsayılan kabul etmek yerine passkey’i birincil kimlik doğrulama olarak düşünmek artık pratik ve rekabetçidir. Küçük başlayın, conditional UI ile sürtünmeyi azaltın ve kademeli geçiş stratejisiyle mevcut kullanıcı tabanınızı passkey’e taşıyın.

3.

10 Eylül 2025 Çarşamba

Passkey (FIDO2/WebAuthn) ile Parolasız Giriş: Adım Adım Kurulum ve En İyi Uygulamalar

Passkey nedir ve neden şimdi?

Şifreler tarihsel olarak en zayıf halkaydı: yeniden kullanım, kimlik avı, veri sızıntıları ve karmaşa. Passkey, FIDO2 ve WebAuthn standartlarını temel alarak parolayı tamamen devreden çıkarır. Kullanıcı, cihazındaki biyometrik sensör (Face ID, Touch ID, Windows Hello) veya donanımsal güvenlik anahtarıyla (YubiKey vb.) kimlik doğrular; site ise yalnızca herkese açık anahtarı saklar. Bu yaklaşım, kimlik avına dayanıklı, hızlı ve kullanıcı dostu bir deneyim sunar.

Mimari: Nasıl çalışır?

Passkey, tarayıcı ve işletim sistemi ile cihazdaki “Authenticator” (platform ya da harici) arasında köprü kuran WebAuthn API’sini kullanır. Sunucu tarafında “Relying Party” (RP) olarak adlandırılan uygulamanız, kullanıcıyı kaydederken ve oturum açarken kriptografik bir “challenge” üretir. Tarayıcı, navigator.credentials üzerinden bu challenge’ı imzalatır ve sonucu sunucuya gönderir. Sunucu, imzayı doğrular ve kullanıcıyı oturum açmış kabul eder. Bu süreçte parola yoktur; saklanan tek kalıcı bilgi, cihazın herkese açık anahtarı ve kimlikleyici meta verileridir.

Ön koşullar ve gereksinimler

- HTTPS zorunludur. Lokal geliştirme için localhost istisnadır, üretimde sertifikanızın düzgün kurulu olması gerekir.
- Modern tarayıcı desteği (Chrome, Edge, Safari, Firefox) yaygınlaşmıştır; mobil işletim sistemlerinde de yerleşik destek mevcuttur.
- Alan adı ve rpId uyumu: Örneğin uygulamanız auth.example.com’da ise RP ID’nizi example.com veya ilgili alt alan adıyla uyumlu ayarlayın.

Uygulama seçenekleri

1) Sıfırdan uygulama: Sunucu dilinize uygun bir WebAuthn kütüphanesi kullanın. Node.js için @simplewebauthn/server, Go için duo-labs/webauthn, Python için webauthn, Java için webauthn4j gibi olgun projeler mevcuttur. Bu kütüphaneler, challenge üretimi, attestation/assertion doğrulaması ve anahtar formatlarını sizin yerinize yönetir.

2) Kimlik sağlayıcıları: Auth0, Azure AD B2C, Okta, Firebase gibi servisler passkey desteğini hızla entegre etmenizi sağlar. Bu yol, güvenlik ve mevzuat tarafında işleri kolaylaştırırken, özelleştirme esnekliğini sınırlayabilir.

3) CMS ve hazır platformlar: Bazı modern CMS’ler ve e-ticaret eklentileri passkey desteği sunmaya başladı. Kod yazmadan aktivasyon yapmak mümkün olsa da RP ID, yedek yöntemler ve çok cihaz desteği gibi ayarları doğru yapılandırdığınızdan emin olun.

Adım adım temel kurulum

1) Kullanıcı modeli: Veritabanında kullanıcıya kalıcı bir benzersiz tanımlayıcı (user.id) atayın. E-posta/telefon gibi iletişim bilgilerini tutun; kurtarma senaryoları için gerekecektir.

2) Kayıt (registration) başlangıcı: /webauthn/register/options benzeri bir uç nokta üzerinden, kullanıcı için publicKeyCredentialCreationOptions oluşturun. Parametrelerde rpId, challenge (kısa ömürlü, tek kullanımlık), user bilgisi, algoritmalar (ES256 varsayılan), residentKey ve userVerification politikalarını belirleyin.

3) İstemci tarafı kayıt: Tarayıcıda navigator.credentials.create() çağrısı yapılır. Kullanıcı, biyometri veya güvenlik anahtarıyla onay verir. Dönen PublicKeyCredential nesnesini sunucuya gönderirsiniz.

4) Sunucu doğrulaması: Attestation verisini kontrol edin (origin, rpIdHash, challenge eşleşmesi, algoritmalar). Gerekirse attestation’ı “none” kabul ederek gizliliği artırın. Sonuçta credentialId, publicKey ve signCount değerlerini veritabanına kaydedin.

5) Giriş (authentication) başlangıcı: /webauthn/authenticate/options ile publicKeyCredentialRequestOptions üretin. İlgili kullanıcı için kayıtlı kimlikleyicileri gönderin ya da kullanıcı adı olmadan (discoverable credentials) giriş akışını destekleyin.

6) İstemci tarafı giriş: navigator.credentials.get() çağrısıyla imzalanmış assertion elde edilir ve sunucuya gönderilir.

7) Sunucu doğrulaması ve oturum: İmzayı publicKey ile doğrulayın, signCount artışını kontrol edin (geri sarma tespitleri için). Başarılıysa oturum oluşturun veya JWT üretin. Risk tabanlı ek doğrulamalar (cihaz parmak izi, IP, hız limiti) bu aşamada değerlendirilebilir.

UX ve güvenlik için en iyi uygulamalar

- Kullanıcıyı bilgilendirin: “Passkey, cihazınızda güvenle saklanır ve kimlik avına dayanıklıdır” gibi net açıklamalar ekleyin. İlk oturum açmada kısa bir tur (tooltip) deneyimi dönüşümü artırır.

- Çok cihaz desteği: Platform (telefon/laptop) ve harici (NFC/Bluetooth/USB) anahtarlarla kayıt izni verin. Böylece cihaz kaybında erişim riski azalır.

- Kurtarma stratejisi: En az bir yedek yöntem tanımlayın (destek bileti, güvenlik sorularından kaçının; e-posta veya TOTP daha güvenlidir). İş kritik ortamlarda yönetici onayı veya kimlik doğrulama akışıyla destekleyin.

- Gizlilik ve attestation: Çoğu tüketici uygulaması için attestation “none” politikası yeterlidir. Regülasyon gerektiren ortamlarda üretici sertifikalarını doğrulayan bir güven zinciri kullanın.

- RP ID ve alt alan adları: Oturum açma alan adınız ile uygulama alan adınız farklıysa, rpId ayarını yanlış yapılandırmak en yaygın hatalardandır. Tarayıcı hataları “rpId mismatch” olarak döner.

- Performans: Challenge süre sonunu kısa (örn. 60–120 sn) tutun, CDN önbelleğini bu uç noktalardan uzak tutun. Mobil tarayıcıların arka plan kısıtlarına dikkat edin.

Test ve sorun giderme

- Sanal kimlikleyici: Chrome DevTools > More tools > Virtual authenticator environment ile local test yapın; farklı alg, UV politikaları ve resident key senaryolarını simüle edin.

- Uçtan uca test: WebAuthn.io gibi topluluk araçlarıyla doğrulama akışınızı karşılaştırın. Farklı tarayıcı ve platformlarda (iOS, Android, Windows, macOS) gerçek cihaz testleri yapın.

- Yaygın hatalar: NotAllowedError (kullanıcı iptali veya zaman aşımı), InvalidStateError (mevcut credential ile tekrar kayıt), COSE algoritma uyumsuzluğu (ES256 önerilir) ve saat farkları (server/client saat uyuşmazlığı) sık karşılaşılır. Log’larda challenge-id eşleşmesini ve origin değerini mutlaka izleyin.

Sonuç

Passkey, hem güvenlik hem de kullanıcı deneyimi açısından parolaların doğal halefidir. Doğru RP ID yapılandırması, sağlam bir kurtarma stratejisi ve tarayıcılar arası test ile haftalar içinde üretime alınabilir. İster hazır bir kimlik sağlayıcısıyla hızlıca başlayın, ister kendi WebAuthn katmanınızı inşa edin; passkey, kimlik avına dayanıklı, hızlı ve modern bir giriş deneyimini standart hale getirir.

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.

8 Eylül 2025 Pazartesi

Dizüstünüzde Yerel Yapay Zeka: Ollama ile LLM Çalıştırma ve API Entegrasyonu (Güncel Rehber)

Giriş

Yerel olarak çalışan büyük dil modelleri (LLM), gizlilik, gecikme süresi ve maliyet açısından bulut tabanlı çözümlere güçlü bir alternatif sunuyor. Özellikle geliştiriciler, veri güvenliği kritik olan kurumlar ve offline çalışması gereken uygulamalar için yerel LLM’ler ciddi avantaj sağlıyor. Bu rehberde, açık kaynak odaklı Ollama ile Windows, macOS ve Linux üzerinde LLM çalıştırmayı, ilk model indirme ve etkileşim, API entegrasyonu ve performans ipuçlarını adım adım anlatıyorum.

Neden Yerel LLM?

Gizlilik ve kontrol: Veriniz makinenizden çıkmaz. Hassas dokümanlar, müşteri bilgileri veya fikri mülkiyet içerikleri buluta gönderilmeden işlenir.

Düşük gecikme: İnternet bağlantısı ve servis yoğunluğundan bağımsız, tutarlı yanıt süreleri elde edilir.

Maliyet: Deney, prototip ve düşük trafikli senaryolarda API maliyetleri olmadan ilerleme şansı sağlar.

Özelleştirme: Modeli ve çalışma parametrelerini dilediğiniz gibi ayarlayabilir, hatta kendi verilerinizle yerelde ince ayar (LoRA) yapabilirsiniz.

Önkoşullar ve Donanım Notları

- RAM: 8 GB minimum; 16 GB ve üzeri rahat bir deneyim sunar. Büyük bağlam pencereleri (context) için daha fazla RAM yararlıdır.

- GPU/VRAM: GPU hızlandırma şart değil, ancak 6–8 GB VRAM orta boy modellerde belirgin hız kazandırır. Apple Silicon (M1/M2/M3) cihazlarda Metal hızlandırma iyi sonuç verir.

- Disk: Modellerin boyutu kuantizasyona göre değişir. 4–10 GB arası tek bir model için tipik bir aralıktır; birden fazla model planlıyorsanız boş alanı buna göre düşünün.

Ollama Kurulumu

macOS: Homebrew kullanıyorsanız brew install ollama komutuyla kurulum yapabilirsiniz. Alternatif olarak resmi sitedeki yönergeleri izleyebilirsiniz.

Windows: Resmi yükleyiciyi indirip çalıştırın. Kurulumdan sonra Ollama hizmeti arka planda çalışmaya başlar.

Linux: Dağıtımınıza uygun olarak resmi kurulum komutunu kullanın. Tipik kurulum için: curl -fsSL https://ollama.com/install.sh | sh. Ardından servisi başlatın: ollama serve.

İlk Modeli Çalıştırma

Ollama, “komut ver, model çekilsin ve çalışsın” deneyimi sunar. Örneğin:

ollama run mistral

Komut, ilgili modeli indirir ve etkileşimli bir kabuk açar. Alternatif olarak bir başka popüler seçenek:

ollama run llama3

İlk mesajınızı yazıp Enter’a basmanız yeterli. Çıkmak için /bye kullanabilirsiniz.

Model Yönetimi ve Faydalı Komutlar

ollama list — İndirilen modelleri ve boyutlarını listeler.

ollama pull MODEL_ADI — Modeli önceden indirir (ör. ollama pull llama3).

ollama show MODEL_ADI — Parametreler ve etiketler hakkında bilgi verir.

ollama rm MODEL_ADI — İlgili modeli diskten kaldırır.

API ile Entegrasyon

Ollama yerelde bir HTTP API sunar. Varsayılan uç nokta: http://localhost:11434. Basit bir üretim (generate) çağrısı için:

curl http://localhost:11434/api/generate -d '{ "model": "mistral", "prompt": "Merhaba! Bugün hava nasıl?" }'

Streaming yanıt almak için istemcinizde chunk’ları işleyebilir veya HTTP/2 ile daha pürüzsüz bir akış sağlayabilirsiniz. Çoğu dilde basit bir fetch/requests ile entegrasyon dakikalar içinde tamamlanır. Parametreler (ör. temperature, top_p, num_ctx) aynı JSON içinde belirtilebilir.

Performans İpuçları

Kuantizasyon seçimi: Küçük disk izi ve hızlı ilk token için Q4 serisi (ör. q4_k_m) iyi bir başlangıçtır; kalite gerekirse Q5/Q6 düşünebilirsiniz. Ollama çoğu model için mantıklı bir varsayılan indirir.

Bağlam penceresi (num_ctx): Daha büyük bağlam, daha çok RAM/VRAM kullanır. İhtiyacınıza göre 4K–16K aralığında deneyin.

GPU kullanımı: Uygunsa GPU hızlandırmayı etkinleştirin. NVIDIA için sürücü/CUDA tarafı düzenli; Apple Silicon’da Metal otomatikleşmiştir. Çalışma anında performans farkını kolayca hissedersiniz.

İlk token süresi: Soğuk başlangıçta üst seviye modeller birkaç saniye geç yanıt verebilir. Sık kullanılan modelleri “sıcak” tutmak için servis açık kalsın.

Kaliteyi Artırma: İpuçları ve Prompt Tasarımı

Sistem talimatı: Yanıtı kısıtlamayan, görev odaklı net bir sistem mesajı üretim kalitesini yükseltir.

Yapılandırılmış çıktı: JSON şema, maddeler veya adım adım çözüm isteyin. Örneğin: “Lütfen JSON döndür: {title, summary, keywords}”.

Kısa bağlamlar: Gereksiz detayları azaltıp örnek odaklı içerik verin; yerel modellerde bağlam ekonomisi fark yaratır.

Güvenlik ve Kurumsal Kullanım

Yerelde çalışma, veri sızıntısı riskini doğal olarak azaltır. Yine de uygulama düzeyinde giriş/çıkış filtreleri, PII maskeleme ve log politikasını konumlandırın. Paylaşılan iş istasyonlarında model dizinlerinin erişim izinlerini düzenlemek iyi bir fikirdir.

Sorun Giderme

Model indirme yavaş: Ayna (mirror) seçeneklerini kullanın ya da indirmeyi önceden planlayın. Ağ kesintilerinde indirme tekrar başlatılabilir.

Yüksek bellek kullanımı: Daha agresif kuantizasyon seçin, num_ctx değerini düşürün veya daha küçük bir model deneyin.

Yanıt kalitesi yetersiz: Talimatı netleştirin, örnek verin, gerekirse farklı bir model ailesi (mistral, llama, phi, qwen) deneyin.

Sonuç

Ollama, yerel LLM çalıştırmayı basit bir komutla mümkün kılıyor. Geliştirici bilgisayarında hızlı prototip, kurum içinde gizli veriyle güvenli deneme veya offline asistan gibi senaryolarda verimli bir temel sunuyor. Kurulumu tamamlayıp ilk modeli koşturduktan sonra, API üzerinden uygulamanıza entegre etmek yalnızca birkaç satır kod. Doğru kuantizasyon ve bağlam ayarıyla, oldukça akıcı ve ekonomik bir yapay zeka deneyimi elde edebilirsiniz.