---
title: 'Yanıt Akışı'
source: 'https://academia.sh/tr/kurslar/model-apileri/yanit-akisi'
course: "Model API'leri ile Uygulama Geliştirme"
language: tr
updated: '2026-08-17T18:06:38+00:00'
license: 'CC BY-SA 4.0'
---

# Yanıt Akışı

Yanıtın parça parça alınmasının ölçülmesi: 320 çağrılık aynı iş yükünde üç kurulum da 23338 giriş ve 4049 çıkış belirteci harcıyor ve 33 çağrıda yarıda kesiliyor, yani akış tek bir belirteci bile değiştirmiyor. Değişen şey bekleme adımıdır: akışsız istemcide ilk görünen şey ortalama 16,03 adımda gelirken akan istemcide 3,29 adımda geliyor. Ama akış tek başına kullanılabilirliği değiştirmiyor; etiket yanıtın sonundayken kullanılabilir adım iki kurulumda da 16,03 ve kesilen 33 yanıttan kurtarılan 0. Etiket yanıtın başına alındığında kullanılabilir adım 4,96'ya, kesilenlerden kurtarılan 31'e, kullanılabilir pay 0,8625'ten 0,9594'e çıkıyor. Kesilen yanıtların ortalama 0,5801'i elimize ulaşmış oluyor ve alan sırası bu payın işe yarayıp yaramadığını belirliyor.

Önceki ders konuşma durumunu istemciye yerleştirdi ve her gönderim kararının belirteç bedelini
yazdı. Her çağrının yanıtı orada tek parça hâlinde geldi: istemci isteği gönderdi, bekledi, ve
elinde bütün bir metin buldu. Basılan **ilk parça adımı** sütunu hiçbir karara girmemişti.

Yanıt aslında tek parça üretilmez. Model çıktıyı adım adım kurar ve arayüz bu parçaları
üretildikleri sırada gönderebilir. Bu ders o seçeneği ölçer ve üç soruyu ayırır: akış **toplam
belirteci** değiştirir mi, **ilk görünen adımı** ne kadar düşürür, ve ağ yanıtı ortasında
kestiğinde geriye **kullanılabilir** ne kalır. Üçüncü soru bu kursun kuralına doğrudan bağlıdır:
başarısızlığı yazılmayan çağrı ölçülmemiş sayılır, ve yarım kalan bir yanıt bir başarısızlıktır.

- **AK9.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Görüşmeler **kurgudur**,
  tohum **20260218**. Benzetici önceki derste kurulan ağ katmanını taşır.
- **AK10. Yanıt bir parça listesidir.** Benzetici `parca` alanını da döndürür; akan istemci bu
  listeyi geldiği sırayla birleştirir, akışsız istemci ise ancak tamamlandığında görür.
- **AK11. Ağ kesmesi istemin içeriğine bağlıdır, alan sırasına değil.** Üç kurulum aynı istemleri
  gönderdiği için **aynı çağrılar kesilir**; karşılaştırma aynı ağ koşulunda yapılır.
- **AK12. Alan sırası bir istek alanıdır**, isteme yazılan bir cümle değil. Böylece giriş
  belirteci üç kurulumda birebir aynı kalır ve yalnız sıra değişir.
- **AK13. İki ayrı bekleme ölçülür:** **ilk görünen adım** (kullanıcının ekranda bir şey gördüğü
  an) ve **kullanılabilir adım** (istemcinin etiketi okuyup iş başlatabildiği an).
- **AK14. Kullanılabilirlik ölçütü etiketin okunabilmesidir.** Akışsız istemcide yarıda kesilen
  yanıtın gövdesi hiç elde olmaz; akan istemcide gelen parçalar elde kalır.
- **AK15.** Gönderim kararı önceki dersten devralınır ve üç kurulumda da aynıdır: **yalnız
  kullanıcı sıraları**. İş yükü kırk görüşmenin sekiz turu, toplam **320 çağrıdır**.
- **AK16.** Gecikme ham süre olarak değil **adım** olarak yazılır; gecikme sınıfı yine
  **zincirdir**.

## Parça Parça Gelen Yanıt

Akan bir istemcinin yaptığı iş iki satırdır: gelen parçayı biriktir, ve biriken metnin **karar
verilebilir** hâle gelip gelmediğine bak. Aşağıdaki `akan_istemci` bunu yapar ve etiketi ilk
okuduğu adımı yazar. `butun_istemci` ise yanıtın tamamlanmasını bekler; tamamlanmazsa elinde
hiçbir şey kalmaz.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; ag katmani da benzeticide.
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, EN_UZUN, HIZ = 240, 24, 37


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def parcala(m):
    """KURGU belirtecleyici; parca en cok bes damga."""
    b = []
    for s in m.lower().replace(",", " , ").split():
        yeni = True
        while len(s) > 5:
            b.append((s[:5], yeni))
            s, yeni = s[5:], False
        b.append((s, yeni))
    return b


def belirtecle(m):
    return [p for p, _ in parcala(m)]


def birlestir(pl):
    s = ""
    for p, yeni in pl:
        s += (" " if yeni and s else "") + p
    return s


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


def cekilis(istem, tohum, tuz):
    return uretec((tohum + tuz) ^ izno(istem))()


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "fatura",
      "ariza": "ariza", "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza",
      "sayac": "sayac", "endek": "sayac", "okuma": "sayac", "rande": "sayac",
      "tarif": "tarife", "birim": "tarife", "abone": "tarife", "basam": "tarife",
      "kesin": "kesinti", "duyur": "kesinti", "mahal": "kesinti",
      "odeme": "odeme", "sikay": "sikayet", "bilgi": "bilgi"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "ekip": "kesinti", "takip": "tarife"}
GOVDE = "talebiniz incelendi ve ilgili ekibe iletildi"
SAYAC = [0]


def duzlestir(mesajlar):
    return " ".join(f"{r} : {i}" for r, i in mesajlar)


def cagir(mesajlar, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN, yer="tek"):
    """yer bir istek alanidir: etiket yanitin basinda mi sonunda mi uretilsin."""
    SAYAC[0] += 1
    istem = duzlestir(mesajlar)
    bel = belirtecle(istem)
    ilk = 1 + len(bel) // 40                      # ilk parcaya kadar gecen adim
    bos = {"giris": len(bel), "cikis": 0, "parca": [], "ilk": ilk}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % HIZ == 0:
        return dict(bos, durum="hiz_siniri")
    r = uretec(tohum ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return dict(bos, durum="zaman_asimi")
    aday = [k for k in KAVRAM if k[:5] in bel]
    if len(aday) < 3:
        aday = list(KAVRAM)
    p = {k: 0.15 for k in aday}
    for t in bel:
        for tablo, w in ((IZ, 1.0), (TUZAK, 0.6)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    ad = sorted(p)
    if sicaklik <= 0.0:
        k = max(ad, key=lambda a: p[a])
    else:
        from math import exp
        e = [exp(p[a] / sicaklik) for a in ad]
        k = ad[ayrik(r(), [x / sum(e) for x in e])]
    if yer == "basta":
        metin = f"konu {k} , {GOVDE}"
    elif yer == "sonda":
        metin = f"{GOVDE} , konu {k}"
    else:
        metin = k
    pl, durum = parcala(metin), "tamam"
    if len(pl) > en_uzun:
        pl, durum = pl[:en_uzun], "durduruldu"
    u = cekilis(istem, tohum, 91)                 # ag yaniti yarida keser
    if len(pl) > 3 and u < 0.08:
        pl, durum = pl[:1 + int(u / 0.08 * (len(pl) - 1))], "kesildi"
    return {"durum": durum, "giris": len(bel), "cikis": len(pl),
            "parca": pl, "ilk": ilk}


def oku(y):
    return next((s for s in y.split() if s in KONU), None)


def butun_istemci(s):
    """Yanit tamamlanmazsa govde hic elde olmaz."""
    if s["durum"] != "tamam":
        return "", None
    metin = birlestir(s["parca"])
    return metin, (s["ilk"] + s["cikis"]) if oku(metin) else None


def akan_istemci(s):
    """Parcalar geldikce baglanir; etiket okunur okunmaz adim yazilir."""
    metin, kullanilabilir = "", None
    for i, (p, yeni) in enumerate(s["parca"], 1):
        metin += (" " if yeni and metin else "") + p
        if kullanilabilir is None and oku(metin):
            kullanilabilir = s["ilk"] + i
    return metin, kullanilabilir


ACILIS = ["merhaba yardim gerekiyor", "iyi gunler destek istiyorum",
          "selam bir sorunum var", "merhaba destek almak istiyorum"]
ANAHTAR = {"fatura": ["bu ayki fatura tutari gecen aya gore cok yuksek geldi",
                      "faturami odedim ama sistemde borc gorunuyor",
                      "fatura ayrintisini nereden gorebilirim"],
           "ariza": ["evde su akmiyor bir ariza var galiba",
                     "baglanti bozuk oldu ve hic calismiyor",
                     "ariza kaydi actim ama ekip gelmedi"],
           "sayac": ["sayac okumasi yanlis girilmis endeks tutmuyor",
                     "sayac degisimi icin randevu istiyorum",
                     "sayac uzerindeki endeks ile fatura ayni degil"],
           "tarife": ["hangi tarife basamagindayim ogrenmek istiyorum",
                      "tarife degisikligi icin ne yapmam gerekiyor",
                      "birim ucret abone tipine gore degisiyor mu"],
           "kesinti": ["mahallede kesinti var ne zaman gelecek",
                       "planli kesinti duyurusu nereden takip edilir",
                       "aksamdan beri kesinti yasiyoruz"]}
DOLGU = ["tesekkur ederim not aldim", "peki bunun icin ne kadar beklemem gerekir",
         "daha once de ayni durum olmustu", "yazili bir bildirim alabilir miyim",
         "bu konuda kayit acildi mi", "degisiklik yapilirsa haber verilir mi",
         "ekip ne zaman gelir", "hafta sonu da ulasabilir miyim"]
SISTEM = ("sistem", "destek yardimcisisin . etiket kumesi : fatura , ariza , "
                    "sayac , tarife , kesinti .")
SORU = "gorusme {n} icin konu etiketi ver"

GORUSME = []
for i in range(40):                               # 40 KURGU gorusme, sekizer tur
    r = uretec(TOHUM + 7 * i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    anahtar = ANAHTAR[k][int(r() * 3)]
    yeri = 1 + int(r() * 5)
    tur = [ACILIS[int(r() * 4)]]
    for t in range(1, 7):
        tur.append(anahtar if t == yeri else DOLGU[int(r() * 8)])
    tur.append(SORU.format(n=7301 + i))
    GORUSME.append({"no": 7301 + i, "konu": k, "yeri": yeri + 1, "tur": tur})

g = GORUSME[0]
mesaj = [SISTEM] + [("kullanici", m) for m in g["tur"]]
print(f"gorusme {g['no']} , konu {g['konu']} , giris"
      f" {cagir(mesaj)['giris']} belirtec")
for yer in ("sonda", "basta"):
    s = cagir(mesaj, yer=yer)
    metin, ka = akan_istemci(s)
    print(f"  etiket {yer:<5} cikis {s['cikis']:>2}  ilk parca adimi {s['ilk']}"
          f"  akan istemcide kullanilabilir adim {ka}"
          f"  butun yanit adimi {butun_istemci(s)[1]}")
    print(f"                yanit : {metin}")
print("  ayni istek tohum 20260219 ile ->",
      birlestir(cagir(mesaj, TOHUM + 1, yer="basta")["parca"]))
```

```
gorusme 7301 , konu kesinti , giris 113 belirtec
  etiket sonda cikis 14  ilk parca adimi 3  akan istemcide kullanilabilir adim 17  butun yanit adimi 17
                yanit : talebiniz incelendi ve ilgili ekibe iletildi , konu kesinti
  etiket basta cikis 14  ilk parca adimi 3  akan istemcide kullanilabilir adim 6  butun yanit adimi 17
                yanit : konu kesinti , talebiniz incelendi ve ilgili ekibe iletildi
  ayni istek tohum 20260219 ile -> konu kesinti , talebiniz incelendi ve ilgili ekibe iletildi
```

Aynı görüşme, aynı istem ve aynı çıkış uzunluğu: iki kurulumda da yanıt **14 parça**. Değişen tek
şey etiketin nerede durduğudur. Etiket sonda olduğunda akan istemci de bütün istemci de
**17. adımda** karar verebiliyor; akış hiçbir şey kazandırmıyor. Etiket başa alındığında akan
istemci **6. adımda** kararı veriyor, bütün istemci ise yine 17. adımı bekliyor. Aradaki on bir
adım, yanıtın gövdesini okumadan atılabilecek bir beklemedir.

Son satır kursun üçüncü kuralının gereğidir: aynı istek ikinci bir tohumla yine aynı etiketi ve
aynı sırayı verdi.

## Üç Kurulumun Bekleme ve Kullanılabilirlik Tablosu

Üç kurulum aynı 320 çağrıda koşturulur. İlki akışsızdır ve etiketi sonda ister; ikincisi aynı
isteği akıtarak okur; üçüncüsü akıtır ve etiketi başta ister. Çağrılar birebir aynı olduğu için
ağ koşulu da aynıdır.

```python
def olc(yer, akis, tohum=TOHUM):
    """yer: sonda | basta. akis: parcalar geldikce mi okunuyor."""
    SAYAC[0] = 0
    g = c = kesik = kesik_kurtulan = dogru = 0
    gorunen, kullanilir = [], []
    for gr in GORUSME:
        for t in range(1, 9):
            mesaj = [SISTEM] + [("kullanici", m) for m in gr["tur"][:t]]
            s = cagir(mesaj, tohum, yer=yer)
            g, c = g + s["giris"], c + s["cikis"]
            if akis:
                metin, adim = akan_istemci(s)
                if s["parca"]:
                    gorunen.append(s["ilk"] + 1)
            else:
                metin, adim = butun_istemci(s)
                if adim is not None:
                    gorunen.append(adim)
            if s["durum"] == "kesildi":
                kesik += 1
                kesik_kurtulan += adim is not None
            if adim is not None:
                kullanilir.append(adim)
            if t == 8 and oku(metin) == gr["konu"]:
                dogru += 1
    ort = sum(gorunen) / len(gorunen), sum(kullanilir) / len(kullanilir)
    return g, c, kesik, kesik_kurtulan, ort[0], ort[1], len(kullanilir) / 320, dogru / 40


KURULUM = [("akissiz , etiket sonda", "sonda", False),
           ("akis , etiket sonda", "sonda", True),
           ("akis , etiket basta", "basta", True)]
print("kurulum                 giris  cikis  kesik  kurtulan  ilk gorunen"
      "  kullanilabilir  kullanilir pay  isabet A  isabet B")
for ad, yer, akis in KURULUM:
    a, b = olc(yer, akis), olc(yer, akis, TOHUM + 1)
    print(f"{ad:<22} {a[0]:>6} {a[1]:>6} {a[2]:>6} {a[3]:>9}  {a[4]:>11.2f}"
          f"  {a[5]:>14.2f}  {a[6]:>14.4f}  {a[7]:>8.4f}  {b[7]:>8.4f}")

SAYAC[0] = 0
pay = []
for gr in GORUSME:
    for t in range(1, 9):
        s = cagir([SISTEM] + [("kullanici", m) for m in gr["tur"][:t]], yer="basta")
        if s["durum"] == "kesildi":
            pay.append(s["cikis"] / 14)
print(f"\nkesilen {len(pay)} yanitta gelen parca payi : en az {min(pay):.4f} ,"
      f" ortalama {sum(pay) / len(pay):.4f} , en cok {max(pay):.4f}")
```

```
kurulum                 giris  cikis  kesik  kurtulan  ilk gorunen  kullanilabilir  kullanilir pay  isabet A  isabet B
akissiz , etiket sonda  23338   4049     33         0        16.03           16.03          0.8625    0.7500    0.6500
akis , etiket sonda     23338   4049     33         0         3.29           16.03          0.8625    0.7500    0.6500
akis , etiket basta     23338   4049     33        31         3.29            4.96          0.9594    0.7750    0.6750

kesilen 33 yanitta gelen parca payi : en az 0.0714 , ortalama 0.5801 , en cok 0.9286
```

İlk iki sütun bu dersin en önemli sonucudur. Giriş **23338**, çıkış **4049** ve kesilen çağrı
sayısı **33**, üç kurulumda da birebir aynı. Akış **tek bir belirteci bile değiştirmiyor**; ne
maliyeti düşürüyor ne yükseltiyor. Bir maliyet muhasebesi tablosunda akışlı ve akışsız istemci
ayırt edilemez.

Değişen şey bekleme sütunudur. Akışsız istemcide ilk görünen şey ortalama **16,03 adımda**
geliyor, çünkü görünen ilk şey zaten bütün yanıttır. Akan istemcide bu **3,29 adıma** düşüyor:
yaklaşık beşte bir. Kullanıcının ekranında bir şeyin belirmesi bu kadar erkene çekiliyor ve
bunun için hiçbir belirteç ödenmiyor.

## Akışın Kazandırmadığı ve Alan Sırasının Kazandırdığı

İkinci satırın **kullanılabilir adım** değeri 16,03'tür, yani birinci satırla aynı. Akış ekrana
bir şey getirdi ama istemciye **karar verdirmedi**, çünkü kararın dayandığı alan yanıtın en
sonundaydı. Aynı satırın kurtulan sütunu da sıfırdır: kesilen 33 yanıtın hiçbiri kullanılabilir
kalmadı. Akış tek başına bir dayanıklılık düzeneği değildir.

Üçüncü satır farkı alan sırasıyla açar. Kullanılabilir adım **4,96**'ya iniyor, kesilen 33
yanıttan **31'i** kurtarılıyor ve kullanılabilir pay **0,8625'ten 0,9594'e** çıkıyor. Kesilen
yanıtlarda gelen parça payı en az 0,0714, ortalama **0,5801**, en çok 0,9286: yarıda kesilen bir
yanıtın ortalama olarak yarısından fazlası elimize ulaşıyor. O payın işe yarayıp yaramaması
tümüyle **hangi alanın önce üretildiğine** bağlı.

Son iki sütun bir uyarı taşıyor. Etiket isabeti üç kurulumda 0,7500 / 0,7500 / 0,7750; ikinci
tohumda 0,6500 / 0,6500 / 0,6750. Alan sırasının isabete kattığı **0,0250**, aynı satırın iki
koşum farkı ise **0,1000**. Bu kazanç **ölçülmemiş sayılır** ve öyle yazılır. Alan sırasının
ölçülen kazancı isabette değil, **kullanılabilirlik ve bekleme** sütunlarındadır; bunlar da
koşumdan koşuma değişmeyen sayılardır.

## Özet

- Akış toplam belirteci değiştirmez: üç kurulum da 23338 giriş, 4049 çıkış harcar ve 33 çağrıda
  kesilir.
- Akış ilk görünen adımı 16,03'ten 3,29'a düşürür ve bunun için hiçbir belirteç ödenmez.
- Akış tek başına kullanılabilirliği değiştirmez: etiket sonda olduğunda kullanılabilir adım iki
  kurulumda da 16,03 ve kesilen 33 yanıttan kurtarılan 0'dır.
- Etiket yanıtın başına alındığında kullanılabilir adım 4,96'ya, kurtarılan yanıt 31'e,
  kullanılabilir pay 0,9594'e çıkar.
- Kesilen yanıtların ortalama 0,5801'i elimize ulaşır; bu payın işe yarayıp yaramadığını alan
  sırası belirler.
- Alan sırasının isabete kattığı 0,0250, iki koşum farkı 0,1000 olduğu için ölçülmemiş sayılır;
  ölçülen kazanç bekleme ve kullanılabilirlik sütunlarındadır.

## Sonraki Adım

İki derste yanıt hep **okunacak bir metin** oldu. Etiket erken geldiğinde iş erken başlıyordu,
ama o işi başlatan hep bir insan ya da basit bir yönlendirme kuralıydı. Yanıt doğrudan bir **kod
yürütmesini** tetikleyecekse ölçüt değişir: biçimin okunabilir olması yetmez, çağrılan şeyin
**var olması** ve verilen değerlerin **kabul edilebilir** olması da gerekir. Sonraki ders modelin
çıktısını yürütülecek bir çağrıya bağlar ve üç sayıyı yan yana basar: kaç yanıt şemaya uygun bir
çağrı üretiyor, kaçı var olmayan bir ad uyduruyor, ve doğrulama bunların kaçını yakalıyor.
