Yazılım eğitimi asistanlarında token üretim hızını tek başına artırmak yeterli değildir. Sürekli batching, kuyruk kabul kontrolü ve oturum bazlı adalet ile TTFT, p95 gecikme ve GPU bellek basıncını birlikte yönetebilirsiniz.
Yazılım Eğitimi Asistanlarında Sürekli Batching ve Kuyruk Disiplini
Yazılım eğitimi isteklerinde TTFT ve token gecikmesini ayırın
Bir yazılım eğitimi asistanında kullanıcı için iki farklı gecikme vardır: ilk tokena kadar geçen süre (TTFT) ve sonraki tokenların akış aralığı (TPOT). Bunları tek bir 'response time' metriğinde birleştirmek, sorunun kuyrukta mı yoksa model decode aşamasında mı olduğunu gizler. OpenTelemetry span'larına queue_wait_ms, prefill_ms, time_to_first_token_ms ve decode_tokens_per_second alanlarını ekleyin. vLLM kullanan bir sunucuda Prometheus endpoint'ini scrape ederek vllm:num_requests_waiting, vllm:gpu_cache_usage_perc ve token sayaçlarını Grafana'da aynı zaman ekseninde inceleyin.
from time import perf_counter
from opentelemetry import trace
tracer = trace.get_tracer('tutor-api')
async def stream_answer(request):
enqueued_at = perf_counter()
async with scheduler.acquire_slot(request.tenant_id):
admitted_at = perf_counter()
with tracer.start_as_current_span('llm.generate') as span:
span.set_attribute('llm.queue_wait_ms', (admitted_at - enqueued_at) * 1000)
first_token_at = None
token_count = 0
async for token in llm.stream(request.messages):
if first_token_at is None:
first_token_at = perf_counter()
span.set_attribute(
'llm.ttft_ms',
(first_token_at - admitted_at) * 1000
)
token_count += 1
yield token
finished_at = perf_counter()
decode_seconds = max(finished_at - (first_token_at or admitted_at), 0.001)
span.set_attribute('llm.output_tokens', token_count)
span.set_attribute('llm.decode_tps', token_count / decode_seconds)Yük testi için sabit bir veri kümesi kullanın: örneğin %70'i 300 giriş tokeni ve 120 çıkış tokeni olan kod açıklama isteği, %25'i 2000 tokenlik hata ayıklama bağlamı, %5'i 8000 tokenlik proje inceleme isteği olsun. Locust veya k6 ile aynı istek dağılımını en az 15 dakika çalıştırın. Önce sınırsız kabul ile p50, p95, p99 TTFT değerlerini ölçün; sonra kuyruk sınırı ve batching ayarını değiştirip tam olarak aynı yükte yeniden ölçün. Ortalama TPS yükselirken p95 TTFT iki katına çıkıyorsa, sistem etkileşimli eğitim akışı için gerilemiştir.
Sürekli batching için token ve istek bütçesini ayrı yönetin
Statik batching, aynı anda gelen istekleri tek batch'e koyar ve uzun bir kod inceleme yanıtının kısa bir sözdizimi sorusunu bekletmesine neden olur. Sürekli batching yapan motorlar decode adımlarında biten isteğin yerini yeni istekle doldurur. Ancak admission control yalnızca istek sayısına göre yapılırsa, az sayıda fakat yüksek bağlamlı istek KV cache'i tüketir. Bu nedenle sınırı hem eşzamanlı istek hem de tahmini token bütçesi ile koyun.
vllm serve your-model --max-model-len 16384 --max-num-seqs 96 --max-num-batched-tokens 12288 --gpu-memory-utilization 0.88 --enable-prefix-caching--max-num-seqs eşzamanlı decode dizisi sayısını, --max-num-batched-tokens ise bir scheduler iterasyonunda işlenecek toplam tokeni sınırlar. İkincisi çok düşükse GPU küçük kernel çağrılarıyla çalışır ve throughput düşer. Çok yüksekse uzun prefill işleri kısa isteklerin TTFT değerini bozar. Başlangıç deneyi olarak 64, 96 ve 128 sequence; her biri için 8192, 12288 ve 16384 batched token kombinasyonlarını deneyin. Her denemede GPU SM kullanımı için NVIDIA DCGM Exporter'dan DCGM_FI_DEV_GPU_UTIL, bellek için DCGM_FI_DEV_FB_USED ve API tarafında p95 TTFT kaydedin.
Yaygın hata, modelin teorik context window değerini doğrudan --max-model-len olarak vermektir. KV cache kapasitesi yaklaşık olarak katman sayisi x KV head sayisi x head dimension x token sayisi x 2 x dtype byte ile büyür; buna aktif sequence sayısı da eklenir. Uzun ders materyali ve çok sayıda eşzamanlı öğrenci aynı GPU'da OOM üretiyorsa, önce maksimum bağlamı ürün gereksinimine göre sınırlayın. Örneğin kaynak dosyayı bütünüyle göndermek yerine AST ile ilgili fonksiyon, import listesi ve hata stack trace'ini seçmek, prefill token maliyetini doğrudan azaltır.
Kuyruk disiplini ile kısa kod sorularını uzun analizlerden koruyun
FIFO kuyrukta 12 bin tokenlik bir repository analizi, arkasındaki 'bu TypeScript hatası neden oluşuyor?' isteğini bekletir. Bu durum head-of-line blocking'dir. İstekleri giriş tokeni ve istenen çıktı tokeni üzerinden maliyet sınıfına ayırın: small, medium ve large. Scheduler, small kuyruğuna ayrılmış bir concurrency payı tutmalıdır; aksi halde yoğun saatlerde hızlı geri bildirim bekleyen öğrenciler uzun görevlerden etkilenir.
def classify_request(input_tokens: int, max_output_tokens: int) -> str:
estimated_work = input_tokens + max_output_tokens
if estimated_work <= 1200:
return 'small'
if estimated_work <= 5000:
return 'medium'
return 'large'
LIMITS = {'small': 32, 'medium': 20, 'large': 4}
async def admit(req):
lane = classify_request(req.input_tokens, req.max_output_tokens)
async with lane_semaphores[lane]:
return await backend.generate(req)Bu basit ayrımda edge case şudur: istemci max_output_tokens=32 gönderip stream başladıktan sonra devam komutlarıyla yanıtı uzatabilir. Kota hesabını yalnızca isteğin beyanına güvenerek yapmayın. Sunucu tarafında üretilen token sayısını periyodik ölçün ve örneğin 256 tokeni geçen small isteği medium kotasına taşıyın veya stream'i güvenli bir kesme mesajıyla sonlandırın. Redis tabanlı dağıtık kota kullanıyorsanız bu geçişi Lua script ile atomik yapın; ayrı GET ve DECR işlemleri çok pod'lu dağıtımda negatif kotaya izin verir.
Karşılaştırmayı ölçülebilir kılın: FIFO ile 20 eşzamanlı large ve 80 eşzamanlı small istek gönderin. Sonra 32/20/4 lane sınırlarıyla aynı senaryoyu çalıştırın. Beklenen iyileşme small sınıfının p95 TTFT değerindedir; large sınıfının tamamlanma süresi artabilir. Bu artış kabul edilebilir mi sorusunu ürün SLO'su belirler. Örneğin etkileşimli soru-cevap için p95 TTFT hedefi 2 saniye iken repository analizi için asenkron iş ve bildirim tasarımı daha doğru olabilir.
Prefix cache hit oranını prompt kimliği ile doğrulayın
Yazılım eğitimi sistemlerinde aynı ders talimatı, rubrik ve araç açıklaması her istekte tekrarlandığında prefix caching prefill maliyetini düşürebilir. Cache yalnızca token dizisi aynıysa eşleşir. İstek zaman damgası, rastgele sıra ile serialize edilmiş JSON, kullanıcı adına göre değişen sistem prompt'u veya her çağrıda değişen tool schema alanları token dizisini değiştirdiği için hit oranını sıfıra yaklaştırabilir. Bu nedenle cache'i açmakla yetinmeyin, kanonik prompt üretin.
import json
from hashlib import sha256
def canonical_tools(tools: list[dict]) -> str:
return json.dumps(
tools,
ensure_ascii=False,
sort_keys=True,
separators=(',', ':')
)
def prompt_fingerprint(system_prompt: str, tools: list[dict]) -> str:
stable_prefix = system_prompt + '\nTOOLS=' + canonical_tools(tools)
return sha256(stable_prefix.encode('utf-8')).hexdigest()[:16]Her istekte prompt_fingerprint, input token sayısı ve cache hit bilgisini loglayın. Aynı fingerprint için prefill süresi belirgin biçimde değişiyorsa cache eviction, farklı tokenizer ayarı veya farklı model replica'sı devrededir. Prometheus'ta sum(rate(prefix_cache_hits_total[5m])) / sum(rate(prefix_cache_queries_total[5m])) ile hit oranını izleyin. Hit oranı yüksek fakat TTFT düzelmiyorsa, darboğaz prefill değil kuyruk beklemesi veya decode kapasitesidir; bu ayrımı ilk bölümdeki span alanları verir.
Cache anahtarına kullanıcıya ait ham içerik eklemeyin. Teknik neden yalnızca gizlilik değildir: kullanıcıya özgü değişken prefix'i uzattıkça paylaşılan sabit prefix yüzdesi azalır ve KV blokları düşük yeniden kullanım oranıyla belleği işgal eder. Sabit ders talimatını, araç şemalarını ve sürümü değişmeyen güvenlik kurallarını prefix'te tutun; öğrenci kodunu ve son konuşma dönüşlerini bunun sonrasına ekleyin.
Geri basınç, iptal ve kapasite kararlarını üretim ölçümüyle bağlayın
HTTP bağlantısı kapanan bir kullanıcı için backend decode işlemine devam etmek GPU zamanını tüketir. Streaming endpoint'te istemci kopmasını algılayıp üretim görevini iptal edin. Ancak iptalin gerçekten inference motoruna ulaşması gerekir; yalnızca Python coroutine'ini iptal etmek, arka plandaki HTTP çağrısını veya kuyruktaki işi çalışır bırakabilir. Backend'in abort endpoint'ini istek kimliğiyle çağırın ve cancelled_after_tokens metriğini kaydedin.
@app.get('/answer')
async def answer(request: Request, prompt: str):
request_id = new_request_id()
try:
async for token in backend.stream(request_id, prompt):
if await request.is_disconnected():
await backend.abort(request_id)
metrics.cancelled.inc()
break
yield f'data: {token}\n\n'
finally:
await backend.abort_if_active(request_id)Kapasite planında yalnızca GPU utilization kullanmayın. GPU yüzde 95 kullanılırken p95 TTFT hedefte olabilir; bu sağlıklı bir doygunluk olabilir. Alarm koşulunu üç sinyalle kurun: 5 dakika boyunca waiting queue derinliği eşik üzerinde, p95 TTFT SLO üzerinde ve KV cache kullanımı yüksek. Bu kombinasyon, kısa süreli trafik sıçramasını kalıcı kapasite yetersizliğinden ayırır. Ölçüm sonucunda önce küçük istek lane'ini koruyup large işleri asenkronlaştırmak, doğrudan replica artırmaktan daha düşük gecikme etkisi yaratabilir.
TechCareer İlgili Eğitimler
Sık Sorulan Sorular
Yazılım eğitimi asistanında p95 TTFT neden ortalama gecikmeden daha önemlidir?
Ortalama, boş GPU anlarında tamamlanan kısa isteklerle aşağı çekilir. p95 TTFT, yoğun saatte öğrencinin ilk açıklamayı beklediği kötü deneyimi gösterir. OpenTelemetry'de queue_wait_ms ve prefill_ms ayrı histogram olarak tutun; p95 artışının kuyruktan mı yoksa uzun bağlam prefill işleminden mi geldiğini bu iki seriyle ayırabilirsiniz.
Yazılım eğitimi LLM servisinde sürekli batching ayarı nasıl test edilir?
k6 veya Locust ile sabit bir input-output token dağılımı tanımlayın ve her ayarı en az 15 dakika çalıştırın. --max-num-seqs ile --max-num-batched-tokens değerlerini tek seferde değil, matris halinde değiştirin. Her koşulda p50/p95 TTFT, output token/s, waiting queue derinliği ve DCGM GPU bellek kullanımını aynı dashboard'a kaydedin.
Prefix cache neden yazılım eğitimi promptlarında beklenen hit oranını vermiyor?
Cache eşleşmesi genellikle token düzeyindedir. Dinamik tarih, kullanıcı adı, sırası değişen JSON tool schema'sı veya rastgele üretilen request alanı prefix'i değiştirir. Sistem talimatı ve tool şemalarını sort_keys=True ile kanonik JSON'a dönüştürün, sabit prefix'in SHA-256 fingerprint'ini loglayın ve hit/query oranını Prometheus üzerinden doğrulayın.
Uzun kod inceleme istekleri kısa öğrenci sorularını nasıl bekletmez?
FIFO yerine tahmini token maliyetine göre small, medium ve large kuyrukları kullanın. Small lane için ayrılmış concurrency limiti belirleyin ve çıktı tokeni büyüyen istekleri çalışma sırasında üst sınıfa taşıyın. Aynı karma yükte FIFO ve lane tabanlı scheduler sonuçlarının small sınıfı p95 TTFT değerlerini karşılaştırarak politikanın etkisini ölçün.
AI / LLM Discovery
Bu makale Opendart Akademi Yapay Zeka eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.


