Tokenizer Nedir: Hugging Face ile Metin Ön İşleme
Bir dil modeliyle çalışmaya başladığınızda, ilk fark ettiğiniz şeylerden biri şudur: model metni doğrudan okuyamaz. Ham string alıp içinden bir anlam çıkarmaz. Bunun yerine, metni sayısal temsillere dönüştürmek gerekir. İşte bu noktada tokenizer devreye girer ve aslında çoğu sysadmin’in göz ardı ettiği ama iş yaparken farkında olmadan takıldığı en kritik bileşen budur.
Tokenizer’ı basitçe şöyle düşünebilirsiniz: bir çevirmen gibi çalışır. İnsan dilini alır, modelin anlayabileceği sayısal bir formata çevirir. Ve ters yönde de çalışır; modelin ürettiği sayıları tekrar okunabilir metne dönüştürür. Hugging Face ekosisteminde bu süreç son derece standartlaşmış durumda ve transformers kütüphanesi bu konuda size ciddi kolaylık sağlıyor.
Tokenizer Tam Olarak Ne Yapar
Bir cümle düşünün: “Merhaba, nasılsın?” Bu cümleyi bir LLM’e beslemek istediğinizde, model bunu olduğu gibi işleyemez. Önce bu cümle parçalara ayrılır, her parçaya bir ID atanır, sonra bu ID’ler modele gönderilir.
Peki bu parçalar nedir? İşte burada farklı tokenization stratejileri var:
- Word-level tokenization: Her kelimeyi bir token olarak kabul eder. “Merhaba” bir token, “nasılsın” bir token gibi. Basit ama kelime hazinesi devasa olur.
- Character-level tokenization: Her karakteri ayrı token olarak alır. Esnek ama diziler çok uzun olur.
- Subword tokenization: En yaygın kullanılan yöntem. Kelimeleri anlamlı alt parçalara böler. “tokenization” kelimesi “token”, “ization” şeklinde ikiye bölünebilir.
Modern LLM’lerin büyük çoğunluğu subword tokenization kullanır. GPT ailesi BPE (Byte Pair Encoding) kullanırken, BERT ailesi WordPiece kullanır. SentencePiece ise özellikle çok dilli modellerde yaygındır.
Hugging Face Tokenizer Kütüphanesi
Hugging Face’in transformers kütüphanesi, tokenizer’ları model ağırlıklarıyla birlikte indirip kullanmanızı sağlar. Başlamak için gerekli kurulum oldukça basit:
pip install transformers
pip install tokenizers
# GPU ortamı için
pip install torch torchvision torchaudio
İlk tokenizer yükleme işlemi şu şekilde yapılır:
python3 << 'EOF'
from transformers import AutoTokenizer
# BERT tokenizer yükle
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Basit bir metin tokenize et
text = "Hello, how are you doing today?"
tokens = tokenizer.tokenize(text)
print("Tokenlar:", tokens)
# Token ID'lerine çevir
input_ids = tokenizer.convert_tokens_to_ids(tokens)
print("Token ID'leri:", input_ids)
EOF
Bu çıktı size şunu gösterir: “doing” kelimesi “do” ve “##ing” olarak ikiye bölünmüş olabilir. “##” prefix’i, bu parçanın bir önceki token’ın devamı olduğunu gösterir. Bu WordPiece tokenizer’ın özelliğidir.
Encode ve Decode İşlemleri
Tokenizer kullanırken iki temel işlem var: encode ve decode. Encode, metni sayılara çevirir; decode ise sayıları tekrar metne döndürür.
python3 << 'EOF'
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Encode işlemi - tam pipeline
text = "Sistem yöneticiliği zorlu ama keyifli bir iştir."
encoded = tokenizer(text, return_tensors="pt")
print("Input IDs:", encoded["input_ids"])
print("Attention Mask:", encoded["attention_mask"])
print("Token sayisi:", encoded["input_ids"].shape[1])
# Decode işlemi
decoded = tokenizer.decode(encoded["input_ids"][0])
print("Geri cevrilen metin:", decoded)
# Special token'lar olmadan decode
decoded_clean = tokenizer.decode(
encoded["input_ids"][0],
skip_special_tokens=True
)
print("Temiz metin:", decoded_clean)
EOF
[CLS] ve [SEP] gibi özel token’ları fark edeceksiniz. BERT bunları her dizinin başına ve sonuna ekler. Bu modelin kendi dili ve her model farklı special token kullanır.
Batch Processing: Gerçek Dünya Senaryosu
Production ortamında tek bir cümleyle uğraşmıyorsunuz. Log dosyalarını işliyorsunuz, binlerce kayıt var, her birini ayrı ayrı tokenize etmek performans açısından felakettir. Batch processing tam burada kritik hale geliyor.
python3 << 'EOF'
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# Gerçek dünya senaryosu: Log satırlarını işleme
log_entries = [
"ERROR: Connection timeout on port 443",
"WARNING: Disk usage above 85% on /dev/sda1",
"INFO: Service restarted successfully",
"CRITICAL: Memory usage reached 95%, OOM killer activated",
"ERROR: Failed to authenticate user admin from 192.168.1.100"
]
# Padding ve truncation ile batch encode
batch_encoded = tokenizer(
log_entries,
padding=True, # Kısa dizileri uzatır
truncation=True, # Uzun dizileri kırpar
max_length=64,
return_tensors="pt"
)
print("Batch shape:", batch_encoded["input_ids"].shape)
print("Attention masks:")
for i, mask in enumerate(batch_encoded["attention_mask"]):
real_tokens = mask.sum().item()
print(f" Log {i+1}: {real_tokens} gerçek token")
EOF
Buradaki padding ve truncation parametreleri çok önemli. Batch içindeki tüm dizilerin aynı uzunlukta olması gerekir. Padding kısa olanları doldurur, truncation uzun olanları keser. Attention mask ise hangi token’ların gerçek, hangilerinin padding olduğunu modele söyler.
Max Length ve Truncation Stratejileri
Özellikle log analizi veya uzun dokümanları işlerken token limitleriyle çok sık karşılaşırsınız. BERT’in maksimum 512 token sınırı var. GPT-2 için bu 1024. Daha yeni modeller daha fazlasını desteklese de pratik sınırlar her zaman vardır.
python3 << 'EOF'
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Uzun bir metin simülasyonu - büyük bir config dosyası içeriği
long_text = """
This is a very long system configuration document that contains
multiple sections including network configuration, firewall rules,
service definitions, user management policies, backup procedures,
monitoring thresholds, alerting rules, incident response playbooks,
change management workflows, and disaster recovery procedures.
""" * 10 # 10 kez tekrarla
# Truncation olmadan token sayısını kontrol et
tokens_no_truncation = tokenizer.tokenize(long_text)
print(f"Toplam token sayisi: {len(tokens_no_truncation)}")
# Farklı truncation stratejileri
# Sadece sonu kes
encoded_tail = tokenizer(
long_text,
max_length=512,
truncation=True,
truncation_strategy="longest_first"
)
# Stride ile overlapping windows
# Uzun metni parçalara böl
encoded_chunks = tokenizer(
long_text,
max_length=512,
stride=128,
truncation=True,
return_overflowing_tokens=True,
return_offsets_mapping=True
)
print(f"Kac parcaya bolundu: {len(encoded_chunks['input_ids'])}")
print(f"Her parcadaki token sayisi: {[len(chunk) for chunk in encoded_chunks['input_ids']]}")
EOF
Stride parametresi özellikle ilginç. 512 token’lık bir pencere kullanırken 128 token’lık örtüşme bırakırsanız, bağlamı kaybetme ihtimalini azaltırsınız. Özellikle soru-cevap sistemleri veya doküman sınıflandırma senaryolarında bu tekniği çok kullanacaksınız.
Farklı Modeller, Farklı Tokenizer’lar
Şimdi burası kritik: Her model kendi tokenizer’ını kullanır ve bu tokenizer’lar birbirleriyle uyumsuz olabilir. Bir modelin tokenizer’ını başka bir modele beslerseniz anlamsız sonuçlar alırsınız.
python3 << 'EOF'
from transformers import AutoTokenizer
test_text = "The sysadmin deployed the containerized microservice architecture."
# Farklı modeller, farklı tokenization
models = [
"bert-base-uncased",
"gpt2",
"roberta-base"
]
for model_name in models:
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokens = tokenizer.tokenize(test_text)
print(f"n{model_name}:")
print(f" Tokenlar: {tokens}")
print(f" Token sayisi: {len(tokens)}")
print(f" Vocab boyutu: {tokenizer.vocab_size}")
EOF
Bu kodu çalıştırdığınızda ilginç bir şey göreceksiniz. Aynı cümle farklı modellerde farklı sayıda token’a bölünür. GPT-2 BPE kullanır ve genellikle daha az token üretir. BERT WordPiece ile daha parçalı bir yapı oluşturabilir. Bu fark, token limitleri ve maliyet hesabı açısından son derece önemli.
Türkçe Metin İşleme: Özel Dikkat Gerektiren Durumlar
Türkçe, sondan eklemeli bir dil olduğundan tokenizer’lar için oldukça zorlu bir dil. “Yapıyormuşsunuzdur” gibi bir kelime, İngilizce eğitilmiş bir tokenizer tarafından onlarca parçaya bölünebilir.
python3 << 'EOF'
from transformers import AutoTokenizer
# Çok dilli model - Türkçe için daha iyi
multilingual_tokenizer = AutoTokenizer.from_pretrained(
"bert-base-multilingual-cased"
)
# İngilizce odaklı model
en_tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
turkish_texts = [
"Sunucu yöneticisi sistemi yeniden başlattı.",
"Güvenlik duvarı kurallarını güncelledim.",
"Veri tabanı bağlantısı zaman aşımına uğradı."
]
for text in turkish_texts:
multi_tokens = multilingual_tokenizer.tokenize(text)
en_tokens = en_tokenizer.tokenize(text)
print(f"nMetin: {text}")
print(f" Çok dilli model - {len(multi_tokens)} token: {multi_tokens}")
print(f" İngilizce model - {len(en_tokens)} token: {en_tokens}")
EOF
Çıktıya bakarsanız, çok dilli modelin Türkçe metni çok daha az parçaya böldüğünü görürsünüz. Türkçe içerik işleyecekseniz bert-base-multilingual-cased veya dbmdz/bert-base-turkish-cased gibi Türkçe destekli modeller kullanmanız ciddi fark yaratır. Hem kalite artar hem de gereksiz token harcanmaz.
Özel Token’lar ve Vocabulary Genişletme
Production senaryolarında bazen mevcut tokenizer’ın kelime hazinesine özel token’lar eklemeniz gerekebilir. Özellikle domain-specific fine-tuning yapıyorsanız bu kaçınılmazdır.
python3 << 'EOF'
from transformers import AutoTokenizer, AutoModelForMaskedLM
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# Sysadmin domaininde özel terimler
special_tokens = {
"additional_special_tokens": [
"[HOSTNAME]",
"[IP_ADDRESS]",
"[LOG_LEVEL]",
"[TIMESTAMP]"
]
}
# Token'ları ekle
num_added = tokenizer.add_special_tokens(special_tokens)
print(f"Eklenen token sayisi: {num_added}")
print(f"Yeni vocab boyutu: {len(tokenizer)}")
# Özel token'larla metin encode et
log_text = "[TIMESTAMP] [HOSTNAME] [LOG_LEVEL]: Connection refused from [IP_ADDRESS]"
encoded = tokenizer(log_text)
print(f"nEncode edilen metin: {log_text}")
print(f"Token sayisi: {len(encoded['input_ids'])}")
print(f"Decode: {tokenizer.decode(encoded['input_ids'])}")
# Tokenizer'ı kaydet
tokenizer.save_pretrained("./custom_tokenizer")
print("nTokenizer kaydedildi: ./custom_tokenizer")
EOF
Model tarafında da resize_token_embeddings çağrısını yapmanız gerektiğini unutmayın. Tokenizer’a yeni token eklerken modelin embedding matrisini de genişletmek zorundasınız, aksi takdirde boyut uyumsuzluğu alırsınız.
Tokenizer Bilgilerini Analiz Etme
Bir production sistemi kuruyorsanız, tokenizer hakkında detaylı bilgiye ihtiyaç duyarsınız. Hangi özel token’lar var, padding stratejisi ne, vocab boyutu kaç gibi sorular önemli.
python3 << 'EOF'
from transformers import AutoTokenizer
import json
def tokenizer_raporu(model_name):
tokenizer = AutoTokenizer.from_pretrained(model_name)
print(f"n{'='*50}")
print(f"Model: {model_name}")
print(f"{'='*50}")
print(f"Tokenizer tipi: {type(tokenizer).__name__}")
print(f"Vocab boyutu: {tokenizer.vocab_size}")
print(f"Max pozisyon: {tokenizer.model_max_length}")
print(f"nOzel tokenlar:")
print(f" PAD token: {tokenizer.pad_token} (ID: {tokenizer.pad_token_id})")
print(f" UNK token: {tokenizer.unk_token} (ID: {tokenizer.unk_token_id})")
print(f" CLS token: {getattr(tokenizer, 'cls_token', 'Yok')}")
print(f" SEP token: {getattr(tokenizer, 'sep_token', 'Yok')}")
print(f" BOS token: {getattr(tokenizer, 'bos_token', 'Yok')}")
print(f" EOS token: {getattr(tokenizer, 'eos_token', 'Yok')}")
# Test cümlesi
test = "Tokenizer analysis for production systems."
tokens = tokenizer.tokenize(test)
print(f"nTest: '{test}'")
print(f"Token sayisi: {len(tokens)}")
# Farklı modelleri karşılaştır
for model in ["bert-base-uncased", "gpt2", "distilbert-base-uncased"]:
tokenizer_raporu(model)
EOF
Bu script’i CI/CD pipeline’ınıza ekleyerek model değişikliklerinde tokenizer davranışının değişip değişmediğini otomatik kontrol edebilirsiniz.
Tokenizer’ı Offline Kullanmak
Production ortamında internet erişimi olmayan sunucularda çalışmak çok yaygın. Tokenizer ve model dosyalarını önceden indirip offline kullanmak hem güvenlik açısından hem de bant genişliği açısından doğru yaklaşım.
# Tokenizer dosyalarını indirip kaydet
python3 << 'EOF'
from transformers import AutoTokenizer
import os
model_name = "distilbert-base-uncased"
save_path = "/opt/ml_models/distilbert-tokenizer"
os.makedirs(save_path, exist_ok=True)
# İndir ve kaydet
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.save_pretrained(save_path)
print(f"Tokenizer kaydedildi: {save_path}")
print(f"Dosyalar:")
for f in os.listdir(save_path):
size = os.path.getsize(os.path.join(save_path, f))
print(f" {f}: {size/1024:.1f} KB")
EOF
# Daha sonra offline olarak yükle
python3 << 'EOF'
from transformers import AutoTokenizer
# Internet olmadan local yolu kullan
tokenizer = AutoTokenizer.from_pretrained(
"/opt/ml_models/distilbert-tokenizer",
local_files_only=True
)
print("Offline tokenizer basariyla yuklendi")
print(f"Vocab boyutu: {tokenizer.vocab_size}")
test_text = "Offline NLP processing in air-gapped environments"
encoded = tokenizer(test_text)
print(f"Token sayisi: {len(encoded['input_ids'])}")
EOF
local_files_only=True parametresi, HuggingFace’in internete bağlanmaya çalışmasını tamamen engeller. Air-gapped ortamlarda bu parametre olmadan da çalışsa bile eklemek iyi pratik.
Pipeline ile Entegrasyon
Son olarak, tokenizer’ı bir bütün olarak pipeline içinde nasıl kullandığınıza bakalım. Gerçek projede genellikle tokenizer’ı ayrı ayrı değil, bir pipeline’ın parçası olarak kullanırsınız.
python3 << 'EOF'
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
# Tokenizer ve model birlikte yükle
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# Sentiment analizi pipeline'ı
classifier = pipeline(
"sentiment-analysis",
model=model_name,
tokenizer=tokenizer,
truncation=True,
max_length=512
)
# Gerçek senaryo: IT ticket sınıflandırma
tickets = [
"The server is down and we cannot access any services, this is critical!",
"I would like to request access to the development environment when possible.",
"Everything is working great after the last update, thank you!",
"Database connection keeps failing every few minutes, very frustrated."
]
print("IT Ticket Duygu Analizi:")
print("-" * 50)
for ticket in tickets:
result = classifier(ticket)[0]
print(f"nTicket: {ticket[:60]}...")
print(f" Duygu: {result['label']}")
print(f" Güven: {result['score']:.3f}")
EOF
Bu örnekte tokenizer, modelin beklediği formata otomatik olarak dönüşüm yapıyor. Pipeline abstraction’ı altında yine tokenizer(text, ...) çağrısı yapılıyor ama siz bunu görmüyorsunuz.
Sonuç
Tokenizer, LLM dünyasının en temel ama en az anlatan bileşenidir. Çoğu geliştirici modeli çalıştırıp çıktıyı görünce tokenizer’ın varlığını unutur. Ama sysadmin olarak production sistemleri yönetiyorsanız, token limitleri, padding stratejileri, dil uyumu ve offline kullanım gibi konuları mutlaka anlamanız gerekir.
Özetlemek gerekirse:
- Her modelin kendine ait tokenizer’ı var ve bunları karıştırmayın
- Türkçe içerik işliyorsanız çok dilli veya Türkçe özel modeller tercih edin
- Batch işlemde padding ve truncation stratejilerini bilinçli seçin
- Production’da tokenizer dosyalarını local’e alın, internet bağımlılığından kurtulun
- Token sayısını izleyin; hem maliyet hem de performans açısından kritik
model_max_lengthsınırını aşan metinleri stride tekniğiyle parçalara bölün
Hugging Face ekosisteminde AutoTokenizer sınıfı neredeyse her senaryoyu karşılayacak esnekliktedir. Temel kullanımı anladıktan sonra fine-tuning, custom vocabulary ve domain-specific adaptasyon konularına geçebilirsiniz. Bir sonraki yazıda tokenizer’dan sonra gelen adımı, yani modele veriyi nasıl besleyeceğinizi ve inference pipeline’ını ele alacağız.
