LLM’ler Sıralamayı Zaten Biliyor, Sorun Onu Yazmaları

Meta’nın SPD makalesi üzerine: sıralama modellerindeki gecikme modelden değil, cevabın yazılma biçiminden geliyor.

Bir Saniyenin Nereye Gittiği

Meta’nın SPD makalesi üzerine: sıralama modellerindeki gecikme modelden değil, cevabın yazılma biçiminden geliyor.


Bazı makaleler yeni bir şey icat ettiği için değil, herkesin baktığı ama kimsenin görmediği bir şeyi işaret ettiği için iyidir. SPD böyle bir makale.

Hikâye şuradan başlıyor. Bir öneri sisteminin son katmanındasınız. Arama motoru ya da aday üretici işini yapmış, size 50 film getirmiş. Geriye tek şey kaldı: bunları bu kullanıcı için doğru sıraya dizmek.

Bu işe reranking deniyor ve son birkaç yıldır bunu büyük dil modelleriyle yapmak moda. Sebebi de ortada. Klasik bir sıralayıcı her filme tek tek puan verir, sonra puanları sıralar; filmleri birbiriyle konuşturmaz. Bir LLM ise 50 adayın hepsini aynı anda bağlamında tutar, kullanıcının izleme geçmişiyle yan yana koyar, aralarındaki ilişkiyi görür. “Bu kullanıcı üç gün önce bir Nordic noir bitirdi, o yüzden şu polisiye ikinci sıraya çıkmalı ama aynı dizinin diğer sezonunu hemen altına koymayalım” diyebilir. Buna generative ranking deniyor.

Kalitesi iyi. Tek bir kusuru var.

Berbat derecede yavaş.

Meta’dan Emil Laftchiev ve ekibinin Eylül 2026’da yayınladığı SPD: Single Pass Decoding for Generative Reranking, bu yavaşlığın tam olarak nereye gittiğini ölçüyor. Ve cevap, en azından benim için, beklediğim yerde değildi.

Bir saniye, tek bir sayıda

Makalenin deneyindeki öğretmen model, istek başına 1807 milisaniye harcıyor. Bir saniye sekiz yüz milisaniye. Kullanıcı ana sayfayı açtı ve sizin öneri satırınız hâlâ düşünüyor.

Şimdi bu sürenin dağılımına bakın:

AşamaSüre
Prefill — kullanıcı bağlamı + 50 adayı okumak, anlamak28 ms
Decode — cevabı yazmak1779 ms

Bir dakika durun ve buna bakın.

Model, 50 filmi okumayı, kullanıcıyı tanımayı, hepsini birbiriyle karşılaştırmayı 28 milisaniyede bitiriyor. Sonra bulduğu cevabı yazmak için bir buçuk saniyeden fazla harcıyor.

Düşünmek ucuz. Konuşmak pahalı.

Sebebi mimarinin en temel özelliğinde. LLM’ler çıktıyı token token üretir ve her token için modelin tamamından bir geçiş yapar. Model “3, 17, 8, 42, …” diye elli sayı yazacaksa, elliden fazla ardışık geçiş demek bu. Ve bu geçişler paralelleştirilemez — 17’yi yazabilmek için önce 3’ü yazmış olmanız gerekir. Kaba bir ifadeyle:

Autoregressive decode maliyeti = O(N · T) ardışık geçiş

Burada N aday sayısı, T her item tanımlayıcısı için gereken token sayısı. Deneyde reasoning açıkken T ≈ 657, kapalıyken T ≈ 39. Prefill ise N ne olursa olsun sabit 28 ms, çünkü tüm adaylar tek seferde ve paralel işleniyor.

Makalenin çıkış cümlesi tam olarak bu: bu bir decoder darboğazı, model darboğazı değil.

Sıralama, sıradan bir metin değildir

Buradan güzel bir soru doğuyor. Bir sıralama modelinin ürettiği çıktı ne kadar “serbest” bir metin?

Hiç değil, aslında. Bakın:

  • Alfabesi kapalı: yalnızca {1, 2, ..., N}
  • Uzunluğu önceden biliniyor: tam olarak N sayı
  • Her değer tam olarak bir kez geçmek zorunda

Bu bir permütasyon. Ve permütasyon üretmek, serbest metin üretmekle aynı problem değil. Serbest metinde bir sonraki kelime her şey olabilir; burada olabileceklerin listesi zaten elinizde, hatta her adımda kısalıyor.

Yazarların sorduğu soru şu, ve makalenin tamamı bunun cevabı:

N sıra numarasının tamamı sabit sayıda forward pass’te çözülebilir mi — hem de autoregressive modelin yüzlerce geçişte bulduğu sıralamayı kaybetmeden?

Cevap gizli durumlarda saklı

SPD’nin dayandığı iddia zarif: model prefill sırasında adayları okurken, self-attention katmanları sayesinde karşılaştırmayı zaten yapıyor. Bilgi orada, gizli durumların (hidden states) içinde duruyor.

Autoregressive decoding bu bilgiyi alıp token token yeniden serileştiriyor. Bir bakıma, zaten bildiği şeyi yavaş yavaş dikte ediyor.

SPD ise onu bulunduğu yerde okuyor.

Bunun için sıralamayı yeniden formüle ediyorlar. Bir tarafta N item, diğer tarafta K sıra pozisyonu olan iki parçalı bir graf düşünün. Aralarında bir skor matrisi var:

M ∈ ℝ^(N×K),    M[i][j] = "item i'nin j. sırada olma yatkınlığı"

En iyi sıralama, bu matriste toplam skoru maksimize eden bire-bir eşleştirmedir:

π* = argmax  Σ  M[i, π(i)]
     π∈Π_N   i=1..N

Bu denklem yeni bir şey değil. Operasyon araştırmasının en klasik problemi: linear assignment problem. Ve 1955’ten beri kesin çözümü var — Harold Kuhn’un Macar algoritması. En kötü durumda O(N³); Jonker–Volgenant varyantıyla (LAPJV) ortalama O(N²).

Burada bedava gelen bir hediye var. Macar algoritması matematiksel olarak her zaman geçerli bir permütasyon döndürür. Aynı item iki pozisyona atanamaz. Bir pozisyon boş kalamaz. Bu bir garanti, modelin öğrenmesi gereken bir davranış değil — algoritmanın yapısından geliyor.

Autoregressive bir model ise pekâlâ [3, 17, 3, 42, ...] diye tekrarlı bir çıktı üretebilir. Makale bunun pratikte olduğunu da not ediyor, ve SPD’nin liste seviyesi metriklerde öğretmeni hafifçe geçmesinin bir sebebini buna bağlıyor. Bozuk çıktı üretmiyor olmak, tek başına bir kalite kaynağı.

Mimari: üç parça

1. Backbone — okur, konuşmaz

0.6B parametreli, decoder-only bir transformer. 28 katman, hidden boyutu 1024, 16 attention head.

Dikkat edilecek nokta: bu model hiç decode yapmıyor. Sadece prefill. Prompt’u okuyor ve susuyor.

Prompt’un yapısı şöyle:

[kullanıcı bağlamı: profil, izleme geçmişi, oturum sinyalleri]
[aday 1 metadata]   ← h₁ buradan alınır
[aday 2 metadata]   ← h₂
...
[aday N metadata]   ← h_N

Kullanıcı bağlamı önce gelmek zorunda. Sebep basit: model causal attention kullanıyor, yani her token yalnızca kendinden öncekilere bakabiliyor. Bağlamı sona koyarsanız hiçbir aday onu görmez.

Her adayın açıklamasının son token’ındaki gizli durum, o item’ın temsili oluyor. Makale buna readout pozisyonu diyor.

import torch

def gather_item_states(backbone, input_ids, attention_mask, readout_idx):
    """
    readout_idx: [B, N] — her adayın son token'ının dizi içindeki indeksi.
    Döndürür: [B, N, D]
    """
    out = backbone(
        input_ids=input_ids,
        attention_mask=attention_mask,
        output_hidden_states=True,
    )
    hidden = out.hidden_states[-1]                      # [B, T, D]

    B, N = readout_idx.shape
    batch_idx = torch.arange(B, device=hidden.device).unsqueeze(1).expand(B, N)
    h_items = hidden[batch_idx, readout_idx]            # [B, N, D]
    return h_items

Bu fonksiyon masum görünüyor ama burada bu tür implementasyonların en sinsi hatası saklı. Batch içinde farklı uzunlukta slate’ler varsa, padding’in soldan mı sağdan mı eklendiğine göre readout_idx kayar. Model yine eğitilir, loss yine düşer, ama yanlış pozisyonlardan okuduğunuz için sonuç asla iyi olmaz — ve hiçbir yerde hata mesajı görmezsiniz.

Bunun için tek satırlık bir sağlık kontrolü öneriyorum, eğitime başlamadan önce:

# İki adayı prompt içinde yer değiştirin.
# Topladığınız h vektörleri de yer değiştirmeli.
h_a = gather_item_states(model, ids_orig, mask, idx_orig)
h_b = gather_item_states(model, ids_swapped, mask, idx_swapped)
assert torch.allclose(h_a[0, 2], h_b[0, 5], atol=1e-3)

Backbone LoRA ile uyarlanıyor, rank 64, tüm linear projeksiyonlara. Tam fine-tuning yok. Bunun neden kritik olduğuna birazdan geleceğiz.

2. Skorlama kafası — simetriyi geri kurar

Prefill bitti, elimizde N tane vektör var. Ama bu vektörlerin bir sorunu var ve makale bunu doğrudan söylemiyor, yapıdan çıkıyor:

h₁ sadece kullanıcı bağlamını görmüştür. Diğer 49 adaydan haberi yoktur. h₅₀ ise her şeyi görmüştür. Causal maske yüzünden temsiller asimetrik.

İşte skorlama kafası tam olarak bunu düzeltiyor. İki katmanlı, çift yönlü küçük bir transformer encoder. Her item burada diğerlerinin hepsine bakabiliyor.

import torch.nn as nn

class ScoringHead(nn.Module):
    """~4.2M parametre. Makalenin kazanan konfigürasyonu."""

    def __init__(self, d_model=1024, d_head=512, n_positions=50,
                 n_layers=2, n_heads=8):
        super().__init__()
        self.down = nn.Linear(d_model, d_head)

        layer = nn.TransformerEncoderLayer(
            d_model=d_head,
            nhead=n_heads,
            dim_feedforward=d_head,
            batch_first=True,
            norm_first=True,
        )
        self.encoder = nn.TransformerEncoder(layer, num_layers=n_layers)
        self.to_positions = nn.Linear(d_head, n_positions)

    def forward(self, h_items, item_pad_mask=None):
        """
        h_items:      [B, N, D]
        item_pad_mask:[B, N]  True = padding
        döner:        [B, N, K] skor matrisi
        """
        z = self.down(h_items)
        z = self.encoder(z, src_key_padding_mask=item_pad_mask)
        return self.to_positions(z)

Makale üç kafa varyantını karşılaştırıyor ve fark küçük ama tutarlı:

KafaNe yapıyorAUCR@1Param
Self-attention, L=2Item’lar birbirine bakıyor0.59070.16524.2M
Linear probeHer item bağımsız puanlanıyor0.58410.1650550K
Slot-queryK pozisyon embedding’i item’lara soruyor0.58160.15794.0M

İlginç bir detay: donuk backbone’da linear probe rekabetçi. Backbone LoRA ile uyarlandığında self-attention kafası öne geçiyor. Yani kafanın ifade gücü, ancak backbone da adapte olabildiğinde işe yarıyor. Bu tesadüf değil, birazdan göreceğiz.

3. Macar algoritması — decoder’ın kendisi

Skor matrisi hazır. Şimdi sıralamayı çıkarma vakti.

import numpy as np
from scipy.optimize import linear_sum_assignment

def spd_decode(M):
    """
    M: [N, K] skor matrisi (torch tensor)
    döner: ranked[j] = j. sırada olması gereken item'ın indeksi
    """
    cost = -M.detach().float().cpu().numpy()      # maksimizasyon → minimizasyon
    row_ind, col_ind = linear_sum_assignment(cost)

    # DİKKAT: col_ind[k], row_ind[k] numaralı item'ın ATANDIĞI POZİSYONDUR.
    # Bu doğrudan sıralı liste değildir. Ters çevirmemiz gerekiyor.
    position_of_item = np.empty(len(row_ind), dtype=np.int64)
    position_of_item[row_ind] = col_ind

    ranked = np.argsort(position_of_item)          # pozisyon → item
    return ranked

Şu argsort satırının altını çizmek istiyorum. Bu kodu internette gördüğüm birçok versiyonda col_ind doğrudan sıralama olarak döndürülüyor. Değil. col_ind[i], i numaralı item’ın kaçıncı sıraya gittiğini söyler; siz ise “birinci sıraya hangi item gitti” bilgisini istiyorsunuz. İkisi birbirinin tersi.

Ve burada makalenin en güzel kavramsal hamlesi var. DETR gibi çalışmalarda Macar algoritması eğitimde loss hesaplamak için kullanılır. SPD’de ise inference’ta decoder’ın ta kendisi.

Yazarların kendi benzetmesiyle: sampling döngüsü autoregressive bir decoder ne ise, Macar çözücü de SPD için odur. Model çıktısını emitilen sıra numaralarına çeviren bileşen.

Eğitim: türevlenemeyeni türevlenebilir yapmak

Bir problem var. Macar algoritması türevlenebilir değil. Ayrık bir permütasyon döndürüyor, gradyan akmıyor. Bu haliyle eğitemezsiniz.

Çözüm Sinkhorn operatörü (Cuturi 2013, Mena 2018). Fikir şu: skor matrisini, satır ve sütun normalizasyonunu dönüşümlü uygulayarak “yumuşak permütasyon”a dönüştürmek. Teknik adıyla, matrisi çift-stokastik matrislerin oluşturduğu Birkhoff politopuna projekte etmek.

S⁽⁰⁾ = exp(M / τ)
S⁽ˡ⁺¹⁾ = D_r⁻¹ · D_c⁻¹ · S⁽ˡ⁾

Burada D_r ve D_c satır ve sütun toplamlarını 1’e çeken köşegen normalizasyon matrisleri, τ ise gevşemenin keskinliğini kontrol eden sıcaklık. τ sıfıra giderken S gerçek bir permütasyon matrisine yakınsıyor.

Pratikte bunu log uzayında yazmak gerekiyor, yoksa exp(M/τ) küçük τ değerlerinde taşar:

def log_sinkhorn(M, tau=0.1, n_iters=20):
    """
    M: [B, N, K]
    döner: log S — satır ve sütun toplamları ≈ 1 olan matrisin logaritması
    """
    log_S = M / tau
    for _ in range(n_iters):
        log_S = log_S - torch.logsumexp(log_S, dim=-1, keepdim=True)   # satırlar
        log_S = log_S - torch.logsumexp(log_S, dim=-2, keepdim=True)   # sütunlar
    return log_S

Kayıp fonksiyonu, öğretmenin permütasyon matrisine karşı cross-entropy:

L = − Σ  P_teacher[i][j] · log S[i][j]
    i,j

Kodda:

def sinkhorn_ce_loss(M, P_teacher, tau=0.1, n_iters=20):
    """
    M:         [B, N, K] öğrencinin skor matrisi
    P_teacher: [B, N, K] one-hot öğretmen permütasyon matrisi
    """
    log_S = log_sinkhorn(M, tau=tau, n_iters=n_iters)
    return -(P_teacher * log_S).sum(dim=(-1, -2)).mean()

Öğretmen permütasyonunu matrise çevirmek de düşündüğünüzden kolay:

def permutation_to_matrix(ranking, n_items, n_positions):
    """
    ranking: öğretmenin çıktısı, ranking[j] = j. sıradaki item indeksi
    """
    P = torch.zeros(n_items, n_positions)
    for position, item in enumerate(ranking):
        P[item, position] = 1.0
    return P

Ve işte tüm eğitim adımı, baştan sona:

def training_step(backbone, head, batch, tau=0.1):
    h_items = gather_item_states(
        backbone, batch["input_ids"], batch["attention_mask"], batch["readout_idx"]
    )                                                    # [B, N, D]

    M = head(h_items, item_pad_mask=batch["item_pad_mask"])   # [B, N, K]

    # padding item'ları her pozisyondan dışla
    M = M.masked_fill(batch["item_pad_mask"].unsqueeze(-1), -1e4)

    return sinkhorn_ce_loss(M, batch["P_teacher"], tau=tau)

Inference’ta Sinkhorn tamamen atlanıyor. M doğrudan Macar algoritmasına gidiyor ve kesin permütasyon çıkıyor. Eğitimde yumuşak, çıkarımda keskin.

Öğretmen tarafı: beklenenden basit

Damıtma kısmı bu tür makalelerde genelde karmaşıktır. Burada değil.

Faz 1, bir kerelik. Güçlü bir autoregressive sıralama modeli, eğitim setindeki her slate için greedy decoding ile bir sıralama üretiyor — chain-of-thought olmadan, doğrudan çıktı modunda. Bu permütasyonlar bir kez hesaplanıp diske yazılıyor. Bitti.

Faz 2. Öğrenci bu sabit etiketlere karşı eğitiliyor. Öğretmenle online etkileşim yok, on-policy döngü yok.

Yazarlar bunun neden yeterli olduğunu güzel savunuyor, ve bu savunma aslında mimarinin kendisinden geliyor: SPD’nin decoder’ında ara durum yok, rollout yok, M yalnızca prompt’a koşullu, Macar çözümü M’nin deterministik bir fonksiyonu. Dolayısıyla eğitim zamanı ve çıkarım zamanı girdi dağılımları inşa gereği aynı. Düzeltilecek bir exposure bias yok. Öğretmenin puanlayacağı bir öğrenci yörüngesi yok. Kayıp zaten token bazlı bir vekil değil, tüm permütasyon üzerinde tanımlı.

Tek bir offline öğretmen geçişi yetiyor. Bu, mühendislik açısından makalenin en rahatlatıcı kısmı.

Kapasite açığı: makalenin en öğretici bulgusu

Şimdi geldik benim en sevdiğim tabloya.

Eğitim sinyaliBackboneAUC
Click etiketleri (binary)Donuk0.5187
Öğretmen permütasyonuDonuk0.5573
Öğretmen permütasyonuLoRA (r=64)0.5842

İlk satır beklenen: click sinyali fazla seyrek, “tıklananı yukarı it” dışında bir şey söylemiyor.

Ama ikinci satıra bakın. Zengin permütasyon hedefi, donuk bir backbone’a tek başına yetmiyor.

Yazarların açıklaması şu ve okumaya değer: tam bir N-item permütasyonunu üretebilmek, her item çifti arasındaki ince göreli tercihleri kodlayan gizli durumlar gerektiriyor. Dil modellemesi için optimize edilmiş temsillerde bu bilgi yok. Backbone donuksa temsillerini bu daha zengin hedefe göre yeniden şekillendiremiyor — ve zengin sinyal, faydalı olmak yerine zararlı hale geliyor.

600M parametrelik bir backbone üzerinde yaklaşık 4M eğitilebilir parametre (LoRA) bu açığı kapatıyor.

Buradan çıkan pratik ders açık: bir LLM’in üzerine skorlama kafası takıp gövdeyi dondurmak, işe yarayacağını sandığınız ama yaramayacak bir kısayol. İki bileşen de tek başına yetmiyor; yalnızca birlikte çalışıyorlar.

Sonuçlar, ve rakamları dürüstçe okumak

ModelGecikmeDecode geçişiAUCR@1NDCG@1
Öğretmen (reasoning’li)1807 ms7680.59110.16340.1776
Öğretmen (reasoning’siz)88 ms390.59120.16350.1779
SPD28 ms10.59070.16520.1791

Kalite pratikte aynı; liste seviyesi metriklerde SPD öğretmeni hafifçe geçiyor bile.

Başlıktaki rakam 64× hızlanma. Ama bu rakamı olduğu gibi yutmadan önce, makalenin kendisinin de yaptığı bir ayrımı yapmak lazım.

Öğretmenden yalnızca reasoning trace’i kaldırın: 1807 → 88 ms. Hiçbir mimari değişiklik yok, hiçbir yeni fikir yok, 20× hızlanma ve kalite düşmüyor.

Bu tek başına makalenin en ucuz ve belki en pratik bulgusu: sıralama için reasoning token’ları taşıyıcı değil. Model uzun uzun düşünmesini yazmasa da aynı sıralamayı buluyor.

Geriye kalan 88 → 28 ms, yani 3.1×, SPD’nin saf decoding katkısı. Küçük görünebilir. Ama şunu düşünün: reasoning’siz öğretmen zaten her gereksiz token’ı atmış durumda, sadece cevabı yazıyor. O 3.1×, tamamen nasıl yazdığından geliyor. Kısaltacak bir şey kalmamışken elde edilmiş.

Amazon Beauty tarafında da benzer bir tablo var, ve orada bir kayıp da görünüyor:

ModelGecikmeAUCR@1
Qwen3-32B (öğretmen)5075 ms0.62920.1384
Qwen3-0.6B921 ms0.51220.0232
SPD 0.6B113 ms0.61680.1321

32B öğretmene karşı hafif bir kalite kaybı var. Ama aynı boyuttaki (0.6B) autoregressive modele karşı fark uçurum: AUC 0.5122 → 0.6168, R@1 0.0232 → 0.1321. Küçük modeller listwise sıralamayı token token yazmakta gerçekten kötü.

Macar algoritması ne kadara mal oluyor?

Bir kombinatoryal çözücüyü inference yoluna koymak kulağa pahalı geliyor. Değil:

BileşenGecikme
Backbone prefill (GPU)27.9 ms
Skorlama kafası (GPU)< 0.1 ms
LAPJV atama, N=50 (CPU)0.008 ms
Toplam28 ms

Toplam gecikmenin %0.03’ünden azı. Teoride O(N³) olsa da N=50 için kabaca 1.25 × 10⁵ aritmetik işlem, CPU’da mikrosaniyeler sürüyor ve GPU forward pass’iyle tamamen örtüşüyor. Zaten devam eden bir hesabın gölgesinde bitiyor.

Ama bu tablonun asıl mesajı sayılarda değil. SPD, darboğazı sıralı bir bağımlılıktan — paralelleştirilemeyen autoregressive decode — paralel bir bağımlılığa taşımış: tüm adaylar üzerinde tek bir prefill.

Bu, sistemin karakterini değiştiriyor. Bundan sonra hızlanmak istiyorsanız gideceğiniz yer backbone’un kendisi: quantization, pruning, early exit. Sıralama makinesi artık bedava.

Makalenin söylemedikleri

Bunu bir sisteme koymayı düşünüyorsanız, bilmeniz gereken boşluklar var. Makale bunları gizlemiyor, sadece kapsamına almıyor.

Klasik reranker’larla hiçbir karşılaştırma yok. Ne BGE-reranker, ne başka bir cross-encoder, ne LambdaMART. Tüm baseline’lar autoregressive LLM. “Cross-encoder’lardan iyidir” iddiası bu makalede yok — ve 0.6B’lik bir backbone, BGE-M3 sınıfı modellerle zaten aynı boyut aralığında, yani otomatik bir avantaj da yok. SPD’nin cross-encoder’a karşı gerçek argümanı hız değil, listwise olması: slate’in tamamını ve kullanıcı bağlamını aynı anda görmesi.

Sorgu tabanlı arama testi yok. Formülasyon “kullanıcı bağlamı + aday slate” üzerine kurulu. Öneri senaryosu için kanıt var, arama kutusu için yok. Sorguyu prompt’a eklemek teknik olarak sorunsuz ama makale bunun çalıştığını göstermiyor.

O(1) toplam hesap değil, geçiş sayısı. Sabit olan forward pass adedi. Prefill hâlâ N adayın tamamını işliyor ve attention maliyeti dizi uzunluğunda kareseldir. Kısa metadata ile bu sorun değil; uzun doküman metinleriyle o 28 ms rakamı geçerliliğini kaybeder.

Prompt şablonu paylaşılmamış. Kullanıcı bağlamının nasıl serileştirildiği, adayların hangi formatta verildiği, ayırıcıların ne olduğu — hiçbiri yok. Internal veri seti tescilli olduğu için muhtemelen kasıtlı. Yeniden üretecekseniz bu kısmı sıfırdan tasarlayacaksınız, ve 0.6B’lik bir modelde format tutarlılığının önemli olduğunu hatırlatayım.

Aday sırasına duyarlılık test edilmemiş. Causal attention yüzünden adayları prompt’a hangi sırayla koyduğunuz temsilleri değiştirir. Listwise LLM sıralayıcılarında bilinen bir problem; burada değinilmemiş. Eğitimde shuffle edip, değerlendirmede aynı slate’i farklı sıralarla verip çıktı kararlılığını ölçmenizi öneririm.

Mutlak kalite sayıları mütevazı. AUC 0.59, NDCG@1 0.179. Bu bir kalite makalesi değil, bir gecikme makalesi. Öyle okunmalı, ve makale de kendini öyle sunuyor.

Geriye kalan fikir

SPD’nin kalıcı katkısı bence yeni bir mimari değil. Bir bakış açısı:

Çıktının yapısını biliyorsanız, onu genel amaçlı bir decoder ile üretmek zorunda değilsiniz.

Sıralama bunun en temiz örneği, çünkü permütasyon yapısı yetmiş yıllık kesin çözümü olan bir kombinatoryal probleme birebir oturuyor. Autoregressive decoding burada aşırı genel bir araç — serbest metin için tasarlanmış bir mekanizmayı, alfabesi ve uzunluğu önceden belli bir çıktıya uyguluyoruz ve bedelini milisaniyelerle ödüyoruz.

Aynı mantığın uygulanabileceği başka yapılı çıktılar da var: küme seçimi, eşleştirme, kaynak atama, kısıtlı planlama. Her birinde “modelin bildiğini yazdırmak” ile “modelin bildiğini okumak” arasında benzer bir uçurum olabilir.

Makalenin kendi son cümlesi de bunu söylüyor: generative ranking ile kombinatoryal optimizasyon arasında bir köprü kurmak ve gerçek zamanlı sistemler için başka O(1)-decode mekanizmalarının yolunu açmak.

Bir saniyenin nereye gittiğini bilmek, çoğu zaman onu geri kazanmanın yarısı.


Kaynak: Laftchiev, E., Agrawal, P., Kayali, M., Yan, B., Xu, Q., Lei, Z., Qiu, C., Hua, Z., Li, K., Simon, L. SPD: Single Pass Decoding for Generative Reranking. Meta Platforms, arXiv:2609.01807v2, Eylül 2026. Preprint, hakem sürecinde.

Yazıdaki kod parçaları makalenin tarifinden yola çıkarak benim yazdığım örneklerdir; yazarların resmi implementasyonu değildir.

Scroll to Top