GPT-2 tabanlı, 3000 baytlık C ile yazılmış ChatGPT klonu (2023)
(nicholas.carlini.com)- Yalnızca yaklaşık 3000 baytlık C koduyla bir GPT-2 çıkarım motoru kuruluyor; ağırlık yüklemeden tokenleştirme, Transformer çalıştırma ve çıktıyı dönüştürmeye kadar tüm akış tek parçada ele alınıyor
- Küçük kod boyutu korunurken KV cache, hızlı matris çarpımı ve isteğe bağlı OMP paralelleştirmesiyle GPT-2 Small yanıtları modern makinelerde birkaç saniye içinde üretiliyor
- Çıktı kalitesi “nesnel olarak oldukça kötü” düzeyinde ve UTF-8 işleme ile büyük modelleri çalıştırırken gereken bellek miktarı gibi pratik kısıtlar sürüyor
- Uygulama; matris işlemleri, sinir ağı katmanları, Transformer, Byte Pair Encoding, G/Ç ve ağırlık/BPE yükleme olarak ayrılıyor ve küçük bir çıkarım motorunun bütün yapısını gösteriyor
- GPT-2, GPT-4'e kıyasla çok daha zayıf bir 2019 açık kaynak modeli olsa da, modern dil modellerini çalıştırmanın temel bileşenleri küçük bir C koduyla da ifade edilebiliyor
3000 baytlık C ile yapılmış GPT-2 çalıştırıcısı
- Bu program, bağımlılığı olmayan bir GPT-2 uygulaması ve orijinal TensorFlow dosyalarından ağırlık matrislerini ve BPE dosyasını okuyor
- Girdi, basit bir Byte Pair Encoding (BPE) kodlayıcısıyla tokenleştiriliyor; çıktı ise BPE çözücüsüyle tekrar metne dönüştürülüyor
- İç yapı; temel bir lineer cebir paketi, matris işlemleri, Transformer mimarisi ve çıkarım kodu olarak ilerliyor
- Kod GitHub'da açık olarak paylaşılıyor
- GPT-2 Small, modern bir makinede tek bir yanıtı birkaç saniyede üretiyor
- KV cache uygulanıyor
- Verimli matris çarpımı kullanılıyor
- İsteğe bağlı olarak OMP paralelleştirmesi açılabiliyor
Çalışma koşulları ve sınırlamalar
- Bu uygulamayla ChatGPT benzeri etkileşimli bir program yapmak mümkün, ancak çıktı kalitesi iyi değil
- UTF-8 karakter işleme konusunda bazı tuhaflıklar var
- XL boyutlu modeli uzun bağlam uzunluğuyla çalıştırmak yaklaşık 100 GB RAM gerektirebilir
- ASCII girdi ve GPT-2 Small birleşimiyle neredeyse her yerde çalıştırılabiliyor
GPT-2 ve Transformer'ın çalışma biçimi
- ChatGPT, insan gibi konuşabilen bir uygulama olarak tanımlanıyor; GPT-4 ise ChatGPT'yi çalıştıran güncel model olarak sunuluyor
- Bu C programı, 2019 modeli GPT-2 ile ChatGPT'ye benzer bir davranış üretiyor
- GPT-2, Transformer ailesinden bir makine öğrenimi modeli
- Transformer, sabit boyutlu bir kelime dizisini girdi olarak alıp sonraki kelimeyi tahmin ediyor
- Aynı süreç tekrarlandığında istenen uzunlukta dizi üretilebiliyor
Matris işlemleri ve makro tabanlı sıkıştırma
- Sinir ağları matris işlemlerinden oluştuğu için uygulama, en az düzeyde bir Matrix yapısı ile başlıyor
float* datint rows, cols
- Gerekli işlemler temelde iki türe ayrılıyor
- Matris-sabit işlemleri
- Matris-matris işlemleri
- C makrolarıyla tekrar eden döngü yapıları azaltılıyor ve yalnızca belirli operatörleri değiştirerek birden çok fonksiyon üretiliyor
- C'deki
#define, basit değiştirmeye yakın çalıştığı için yalnızca normal operatörler değil, noktalı virgül içeren ifadeler bile makro argümanı olarak verilip kod boyutu küçültülebiliyor
Hızlı matris çarpımı
- Temel matris çarpımı, üç iç içe döngü kullanan basit O(n³) uygulamayla başlıyor
- Cache ve bellek erişim özellikleri dikkate alınarak, aynı belleğin tekrar tekrar okunup yazılacağı şekilde döngüler değiştiriliyor
- Hızlı uygulama
jvekdeğerlerini 4'er artırıyor ve içeridek2,j2döngülerini kullanıyor - Çıkarım aşamasında daha önce hesaplanmış sonuçların bir kısmını yeniden kullanmak için, matris A'nın yalnızca bir kısmının B ile çarpıldığı bir yöntem ekleniyor
Sinir ağı katmanlarının uygulanması
- Transformer kurmak için birkaç sinir ağı katmanı doğrudan uygulanıyor
- GELU etkinleştirme fonksiyonu makroyla uygulanıyor
- causal attention için matrisin alt üçgen kısmını işleyen bir fonksiyon bulunuyor
- Attention matrisi, gelecekteki token'lara bakmadan yalnızca geçmişi görecek şekilde sınırlandırılıyor
- LayerNorm, her katmandaki ortalama ve varyansı normalize ediyor
- Linear fonksiyonu, matris çarpımından sonra bias'ı döşeme yöntemiyle ekliyor
Transformer gövdesi
- Transformer uygulaması her katmanda şu akışı tekrar ediyor
- LayerNorm ve Linear üzerinden geçerek query, key, value değerlerini tek seferde hesaplıyor
- qkv, head bazında ayrılıyor
- query ile key çarpımı hesaplanıyor ve causal attention uygulanıyor
- softmax sonucu value matrisiyle çarpılıyor
- Sonuçlar birleştirilip residual connection uygulanıyor
- GELU ve Linear'dan geçtikten sonra yeniden residual connection uygulanıyor
- Sonunda son LayerNorm uygulanıyor, ardından son token konumunun çıktısı embedding ağırlıklarıyla çarpılarak sonraki token adayları hesaplanıyor
KV cache yöntemi
- Transformer çıkarımında bir token üretildikten sonra bir sonrakini üretmek için tüm fonksiyonun yeniden hesaplanması gerekmiyor
- N'inci token'a kadar hesaplanan sonuçların büyük kısmı yeniden kullanılırsa, N+1'inci token üretimi için yalnızca ek birkaç işlem gerekiyor
- Uygulama, tüm bellek tahsislerini aynı bellek bloğu içinde sıralı olarak yapıyor
- Her matris çarpımının her zaman aynı belleği kullanması sağlanıyor; böylece sonraki yinelemede belleği 0'a sıfırlamak yerine önceki sonuçlar korunuyor
- Yeni yinelemede yalnızca N+1'inci satır hesaplanıyor
Byte Pair Encoding uygulaması
- Dil modelleri sabit boyutlu girdi gerektirdiğinden, sonsuz sayıdaki kelimeyi doğrudan kelime düzeyinde işlemek zor
- Karakter düzeyindeki modeller, her kelimenin anlamını en baştan öğrenmek zorunda kalıyor ve etkili bağlam boyutunu ortalama kelime uzunluğu kadar azaltıyor
- GPT-2 gibi modeller, kelimeleri parçalara ayıran BPE kullanıyor
- Sık kullanılan kelimeler tek bir token olabilir
- Nadir kelimeler daha küçük parçalara bölünür
- Örneğin
nicholas,nich,o,lasolarak ayrılabilir
- Tipik BPE algoritması, bitişik token çiftlerini tekrar tekrar birleştirir
- Bu C uygulaması, kod boyutunu küçültmek için lineer zamanlı algoritma yerine potansiyel olarak üstel zaman alabilen özyinelemeli bir yaklaşım kullanıyor
- Mevcut kelimenin prefix'i ile eşleşen vocabulary öğeleri aranıyor
- Kalan metin özyinelemeli olarak tokenleştiriliyor
- Uzunluk ve vocabulary indeksi temelinde en iyi tokenleştirme seçiliyor
Ağırlık yükleme
- Sinir ağı ağırlıkları diskten okunmalı; dosya biçimi 32 bit float'ların düz bir ikili serileştirme biçimi
- GPT-2 model boyutlarının hepsi aynı mimariyi kullanıyor ve ağırlıklar da aynı sırayla saklanıyor; bu yüzden doğru şekle sahip matrisleri sırayla okumak yeterli
- Katmanların kaydedilme sırası beklenenden farklı
- Katman 0 ve 1'den sonra 10 geliyor
- Çünkü adlar lexicographic order ile sıralanıyor
- Metin sıralamasında
10,2'den önce geliyor
- Uygulama, bu sırayı gerçek katman sırasına çevirmek için permutation kodu kullanıyor
BPE vocabulary yükleme
- BPE'yi çalıştırmak için önce vocabulary dosyasının diskten okunması gerekiyor
- Orijinal dosya, Python'da okunmak üzere tasarlanmış bir biçimde ve küçük bir C koduyla ayrıştırılması kolay değil
- Dosya, bir kelime listesi değil BPE birleştirme listesi
- Örneğin
Hellotoken'ı doğrudan saklanmak yerineHileello'nun birleştirilmesi gerektiği biçimde tutuluyor
- Örneğin
- Dosya, UTF-8'e benzer ama tam olarak aynı olmayan bir kodlama kullanıyor
- Yazdırılabilir ASCII karakterleri olduğu gibi saklanıyor
- 0-31 aralığındaki yazdırılamayan karakterler
188 + karakter değeriolarak kodlanıyor - Örneğin boşluk,
Ġtoken'ı olarak kodlanıyor
- Diskteki
Ġ, UTF-8'de0xc4 0xa0olduğundan, bunu yeniden boşluğa çevirmek için ayrı işlem gerekiyor
Küçük kodun gösterdiği şey
- Onlarca yıllık makine öğrenimi gelişimi birkaç bin baytlık koda sıkıştırılabiliyor
- Gerçek model ağırlıkları hariç tutulduğunda, modern sinir ağlarını çalıştırmak için gereken unsurların neredeyse hiçbiri eksik kalmıyor
- Bu uygulama esas olarak eğlence için yapılmış olsa da, sinir ağlarının gerçekte basit bileşenlerle çalıştırılabildiğini gösteren bir örnek
1 yorum
Hacker News yorumları
Kodu bizzat çalıştırmadım ama küçük boyutlu olması etkileyici
İlk ELIZA programlarının daha büyük olduğunu düşününce, son 4 yılda bunun bayt düzeyinde bu kadar sıkıştırılabilir hale gelmiş olması dikkat çekici
Sihirin nerede saklı olduğunu bilen biri varsa açıklamasını isterdim. Bunun GELU fonksiyonu mu, yoksa Bash betiğiyle indirilen model mi olduğunu merak ediyorum
Who are you?sorusunaI am Alice.diye yanıt veriyor; bilgisayarı ya da işlevlerini sorunca daI am a computer model trained by OpenAI. How can I help you?cümlesini tekrarlıyorToplamayı açıklamasını isteyince çarpmayı anlatıyor,
2+2ya daSum 2+2içinse sadece aynısını tekrar ediyorGPT-2 ilk çıktığında onunla uğraştığımı hatırlıyorum
Bir arkadaşımla sohbet kayıtlarını dışa aktarıp GPT-2'yi ince ayar yaparak ikimizin konuşmalarını taklit ettirmiştik; hem çok komikti hem de bazen ürkütücü derecede isabetliydi
GPT-2'den GPT-3'e geçişteki sıçramanın nedenini merak ediyorum. Daha büyük model mi, daha fazla veri mi, yoksa ikisi birden mi bilmiyorum
RLHF'nin büyük fark yarattığını biliyorum ama temel GPT-3 modeli de yeterince örnek verildiğinde yalnızca metin tamamlama ile epey kullanışlıydı
Çok bilgim yok ama GPT-2'nin yazdığı sevdiğim masallar var
https://deepdreams.stavros.io/episodes/the-princess-the-fair...
Bunun bu sayfadaki GPT-2 ile yapılıp yapılmadığını merak ediyorum
“Çoğunlukla eğlence için yapılmış olsa da, sinir ağlarının aslında ne kadar basit olduğunu göstermeye yarayan iyi bir örnek” kısmı hoşuma gitti
Şşşt, kimseye söylemeyelim. Yapay zeka para kazanmak için kullanılan kara büyü
GPT-2 komut ayarlı olduğu için mi bunu gerçekten sohbet için kullanabiliyoruz?
Değilse buna ChatGPT klonu demek bana biraz zorlama geliyor
Pratikte kullanılamaz ve ismi çağrıştırması dışında pek alakası yok. Yine de derlenip çalışan bir program
Bunu yapan kişinin de düzgün çalışmadığını kabul ettiği bir projenin performansını öven tepkilere bakınca, asıl meselenin moda sözcükle ilgi çekmek olduğu anlaşılıyor
“Düzgün makroları olan dillere bakın. Lisp her zaman C'den üstün değildir!” cümlesi bu kez kabul edilebilir. Sonuçta yukarıya doğru bir şaka
Kod bağlantısını görmediyseniz metnin içine gömülü: https://github.com/carlini/c-chat-gpt-2
Bundan daha iyi klasik yapay zeka sohbet botları gördüm
https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/areas...
Splotch biraz düzeltmeyle modern Unix türevlerinde de rahatça derleniyor
Bunu yerelde çalıştırıp bu GPT-2'nin nasıl çıktılar verdiğini gören biri var mı diye merak ediyorum
Yine de oldukça ilginç ve içine bakıp kurcalamak isterdim. Bir süredir yerelde GPT-2 ile uğraşmak istiyordum
Kodda sıcaklığı ve seed'i bizzat teyit edemedim; daha çok neden obfuscation yapıldığını anlamaya çalışıyordum
Obfuscation kaldırıldığında kodun aşırı uzamayacağını tahmin ediyorum; kabaca 10 bin karakter civarında olsa bile yalnızca ekranda görmek bile yeterince etkileyici olurdu
Bugünlerde gptscript ile kendi ChatGPT'nizi çok hızlı biçimde kurabilirsiniz
https://github.com/gptscript-ai/gptscript
GELU gerçekten büyü gibi:
UNARY(GELU, b / 2 * (1 + tanh(.7978845 * (b + .044715 * b * b * b))))Tanım
GELU(x) := x * Φ(x)şeklinde ve burada Φ(x), Gauss dağılımının kümülatif dağılım fonksiyonu