Büyük dil modellerinin temel mimarisini anlamak
Bunu anlamak neden önemli?
Bir modele 50 sayfalık bir doküman veriyorsun, saniyeler içinde kıdemli bir analist seviyesinde kusursuz bir analiz alıyorsun. Ray Kurzweil'in The Singularity is Nearer kitabında vurguladığı o net gerçekle tam da burada yüzleşiyoruz. İnsanın biyolojik donanımı, veriyi bu ölçekte ve hızda işlemek için artık fazlasıyla yetersiz. Kendi sınırlarımızın bu kadar rahat aşıldığını gördüğümüzde, karşımızda okuduğunu anlayan bilinçli bir süper zeka olduğunu düşünüyoruz.
Ama burada asıl devrimci olan şey zeka değil, mimari. 2017'de yayınlanan bir makale, dil modellerinin metni nasıl işlediğini kökten değiştirdi. Ondan önceki modeller cümleyi kelime kelime, sırayla okuyordu, tıpkı bizim gibi. Transformer mimarisi bu sıralı okumayı terk etti, cümledeki her kelimeye aynı anda bakmayı ve aralarındaki ilişkiyi paralel şekilde hesaplamayı mümkün kıldı. Bu tek fark, hem çok daha büyük veriyle eğitilebilmenin hem de bugün gördüğümüz hızın kapısını açtı.
Evet, kaputun altında insan bilişini taklit eden muazzam bir soyut mimari var. Ama burayı devasa bir matematik fabrikası gibi düşünmek gerekiyor. O soyut mimari fabrikanın üretim bandı, en temeldeki silikon çipler ise bu banda güç veren motorlar. Bu dev makinenin içinde bir niyet, farkındalık veya metni gerçekten anlama durumu yok. Gördüğümüz o zeka parıltıları makinenin düşünmesinden değil, üretim bandındaki işlem gücünün bir sonraki adımı en yüksek olasılıkla hesaplamasından kaynaklanıyor.
Eğer bu teknolojinin üzerine bir vizyon, bir ürün veya yeni bir altyapı inşa ediyorsan, illüzyonun bittiği ve matematiğin başladığı o sınıra inmen mecburi. Çünkü bugün gördüğün her uygulama katmanı, bu mimarinin üzerine kuruluyor.
Sürekli yenisi çıkan bu modellerin ortak bir noktası var
Yapay zeka yarışı dışarıdan bakıldığında baş döndürücü bir kaos gibi görünüyor. Teknoloji devlerinin kapalı ekosistemlerinden, liderlik tablolarını her hafta altüst eden açık kaynaklı modellere (Llama, DeepSeek, Mistral) kadar, sanki birbirinden bağımsız yüzlerce farklı zeka inşa ediliyormuş gibi bir izlenim var.
Ama işin merkezine indiğinizde durum hiç de öyle değil. İsimleri, logoları ve fiyat etiketlerini bir kenara bırakın, hepsinin altında aynı temel yapı çalışıyor.
Aralarındaki farklar, farklı bir felsefeden gelmiyor. Eğitim verisinin kalitesi, metni parçalama biçimi, ince ayar sırasında yapılan tercihler gibi, mühendislerin aldığı somut kararlardan doğuyor. Bu detayları bir kenara koyduğunuzda, hepsinin kalbinde aynı mimari var: Transformer.
Ve bu mimarinin yaptığı şey, göründüğü kadar karmaşık değil. Model, elindeki metne bakıp kendine tek bir soru soruyor: buradan sonra en olası gelecek şey ne? Bu aslında yeni bir soru değil, dil modellerinin en eski hallerinden (basit istatistiksel tahmin yöntemlerinden) beri sorulan bir soru. Değişen şey sorunun kendisi değil, bu soruyu artık ne ölçekte ve ne kadar zengin bir bağlamla sorabildiğimiz.
Peki bu soru, model içinde tam olarak nasıl soruluyor? Bunu görmek için artık mimarinin içine girmemiz gerekiyor.
İllüzyonu inşa eden birkaç aşamalı üretim bandı
Dışarıdan bakıldığında hiper ölçekli ve aşılmaz görünen bu sistem, içeride beklediğinden çok daha düzenli bir yapıya sahip. Modeli tek parça ve gizemli bir zihin gibi düşünmek yerine, bir üretim bandı (pipeline) gibi hayal edebilirsin. Girdi (metin, görsel, ses) bir uçtan giriyor, birkaç temel aşamadan geçiyor ve sonunda çıktı olarak diğer uçtan çıkıyor. Biz bu süreci dört ana bölümde inceleyeceğiz.
Bu bandın üzerindeki işlem hacmi muazzam olsa da mimarinin kendisi şaşırtıcı derecede yalın. Modelin içinde olup bitenler temelde hep aynı tür işlemlerden ibaret: Matrisi çarp, topla, normalize et ve tekrarla.
Bu akışın temel mantığı şu basit pseudocode'a sığacak kadar net:
prompt = "CEO'nun yarınki yönetim kurulu sunumu için, üç aylık büyüme rakamlarını savunan ama olası zayıf noktaları da önceden yanıtlayan bir konuşma notu yaz"
tokens = tokenizer(prompt);while (true) { embeddings = embed(tokens); for ([attention, feedforward] of transformers) { embeddings = attention(embeddings); embeddings = feedforward(embeddings); } output_token = output(embeddings);
if (output_token === END_TOKEN) { break; // Decode'a hiç uğramadan döngüden çıkılıyor }
tokens.push(output_token); print(decode(output_token)); // Sadece normal token'lar decode edilip anında akıtılıyor}Hatta bazı açık kaynaklı modellerin çalışan örnekleri birkaç yüz satır Python koduyla ayağa kaldırılabiliyor. Sebastian Raschka gibi araştırmacıların PyTorch kullanarak bu mimarileri sıfırdan kurduğu sade örnekler de bunun en güzel kanıtı.
Ancak mimarinin bu kadar sade olması seni yanıltmasın. Aksine, bu kadar yalın olması, altında yatan kaba kuvvetin (brute force) korkunç boyutlarda olması demek. Modelin attığı en ufak bir adım bile, aslında milyarlarca sayının aynı anda birbiriyle çarpışması demek.
Şimdi bu üretim sürecini baştan sona anlatalım.
Tokenizer
Modele verdiğin metin, sisteme doğrudan kelimeler halinde girmez, çünkü makineler sadece sayılarla konuşuyor. Ancak tokenizer'ı basit bir metin çevirmeni olarak görmemek lazım. API faturalarından ürünün tepki süresine (latency) kadar pek çok performans göstergesini doğrudan etkileyen kritik bir bileşen.
Sistemin metni kelime veya harf yerine alt-kelime (subword) mantığıyla parçalamasının arkasında saf bir verimlilik hesabı var. Tokenizer, kelime kadar anlamlı ama harf kadar esnek olan o altın ortayı buluyor. "Kitapçılık" gibi bir terimi tek parça değil, mantıklı alt birimlere ayırarak hem sözlüğü şişirmiyor hem de esnekliğini koruyor.
Bu konu o kadar derin ve kritik ki, yapay zekâ dünyasının efsane isimlerinden Andrej Karpathy'nin sadece sıfırdan bir tokenizer inşa etmek üzerine saatler süren meşhur bir videosu var.
Tokenizer de kendi eğitim verisinin izlerini taşıyan bir sistem
Tokenizer'ı, arka planda rastgele veya her dile eşit davranan tarafsız bir algoritma sanmak yanlış olur. O da tıpkı bağlandığı dil modeli gibi kendi eğitim verisi üzerinde optimize edilmiş, ayrı bir sistem. Hangi kelimelerin tek token'a hangi kelimelerin birden fazla token'a bölüneceği, eğitim verisinde o kelimenin ne sıklıkla geçtiğine bağlı.
Tam bu yüzden, İngilizce ağırlıklı eğitilmiş bir tokenizer "the" kelimesini tek bir token (maliyet) olarak sayarken, spesifik bir Türkçe terimi veya kodu üç farklı token'a bölebiliyor.
Bugün açık kaynak dünyasında ibrenin Alibaba'nın Qwen'i veya DeepSeek gibi Çin merkezli modellere kaymasının nedenlerinden biri tam olarak bu. Batılı modeller genellikle sözlüklerini (vocabulary) dar tutarken, Qwen hem İngilizce hem de Çince tokenlara sahip devasa bir sözlük kullanıyor.
Bu geniş sözlük, modelin çok dilli ve kod ağırlıklı bir veri karışımıyla eğitilmesinden geliyor. Sonuç olarak Qwen, Çince kadar Türkçeyi, diğer Avrupa dillerini ve kodu da rakiplerine göre daha az parçaya bölüyor, bu da işlem maliyetini doğrudan düşürüyor. Yani bazı Çin merkezli modellerin belirli görevlerde daha ucuza çalışması sadece mimari bir farktan değil, tokenizer'ın hangi verilerle büyüdüğünden kaynaklanıyor.
Tokenizer daha önce hiç görmediği bir kelimeyle karşılaştığında onu sözlüğüne yeni bir giriş olarak eklemez, halihazırda bildiği parçalardan en mantıklı şekilde böler. Tıpkı bilmediği bir dildeki uzun kelimeyi hecelemeye çalışan birinin yaptığı gibi.
Sen bir prompt girdiğinde, ilk faturanın kesildiği o üç aşamalı operasyon şöyle işliyor:
- Parçalama: Metni bildiği en verimli alt parçalara (sub-tokens) ayırıyor.
- Eşleme: Her parçayı o devasa sözlüğündeki doğru konuma haritalıyor.
- ID Üretimi: Matris çarpımlarına girecek olan o benzersiz Token ID'lerini üretiyor.
Kendi token faturanı test edebilirsin: OpenAI’ın online tokenizer aracı ile İngilizce bir prompt ile Türkçe bir prompt arasındaki token yoğunluğu farkını saniyeler içinde görebilirsin. Aynı uzunluktaki iki metnin neden farklı maliyetler çıkardığını görmek için harika bir sağlama.
Embeddings
Tokenizer'dan çıkan ID'ler model için hâlâ kuru birer rakamdan ibaret. Bu numaralar arasında hiçbir matematiksel ilişki yok. 47 numaralı token'ın 48'e yakın olması, aralarında anlamca bir yakınlık olduğu anlamına gelmiyor, numaralandırma tamamen keyfi. Bu yüzden bu sayılarla kelimelerin benzerliğini veya aralarındaki mantıksal bağı ölçemezsin. Anlamın inşa edilebilmesi için bu numaraların kıyaslanabilir, matematiksel bir zemine oturması şart. Embeddings katmanı da tam olarak bu dönüşümü üstleniyor.
Süreç aslında basit. Modelin içinde, her token ID için bir satır ayrılmış devasa bir tablo var (embedding table). Token ID, bu tabloda kendi satırına gidiyor ve o satırdaki sayı listesini (vektörü) alıyor. Artık kelime tek bir sayı değil, bu sayı listesinden oluşan çok boyutlu bir vektör.
Nedir bu vektör dersen, onu devasa bir uzaydaki harita koordinatı gibi düşünebilirsin. Sadece 3 boyutlu bir dünyada olsaydık bir kelimenin koordinatı [10, 4, 2] gibi bir dizi olurdu. Ancak güncel modellerde bu uzay üç beş boyutla değil, binlerce farklı eksenle ifade ediliyor. Kelimeler bu uçsuz bucaksız uzayda anlamlarına, tonlarına ve bağlamlarına göre birbirlerine yaklaşıyor veya öbekler halinde kümeleniyor.
Sayıların koordinata dönüştüğü yer
Görseldeki tablodaki her bir satır, Tokenizer'dan çıkan bir ID'nin model içindeki o devasa tablodan çektiği karşılığı gösteriyor. Her bir sütun ise o kelimenin karakterini belirleyen farklı bir boyutu (ekseni) temsil ediyor.
Henüz statik bir haritadayız
Bu noktada token'lar ilk kez birbiriyle kıyaslanabilir hale geliyor. Ancak atlanmaması gereken ince bir detay var. Ortada henüz gerçek bir anlam yok. Sadece o anlamın üzerine inşa edileceği matematiksel zemin hazırlandı.
Buradaki kilit nokta şu: Embedding'ler cümleye değil, token'a özeldir. "Banka" token'ı sözlükten her zaman aynı ID'yi taşır ve o ID her zaman aynı koordinatı çeker. Bu koordinat, token'ın hangi bağlamda kullanıldığını henüz umursamaz. Parktaki banka oturdum cümlesindeki "banka" token'ı ile maaşın yattığı banka cümlesindeki "banka" token'ı, aynı ID'ye sahip oldukları için bu aşamada birbirinden ayırt edilemez. Model ikisine de aynı sayı dizisini çağırır.
Özetle Embeddings katmanının tek yaptığı şey, token'ları devasa ama statik bir haritaya yerleştirmektir. Model bu aşamada o koca bağlamı çözecek şu kritik soruların cevabını hâlâ bilmiyor:
- Bu cümlede asıl ağırlığı hangi kelime taşıyor?
- Şu an metnin tam olarak neresine odaklanmalıyım?
- Yanındaki kelime, bu kelimenin anlamını (vektörünü) nasıl değiştiriyor?
İşte tam bu noktada asıl motor, yani Transformer mimarisi devreye giriyor. Bu statik ve ruhsuz koordinatları alıp o meşhur Attention (Dikkat) mekanizmasıyla birbiriyle etkileşime sokarak bağlamı inşa eden yer burası.
Transformer
Embeddings aşamasında kelimeleri sayılara çevirip çok boyutlu bir haritadaki koordinatlarına yerleştirdik. Artık her token’ın bir adresi var ama bu adres tek başına bir anlam ifade etmiyor. Transformer katmanının görevi tam olarak burada başlıyor. Bu statik ve ruhsuz vektörleri alıp cümledeki diğer token’larla çarpıştırarak onları bağlama göre yeniden şekillendiriyor. Yapay zekanın o meşhur anlamlandırma illüzyonu ilk kez burada filizleniyor.
Statik vektörlerden dinamik bağlama
Embedding aşamasında her kelime cümleden bağımsız olarak uzayda tek bir noktaya sabitlenmişti. Az önce bahsettiğimiz örneği düşün:
- Parktaki eski bir banka oturup dinlendi.
- Banka şubesine giderek yeni hesap açtı
Banka kelimesi aynı olsa da taşıdığı anlamlar tamamen farklı. Transformer'ın yaptığı şey, bu farkı görünür kılmak. Statik embedding’leri alır, cümledeki diğer kelimelerle etkileşime sokar ve her token’ı o anki bağlama göre haritada yepyeni bir konuma taşır. Artık her kelime sadece sözlükteki köküyle değil, etrafındaki diğer kelimelerle kurduğu ilişki üzerinden temsil edilir.
Bu dönüşüm birkaç farklı matematiksel adımdan geçse de sistemin kalbinde tek bir altın kural yatıyor: Her kelime eşit derecede önemli değil. İşte tam bu noktada, modelin hangi kelimeye ne kadar odaklanacağını hesaplayan ve o devasa işlem gücünü asıl tüketen Attention (Dikkat) mekanizması devreye giriyor.
Attention: Hangi token, ne kadar önemli?
(Ön kabul: Attention aslında iki farklı iş için kullanılıyor, biri modelin eldeki metni (senin yazdığın prompt'u) anlaması, diğeri bir sonraki kelimeyi tahmin etmesi. Burada anlama tarafını izleyeceğiz, tahmin tarafına yazının Output bölümünde geleceğiz.)
Attention mekanizmasının yaptığı iş aslında gündelik. Bir cümleyi anlarken hangi kelimelere ne kadar dikkat etmemiz gerektiğini biz de sürekli tartıyoruz, model de aynısını yapıyor.
Parayı bankaya yatırdım cümlesinde "yatırdım" token'ı kendi anlamını netleştirmek için, ondan önceki token'lara bakıyor, ama her birine eşit önem vermiyor:
- %48 → bankaya: Eylemin nereye yapıldığını belirlediği için aslan payı burada
- %34 → parayı: Neyin yatırıldığını söylediği için ikinci kritik odak noktası.
- %18 → geçmiş bağlam: Zaman, gramer ve akış sinyalleri gibi yardımcı unsurlar.
Bu harmanlama "yatırdım" token'ının kendi vektöründe gerçekleşiyor. Bankaya ve parayı kelimelerinin anlamı bu vektörün içine karışıyor, sonuçta ortaya çıkan "yatırdım" artık tek başına duran belirsiz bir eylem değil, neyin nereye yatırıldığını da taşıyan, netleşmiş bir vektör.
Attention bunu nasıl yapıyor? (Q, K, V mantığı)
Az önce bahsettiğimiz o %48, %34 gibi dikkat oranları modelin içinde kendiliğinden oluşmuyor. Arka planda tamamen matris çarpımlarına dayanan, her kelimenin ihtiyacı olan bağlamı öncekilerden çektiği bir hesaplama var.
Şimdi bu süreci basitleştirilmiş bir örnek üzerinden adım adım görelim. Prompt'umuz yine aynı olsun: Parayı bankaya yatırdım.
- Token'lar (Tokenizer bu cümleyi dört parçaya böldü): [Parayı], [bankaya], [yatır], [dım]
- Embedding'ler (Ham, attention'a girmemiş hali): Görselleştirmeyi kolaylaştırmak için 3 boyutlu bir uzayda olduğumuzu hayal edelim. Her boyutun kabaca bir özelliği temsil ettiğini düşünebiliriz, mesela biri kelimenin duygusal tonunu, biri resmiyet derecesini, biri de hangi konu alanına ait olduğunu (gerçekte model binlerce boyut kullanıyor ve bu boyutlar bizim gibi isimlendirilebilir değil, çok daha soyut, ama mekanizmayı kavramak için bu basitleştirme yeterli)
Embeddings (4 × 3)
Token 1: Parayı → Embedding 1:[ 0.2 , -0.1 , 0.7 ]
Token 2: bankaya → Embedding 2:[ 0.9 , 0.3 , -0.2 ]
Token 3: yatır → Embedding 3:[ 0.4 , 0.8 , 0.1 ]
Token 4: dım → Embedding 4:[ -0.3, 0.2 , 0.6 ]Bu 4 satır ve 3 sütundan oluşan tablo, bu cümle için elimizdeki ham madde. Her token'ın kendi statik koordinatı belli ama henüz yanındakinden haberi yok. Tam bu noktada Attention devreye giriyor ve her token'ın vektörünü üç farklı matematiksel dönüşümden geçiriyor. Bu üç dönüşüme Query (Sorgu), Key (Anahtar) ve Value (Değer) diyoruz.
Query, Key ve Value şöyle çalışıyor:
- Query (Ne arıyorum?): Yatırdım token'ı, kendi anlamını netleştirmek için öncekilerden ne almalı? "Bana nereye veya neyin yatırıldığını söyleyen bir token lazım" der. Bu onun arama motoruna yazdığı sorgu.
- Key (Ben kimim?): Bankaya token'ı dışarıya hangi sinyali veriyor? "Ben bir mekanım ve finansal bağlam taşıyorum" der. Bu da onun sistemdeki kimlik kartı.
- Value (Özüm ne?): Bankaya token'ı, eğer Query onu bulursa, karşı tarafa gerçekte ne aktaracak? "Beni seçersen sana taşıyacağım anlam bu" der. Q ve K sadece eşleşmeyi sağlıyor, asıl aktarılan içerik bu.
Q ve K karar verir, V aktarılır
Bir sonraki aşamada, prompt'taki token'ların birbirine ne kadar alakalı olduğunu skorluyoruz
Q ve K matrislerini hesapladıktan sonra yapacağımız ilk iş, bu iki matrisi matematiksel olarak çarpmak ().
Dikkat edersen formülde K'nın üzerinde bir "T" (Transpoz) harfi var. Transpoz, bir tablonun satırlarını sütun haline getirmek, yani matrisi yan yatırmak demekti. Peki bu matematiksel taklayı neden atıyoruz ve çıkan sonuca neden "skor" diyoruz?
Matris çarpım kuralı gereği, birinci tablonun satırları, ikinci tablonun sütunlarıyla çarpılır. Amaç, Q matrisindeki her bir token'ın sorgusunu (satırını), K matrisindeki diğer tüm token'ların kimlikleriyle (satırlarıyla) teker teker kıyaslamak. K matrisini yan yatırdığımızda, her bir kelimenin arayışını (Q), sistemdeki tüm anahtarlarla (K) tek bir hamlede, paralel ve süper hızlı bir şekilde tarayabilir hale geliriz.
Peki bu eşleşmeyi neden doğrudan başlangıçtaki kelime vektörlerini çarparak yapmıyoruz?
Vektör matematiğinde iki sayı listesini birbiriyle çarptığınızda (dot product) elde ettiğin sonuca skor denir. Bu skor, o iki vektörün uzayda ne kadar aynı yöne baktığını, yani birbiriyle ne kadar hizalandığını (alakalı olduğunu) gösterir. Doğrudan kelimelerin kendisini (embedding'leri) çarpmadık, çünkü dil sözlük anlamıyla çalışmaz. Yatırdım kelimesi ile bankaya kelimesi sözlükte birbirine hiç benzeme. Doğrudan çarparsan, skorları çok düşük çıkar.
Ancak sistemin kurduğu bu arama motoru mantığında:
- Q (Sorgu): Yatırdım kelimesinin bağlam arayışını (finansal bir mekan aramasını) temsil eder.
- K (Anahtar - Transpoz edilmiş): Bankaya kelimesinin sunduğu kimliği temsil eder.
Bu çarpım işlemi (), bir token'ın talebi ile diğerinin arzı arasındaki matematiksel kesişimi bulur. Çarpım sonucunda ortaya bir Scores (Skorlar) tablosu çıkar. Bu tablo, "hangi token diğerinin bağlam boşluğunu ne kadar iyi dolduruyor" sorusuna verilen net bir alaka (relevance) puanı.
Modelin, henüz yazılmamış tokenlardan kopya çekmesini engellemek için bir çeşit maskeleme (masking) uyguluyoruz
Skor tablosunu oluşturduk ve token'ların birbirleriyle olan alakasını hesapladık. Ancak şu anki tabloda ciddi bir mimari problem var, her token sağındaki ve solundaki tüm token'lara serbestçe bakabiliyor.
Şu soruyu sorabilirsin: model sağındaki (gelecekteki) kelimelere bakarsa ne olur, kopya çekmesinin sisteme ne zararı var?
Bu, sistemin çalışıp çalışmayacağını belirleyen en kritik mimari noktadır. Çünkü bu modellerin tek bir varoluş amacı var, sadece geçmişe bakarak bir sonraki token'ı tahmin etmek.
Eğitim aşamasında modele trilyonlarca tamamlanmış cümle veriliyor. Eğer model bankaya token'ını işlerken sağa bakıp sıradakinin yatırdım olduğunu görebilirse, iki token arasındaki bağlamı öğrenmesine gerek kalmaz, doğrudan cevabı kopyalar. Tıpkı sınavda cevap anahtarını gören bir öğrencinin matematiği asla öğrenmemesi gibi, %100 başarı gösterir ama hiçbir şey anlamaz.
İşin asıl sorunlu kısmı, model canlıya alındığında (ürün olarak kullanıma açıldığında) ortaya çıkar. Sen ekrana "Parayı bankaya..." yazdığında, ortada modelin kopya çekebileceği bir gelecek yok. Gelecek henüz yazılmamış. Eğer model eğitimde sıradaki kelimeyi bulmak için sürekli sağ tarafa bakmaya alışmışsa, canlı kullanımda o geleceği bulamadığı an sistem tamamen çuvallar, tek bir mantıklı cümle kuramaz.
İşte bu yüzden sisteme bir zaman disiplini dayatıyoruz, o da Maskeleme (Masking). Skor tablosunda, henüz üretilmemiş token'lara denk gelen hücreleri eksi sonsuz () değeriyle doldurarak o kısmı tamamen karartıyoruz. Bu maske sayesinde model, sıradaki adımı tahmin edebilmek için mecbur kalıp kelimelerin birbirleriyle olan gerçek ilişkilerini (Q ve K eşleşmelerini) öğrenmeye zorlanıyor.
Maskeleme hesaplamasını göster
Maskelemeden sonra, bir çeşit filtreleme ile ham skorları temiz yüzdelere dönüştürüyoruz
Maskeleme bittikten sonra elimizde hâlâ eksi sonsuzlarla ve ham sayılarla dolu, birbiriyle kıyaslanması zor bir tablo var. İşte tam burada devreye makine öğrenmesinin en bilinen süzgeçlerinden biri olan Softmax giriyor.
Softmax işlemi, bu dağınık sayıları alıp her satırın toplamını 1 (yani %100) yapacak şekilde, pürüzsüz olasılık ağırlıklarına dönüştürür. İşin en şık tarafı, maskeleme aşamasında geleceği gizlemek için koyduğumuz o eksi sonsuz () değerleri, Softmax filtresinden geçince matematiksel olarak tam sıfıra (0) dönüşür.
Ortaya çıkan bu nihai tabloya Attention Ağırlık Matrisi (Weights) diyoruz. Bu matrise baktığında, herhangi bir token'ın kendisinden önceki token'lara yüzde kaç oranında odaklandığını net bir şekilde görebilirsin. Sıfır olan hücreler (maskelenmiş kısımlar), modelin o tarafa (henüz yazılmamış token'lara) fiilen hiç bakamadığının matematiksel garantisi.
Value (V) matrisi, dikkat edilen token'dan asıl aktarılacak içeriği çıkarıyor
Şu ana kadar Query (Q) ve Key (K) matrislerini çarparak sadece tek bir sorunun cevabını bulduk, hangi token'a yüzde kaç oranında dikkat etmeliyiz.
Ancak bu oranlar (yüzdeler) tek başlarına bir anlam ifade etmez. Modelin, dikkat etmeye karar verdiği o token'lardan asıl özü (anlamı) çekip alması gerekir. İşte burada sistemin üçüncü ve son filtresi olan Value (V) matrisi devreye giriyor.
Value (V) matrisini, o token'ın taşınabilir bilgi paketi (payload) olarak düşünebilirsin. Q ve K eşleşmesi bittiği için bu aşamada artık "ne arıyoruz?" sorusu devreden çıkar ve geriye sadece karşı tarafa aktarılacak saf içerik kalır. Daha önce olduğu gibi, burada da modelin eğitim sırasında öğrendiği bir matrisi kullanılır ve token'ların ham halleri transfer edilecek bilgi paketlerine dönüştürülür.
Value (V) matrisi hesaplamasını göster
Ağırlık yüzdeleri ile Value matrisini çarparak anlamı harmanlıyoruz
Artık son vuruşu yapma zamanı. Elimizde iki veri var, hangi token'dan ne kadar bilgi alacağımızı söyleyen Weights (yüzdeler) ve o token'ların taşıdığı saf bilgi olan Value (V). Yapacağımız son işlem, Softmax'ten çıkan o hassas yüzdeler ile V matrisini çarpmak (Weights × V). Bu işlem, her token'ın kendi yüzdesi kadar bilgi paketini alıp, mevcut token'ın üzerine eklemesini sağlar.
Bu işlemin sonucunda elimize geçen Output (Çıktı) vektörleri, artık Transformer'a ilk başta giren o ruhsuz ve birbirinden habersiz token'lar değil, kendinden önceki token'ların anlamlarıyla (dikkat oranlarına göre) yoğrulmuş, yepyeni ve dinamik Bağlamsal Vektörlerdir.
Ancak model hâlâ bir token üretmemiştir. Bu çıktılar, son durağımız olan Feedforward (İleri Besleme) ağına gönderilecek zenginleştirilmiş hammaddelerdir.
Attention token'lar arasında kimin kiminle ilgili olduğunu bulur, Feedforward o ilişkiden bir sonuç çıkarır (parayı + bankaya = finansal işlem)
Örneğin, Attention mekanizması "yatırdım" token'ının, kendinden önceki "parayı" ve "bankaya" ile güçlü bir bağı olduğunu tespit edip bu bilgiyi "yatırdım"ın vektörüne taşır. Feedforward katmanı ise bu parayı + bankaya kombinasyonunu alır ve modelin eğitim aşamasında oluşturduğu milyarlarca parametrelik bilgi havuzuna sokarak şu net sonucu çıkarır, "bu bir finansal işlemdir."
Attention her token'ın kendinden önceki token'larla ilişkisini kurarken, Feedforward ağı her bir token'ı kendi özelinde ele alır. Sistemin "bu iki kelime yan yana gelmiş, demek ki burada şu kavramdan bahsediliyor" diyerek o ilişkiden bir anlam (desen) ürettiği yer burasıdır.
Bu ağın kaputunun altında çalışan ReLU veya GELU adı verilen fonksiyonlar tam olarak bu desen eşleştirmesini yapar. Hatta birçok araştırmacı, modelin "Türkiye'nin başkenti Ankara'dır" gibi eğitim sırasında ezberlediği somut gerçeklerin doğrudan bu Feedforward katmanlarındaki milyarlarca parametrede (yapay zeka jargonuyla ağırlıklarda), devasa bir ansiklopedi gibi depolandığını kabul eder.
Özetle Feedforward katmanı yeni bir bağlam eklemez veya token'lar arasında baştan bir ilişki kurmaz. Tek görevi, Attention'ın kurduğu o ilişkiyi alıp modelin geçmişte öğrendiği bilgilerle harmanlayarak ortaya kavramsal bir sonuç çıkarmaktır. Bu yüzden modern LLM mimarilerinde bu ikili her zaman ayrılmaz bir paket (Transformer Bloğu) olarak çalışır.
Bu Attention ve Feedforward işlemleri, onlarca katman boyunca tekrarlanır
Bir Transformer bloğu (Attention ve Feedforward) görevini tamamladığında süreç sona ermez. Modern dil modelleri tek bir bloktan değil, üst üste dizilmiş onlarca, bazen yüzlerce katmandan oluşur. Transformer Explainer aracında gördüğün 11 more identical Transformer Blocks ifadesi tam olarak bu dikey mimariye işaret ediyor.
Bir bloktan çıkan işlenmiş veri, hemen bir üstteki bloğun girdisi olur ve yeniden Attention ile Feedforward işlemlerinden geçer. Veri bu katmanları tek tek aştıkça bağlam giderek daha karmaşık ve soyut bir yapıya dönüşür. Katman sayısı artsa da her token'ın görebildiği geçmiş aynı kalır, değişen şey o geçmişin ne kadar derinlemesine işlendiği.
En alt katmanlardaki bloklar genellikle basit dilbilgisi kurallarını ve yüzeysel kelime ilişkilerini (hangi sıfat hangi ismi niteliyor) çözer. Ancak veri üst katmanlara doğru tırmandıkça, "yatırdım" token'ının vektörü artık metnin genel tonunu, arka plandaki niyeti ve cümlenin asıl kurgusunu işlemeye başlar.
Kaputun altındaki o devasa zeka illüzyonu, aslında "yatırdım" token'ının "parayı" ve "bankaya" ile kurduğu bağın, onlarca katmandan geçerek gitgide netleşmesinden ibarettir. İlk katmanda sadece basit bir ilişki vardır. Son katmana geldiğinde ise aynı bağ, artık bunun tam olarak ne tür bir finansal işlem olduğunu, hangi tonda anlatıldığını kavramış olur. Girdiye dışarıdan hiçbir yeni bilgi eklenmiyor, aynı sayılar üzerinde işlem tekrar tekrar derinleşiyor.
Output
Onlarca katmandan süren o dikey yolculuk bittiğinde, elimizde "yatırdım" token'ına ait tek bir vektör var, ama bu vektör artık kendinden önceki her şeyi (parayı, bankaya) görmüş durumda. Ama bu hâlâ bir sayı dizisi. Modelin bize bir cevap verebilmesi için bu sayıları tekrar token'a çevirmesi gerekiyor.
Burada Linear Layer (Doğrusal Katman) devreye giriyor. Bu katman, elimizdeki o son vektörü alıp modelin sözlüğündeki (genellikle 50-100 bin token'lık) tüm adaylarla karşılaştırıyor. Sözlükteki her token için bir uygunluk puanı hesaplanıyor.
Örneğin Parayı bankaya bağlamında [yatırdım], [gönderdim] ve [havale] gibi token'lar yüksek puan alırken [elma] dibe vuruyor. Bu ham puanlar Softmax'tan geçip toplamı %100 eden olasılıklara dönüşüyor:
- [yatırdım] -> %88
- [gönderdim] -> %7
- [havale ettim] -> %4
Sistemin yaratıcılığı olasılıklar arasında zar atmasından gelir
Puanlar hesaplandıktan sonra sistemin işi sadece ekrana en yüksek olasılıklı token'ı basmak gibi görünebilir. Ama model her zaman %88'i seçmek zorunda değil.
Sürekli en yüksek olasılığı seçseydi metin robotik ve tekrarcı olurdu. Tam bu noktada Temperature (Sıcaklık) ve Sampling (örnekleme) devreye giriyor. Düşük sıcaklık modeli en garanti cevaba zorlarken, sıcaklığı artırmak %7'lik veya %4'lük alternatifleri de devreye sokuyor. Ekranda gördüğümüz o akıcı, insansı dil illüzyonu, aslında bu kontrollü zar atma mekanizmasından ibaret.
Autoregression
Peki sıradaki token seçildikten sonra ne oluyor? Cümle bitmiş değil, model bir sonrakini bulmak zorunda
Bu devasa mimari (milyarlarca parametre, onlarca katman) tek seferde bir paragraf üretmiyor. Görevi, sıradaki tek bir token'ı seçmek.
Diyelim model "yatırdım" token'ını seçti. Önce bir kontrol yapılıyor, bu bitiş sinyali mi? Değilse, token hemen decode edilip ekrana basılıyor ve kendi girdisinin sonuna ekleniyor: Parayı bankaya yatırdım...
Autoregressive (kendi çıktısını girdi olarak alan) döngü tam burada başlıyor. Güncellenmiş dizi yeniden Embeddings'ten geçip Attention ve Feedforward katmanlarında işleniyor, yeni bir olasılık dağılımı çıkıyor. Bitiş sinyali gelene kadar bu tekrarlanıyor, geldiğinde decode hiç çalışmadan döngü duruyor.
Ekranda kelime kelime akan o insansı cevap, aslında turdan tura tekrarlanan bu tahmin, decode ve geri besleme döngüsünün sonucu.