- GGUF, llama.cpp'nin kullandığı dil modeli dosya biçimi; çalıştırma için gereken meta verileri tek bir dosyada toplayarak model dağıtımını ve yüklemeyi basitleştiriyor
- Sohbet şablonları, konuşma biçimini, araç çağrılarını ve multimedya mesaj kodlamasını işleyen Jinja2 betikleridir; ancak uygulamaya göre davranış farklılıkları bulunur
- GGUF; bitiş token'ı gibi özel token'ları ve önerilen örnekleyici ayarlarını içerebilir; yakın zamanda örnekleyici zinciri sırası da belirtilebilir hâle geldi
- Araç çağrısı biçimleri hâlâ modelden modele değiştiği için, çıkarım motorlarında sabit kodlanmış mantık gerekiyor; dilbilgisi tabanlı ayrıştırıcı üretimi ise standart için iyileştirme adayı olarak duruyor
think_token, projeksiyon modeli paketleme ve özellik bayrakları eksik olduğu için düşünme bölümlerini ayırmak, multimodal yapılandırmaları kurmak ve desteklenen özellikleri algılamak hâlâ zor
GGUF neleri içerir
- GGUF, llama.cpp'nin dil modelleri için kullandığı dosya biçimidir
- GGUF'un temel avantajı, modeli çalıştırmak için gerekli çeşitli bileşenleri tek bir dosyada toplamasıdır
- Hugging Face'teki tipik bir safetensors deposunda gerekli JSON dosyaları farklı yerlere dağılmış durumdadır
- Tipik bir Ollama modeli, katman JSON'ları ve Go şablonları dahil OCI biçimindedir
- GGUF bu tür ek bilgileri tek bir dosyaya koyarak modeli kullanmayı kolaylaştırır
Sohbet şablonları
- Diyalog tabanlı dil modelleri, belirli bir biçimdeki token dizileriyle eğitilir ve bu biçim konuşma yapısı gibi görünür
- Gemma4 biçimi örneği şöyledir
<|turn>user
Hi there!<turn|>
<|turn>model
Hi there, how can I help you today?<turn|>
- LFM2 biçimi şablonu örneği şöyledir
<s>
<|im_start|>user Hi there!<|im_end|>
<|im_start|>assistant Hi there, how can I help you today?<|im_end|>
- Gerçek şablonlar; çıkarım blokları, araç açıklamaları, araç çağrıları ve yanıtları, ayrıca görüntü, ses ve video gibi multimedya mesajlarının kodlanmasını da içerdiğinden çok daha karmaşıktır
- Bu işlemi sohbet şablonları üstlenir; bunlar Jinja2 şablon diliyle yazılmış betiklerdir
- Bir modelin birden fazla sohbet şablonu olabilir
- Araç çağrısını destekleyen ve desteklemeyen şablonlar ayrı olabilir
- Çoğu model tek ve büyük bir sohbet şablonu sunar; yalnızca araçlar belirtildiğinde araç çağrısına ilişkin işlemleri devreye sokar
- Bazı modellerde araçlara özel sohbet şablonunu ayrıca bulmak gerekir
- Jinja2; döngüler, koşullar, atamalar, listeler ve sözlükler içeren, programlama diline oldukça yakın bir yapıdır
- Diyalog tabanlı LLM uygulamaları, her yeni mesaj eklendiğinde Gemma'nın sağladığı yaklaşık 250 satırlık Jinja betiği gibi bir programı çalıştıracak bir yorumlayıcı içermek zorundadır
- Uygulamalar arasındaki Jinja işleme biçimi de farklıdır
- Hugging Face transformers, Python'daki mevcut jinja2 kütüphanesini kullanır
- llama.cpp'nin
llama-server ve llama-cli araçları kendi Jinja uygulamasını kullanır
libllama API'sinde açığa çıkan llama_chat_apply_template, birkaç sohbet biçimini doğrudan C++ içine sabit kodlayan eski yaklaşımdır
- NobodyWho, Jinja'nın orijinal yaratıcısının Rust ile yeniden yazdığı minijinja'yı kullanır
- Bu, llama.cpp'nin bir dönem kullandığı minimal Jinja kütüphanesi minja ile aynı değildir
- Jinja uygulamaları arasında kayda değer performans farkları vardır
- Yerel LLM uygulamalarında sohbet şablonu işleme genelde performans darboğazı olmadığı için bu büyük bir tartışma konusu değildir
Özel token'lar
- Dil modeli, verilen token dizisi için bir sonraki token'ı üretmeyi sürdürdüğü için üretimi durdurmanın bir yoluna ihtiyaç vardır
- Yaygın çözüm, bir bitiş token'ı tanımlamak ve model bu token'ı ürettiğinde çıkarım motorunun üretimi durdurmasıdır
- Bitiş token'ı, özel token'ların bir örneğidir
- Özel token'lar genelde sıradan tokenlaştırılmış karakterlerin ötesinde anlam taşır
- Normalde kullanıcıya gösterilmemeleri gerekir, ama çoğunun bir metin gösterimi olduğu için teknik olarak görüntülenebilirler
- Gemma4'teki bazı özel token örnekleri şöyledir
1 / <eos>: dizinin sonunu belirtir; model üretimi durdurmak için bunu çıkarır
2 / <bos>: dizinin başlangıcını belirtir; girdinin başına eklenir
46 / <|tool_call>: araç çağrısının başlangıcını belirtir
47 / <tool_call|>: araç çağrısının sonunu belirtir
105 / <|turn>: konuşma turunun başlangıcını belirtir
106 / <turn|>: konuşma turunun sonunu belirtir
Örnekleyici ayarları ve sırası
- Dil modeli, bir sonraki token için bir olasılık dağılımı üretir ve bu dağılımdan token seçme işlemine örnekleme denir
- En basit yaklaşım, ağırlıklı dağılımdan rastgele seçim yapmaktır
- Pratikte, belirli token seçilmeden önce olasılık dağılımına dönüşümler uygulamak daha iyi sonuçlar verebilir
- Araştırma laboratuvarları yeni model yayımlarken çoğu zaman belirli önerilen örnekleyici ayarlarını da birlikte verir
- Kullanıcıların daha iyi yanıt almak için değerleri Markdown dosyalarından kopyalayıp yapıştırması sık görülür
- NobodyWho, kullanıcıların bunu elle yapma ihtiyacını azaltmak için Hugging Face sayfasında seçilmiş modeller yayımladı ve önerilen örnekleyici ayarlarını kendi biçiminde paketledi
- Bu işe yaradı, ancak modelin kullanışlı olabilmesi için NobodyWho tarafında dönüştürme gerekiyordu
- GGUF biçimine yakın zamanda eklenen özellik sayesinde örnekleyici zinciri artık doğrudan model dosyasında belirtilebiliyor
- Böylece NobodyWho'nun özel biçimi gereksiz hâle geldi; zaten istenen sonuç da buydu
- llm-sampling web uygulamasında farklı örnekleyici adımlarının rolü hızlıca görülebilir
- Tek tek adımlar sürükle-bırak ile yer değiştirildiğinde, örnekleme adımlarının sırasının nihai dağılım üzerinde büyük fark yarattığı görülebilir
- Ollama imajlarındaki JSON dosyaları ya da Hugging Face'teki
generation_config.json dahil birçok örnekleyici ayarı biçimi, örnekleme adımlarının sırasını belirtmenin bir yolunu sunmaz
- GGUF standardı,
general.sampling.sequence alanıyla örnekleme sırasını belirtebilir
- Yine de birçok GGUF modeli bu alanı atlar ve llama.cpp'nin varsayılan davranışı olan örtük sıraya güvenir
Hâlâ eksik olanlar
- İyi bir çıkarım motoru, farklı dil modelleri için birleşik bir arayüz sunmaya çalışır
- GGUF meta verisindeki ek bilgileri ayrıştırıp kullanmak, modele özel kod yollarının çoğunu azaltabilir
-
Araç çağrısı biçimi
- Neredeyse tüm çıkarım motorlarında, farklı araç çağrısı biçimlerini ayrıştırmak için sabit kodlanmış yollar bulunur
- Qwen3'ün araç çağrısı biçimi örneği şöyledir
<tool_call>{"name": "get_weather", "arguments": {"location": "Copenhagen"}}</tool_call>
- Qwen3.5'in araç çağrısı biçimi örneği şöyledir
<tool_call>
<function=get_weather>
<parameter=city>
Copenhagen
</parameter>
</function>
</tool_call>
- Gemma4'ün araç çağrısı biçimi örneği şöyledir
<|tool_call>call:get_weather{city:<|"|>Copenhagen<|"|>}<tool_call|>
- Yeni bir model çıktığında, çeşitli çıkarım motorlarının her biri kendi ayrıştırıcısını uygulamak zorunda kalıyor
- Model dosyasına bir dilbilgisi (grammar) eklenebilse ve bu dilbilgisinden bir ayrıştırıcı türetilebilse, bu GGUF standardına çok iyi bir ekleme olabilir
- NobodyWho, iletilen belirli araca göre kısıtlayıcı bir dilbilgisi üreten ek bir adım daha uygular
- Bu sayede araç çağrılarında tip güvenliği sağlanabilir
- Özellikle 1B ve altındaki küçük modellerin, tam sayı gereken yere float vermesi gibi hatalara karşı kullanışlıdır
- Genel amaçlı bir araç çağrısı ayrıştırıcısı üretmeye yarayan bir dilbilgisi olsa bile, NobodyWho'nun iletilen somut araçlara göre dilbilgisi üreten işlevi yine de uygulanmak zorunda kalacaktır
- Belirli araçlara uygun somut dilbilgileri üretip oradan ayrıştırıcı türetmeye yarayacak bir meta dilbilgisi biçimi, ilginç bir problem olarak duruyor
-
Think token'ı
- Eksik parçalar içinde eklenmesi en kolay olanı
- Yukarı akış Hugging Face deposu,
think_token alanını içermeye başladı
think_token, üretilen çıktının düşünme bölümünü ayırmak için son derece kullanışlıdır
- Düşünme bölümleri genellikle kaldırılmalı ya da ana çıktıdan farklı biçimde gösterilmelidir
- Aşağı akış GGUF dönüştürülmüş sürüm ise bu alanı çoğunlukla içermez
- Bunun sonucu olarak, GGUF tabanlı çıkarım motorları belirli model ailelerine özel kod yazmadan düşünme akışını ana çıktıdan ayıramaz
- Standart GGUF dönüştürme hattına
think_token eklenmesi bu sorunu çözer
-
Projeksiyon modeli
- Görüntü ve sesi metin olarak değil, LLM'in yerel olarak görebileceği biçimde işleyen multimodal LLM etkileşimleri için, metin dışı girdileri işleyecek ek bir modele ihtiyaç vardır
- Bu ek modele projeksiyon modeli denir
- Şu anki yaygın yöntem, iki GGUF dosyası vermektir
- Biri ana dil modeli için GGUF
- Diğeri görüntü ve ses işleme için daha küçük model
- Bu yaklaşım, GGUF'un tek dosya kolaylığını bozar
- Tek bir GGUF dosyasının, projeksiyon modelinin ağırlıklarını ve ayarlarını ana dosyanın içinde birlikte paketleyebilmesi büyük bir iyileştirme olur
- Projeksiyon modelleri çoğu zaman yaklaşık 1 GB boyutundadır
- Kullanılmadığında bu ek yükten kaçınmak isteyecek kadar büyüktürler
- Projeksiyon ağırlıkları içeren ve içermeyen iki GGUF varyantı sunmak makul görünüyor
- Böylece yine tek bir indirme URL'si ve diskte önbelleğe alınacak tek bir dosya yönetilen düzene dönülebilir
-
Desteklenen özellikler listesi
- Modeller arasında desteklenen özellikler farklıdır ve yalnızca GGUF dosyasına bakarak gerçekte hangi özelliklerin desteklendiğini anlamak zordur
- Bazı modeller görüntü girdisini desteklerken bazıları desteklemez
- Şu anda en iyi yaklaşım, projeksiyon modeli verildiyse görüntü desteği olduğunu varsaymaktır
- Bazı modeller yerel araç çağrısını desteklerken bazıları desteklemez
- Şu anda en iyi yaklaşım, sohbet şablonunda araç JSON şeması listesini render etmeye çalışan bir bölüm olup olmadığını dize eşleştirmesiyle kontrol etmektir
- Bu açıkça geçici bir çözümdür
- Bazı modeller düşünme blokları üretirken bazıları üretmez
- Düşünme etiketleri genellikle GGUF meta verisinde yer almadığından, modelden düşünme blokları beklenip beklenemeyeceğini anlamanın iyi bir yolu yoktur
- GGUF topluluğu model dosyasına özellik bayrakları eklerse, modele bağımlı olmayan çıkarım kütüphaneleri daha tutarlı hata mesajları ve uyarılar sunabilir
- Örneğin, yerel araç çağrısını desteklemeyen bir modelde araç çağrısı denenirse daha uygun yönlendirme yapılabilir
Sonuç
- GGUF, modeli doğru biçimde çalıştırmak için gerekli ek bilgileri tek bir dosyada toplayarak modele özel çok sayıda kod yolu ekleme ihtiyacını azaltır
- GGUF açık ve genişletilebilir bir biçimdir; ayrıca güçlü bir topluluğa sahiptir
- Standart birlikte güçlendirilirse, iyi bir geliştirici deneyimi korunurken uygulamalarda modelleri kolayca değiştirmek mümkün olabilir
- GGUF meta verisi zaten birçok açıdan yararlıdır, ancak araç çağrısı dilbilgisi,
think_token, projeksiyon modeli paketleme ve özellik bayrakları gibi alanlarda hâlâ geliştirme payı vardır
1 yorum
Hacker News görüşleri
Projeksiyon modelinin ayrı bir dosyaya bölünmüş olması üzücü; ben de tek dosya içinde yer almasını isterdim
Bunun neden böyle olduğunu tam bilmiyorum ama GGUF tasarlanırken akılda tutulan tek dosya felsefesiyle epey çelişiyor
Umarım birileri ikisini birleştirme işine öncülük eder; bu kez ben akışın fazla dışında kalmış gibiyim :-)
Bu karar hoşuma gidiyor. O halde Mmproj dosyasını da GGUF içine dahil etmeye açık olunabileceğini düşünmek de çok uçuk değil
Aklıma gelen tek sorun hangi formatın konulacağı. BF16, F16 vb. seçenekler var
GGML ve GGUF, açık kaynak makine öğrenimi/yapay zeka ekosistemi için çok önemli oldu
llama.cpp, whisper.cpp, stable-diffusion.cpp gibi projeler çeşitli platformlarda ve donanım arka uçlarında çoğunlukla doğrudan iyi çalışıyor
Derleyip modeli koyup çalıştırıyorsun. Sonra web UI ve API de elde ediyorsun
> <|turn>user Hi there!<|turn>model Hi there, how can I help you todayAman tanrım, XML'den bile daha az okunabilir bir format üretmişler
Bu format, gerçek içerikle karışmaması için tasarlandı ve o içerik internetteki herhangi bir metin olabilir
Bunun için de hiçbir yerde kullanılmayan bir format kullanmak gerekiyor
Şu anda en büyük eksik, model mimarisini mevcut derlemeye hardcode etmeden tanımlamanın bir yolu bence
Tam desteklenen modellerle bire bir performans eşdeğerliği olması gerekmiyor
Çıkışın ilk gününden itibaren üretici tarafından doğrulanmış düzgün desteğin bulunup bulunmaması, modelin harika mı yoksa berbat mı hissettirdiğini belirliyor. Son Gemma ve Qwen çıkışları bunun örneği
Çözümün ne olduğunu bilmiyorum ama model grafiğini tanımlayan bir DSL yazıp GGUF içine koymak mümkün olabilir
Bir başka seçenek de resmi model sürümündeki PyTorch modülünü okuyup bunu bir şekilde GGML işlemlerine dönüştürmek
İlk sürüme koymak istiyordum ama o sırada öncelik, minimum işlevli bir spesifikasyon çıkarıp uygulanmasını sağlamaktı
Hâlâ görmek istiyorum ama şu an GGML IR'ın durumunu çok iyi bilen birinin bunu sahiplenmesi gerekiyor
Sonra ortak parametreleri alan ortak bir arayüz sunulabilir, ek özel parametreler de Wayland'deki gibi uzantı olarak bırakılabilir
Böylece yalnızca LLaMa gibi transformer ailesi değil, RWKV gibi yinelemeli sinir ağı ailesi, multimodal modeller vb. de desteklenebilir
Uygulamada nasıl olur bilmiyorum ama kulağa harika bir fikir gibi geliyor. Yine de hesaplama grafiği model dosyasına gömülü olursa, ağırlıkları değiştirmeyi gerektirmeyen mimari iyileştirmelerin veya optimizasyonların mevcut dosyalara dönüştürme olmadan uygulanamayacağından endişe ediyorum
> GGUF'un gerçekten temiz tarafı tek bir dosya olması. Hugging Face'in tipik safetensors deposuyla karşılaştırınca, gerekli JSON dosyaları oraya buraya dağılmış durumda [...]İlginç şekilde benim için yapay zeka modelleri “her zaman” tek dosya oldu. Çünkü yerel görüntü üretimi tarafında standart buydu
safetensors dosyaları da kendi içinde her türlü şeyi barındırabiliyor; bunun için ille de GGUF gerekmiyor
Ama modern modellerin metin kodlayıcıları başlı başına birkaç GB'lık dil modelleri olduğundan, kimse her checkpoint'in içine bunların kopyasını koymuyor
Görüntü modellerinin çoğu tek dosyaydı ya da hâlâ öyle, ama LLM safetensors en azından o dönemde böyle değildi ve bunu yapısal düzeyde zorunlu kılmak istedim
Ayrıca çalıştırıcının, örneğin llama.cpp'nin, bir JSON okuyucuya ihtiyaç duymasını istemiyordum; ST yaklaşımı bunu gerektirecekti
Daha büyük sorun ise, doğru hatırlıyorsam o dönemde ST'nin GGML'nin yeni niceleme formatlarını destekleyememesi ve kendi dosya formatına sahip olmanın ST ile elde etmesi zor olan bir esneklik sağlamasıydı
Mimarinin ağırlıklarla gerçekten çalıştırılabilmesi için tek bir ağırlık dosyası değil, çeşitli kodlayıcılar ve kod çözücüler vb. de gerekiyor
Kullandığın araç bunu senden gizleyebilir ama görünen yüzeyin altında bunlar hâlâ var
libllama API'sinde dışa açılan ve birkaç sohbet formatını doğrudan C++ içine hardcode eden biraz tuhaf
llama_chat_apply_templatemeselesi; FLTK[0] ile masaüstü tabanlı bir çıkarım uygulaması kurcalayan biri olarak, keşke bunun yerine llama.cpp'nin kullandığı gerçek Jinja2 şablon ayrıştırıcısı kullanılsaYa da bunu yapan başka bir C fonksiyonu olsa. Düzgün ayrıştırmak için örneğin aracın çağrılıp çağrılmayacağını şablonun bilebilmesi adına çeşitli verileri aktarabilmek gerekiyor gibi görünüyor
Şimdilik bu geçici görünümlü fonksiyonu kullanıyorum ama sonunda ya doğrudan bir Jinja2 yorumlayıcısı kullanacağım ya da llama.cpp kodundan alıp yapıştıracağım gibi
Yine de GGUF'un her şeyi tek yerde toplama yaklaşımı çok kullanışlı. Projeksiyon modelinin ayrı dosya olması bana da garip geliyor
İlk kez görüntü destekli bir model aldığımda uygun görünen GGUF'u indirmiştim ama llama.cpp modeli işleyemeyince epey sonra ek bir dosya gerektiğini fark ettim
O an aklımdan kelimesi kelimesine “GGUF her şeyi içine alan format değil miydi?” geçti :-P
[0] https://i.imgur.com/GiTBE1j.png
Ben hep Hugging Face deposuna benzer safetensors + metadata dosyaları formatını kullandım
Büyük bir rahatsızlık hiç olmadı ama GGUF'un daha sıkı bir format ve iyi destek sunması güzel görünüyor
GGUF'ta hâlâ nelerin eksik olduğuna bakarken aslında GGUF hakkında daha çok şey öğrenmiş oldum
Araç çağırma formatı gerçekten çok doğal ve LLM'den ajanlara geçişte bir dönüm noktası olabilir gibi geliyor
Yakın zamanda TheBloke'un 7B Mistral modelini indirip denemek istedim ve elimde 4070 var
Gemma 4 e4b'ye bir şans vermek iyi olabilir. Boyut olarak Mistral 7B'ye yakın ve 4070'te iyi çalışacaktır
“E4B” adı biraz yanıltıcı olabilir
12GB'lık 4070'te Qwen 3.5 9B q4km ya da Qwen 3.6 35B çalıştırabilirsin. İkincisi çok daha akıllı ama bellek offloading yüzünden çok daha yavaş
İkisini de LM Studio'da denersen yeteneklerinin gerçekten şaşırtıcı derecede iyi olduğunu görürsün
TheBloke'u seviyorum; keşke hâlâ model hazırlıyor olsaydı