Transformers.js JavaScript Client-Side AI Hugging Face WebGPU Rehber

Tarayıcıda Çalışan Yapay Zeka: Transformers.js ile JavaScript Üzerinden Yerel Model Nasıl Çalıştırılır?

Orta
person Yapay Zeka Uzmanı
list_altİçindekilerexpand_more
  1. 01Transformers.js Nedir ve Nasıl Çalışır?
  2. 02Sıfırdan Uygulama: HTML ve JavaScript Yapısını Kurma
  3. 03Adım Adım Kodlama: İlk Modelimizi Yüklüyoruz
  4. 04Transformers.js’i Projeye Dahil Etmek
  5. 05Model Seçimi: Hafiflik Öncelikli
  6. 06Arayüz Entegrasyonu ve Canlı Test
  7. 07Uygulamayı Çalıştırmak
  8. 08Test Denemeleri
  9. 09Performans İpucu: WebGPU ile Donanım İvmesi
  10. 10WebGPU Desteğini Kontrol Etme
  11. 11Sıkça Sorulan Sorular (FAQ)
  12. 12Transformers.js tamamen ücretsiz mi?
  13. 13Büyük modeller tarayıcıyı dondurur mu?
  14. 14İnternet olmadan çalışır mı?
  15. 15Hangi dilleri destekliyor?
  16. 16Model verilerim Hugging Face’e gidiyor mu?
  17. 17Tam Proje Kodu
  18. 18Nereden Devam Edilir?

Her ay gelen OpenAI faturası, gecenin bir vakti çöken embedding servisi, rate limit aşımı hataları, bunlardan birini yaşadıysanız şu soruyu sormaya başlamışsınızdır: “Bu işi kendi tarafımda çözemez miyim?”

Cevap artık net: Evet, tarayıcının içinde.

Transformers.js, Hugging Face’in Python ekosistemindeki devasa model kütüphanesini sıfır backend, sıfır sunucu kurulumu ve sıfır API maliyetiyle doğrudan tarayıcıya taşıyan JavaScript kütüphanesidir. Kullanıcı butona tıkladığında, model onun kendi cihazında çalışır. Veri dışarıya çıkmaz, sunucu yoktur, fatura gelmez.

Bu rehberde sıfırdan bir duygu analizi (sentiment analysis) web uygulaması yapacaksınız. Tek bir .html dosyası ve birkaç satır JavaScript ile, kullanıcının yazdığı herhangi bir İngilizce metni gerçek zamanlı olarak Pozitif ya da Negatif olarak sınıflandıracak bir uygulama.

Sunucu tabanlı AI mimarisi ile Transformers.js client-side AI çalışma mantığının karşılaştırmalı şeması Solda: Her istek sunucuya, oradan buluta gidiyor. Sağda: Tüm döngü kullanıcının tarayıcısının içinde kapanıyor.


Transformers.js Nedir ve Nasıl Çalışır?

Hugging Face’in Python transformers kütüphanesi, 2026 itibarıyla yüz binlerce pre-trained modele ev sahipliği yapan dünyanın en büyük açık kaynak AI deposudur. Ancak bu modeller geleneksel olarak Python runtime gerektiriyordu; yani bir sunucu şarttı.

Transformers.js bu denklemi bozdu. Kütüphane iki katmanlı bir yaklaşım kullanır:

1. ONNX (Open Neural Network Exchange) Format: PyTorch veya TensorFlow’da eğitilmiş modeller, ONNX adlı evrensel bir ara formata dönüştürülür. ONNX dosyaları platform bağımsızdır; C++, Rust, Java veya —bizim ilgilendiğimiz— JavaScript runtime’larında çalışabilir.

2. ONNX Runtime Web: Microsoft’un geliştirdiği bu runtime, tarayıcıda WebAssembly (Wasm) veya WebGPU backend’i üzerinden ONNX modellerini yüksek performansla çalıştırır. Transformers.js bu runtime’ı kapot altında kullanır; siz sadece yüksek seviyeli API’yi görürsünüz.

Model İndirme Akışı:
Hugging Face Hub → ONNX dosyası (tarayıcı cache) → ONNX Runtime Web → Sonuç

Yapay zeka modellerinin web tarayıcısında çalışabilmesi, özellikle gizlilik gerektiren uygulamalar (sağlık, hukuk, finans) için çığır açıcı bir gelişmedir. Kullanıcı verileri hiçbir sunucuya gitmez.

Hangi görevleri destekliyor? Transformers.js’nin resmi dokümantasyonu 30’dan fazla task’ı listeliyor:

  • Sentiment analysis / text classification
  • Named entity recognition (NER)
  • Question answering
  • Text generation (GPT benzeri)
  • Image classification ve object detection
  • Speech recognition (Whisper)
  • Translation ve summarization

Sıfırdan Uygulama: HTML ve JavaScript Yapısını Kurma

Framework yok, bundler yok, npm install yok. Sadece bir metin editörü ve bir tarayıcı.

Proje klasörünüzü oluşturun ve içine index.html dosyasını açın:

<!DOCTYPE html>
<html lang="tr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Tarayıcı AI — Duygu Analizi</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: system-ui, sans-serif;
      background: #0f1117;
      color: #e2e8f0;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 2rem;
    }
    .card {
      width: 100%;
      max-width: 600px;
      background: #1a1d27;
      border: 1px solid #2d3148;
      border-radius: 16px;
      padding: 2rem;
    }
    h1 { font-size: 1.5rem; margin-bottom: 0.5rem; }
    p.sub { color: #94a3b8; font-size: 0.9rem; margin-bottom: 1.5rem; }
    textarea {
      width: 100%;
      background: #0f1117;
      border: 1px solid #2d3148;
      border-radius: 10px;
      color: #e2e8f0;
      font-size: 1rem;
      padding: 1rem;
      resize: vertical;
      min-height: 120px;
      outline: none;
    }
    textarea:focus { border-color: #6366f1; }
    button {
      margin-top: 1rem;
      width: 100%;
      padding: 0.85rem;
      background: #6366f1;
      color: #fff;
      border: none;
      border-radius: 10px;
      font-size: 1rem;
      font-weight: 600;
      cursor: pointer;
      transition: background 0.2s;
    }
    button:hover { background: #4f46e5; }
    button:disabled { background: #374151; cursor: not-allowed; }
    #result {
      margin-top: 1.25rem;
      padding: 1rem;
      border-radius: 10px;
      font-weight: 600;
      font-size: 1.1rem;
      text-align: center;
      display: none;
    }
    .positive { background: #052e16; color: #4ade80; border: 1px solid #166534; }
    .negative { background: #2d0a0a; color: #f87171; border: 1px solid #991b1b; }
    #status { margin-top: 1rem; font-size: 0.85rem; color: #64748b; text-align: center; }
  </style>
</head>
<body>
  <div class="card">
    <h1>🧠 Tarayıcı AI</h1>
    <p class="sub">Transformers.js ile tamamen client-side çalışan duygu analizi.</p>

    <textarea id="input" placeholder="Buraya bir İngilizce metin yazın..."></textarea>
    <button id="analyzeBtn" disabled>Model Yükleniyor...</button>

    <div id="result"></div>
    <div id="status">Model ilk kez indiriliyor, lütfen bekleyin...</div>
  </div>

  <!-- Transformers.js CDN — ESM module olarak import ediyoruz -->
  <script type="module" src="app.js"></script>
</body>
</html>

Aynı klasörde app.js dosyasını oluşturun ama içini şimdilik boş bırakın. Projeniz bu kadar sade.

Tarayıcı konsolunda Transformers.js başarıyla yüklenmiş log çıktısı Console sekmesinde hata yok, pipeline 2341ms’de hazır, tek satır HTML ve bir JS dosyasıyla bu kadar.


Adım Adım Kodlama: İlk Modelimizi Yüklüyoruz

Transformers.js’i Projeye Dahil Etmek

Kütüphaneyi CDN üzerinden import ediyoruz. app.js dosyanızı açın:

// Transformers.js'i Hugging Face CDN'inden ESM olarak çekiyoruz
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

// Model dosyaları tarayıcı cache'ine alındıktan sonra
// yerel bir proxy üzerinden okunmasını sağlar.
// false yaparak her zaman Hugging Face Hub'dan çekmesini sağlıyoruz.
env.allowLocalModels = false;

Model Seçimi: Hafiflik Öncelikli

Duygu analizi için Xenova/distilbert-base-uncased-finetuned-sst-2-english modelini kullanacağız. Bu model:

  • DistilBERT mimarisine dayanır (BERT’in %40 daha küçük, %97 performans koruyan damıtılmış versiyonu)
  • ONNX formatına dönüştürülmüş hali yaklaşık 67 MB’tır
  • SST-2 (Stanford Sentiment Treebank) veri setiyle ince ayarlanmıştır
  • İlk yüklemeden sonra tarayıcı cache’ine yazılır; ikinci ziyarette ağdan çekilmez

Büyük modeller tarayıcıda çalıştığında makine öğrenmesi hesaplamaları doğrudan CPU veya GPU üzerinde gerçekleşir. Bu nedenle model boyutu, kullanıcı deneyimi açısından en kritik parametredir.

// pipeline fonksiyonu: görev adı + model adı alarak hazır bir çıkarım
// fonksiyonu döndürür. Model ilk çağrıda indirilir.
let classifier = null;

async function loadModel() {
  const statusEl = document.getElementById('status');
  const btn = document.getElementById('analyzeBtn');

  try {
    statusEl.textContent = 'Model indiriliyor... (ilk açılışta ~60-70 MB)';

    classifier = await pipeline(
      'sentiment-analysis',
      'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
      {
        // İlerleme callback'i: indirme yüzdesini göstermek için
        progress_callback: (data) => {
          if (data.status === 'downloading') {
            const pct = Math.round((data.loaded / data.total) * 100);
            statusEl.textContent = `İndiriliyor: ${data.file} — %${pct}`;
          }
        }
      }
    );

    statusEl.textContent = '✅ Model hazır. Metin girin ve analiz edin.';
    btn.disabled = false;
    btn.textContent = 'Analiz Et';
  } catch (err) {
    statusEl.textContent = `Hata: ${err.message}`;
    console.error(err);
  }
}

// Sayfa yüklenince modeli hemen başlat
loadModel();

Chrome DevTools Network sekmesinde ONNX model dosyalarının tarayıcıya indirme süreci 68.2 MB’lık model dosyaları ilk açılışta bir kez indirilir; sonraki ziyaretlerde Network sekmesi temiz kalır, cache devreye girer.


Arayüz Entegrasyonu ve Canlı Test

Model yükleme kodu hazır. Şimdi butona tıklandığında kullanıcıdan aldığımız metni modele gönderecek ve sonucu ekranda göstereceğiz:

// Analiz fonksiyonu — asenkron çünkü ONNX çıkarımı Promise döndürür
async function analyzeText() {
  const input = document.getElementById('input').value.trim();
  const resultEl = document.getElementById('result');
  const btn = document.getElementById('analyzeBtn');
  const statusEl = document.getElementById('status');

  if (!input) {
    alert('Lütfen bir metin girin.');
    return;
  }

  if (!classifier) {
    alert('Model henüz yüklenmedi, bekleyin.');
    return;
  }

  // Analiz sırasında butonu devre dışı bırak
  btn.disabled = true;
  btn.textContent = 'Analiz ediliyor...';
  resultEl.style.display = 'none';

  try {
    // classifier bir dizi metin kabul eder; tek metin için dizi içinde gönderin
    const output = await classifier([input]);

    // output örneği:
    // [{ label: 'POSITIVE', score: 0.9998 }]
    const { label, score } = output[0];
    const percentage = (score * 100).toFixed(1);

    const isPositive = label === 'POSITIVE';

    resultEl.className = isPositive ? 'positive' : 'negative';
    resultEl.innerHTML = isPositive
      ? `😊 Pozitif — Güven: %${percentage}`
      : `😞 Negatif — Güven: %${percentage}`;
    resultEl.style.display = 'block';

    statusEl.textContent = `Çıkarım tamamlandı. Skoru: ${score.toFixed(4)}`;
  } catch (err) {
    resultEl.className = 'negative';
    resultEl.textContent = `Hata: ${err.message}`;
    resultEl.style.display = 'block';
  } finally {
    btn.disabled = false;
    btn.textContent = 'Analiz Et';
  }
}

// Butona event listener bağla
document.getElementById('analyzeBtn').addEventListener('click', analyzeText);

// Enter ile de gönderilebilsin (Shift+Enter yeni satır)
document.getElementById('input').addEventListener('keydown', (e) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    analyzeText();
  }
});

Uygulamayı Çalıştırmak

Dosyaları doğrudan tarayıcıda açamazsınız, ESM module’ler bir HTTP sunucusu gerektirir. Bunun için:

VS Code Live Server eklentisini kullanabilirsiniz. Ya da terminalden:

# Python 3 yüklüyse (çoğu bilgisayarda yüklüdür)
python3 -m http.server 8080

# Node.js kullanıyorsanız
npx serve .

http://localhost:8080 adresini açın. İlk yüklemede tarayıcının Network sekmesinde .onnx uzantılı dosyaların indirildiğini göreceksiniz. Sayfa yenilendikten sonra model cache’ten gelir, indirme olmaz.

Duygu analizi uygulaması canlı test — "Pozitif %99.8" sonucu localhost:8080’de çalışıyor, internet bağlantısı yok, sunucu yok. Model sonucu milisaniyeler içinde geliyor.

Test Denemeleri

Uygulamayı test etmek için bazı İngilizce cümleler:

✅ POSITIVE beklenen:
"This product is absolutely amazing, I love it!"
"The customer service was incredibly helpful and friendly."
"I had a fantastic experience at the restaurant today."

❌ NEGATIVE beklenen:
"This is the worst software I have ever used."
"I'm really disappointed, nothing works as expected."
"Complete waste of money, do not buy this."

Performans İpucu: WebGPU ile Donanım İvmesi

Varsayılan olarak Transformers.js, WebAssembly (Wasm) backend’ini kullanır. Bu CPU üzerinde çalışır ve 7B+ parametreli büyük modellerde yavaş kalabilir. 2026 itibarıyla Chrome 113+, Edge 113+ ve Safari 18+ WebGPU’yu destekliyor ve bu, GPU hesaplamalarını doğrudan tarayıcıdan erişilebilir kılıyor.

WebGPU backend’ini etkinleştirmek için pipeline çağrısına tek bir seçenek eklemek yeterli:

import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

// WebGPU kullanılabiliyorsa onu tercih et, yoksa Wasm'a düş
const device = navigator.gpu ? 'webgpu' : 'wasm';

classifier = await pipeline(
  'sentiment-analysis',
  'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
  { device }
);

console.log(`Çalışma backend'i: ${device}`);

Benchmark karşılaştırması (DistilBERT, tek cümle çıkarımı):

BackendCihazYaklaşık Süre
Wasm (CPU)M2 MacBook Pro~180 ms
WebGPUM2 MacBook Pro (MPS)~35 ms
Wasm (CPU)Intel i7-12700~220 ms
WebGPUNVIDIA RTX 3060~18 ms

Büyük modellerde (örneğin text generation için Phi-3 Mini) bu fark 10x veya daha fazlasına çıkabilir.

WebGPU Desteğini Kontrol Etme

Tarayıcınızın WebGPU destekleyip desteklemediğini konsoldan anlayabilirsiniz:

if (navigator.gpu) {
  const adapter = await navigator.gpu.requestAdapter();
  console.log('GPU Adaptörü:', adapter.info?.device || 'Bilgi yok');
} else {
  console.warn('WebGPU desteklenmiyor, Wasm kullanılacak.');
}

Chrome’da chrome://flags/#enable-webgpu-developer-features adresinden geliştirici modunu etkinleştirebilirsiniz.

Chrome flags sayfasında WebGPU etkinleştirme ve konsol çıktısı chrome://flags → WebGPU → Enabled. Altında konsoldan navigator.gpu çıktısı: GPUAdapter hazır, 12 özellik aktif.


Sıkça Sorulan Sorular (FAQ)

Transformers.js tamamen ücretsiz mi?

Evet. MIT lisansı altında dağıtılan açık kaynak bir kütüphanedir. Modeller Hugging Face Hub’dan ücretsiz indirilir; ticari projelerinizde de kullanabilirsiniz. Hiçbir API anahtarı veya hesap açma zorunluluğu yoktur.

Büyük modeller tarayıcıyı dondurur mu?

Model yükleme ve çıkarım işlemleri Web Worker ile ana thread’den izole edilmediği sürece UI donabilir. Bunu önlemek için Transformers.js’in resmi önerisi şudur:

// worker.js
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

self.onmessage = async ({ data }) => {
  const classifier = await pipeline('sentiment-analysis', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english');
  const result = await classifier(data.text);
  self.postMessage(result);
};

// main thread'de
const worker = new Worker('./worker.js', { type: 'module' });
worker.postMessage({ text: 'I love this!' });
worker.onmessage = ({ data }) => console.log(data);

Worker kullandığınızda model çalışırken butona tıklayabilir, metni düzenleyebilirsiniz, hiçbir donma yaşanmaz.

İnternet olmadan çalışır mı?

Evet, model bir kez Cache Storage’a (tarayıcının yerleşik önbelleği) alındıktan sonra, internet bağlantısı kesilse bile uygulama çalışmaya devam eder. Service Worker ile bunu kalıcı PWA davranışına dönüştürebilirsiniz:

// service-worker.js
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('transformers-cache-v1').then((cache) =>
      cache.addAll(['./', './app.js', './index.html'])
    )
  );
});

Hangi dilleri destekliyor?

Bu model İngilizce için eğitilmiştir. Türkçe duygu analizi için Xenova/bert-base-multilingual-uncased-sentiment modelini kullanabilirsiniz, bu model 104 dil için eğitilmiştir ve Transformers.js ile aynı şekilde çalışır.

Model verilerim Hugging Face’e gidiyor mu?

Hayır. Model dosyaları ilk indirmede Hugging Face CDN’inden çekilir, sonrasında tarayıcı cache’inde yaşar. Kullanıcının girdiği metinler hiçbir sunucuya gönderilmez; tüm çıkarım hesaplaması kullanıcının cihazında yapılır.


Tam Proje Kodu

İki dosyayı bir arada görmek isteyenler için:

<!-- index.html — tüm stil dahil tam versiyon -->
<!DOCTYPE html>
<html lang="tr">
<head>
  <meta charset="UTF-8" />
  <title>Tarayıcı AI</title>
  <!-- ... stil kodları yukarıdakiyle aynı ... -->
</head>
<body>
  <div class="card">
    <h1>🧠 Tarayıcı AI</h1>
    <p class="sub">Transformers.js — sıfır backend, sıfır maliyet.</p>
    <textarea id="input" placeholder="İngilizce metin girin..."></textarea>
    <button id="analyzeBtn" disabled>Model Yükleniyor...</button>
    <div id="result"></div>
    <div id="status">İlk açılışta model indiriliyor...</div>
  </div>
  <script type="module" src="app.js"></script>
</body>
</html>
// app.js — tam versiyon
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3/dist/transformers.min.js';

env.allowLocalModels = false;

let classifier = null;

async function loadModel() {
  const statusEl = document.getElementById('status');
  const btn = document.getElementById('analyzeBtn');

  try {
    classifier = await pipeline(
      'sentiment-analysis',
      'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
      {
        progress_callback: ({ status, file, loaded, total }) => {
          if (status === 'downloading') {
            const pct = Math.round((loaded / total) * 100);
            statusEl.textContent = `${file} indiriliyor — %${pct}`;
          }
        }
      }
    );
    statusEl.textContent = '✅ Model hazır.';
    btn.textContent = 'Analiz Et';
    btn.disabled = false;
  } catch (err) {
    statusEl.textContent = `Hata: ${err.message}`;
  }
}

async function analyzeText() {
  const text = document.getElementById('input').value.trim();
  const resultEl = document.getElementById('result');
  const btn = document.getElementById('analyzeBtn');

  if (!text || !classifier) return;

  btn.disabled = true;
  btn.textContent = 'Analiz ediliyor...';
  resultEl.style.display = 'none';

  const [{ label, score }] = await classifier([text]);
  const pct = (score * 100).toFixed(1);
  const isPos = label === 'POSITIVE';

  resultEl.className = isPos ? 'positive' : 'negative';
  resultEl.textContent = isPos ? `😊 Pozitif — %${pct}` : `😞 Negatif — %${pct}`;
  resultEl.style.display = 'block';
  btn.disabled = false;
  btn.textContent = 'Analiz Et';
}

document.getElementById('analyzeBtn').addEventListener('click', analyzeText);
document.getElementById('input').addEventListener('keydown', (e) => {
  if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); analyzeText(); }
});

loadModel();

Nereden Devam Edilir?

Buraya kadar geldiyseniz elinizde tam işlevsel, sunucu maliyeti sıfır, gizlilik dostu bir AI uygulaması var. Bundan sonraki adımlar tamamen ihtiyacınıza bağlı:

  • Çok dilli destek: Xenova/bert-base-multilingual-uncased-sentiment ile Türkçe dahil 104 dili destekleyin.
  • Farklı görevler: translation_en_to_fr, question-answering, summarization pipeline’larını deneyin, API değişmiyor.
  • Offline PWA: Service Worker ekleyerek uygulamanızı tam offline çalışır hale getirin.
  • React/Vue entegrasyonu: Transformers.js herhangi bir framework’te kullanılabilir; sadece Web Worker ile birleştirmeyi unutmayın.
  • Kendi modelinizi kullan: Hugging Face’te ONNX formatında yayımladığınız herhangi bir modeli aynı kodla çalıştırabilirsiniz.

Daha fazla teknik rehber, open-source araç analizi ve yapay zeka dünyasından pratik içerikler için yapayzekasozluk.tr/blog adresini takip edin.

auto_stories İlgili Makaleler