---
title: "Model API'leri ile Uygulama Geliştirme"
source: 'https://academia.sh/tr/kurslar/model-apileri'
language: tr
updated: '2026-08-17T04:38:30+00:00'
license: 'CC BY-SA 4.0'
lessons: 26
outcomes:
    - 'Model arayüzlerini akış, araç çağrısı ve yapılandırılmış çıktıyla kullanır ve her birinin bedelini yazar'
    - 'Gecikmeyi ve belirteç maliyetini ölçüp iyileştirir ve dayanıklılık düzeneğinin bozduğu yeri gösterir'
    - 'Kendi barındırdığın ve uzaktan çağrılan seçenekleri bellek, isabet ve kullanım koşulu ekseninde karşılaştırır'
---

# Model API'leri ile Uygulama Geliştirme

Model çağrısının bir işlev çağrısı değil bir ağ işlemi olduğu varsayımıyla düzeneğin ölçülmesi: konuşma durumunun her istekte yeniden gönderilmesinin belirteç bedeli, yanıt akışında ilk parçaya kadar geçen adım ve yarıda kesilen yanıtın kullanılabilirliği, geçerli araç çağrısı oranı ve uydurulan araç adı, arayüz düzeyinde şema zorunluluğunun kattığı, girdi biçiminin belirteç bedeli, gömme boyutu düştükçe saklama ile isabetin takası, uyumlu arayüz katmanının kaybettiği alan, toplu boyut büyüdükçe tek başarısızlığın etkilediği istek sayısı, yeniden denemenin belirteci de katlaması, önbellek isabetiyle birlikte büyüyen bayat yanıt payı, gecikme sınıfı ile isabetin takası, en pahalı yüzde birin toplam içindeki payı, yedek modele düşmenin kaliteyi sessizce düşürmesi, çıktıyı sabitleyen kalemler, kod yardımcısının görev sınıfına göre kabul oranı, ilgisiz bağlamın isabeti düşürdüğü nokta, denetim noktasının hatayı yayılmadan yakalaması, üç denetimin yakaladığı ve kaçırdığı, üretilen sınamanın hep geçen boş sınama payı, bağlama giren sır sınıfı alan sayısı, bellek bütçesinin yettiği eşzamanlı istek, basamak sayısı düştükçe isabetin düştüğü nokta, ince ayarın kazanmadığı durum, güncellenen parametre payı ile isabet, damıtılan küçük modelin kapatamadığı açık ve koşul sınıfı başına kapanan dağıtım seçeneği.

## API Kullanımı

Mesaj tabanlı bir arayüzün ne sunduğunun ve her yeteneğin belirteçle ne kadara mal olduğunun ölçülmesi: konuşma durumunun istemcide taşınması ve uzadıkça büyüyen yeniden gönderim ile üç kısaltma kararının indirdiği, ilk parçaya kadar geçen adım ve yarıda kesilen yanıtın ne kadarının kullanılabilir kaldığı, şemaya uygun araç çağrısı oranı ile uydurulan araç adının doğrulamayla yakalanması, istemle dayatma ile arayüzle dayatmanın uyum oranı ve belirteç farkı, aynı bilginin metin, ızgara ve dizi olarak ettiği belirteç, gömme boyutu düştükçe saklanan sayı ile komşuluk isabeti, ortak arayüzün taşıdığı ve kaybettiği alan sayısı, toplu boyut büyüdükçe düşen çağrı sayısı ile büyüyen etkilenen istek sayısı.

### Mesaj Tabanlı Arayüzler

Source: https://academia.sh/tr/kurslar/model-apileri/mesaj-tabanli-apiler

Konuşma durumunun istemcide taşınmasının belirteç bedeli: sekiz turluk bir görüşmede toplam gönderilen giriş belirteci son turun 3,96 katıdır, çünkü her tur bütün dökümü yeniden gönderir. Kırk kurgu görüşmede beş gönderim kararı yan yana ölçülür: durum göndermeyen istemci 8346 giriş belirteciyle 0,2000 isabet, tam döküm 31160 ile 0,8250, son üç tur 23102 ile 0,4500, yalnız kullanıcı sıraları 19738 ile 0,6750, çıkarılmış durum kaydı 10474 ile 0,6500. Doğru etiket başına belirteç okuması sıralamayı değiştirir: son üç tur 1413,8 ile hiçbir şey yapmayan istemciden pahalıdır, çıkarılmış durum kaydı 494,9 ile en ucuzudur. İki koşum farkı 0,1250'dir, bu yüzden durum kaydı ile yalnız kullanıcı arasındaki 0,0250 fark ölçülmemiş sayılır.

İstem Mühendisliği kursu yirmi iki derste istemi bir tasarım nesnesine dönüştürdü ve her
değişikliğin bedelini belirteçle yazdı. Her satırında sessiz bir varsayım vardı: çağrı **tek
başına, hemen ve hatasız** gerçekleşiyordu.

Bir uygulamanın içinde bu varsayımın hiçbiri durmaz. Çağrı bir ağ üzerinden gider, sıraya girer,
reddedilir, yarıda kesilir ve her seferinde **para yerine belirteç** harcar. Bu kursun kuralı
budur: **bir model çağrısı bir işlev çağrısı değil bir ağ işlemidir; başarısızlığı yazılmayan
çağrı ölçülmemiş sayılır.** İlk ders arayüzün en temel özelliğinden başlar. Mesaj tabanlı bir
arayüzde **konuşma durumu sunucuda tutulmaz**; döküm istemcidedir ve her istekte yeniden
gönderilir. Bu ders o yeniden gönderimin ne tuttuğunu ve beş gönderim kararının onu kaça
indirdiğini sayar.

- **AK1.** Kod bir **benzeticidir**; gerçek bir model uç noktası çağrılmaz. Görüşmeler, talep
  metinleri ve etiket kümesi **kurgudur**, tohum **20260218**.
- **AK2. Benzetici ağ davranışı da taşır:** hız sınırı reddi (her otuz yedinci çağrı), bağlam
  penceresi aşımı, zaman aşımı ve yanıtın **yarıda kesilmesi**. Eşikler kurgudur; ölçülen şey
  eşiğin değeri değil, istemcinin karşılığıdır.
- **AK3. Arayüz üç rol tanır:** sistem, kullanıcı ve model. Rol adları da belirteç eder.
- **AK4. Konuşma durumu sunucuda tutulmaz.** Döküm istemcide durur; her istekte neyin
  gönderileceği bir **istemci kararıdır** ve bu derste beş karar ölçülür.
- **AK5. Gecikme ham süre olarak değil adım olarak yazılır:** ilk parça adımı girişe, toplam
  adım çıkışa bağlıdır. Bir görüşme sekiz ardışık çağrıdır; gecikme sınıfı **zincirdir**.
- **AK6. Kurgu görüşme sekiz turdur.** Konuyu belirleyen **anahtar tur** ikinci ile altıncı
  arasındadır; kalan turlar dolgudur ve üçü yanıltıcı sözcük taşır.
- **AK7. Ölçüt son turda verilen etikettir.** Reddedilen, zaman aşımına uğrayan ya da etiketi
  tamamlanmayan çağrı **yanlış** sayılır.
- **AK8.** Bedel **giriş belirteci, çıkış belirteci, adım ve başarısızlık payı**; çağrı sayısı
  beş kipte de **320**'dir.

#### Mesaj Tabanlı Arayüz ve Ağ Davranışlı Benzetici

Kaynak düzeni, sürümleme, hata yanıtı biçimi ve sözleşme Web API Tasarımı kursunda
ölçüldü; o yordam tekrarlanmaz. Mesaj tabanlı arayüzün eklediği tek şey gövdenin şeklidir: istek
bir alan kümesi değil, **rol ve içerik çiftlerinden oluşan bir listedir**.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; ag katmani da benzeticide:
# hiz siniri reddi, yarida kesilme, parca parca uretim.
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):
    """Parcalari sozcuge geri baglar."""
    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"}
KABUL = ["talebinizi aldim ve kaydi guncelledim",     # etiket istenmediginde
         "ilgili ekibe ilettim donus yapilacak",
         "kaydinizi kontrol ediyorum lutfen bekleyin"]
SAYAC = [0]


def duzlestir(mesajlar):
    """Rol etiketleri de belirtec eder."""
    return " ".join(f"{r} : {i}" for r, i in mesajlar)


def cagir(mesajlar, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN):
    """Mesaj tabanli arayuz. mesajlar: [(rol, icerik)], rol sistem|kullanici|model."""
    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, "yanit": "", "ilk": ilk, "adim": ilk}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % HIZ == 0:                       # hiz siniri cagri sayisinda
        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:                             # etiket kumesi adayi daraltir
        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])]
    c = cekilis(istem, tohum, 17)
    if "tek" in bel:                              # yalniz etiket istendi
        metin = k
    else:
        metin = KABUL[ayrik(c, [0.40, 0.33, 0.27])]
    pl, durum = parcala(metin), "tamam"
    if len(pl) > en_uzun:                         # durdurma kosulu
        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),
            "yanit": birlestir(pl), "ilk": ilk, "adim": ilk + len(pl)}


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


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 . kisa yanit ver .")
SORU = ("gorusme {n} konusunu su etiketlerden birine ata : fatura , ariza , "
        "sayac , tarife , kesinti . tek etiket yaz")

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)                       # anahtar tur ikiden altiya
    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]
print(f"gorusme {g['no']} -- konu {g['konu']} , anahtar tur {g['yeri']}")
gecmis, satir = [SISTEM], []
for t, metin in enumerate(g["tur"], 1):
    gecmis.append(("kullanici", metin))
    s = cagir(gecmis)
    satir.append(s["giris"])
    if t in (1, g["yeri"], 8):
        print(f"  tur {t}  gonderilen {s['giris']:>3}  cikis {s['cikis']:>2}"
              f"  ilk parca {s['ilk']}  {s['durum']:<6} -> {s['yanit'][:34]}")
    gecmis.append(("model", s["yanit"] or "-"))
print("  tur basina gonderilen giris belirteci:", satir)
print(f"  toplam {sum(satir)} belirtec , son turun {sum(satir) / satir[-1]:.2f} kati")
print("  ayni son tur tohum 20260219 ile ->", cagir(gecmis[:-1], TOHUM + 1)["yanit"])
```

```
gorusme 7301 -- konu kesinti , anahtar tur 5
  tur 1  gonderilen  21  cikis  8  ilk parca 1  tamam  -> talebinizi aldim ve kaydi guncelle
  tur 5  gonderilen  99  cikis 10  ilk parca 3  tamam  -> kaydinizi kontrol ediyorum lutfen 
  tur 8  gonderilen 187  cikis  2  ilk parca 5  tamam  -> kesinti
  tur basina gonderilen giris belirteci: [21, 41, 53, 75, 99, 123, 142, 187]
  toplam 741 belirtec , son turun 3.96 kati
  ayni son tur tohum 20260219 ile -> kesinti
```

Kullanıcı sekiz kısa cümle yazdı, ama arayüze giden toplam **741 belirteçtir** ve bu, son turun
tek başına ettiğinin **3,96 katıdır**. Nedeni açıktır: her tur, kendinden önceki bütün turları
yeniden taşır. Tur uzunlukları yaklaşık eşitse $n$ turluk bir görüşmenin toplam gönderimi
$n(n+1)/2$ ile büyür; tur sayısı ikiye katlandığında bedel dörde yaklaşır. İlk parça adımı da
1'den 5'e çıkıyor: uzayan durum yalnız pahalı değil, yavaştır. Son satırda aynı son tur ikinci
tohumla yine `kesinti` verdi; tek çağrıda çıktı sabit kaldı, ama aşağıdaki tablo bu sabitliğin
kırk görüşme ölçeğinde durmadığını gösterecek.

#### Beş Gönderim Kararı

Döküm istemcide olduğuna göre, her istekte **hangi parçasının** gönderileceği bir tasarım
kararıdır. Beş karar aynı kırk görüşmede koşturulur: durum göndermemek, dökümün tamamı, son üç
tur, yalnız kullanıcı sıraları ve döküm yerine istemcide üretilmiş **çıkarılmış bir durum
kaydı**. Sonuncunun çıkarıcısı yedi alan tanır ve tanımadığını sessizce düşürür.

```python
ALAN = {"fatur": "fatura", "borc": "borc", "ariza": "ariza", "sayac": "sayac",
        "endek": "endeks", "tarif": "tarife", "kesin": "kesinti"}


def durum_kaydi(gecmis):
    """Istemcide tutulan durum: dokum degil, alan listesi."""
    a = []
    for rol, icerik in gecmis:
        if rol == "kullanici":
            for t in belirtecle(icerik):
                if t in ALAN and ALAN[t] not in a:
                    a.append(ALAN[t])
    return " , ".join(a) if a else "yok"


def gonder(kip, gecmis, simdi):
    """Dokumun hangi kisminin gonderilecegi karari."""
    su = [("kullanici", simdi)]
    if kip == "durumsuz":
        return [SISTEM] + su
    if kip == "tam durum":
        return [SISTEM] + gecmis + su
    if kip == "son uc tur":
        return [SISTEM] + gecmis[-6:] + su
    if kip == "yalniz kullanici":
        return [SISTEM] + [m for m in gecmis if m[0] == "kullanici"] + su
    return [SISTEM, ("kullanici", "durum : " + durum_kaydi(gecmis))] + su


def olc(kip, tohum=TOHUM):
    SAYAC[0] = 0
    g = c = ad = dogru = basarisiz = 0
    for gr in GORUSME:
        gecmis = []
        for t, metin in enumerate(gr["tur"], 1):
            s = cagir(gonder(kip, gecmis, metin), tohum)
            g, c, ad = g + s["giris"], c + s["cikis"], ad + s["adim"]
            basarisiz += s["durum"] != "tamam"
            gecmis += [("kullanici", metin), ("model", s["yanit"] or "-")]
            if t == 8:
                dogru += oku(s["yanit"]) == gr["konu"]
    return g, c, ad, dogru, basarisiz / 320


KIP = ["durumsuz", "tam durum", "son uc tur", "yalniz kullanici", "durum kaydi"]
print("kip                giris  cikis  adim  isabet A  isabet B  basarisiz"
      "  dogru basina")
for kip in KIP:
    a, b = olc(kip), olc(kip, TOHUM + 1)
    print(f"{kip:<17} {a[0]:>6} {a[1]:>6} {a[2]:>5}  {a[3] / 40:>8.4f}"
          f"  {b[3] / 40:>8.4f}  {a[4]:>9.4f}  {(a[0] + a[1]) / a[3]:>12.1f}")

g0 = GORUSME[0]
print("\ndurum kaydi , gorusme", g0["no"], ":",
      durum_kaydi([("kullanici", m) for m in g0["tur"][:7]]))
bos = sum(durum_kaydi([("kullanici", m) for m in gr["tur"][:7]]) == "yok"
          for gr in GORUSME)
print("cikarici hicbir alan bulamayan gorusme:", bos, "/ 40")

gecmis, t = [], 0
while True:                                  # tam durum penceresi nerede asiyor
    t += 1
    metin = g0["tur"][t - 1] if t <= 7 else DOLGU[t % 8]
    s = cagir([SISTEM] + gecmis + [("kullanici", metin)])
    if s["durum"] == "baglam_asimi":
        print(f"tam durum {t}. turda pencereyi asiyor: {s['giris']} > {PENCERE}")
        break
    gecmis += [("kullanici", metin), ("model", s["yanit"])]
```

```
kip                giris  cikis  adim  isabet A  isabet B  basarisiz  dogru basina
durumsuz            8346   2350  2710    0.2000    0.2500     0.0406        1337.0
tam durum          31160   2341  3294    0.8250    0.7000     0.0625        1015.2
son uc tur         23102   2347  3132    0.4500    0.4250     0.0844        1413.8
yalniz kullanici   19738   2297  2946    0.6750    0.7750     0.1000         816.1
durum kaydi        10474   2393  2753    0.6500    0.5500     0.0375         494.9

durum kaydi , gorusme 7301 : kesinti
cikarici hicbir alan bulamayan gorusme: 5 / 40
tam durum 12. turda pencereyi asiyor: 246 > 240
```

İlk satır düzeneksiz istemcidir: durum taşınmadığında son tur yalnız etiket kümesini ve görüşme
numarasını görür, isabet **0,2000** ile beş etiket arasından şans payıdır. İkinci satır aynı işi
konuşma durumuyla yapar ve isabeti **0,8250**'ye çıkarır. Bedel giriş sütunundadır: **8346'dan
31160'a**, yani **3,73 kat**. Adım 2710'dan 3294'e çıkıyor, çünkü uzayan istem ilk parçayı
geciktiriyor; başarısızlık payı da 0,0406'dan 0,0625'e yükseliyor.

#### Ölçülen Kazanç, Ölçülmeyen Kazanç ve Sessiz Kayıp

Üç kısaltma kararı tabloyu ortadan böler. **Son üç tur** gönderimi girişi %26 azaltır ama isabeti
**0,4500'e** düşürür, çünkü anahtar tur çoğu görüşmede pencerenin dışında kalıyor. **Yalnız
kullanıcı sıraları** girişi %37 azaltır ve isabeti **0,6750**'de tutar; model kendi eski
yanıtlarını görmediğinde bir şey kaybetmiyor. **Çıkarılmış durum kaydı** girişi **%66 azaltır** ve
isabeti **0,6500**'de tutar.

Son iki sayının farkı **0,0250**'dir. İki koşum sütununa bakmak gerekiyor: tam durum satırı ikinci
tohumda 0,8250 yerine 0,7000 veriyor, yani bu düzeneğin koşum farkı **0,1250**'ye çıkabiliyor.
0,0250 bunun beşte biri kadardır ve **ölçülmemiş sayılır**; tam durum ile durum kaydı arasındaki
0,1750 ise koşum farkını aşar ve ölçülmüştür.

Son sütun sıralamayı değiştirir. Doğru etiket başına belirteç, son üç tur kipinde **1413,8**'dir
ve bu, hiç durum göndermeyen istemcinin **1337,0**'ından **pahalıdır**: bir kısaltma kararı hem
tam dökümün hem de düzeneksiz istemcinin altına düşebiliyor. Durum kaydı ise **494,9** ile en ucuz
doğru sonucu veriyor. Ucuzluğun bedeli çıkarıcının sessizliğidir: kırk görüşmenin **beşinde**
hiçbir alan bulunamıyor ve istemci bunu hata olarak değil `yok` diye bildiriyor. Son satır sınırı
söylüyor: görüşme sürdürülürse tam döküm **on ikinci turda** 246 belirteçle bağlam penceresini
aşıyor ve çağrı hiç kurulmuyor. Pencere aşımı Yapay Zekâ Mühendisliğine Giriş kursunda ölçüldü;
burada eklenen tek şey, o sınıra istemcinin **kendi durum kararının** sürüklediğidir.

#### Özet

- Konuşma durumu sunucuda tutulmaz; döküm her istekte yeniden gönderildiği için sekiz turluk bir
  görüşmenin toplam gönderimi son turun 3,96 katı olur.
- Durum taşınmadığında isabet 0,2000 ile şans düzeyinde kalır; döküm tümüyle gönderildiğinde
  0,8250'ye çıkar ve giriş belirteci 3,73 kat artar.
- Son üç tur gönderimi girişi %26 azaltır ama isabeti 0,4500'e düşürür; anahtar tur çoğu
  görüşmede dışarıda kalır.
- Çıkarılmış durum kaydı girişi %66 azaltır ve isabeti 0,6500'de tutar; yalnız kullanıcı
  sıralarıyla arasındaki 0,0250 fark, iki koşum farkı 0,1250 olduğu için ölçülmemiş sayılır.
- Doğru etiket başına belirteç sıralamayı değiştirir: son üç tur 1413,8 ile düzeneksiz istemciden
  pahalı, durum kaydı 494,9 ile en ucuzdur.
- Ucuz kararın bedeli sessiz kayıptır: çıkarıcı kırk görüşmenin beşinde alan bulamıyor ve bunu
  hata olarak bildirmiyor.

#### Sonraki Adım

Bu derste her yanıt tek parça hâlinde geldi ve kullanıcı onun tamamlanmasını bekledi. Basılan
**ilk parça adımı** hiçbir karara girmedi: uzayan istem ilk parçayı 1 adımdan 5 adıma iterken,
beklenen süre yine son parçaya kadar uzadı. Yanıt bütün olarak değil de üretildiği sırayla elimize
geçseydi hangi sayı değişir, hangisi aynı kalırdı. Bir de başarısızlık sütununda görünen
**kesilme** var: yanıtın ortasında olduğunda geriye ne kalıyor. Sonraki ders bu üçünü ayrı ayrı
sayar.

### Yanıt Akışı

Source: https://academia.sh/tr/kurslar/model-apileri/yanit-akisi

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 iniyor, 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 iner; 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.

### Araç ve İşlev Çağrısı

Source: https://academia.sh/tr/kurslar/model-apileri/arac-ve-islev-cagrisi

Model çıktısının yürütülecek bir çağrıya bağlanmasının ölçülmesi: 120 kurgu talepte araç kataloğu isteme yazılmadığında geçerli çağrı oranı 0,0500 ve yanıtların 0,6750'si var olmayan bir araç adı uyduruyor. Yalnız adlar verildiğinde uydurma ad 0,1500'e düşüyor ama parametre hatası 0,0667'den 0,5583'e fırlıyor: hata yok olmuyor, yer değiştiriyor. Adlar ve parametreler birlikte verildiğinde geçerli oran 0,6917, doğru aracı çağıran oran 0,5750 oluyor ve bunun bedeli girişte 3694'ten 11614 belirtece çıkmaktır. Doğru araç başına belirteç yine de 750,5'ten 178,2'ye düşüyor. Doğrulama 37 çağrıyı yakalıyor ama geçerli sayılan 83 çağrının 14'ü kayıtlı fakat yanlış aracı çağırıyor ve bu kalıntıyı hiçbir şema yakalamıyor. Biçim hatası katalogla birlikte azalmıyor, çünkü kaynağı istem değil ağdır.

Önceki iki derste yanıt bir metindi ve onu bir insan ya da basit bir yönlendirme kuralı okudu.
Etiketin erken gelmesi işi erkene çekiyordu, ama işi yapan hep başka bir şeydi.

Bir model çıktısı doğrudan bir **kod yürütmesine** bağlandığında ölçüt değişir. Yanıtın
okunabilir olması yetmez: çağrılan işlevin **var olması**, parametre adlarının **tutması** ve
değerlerin **kabul edilebilir** olması gerekir. Çok adımlı devam, bellek ve planlama burada
**yoktur**; onlar Yapay Zekâ Ajanları kursuna bırakılır. Bu derste hiçbir araç **yürütülmez**,
yalnız çağrının geçerliliği sayılır.

- **AK17.** Kod bir **benzeticidir** ve **araç kaydı da kurgudur**: ölçüm ağının destek hattının
  kendi işlevleri. Talepler kurgudur, tohum **20260218**. Hiçbir araç çalıştırılmaz.
- **AK18. Araç kaydı beş işlevdir**, her biri bir konuya karşılık gelir; birinin iki parametresi
  vardır. Parametre kuralı ya **sayı** ya da kapalı bir değer kümesidir.
- **AK19. Doğrulayıcı dört hata sınıfı sayar:** biçim (çağrı hiç ayrıştırılamadı), **uydurma ad**
  (kayıtta olmayan işlev), parametre (eksik, fazla, ya da geçersiz değer) ve hatasız.
- **AK20. Katalog üç düzeyde verilir:** hiç, yalnız **adlar**, ya da **adlar ve parametreler**.
  Benzetici kayıtlı adı kullanma eğilimini bu üç duruma göre değiştirir; eğilim kurgudur,
  ölçülen şey düzeyler arasındaki farktır.
- **AK21. Kavram seçimi yalnız son kullanıcı mesajından okunur.** Böylece üç düzey arasında
  yalnız çağrının biçimi değişir, modelin hangi konuyu gördüğü değişmez.
- **AK22. Ağ katmanı sürer.** Hız sınırı, zaman aşımı ve yarıda kesilme, çağrı metnini bozar;
  bozulan çağrı biçim ya da uydurma ad sınıfına düşer. Bu yüzden **biçim hatasının bir kısmının
  kaynağı istem değil ağdır** ve katalogla azalmaz.
- **AK23. Ürün ölçütü doğru araç oranıdır:** hem doğrulamayı geçen hem de talebin konusuna karşılık
  gelen işlevi çağıran yanıt.
- **AK24.** Bedel giriş ve çıkış belirteci olarak yazılır; çağrı sayısı üç düzeyde de **120**'dir.

#### Araç Kaydı, Ayrıştırıcı ve Doğrulayıcı

Bir işlev çağrısı, arayüzün ürettiği metnin **kayıtlı bir imzaya** oturtulmasıdır. Aşağıdaki kod
kaydı, çağrı ayrıştırıcısını ve doğrulayıcıyı kurar, sonra aynı talebi üç katalog düzeyinde
sorar.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; araclar da kurgudur ve
# hicbiri yurutulmez, yalniz cagrinin gecerliligi sayilir.
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"]
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"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "ekip": "kesinti", "takip": "tarife"}
SAYAC = [0]

# KURGU arac kaydi: olcum aginin destek hattinin kendi ucuncu taraf olmayan islevleri
ARAC = {"fatura_getir": {"abone": "sayi"},
        "ariza_kaydi_ac": {"abone": "sayi", "konu": KONU},
        "sayac_endeks_sor": {"sayac": "sayi"},
        "tarife_bilgisi": {"abone": "sayi"},
        "kesinti_sorgula": {"bolge": "sayi"}}
DOGRU = dict(zip(KONU, ARAC))
UYDURMA = {"fatura": "fatura_sorgula", "ariza": "ariza_bildir", "sayac": "sayac_oku",
           "tarife": "tarife_getir", "kesinti": "kesinti_listele"}
YANLIS = {"abone": "abone_no", "sayac": "sayac_no", "bolge": "bolge_kodu",
          "konu": "konu_adi"}


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):
    """Yanit bir arac cagrisi metnidir; hicbir arac yurutulmez."""
    SAYAC[0] += 1
    istem = duzlestir(mesajlar)
    bel = belirtecle(istem)
    ilk = 1 + len(bel) // 40
    bos = {"giris": len(bel), "cikis": 0, "yanit": "", "ilk": ilk}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % HIZ == 0:
        return dict(bos, durum="hiz_siniri")
    if len(bel) > 90 and cekilis(istem, tohum, 3) < 0.04:
        return dict(bos, durum="zaman_asimi")
    son = mesajlar[-1][1]                         # kavram yalniz son mesajdan okunur
    p = {k: 0.15 for k in KONU}
    for t in belirtecle(son):
        for tablo, w in ((IZ, 1.0), (TUZAK, 0.6)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    ad = sorted(p)
    from math import exp
    e = [exp(p[a] / sicaklik) for a in ad]
    k = ad[ayrik(cekilis(son, tohum, 5), [x / sum(e) for x in e])]
    kat, par = "arac" in bel, "param" in bel      # istemde katalog var mi
    u4 = cekilis(istem, tohum, 67)
    if u4 < (0.04 if kat else 0.12):              # cagri yerine serbest metin
        metin = f"talebiniz {k} konusunda kaydedildi"
    else:
        esik = 0.15 + (0.73 if kat else 0.0) + (0.06 if par else 0.0)
        adi = DOGRU[k] if cekilis(istem, tohum, 23) < esik else UYDURMA[k]
        no = next((x for x in istem.split() if x.isdigit()), "0")
        dogru_ad = par or cekilis(istem, tohum, 41) < 0.35
        bozuk_deger = cekilis(istem, tohum, 59) < 0.10
        alan = []
        for a, kural in ARAC[DOGRU[k]].items():
            anahtar = a if dogru_ad else YANLIS[a]
            if kural == "sayi":
                alan.append(f"{anahtar}={'bilinmiyor' if bozuk_deger else no}")
            else:
                alan.append(f"{anahtar}={'acil' if bozuk_deger else k}")
        metin = "cagri " + adi + " " + " ".join(alan)
    pl, durum = parcala(metin), "tamam"
    if len(pl) > en_uzun:
        pl, durum = pl[:en_uzun], "durduruldu"
    u = cekilis(istem, tohum, 91)
    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),
            "yanit": birlestir(pl), "ilk": ilk}


def cozumle(y):
    """Yanittan arac cagrisini cikarir: (ad, {parametre: deger}) ya da None."""
    p = y.split()
    if len(p) < 2 or p[0] != "cagri":
        return None
    d = {}
    for x in p[2:]:
        if "=" not in x:
            return None
        a, _, v = x.partition("=")
        d[a] = v
    return p[1], d


def dogrula(c):
    """Dort hata sinifi: bicim, uydurma ad, eksik/fazla parametre, gecersiz deger."""
    if c is None:
        return ["bicim"]
    adi, d = c
    if adi not in ARAC:
        return ["uydurma_ad"]
    sema = ARAC[adi]
    h = [f"eksik:{a}" for a in sema if a not in d]
    h += [f"fazla:{a}" for a in d if a not in sema]
    for a, kural in sema.items():
        if a not in d:
            continue
        if kural == "sayi" and not d[a].isdigit():
            h.append(f"sayi_degil:{a}")
        elif kural != "sayi" and d[a] not in kural:
            h.append(f"gecersiz:{a}")
    return h


KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                              # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})

YALIN = "destek talebini uygun bir islev cagrisiyla karsila ."
ADLAR = YALIN + " arac adlari : " + " , ".join(ARAC) + " ."
TAM = ADLAR + " parametreler : " + " , ".join(
    f"{a} ( {' '.join(s)} )" for a, s in ARAC.items()) + " ."

print("arac kaydi:", " , ".join(f"{a}({' '.join(s)})" for a, s in ARAC.items()))
for adi, onek in (("katalogsuz", YALIN), ("ad listesi", ADLAR),
                  ("ad ve parametre", TAM)):
    x = TALEP[0]
    s = cagir([("sistem", onek),
               ("kullanici", f"Talep {x['no']} : {x['metin']}")])
    h = dogrula(cozumle(s["yanit"]))
    print(f"  {adi:<16} giris {s['giris']:>3}  {s['yanit']}")
    print(f"                   hata {h if h else 'yok'}")
x = TALEP[0]
print("  ayni istek tohum 20260219 ile ->",
      cagir([("sistem", TAM), ("kullanici", f"Talep {x['no']} : {x['metin']}")],
            TOHUM + 1)["yanit"])
```

```
arac kaydi: fatura_getir(abone) , ariza_kaydi_ac(abone konu) , sayac_endeks_sor(sayac) , tarife_bilgisi(abone) , kesinti_sorgula(bolge)
  katalogsuz       giris  32  cagri kesinti_listele bolge_kodu=4001
                   hata ['uydurma_ad']
  ad listesi       giris  57  cagri kesinti_sorgula bolge_kodu=4001
                   hata ['eksik:bolge', 'fazla:bolge_kodu']
  ad ve parametre  giris  98  cagri kesinti_sorgula bolge=4001
                   hata yok
  ayni istek tohum 20260219 ile -> cagri sayac_endeks_sor sayac=4001
```

Üç satır aynı talebi, aynı konuyu ve üç ayrı hatayı gösteriyor. Katalogsuz düzeyde biçim
kusursuzdur: yanıt bir çağrıya benziyor, parametresi var, değeri doğru. Ama `kesinti_listele`
diye bir işlev **yoktur**. Bu, doğrulamanın en kolay yakaladığı ve en tehlikeli hatadır: kayıt
olmadan bakıldığında geçerli görünür.

İkinci satırda ad artık kayıtlıdır, fakat parametre adı `bolge_kodu` yazılmıştır ve kayıt
`bolge` bekler. Doğrulayıcı bunu iki hata olarak sayar: bir eksik anahtar, bir fazladan anahtar.
Üçüncü satırda hem ad hem parametre kayıtla uyuşuyor. Son satır kursun üçüncü kuralının
gereğidir: aynı istek ikinci bir tohumda **başka bir aracı** çağırdı, üstelik o çağrı da
doğrulamadan geçerdi.

#### Üç Katalog Düzeyinin Sayıları

Aynı 120 kurgu talep üç düzeyde koşturulur ve hata sınıfları ayrı ayrı sayılır.

```python
def olc(onek, tohum=TOHUM):
    SAYAC[0] = 0
    g = c = agda = gecerli = uydurma = bicim = param = dogru_arac = 0
    for x in TALEP:
        s = cagir([("sistem", onek),
                   ("kullanici", f"Talep {x['no']} : {x['metin']}")], tohum)
        g, c = g + s["giris"], c + s["cikis"]
        agda += s["durum"] != "tamam"
        cg = cozumle(s["yanit"])
        h = dogrula(cg)
        if not h:
            gecerli += 1
            dogru_arac += cg[0] == DOGRU[x["konu"]]
        elif h == ["uydurma_ad"]:
            uydurma += 1
        elif h == ["bicim"]:
            bicim += 1
        else:
            param += 1
    n = len(TALEP)
    return (g, c, agda, gecerli / n, uydurma / n, bicim / n, param / n,
            dogru_arac / n)


DUZEY = [("katalogsuz", YALIN), ("ad listesi", ADLAR), ("ad ve parametre", TAM)]
print("duzey            giris  cikis  agda  gecerli A  gecerli B  uydurma  bicim"
      "   param  dogru arac")
for adi, onek in DUZEY:
    a, b = olc(onek), olc(onek, TOHUM + 1)
    print(f"{adi:<15} {a[0]:>6} {a[1]:>6} {a[2]:>5}  {a[3]:>9.4f}  {b[3]:>9.4f}"
          f"  {a[4]:>7.4f} {a[5]:>6.4f}  {a[6]:>6.4f}  {a[7]:>10.4f}")

a = olc(TAM)
print(f"\ndogrulama {round((1 - a[3]) * 120)} cagriyi yakaladi ;"
      f" gecerli sayilan {round(a[3] * 120)} cagrinin"
      f" {round((a[3] - a[7]) * 120)} tanesi yanlis araci cagiriyor")
print("dogru arac basina belirtec :", end=" ")
for adi, onek in DUZEY:
    z = olc(onek)
    print(f"{adi} {(z[0] + z[1]) / (z[7] * 120):.1f}", end="  ")
print()
SAYAC[0] = 0
n = 0
for x in TALEP:
    s = cagir([("sistem", TAM), ("kullanici", f"Talep {x['no']} : {x['metin']}")])
    cg = cozumle(s["yanit"])
    if cg and not dogrula(cg) and cg[0] != DOGRU[x["konu"]] and n < 3:
        n += 1
        print(f"  kalinti : konu {x['konu']:<8} -> {s['yanit']}")
```

```
duzey            giris  cikis  agda  gecerli A  gecerli B  uydurma  bicim   param  dogru arac
katalogsuz        3694    809    13     0.0500     0.0500   0.6750 0.2083  0.0667      0.0500
ad listesi        6694    825    12     0.2250     0.2833   0.1500 0.0667  0.5583      0.1833
ad ve parametre  11614    684    25     0.6917     0.6917   0.0500 0.1583  0.1000      0.5750

dogrulama 37 cagriyi yakaladi ; gecerli sayilan 83 cagrinin 14 tanesi yanlis araci cagiriyor
dogru arac basina belirtec : katalogsuz 750.5  ad listesi 341.8  ad ve parametre 178.2  
  kalinti : konu ariza    -> cagri tarife_bilgisi abone=4004
  kalinti : konu kesinti  -> cagri ariza_kaydi_ac abone=4011 konu=ariza
  kalinti : konu tarife   -> cagri fatura_getir abone=4012
```

İlk satır düzeneksiz istemcidir ve tek bir sayıyla özetlenir: yanıtların **0,6750**'si var
olmayan bir işlev adı taşıyor. Geçerli çağrı oranı **0,0500**, yani yirmi talebin birinde
yürütülebilir bir çağrı çıkıyor. Model bir arayüzü görmeden onun adını **uyduruyor** ve uydurduğu
adlar makul görünüyor; bir insan gözü onları hemen ayırt edemez.

İkinci satır bu dersin en öğretici satırıdır. Adları vermek uydurma ad payını **0,6750'den
0,1500'e** düşürüyor, ama geçerli oran yalnız **0,2250**'ye çıkıyor. Çünkü parametre hatası
**0,0667'den 0,5583'e** fırlıyor. Hata yok olmadı, **yer değiştirdi**: model artık doğru kapıyı
çalıyor fakat yanlış anahtarla. Tek bir sayıya bakan bir ölçüm bu kaymayı göremez.

#### Doğrulamanın Yakaladığı ve Yakalamadığı

Üçüncü satır her iki bilgiyi birden verir: geçerli oran **0,6917**, uydurma ad **0,0500**,
parametre hatası **0,1000**. İki koşum farkı ikinci satırda 0,0583'tür ve düzeyler arasındaki
0,1750 ile 0,4667'lik farklar bunun kat kat üstündedir; bu kazançlar **ölçülmüştür**.

Bedel giriş sütununda durur: **3694'ten 11614 belirtece**, yani **3,14 kat**. Buna karşılık
doğru araç başına belirteç **750,5'ten 178,2'ye** düşüyor. Katalog pahalıdır ve yine de ucuzdur;
çünkü ödenen belirteç, atılan çağrı sayısından daha hızlı azalıyor.

Biçim sütunu düzeylerle birlikte inmiyor: 0,2083, sonra 0,0667, sonra 0,1583. Bunun nedeni yan
sütundadır. Ağ katmanında başarısız olan çağrı sayısı sırasıyla 13, 12 ve **25**'tir; en uzun
istemi gönderen düzey en çok kesilen düzeydir ve kesilen bir çağrı metni ayrıştırılamaz. Biçim
hatasının bir kısmının kaynağı istem değil **ağdır** ve hiçbir katalog onu azaltmaz.

Son iki satır doğrulamanın sınırını yazıyor. Doğrulayıcı **37 çağrıyı** yakaladı; geriye kalan 83
çağrının **14'ü** kayıtlı fakat **yanlış** işlevi çağırıyor. Kalıntı örneklerinde bir arıza talebi
için tarife bilgisi, bir kesinti talebi için arıza kaydı isteniyor. Bu çağrılar şemadan geçer,
yürütülür ve **yanlış sonucu** döndürür. Geçerlilik doğruluk değildir; bir şema neyin
çağrılabileceğini söyler, neyin çağrılması gerektiğini değil.

#### Özet

- Araç kaydı, ayrıştırıcı ve dört hata sınıflı doğrulayıcı ders içinde standart kitaplıkla
  yazılır; hiçbir araç yürütülmez.
- Katalog verilmediğinde yanıtların 0,6750'si var olmayan bir işlev adı uydurur ve geçerli çağrı
  oranı 0,0500'de kalır.
- Yalnız adları vermek uydurma adı 0,1500'e düşürür ama parametre hatasını 0,5583'e çıkarır: hata
  yok olmaz, yer değiştirir.
- Adlar ve parametreler birlikte verildiğinde geçerli oran 0,6917, doğru araç oranı 0,5750 olur;
  giriş belirteci 3694'ten 11614'e çıkarken doğru araç başına belirteç 750,5'ten 178,2'ye iner.
- Biçim hatası katalogla azalmaz, çünkü kaynağının bir kısmı ağdır: başarısız çağrı sayısı en
  uzun istemde 25'e çıkar.
- Doğrulama 37 çağrıyı yakalar, ama geçerli sayılan 83 çağrının 14'ü kayıtlı fakat yanlış işlevi
  çağırır ve bu kalıntıyı hiçbir şema yakalamaz.

#### Sonraki Adım

Bu derste geçerlilik **sonradan** denetlendi: yanıt geldi, ayrıştırıldı, doğrulandı ve geçmeyen
atıldı. Doğrulayıcı bir sayaç olarak iyi çalıştı, fakat şemadan geçmeyen 37 çağrı için yapabildiği
tek şey onları saymaktı. İstem Mühendisliği kursu biçimi **isteme yazarak** dayatmayı ölçmüş ve
uyum oranını 0,8000'e çıkarmıştı. Arayüzün kendisi üretimi şemanın dışına **çıkaramayacak** biçimde
kısıtlayabiliyorsa, o zaman istemle dayatma ile arayüzle dayatma arasında iki fark vardır: uyum
oranı ve belirteç. Sonraki ders bu ikisini yan yana basar ve arayüz düzeyindeki zorunluluğun neyi
kattığını, neyi katmadığını sayar.

### Yapılandırılmış Çıktı Kipi

Source: https://academia.sh/tr/kurslar/model-apileri/yapilandirilmis-cikti-kipi

Şemanın isteme yazılmasıyla arayüze verilmesinin yan yana ölçülmesi: dört alanlı şemada isteme yazmak 7654 giriş belirteci harcayıp 0,7583 uyum verirken arayüz alanı 4294 belirteçle 0,9000 veriyor. Şema on iki alana çıktığında istemle uyum 0,6083'e düşüyor, arayüzle 0,9000'de sabit kalıyor ve tasarruf 6360 belirtece çıkıyor. Ağ katmanı dışarıda bırakıldığında arayüz zorunluluğunun uyumu tam olarak 1,0000'dır ve bu, İstem Mühendisliği kursunun ölçtüğü sayıdır; ağ hesaba katıldığında aynı sayı 0,9000'e iniyor, yani şema zorunluluğunun kalan hata payı modelden değil ağdan geliyor. Doğru kayıt başına belirteç dört alanda 125,8'den 65,7'ye, on iki alanda 287,1'den 123,0'a düşüyor. Alan eklemek her iki kipte de çıkış belirtecini büyütüyor ama doğru kayıt oranını yükseltmiyor.

Önceki ders bir çağrının geçerliliğini **sonradan** denetledi: yanıt geldi, ayrıştırıldı,
doğrulandı ve geçmeyen atıldı. Doğrulayıcı iyi bir sayaçtı ama geçmeyen çağrılar için
yapabildiği tek şey onları saymaktı.

İstem Mühendisliği kursu biçimi **isteme yazarak** dayatmayı ölçtü: şemaya uyan yanıt oranı
serbest metinde 0,0000, biçim tarifiyle 0,8000, üretimi kısıtlayan şema dayatmasıyla 1,0000
çıkmıştı. O sayılar bu dersin **girdisidir** ve yeniden türetilmez. Burada eklenen iki şey var.
Birincisi, şema bir istek alanı olarak taşınabildiğinde **istemin uzunluğundan bağımsız** hâle
gelir; şema büyüdükçe iki yolun bedeli ayrışır. İkincisi, o 1,0000 sayısı **ağsız** bir dünyada
ölçülmüştür; bir ağ işleminde aynı zorunluluk aynı sayıyı vermez.

- **AK25.** Kod bir **benzeticidir**; talepler ve alan kümesi **kurgudur**, tohum **20260218**.
  Şema doğrulama yordamı İstem Mühendisliği kursunda ölçüldü ve burada yalnız **sayaç** olarak
  kullanılır.
- **AK26. Alan havuzu on iki alandır**; şema ilk dört, ilk sekiz ya da tümüdür. Alan kuralı ya
  **sayı** ya kapalı bir değer kümesidir.
- **AK27. İki dayatma yolu ölçülür.** İstemle dayatmada şemanın **tarifi** sistem mesajına
  yazılır: alan adları ve izin verilen değerler. Arayüzle dayatmada şema bir **istek alanıdır**;
  yalnız alan adları taşınır ve bu belirteçler de sayıma girer.
- **AK28. Arayüzle dayatmada üretim şemanın dışına çıkamaz.** İstemle dayatmada her alan
  bağımsız bir çekilişle doğru üretilir; başarısız çekilişte alan atlanır, adı bozulur ya da
  değeri kapalı kümenin dışına çıkar.
- **AK29. Ağ katmanı sürer.** Hız sınırı, zaman aşımı ve yarıda kesilme kaydı bozar; **ağsız
  uyum** sütunu yalnız tamamlanan çağrılar üzerinde okunur ve İstem Mühendisliği kursunun ölçtüğü
  sayıya karşılık gelir.
- **AK30. Kavram yalnız son kullanıcı mesajından okunur**, böylece iki kip arasında yalnız
  dayatma yolu değişir.
- **AK31. Ürün ölçütü doğru kayıttır:** hem şemaya uyan hem konu alanı talebin konusuna eşit olan
  yanıt.
- **AK32.** Bağlam penceresi ve en büyük çıktı uzunluğu bu derste büyük kayıtlara göre
  genişletilmiştir; eşikler kurgudur. Çağrı sayısı altı kurulumda da **120**'dir.

#### Şemanın İki Taşınma Biçimi

Aynı şema iki yoldan gidebilir: istemin içinde bir cümle olarak, ya da isteğin bir alanı olarak.
İlkinde şema modelin okuduğu metnin parçasıdır ve her alan için birkaç belirteç eder; ikincisinde
yalnız alan adları taşınır ve **üretim kısıtlanır**.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; ag katmani da benzeticide.
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, EN_UZUN, HIZ = 480, 60, 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"]
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"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "ekip": "kesinti", "takip": "tarife"}
ALANLAR = [("talep_no", "sayi"), ("konu", KONU),
           ("oncelik", ["dusuk", "orta", "yuksek"]),
           ("aksiyon", ["kayit", "yonlendirme", "bilgi"]), ("abone_no", "sayi"),
           ("kanal", ["telefon", "uygulama", "web"]), ("bolge_no", "sayi"),
           ("durum", ["acik", "beklemede", "kapali"]), ("sayac_no", "sayi"),
           ("ariza_kodu", "sayi"), ("adim_no", "sayi"), ("kayit_no", "sayi")]
SAYAC = [0]


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


def cagir(mesajlar, sema, arayuzle, tohum=TOHUM, sicaklik=0.6):
    """sema arayuzle dayatiliyorsa istek alani olarak tasinir ve uretim disina cikamaz."""
    SAYAC[0] += 1
    istem = duzlestir(mesajlar)
    bel = belirtecle(istem)
    if arayuzle:
        bel = bel + belirtecle(" ".join(sema))    # sema istek alani olarak tasinir
    ilk = 1 + len(bel) // 40
    bos = {"giris": len(bel), "cikis": 0, "yanit": "", "ilk": ilk}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % HIZ == 0:
        return dict(bos, durum="hiz_siniri")
    if len(bel) > 90 and cekilis(istem, tohum, 3) < 0.04:
        return dict(bos, durum="zaman_asimi")
    son = mesajlar[-1][1]                         # kavram yalniz son mesajdan okunur
    p = {k: 0.15 for k in KONU}
    for t in belirtecle(son):
        for tablo, w in ((IZ, 1.0), (TUZAK, 0.6)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    ad = sorted(p)
    from math import exp
    e = [exp(p[a] / sicaklik) for a in ad]
    k = ad[ayrik(cekilis(son, tohum, 5), [x / sum(e) for x in e])]
    no = int(next((x for x in istem.split() if x.isdigit()), "0"))
    alan = []
    for i, (a, kural) in enumerate(sema.items()):
        d = k if kural == KONU else (str(no + i) if kural == "sayi"
                                     else kural[(no + i) % len(kural)])
        if arayuzle or cekilis(istem, tohum, 101 + i) < 0.955:
            alan.append(f"{a}={d}")               # sema disina cikilamaz
        else:                                     # istemle dayatmada uc bozulma
            b = ayrik(cekilis(istem, tohum, 211 + i), [0.34, 0.33, 0.33])
            if b == 1:
                alan.append(f"{a.replace('_', '')}={d}")
            elif b == 2:
                alan.append(f"{a}={'x' + d if kural == 'sayi' else 'acil'}")
    pl, durum = parcala(" ; ".join(alan)), "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),
            "yanit": birlestir(pl), "ilk": ilk}


def dogrula(y, sema):
    """Sema dogrulama yordami Istem Muhendisligi kursunda olculdu; burada sayactir."""
    kayit = {}
    for parca in y.split(" ; "):
        a, _, d = parca.partition("=")
        kayit[a.strip()] = d.strip()
    if sorted(kayit) != sorted(sema):
        return False
    for a, kural in sema.items():
        d = kayit[a]
        if (not d.isdigit()) if kural == "sayi" else (d not in kural):
            return False
    return True


def oku(y, sema):
    for parca in y.split(" ; "):
        a, _, d = parca.partition("=")
        if a.strip() == "konu" and "konu" in sema:
            return d.strip()
    return None


KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                              # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})


def tarif(sema):
    """Semanin isteme yazilan hali: alan adlari ve izin verilen degerler."""
    p = [f"{a}=<{'sayi' if k == 'sayi' else '|'.join(k)}>" for a, k in sema.items()]
    return "Yaniti su bicimde yaz : " + " ; ".join(p) + " ."


def istemi(sema, x, arayuzle):
    onek = "" if arayuzle else tarif(sema)
    return [("sistem", "destek kaydi cikaran bir yardimcisin . " + onek),
            ("kullanici", f"Talep {x['no']} : {x['metin']}")]


SEMA4 = dict(ALANLAR[:4])
for arayuzle in (False, True):
    s = cagir(istemi(SEMA4, TALEP[0], arayuzle), SEMA4, arayuzle)
    yol = "arayuzle" if arayuzle else "istemle"
    print(f"{yol:<9} giris {s['giris']:>3}  cikis {s['cikis']:>2}  "
          f"uyum {dogrula(s['yanit'], SEMA4)}  {s['yanit']}")
print("dort alanli semanin tarifi:", len(belirtecle(tarif(SEMA4))),
      "belirtec , istek alani olarak:", len(belirtecle(" ".join(SEMA4))))
print("on iki alanli:", len(belirtecle(tarif(dict(ALANLAR)))), "belirtec ,",
      len(belirtecle(" ".join(dict(ALANLAR)))), "belirtec")
print("ayni istek tohum 20260219 ile ->",
      cagir(istemi(SEMA4, TALEP[0], False), SEMA4, False, TOHUM + 1)["yanit"])
```

```
istemle   giris  65  cikis 15  uyum True  talep_no=4001 ; konu=kesinti ; oncelik=orta ; aksiyon=bilgi
arayuzle  giris  37  cikis 15  uyum True  talep_no=4001 ; konu=kesinti ; oncelik=orta ; aksiyon=bilgi
dort alanli semanin tarifi: 35 belirtec , istek alani olarak: 7
on iki alanli: 74 belirtec , 21 belirtec
ayni istek tohum 20260219 ile -> talep_no=4001 ; konu=sayac ; oncelik=orta ; aksiyon=bilgi
```

İki yol aynı talepte aynı kaydı üretti ve ikisi de doğrulamadan geçti; fark giriş sütunundadır.
Dört alanlı şemanın **tarifi 35 belirteç**, aynı şemanın istek alanı olarak taşınması **7
belirteç**. Aradaki fark şema büyüdükçe sürüyor: on iki alanda 74'e karşı 21. Tarif alan
adlarını, izin verilen değerleri ve bir yönerge cümlesini taşımak zorundadır; istek alanı yalnız
adları taşır ve kuralı arayüz zaten bilir.

Son satır kursun üçüncü kuralının gereğidir: aynı istek ikinci bir tohumda konu alanına başka bir
değer yazdı, üstelik o kayıt da şemadan geçerdi.

#### Altı Kurulumun Uyum ve Bedel Tablosu

Aynı 120 kurgu talep iki dayatma yolunda ve üç şema büyüklüğünde koşturulur.

```python
def olc(n, arayuzle, tohum=TOHUM):
    SAYAC[0] = 0
    sema = dict(ALANLAR[:n])
    g = c = agda = uyan = tamam = tamam_uyan = kayit = 0
    for x in TALEP:
        s = cagir(istemi(sema, x, arayuzle), sema, arayuzle, tohum)
        g, c = g + s["giris"], c + s["cikis"]
        u = dogrula(s["yanit"], sema)
        agda += s["durum"] != "tamam"
        uyan += u
        if s["durum"] == "tamam":
            tamam, tamam_uyan = tamam + 1, tamam_uyan + u
        kayit += u and oku(s["yanit"], sema) == x["konu"]
    return g, c, agda, uyan / 120, tamam_uyan / tamam, kayit / 120


print("kip       alan  giris  cikis  agda  uyum A  uyum B  agsiz uyum  dogru kayit")
for arayuzle in (False, True):
    for n in (4, 8, 12):
        a, b = olc(n, arayuzle), olc(n, arayuzle, TOHUM + 1)
        print(f"{'arayuzle' if arayuzle else 'istemle':<9} {n:>4} {a[0]:>6} {a[1]:>6}"
              f" {a[2]:>5}  {a[3]:>6.4f}  {b[3]:>6.4f}  {a[4]:>10.4f}  {a[5]:>11.4f}")

for n in (4, 12):
    i, y = olc(n, False), olc(n, True)
    print(f"\n{n} alan : arayuz {i[0] - y[0]} giris belirteci tasarruf ediyor ,"
          f" uyum farki {y[3] - i[3]:.4f} ,"
          f" dogru kayit basina belirtec {(i[0] + i[1]) / (i[5] * 120):.1f}"
          f" -> {(y[0] + y[1]) / (y[5] * 120):.1f}")
```

```
kip       alan  giris  cikis  agda  uyum A  uyum B  agsiz uyum  dogru kayit
istemle      4   7654   1658    11  0.7583  0.8167      0.8349       0.6167
istemle      8  10294   3361    14  0.7250  0.7333      0.8208       0.6000
istemle     12  12334   4894    16  0.6083  0.5583      0.7019       0.5000
arayuzle     4   4294   1688    12  0.9000  0.9167      1.0000       0.7583
arayuzle     8   5014   3417    12  0.9000  0.9167      1.0000       0.7583
arayuzle    12   5974   5219    12  0.9000  0.9167      1.0000       0.7583

4 alan : arayuz 3360 giris belirteci tasarruf ediyor , uyum farki 0.1417 , dogru kayit basina belirtec 125.8 -> 65.7

12 alan : arayuz 6360 giris belirteci tasarruf ediyor , uyum farki 0.2917 , dogru kayit basina belirtec 287.1 -> 123.0
```

İstemle dayatma satırları şema büyüdükçe aşağı iner: uyum **0,7583**, sonra 0,7250, sonra
**0,6083**. Nedeni yapısaldır. Her alan bağımsız bir çekilişe bağlıysa, bütün alanların birden
doğru olma olasılığı alan sayısıyla üstel olarak düşer; dört alanda ödenen küçük risk on iki
alanda ödenmez bir hâle gelir. Arayüzle dayatma satırları ise üç büyüklükte de **0,9000**'da
duruyor. Şema büyüdü, uyum değişmedi.

Giriş sütunu aynı ayrışmayı bedelde gösteriyor. İstemle dayatma 7654'ten **12334** belirtece
çıkarken arayüzle dayatma 4294'ten **5974**'e çıkıyor; tasarruf dört alanda 3360, on iki alanda
**6360** belirteç. Çıkış sütunu ise iki kipte de büyüyor (1688'den 5219'a), çünkü kayıt gerçekten
uzuyor. On iki alanda arayüzle dayatmanın çıkışı istemle dayatmanınkinden **fazladır**: 5219'a
karşı 4894. Bunun nedeni bozulan alanların **atlanmasıdır**; eksik kayıt daha kısadır.

#### Ağsız Uyum ve Ağın Payı

Tablonun en önemli sütunu **ağsız uyumdur**. Arayüzle dayatmada bu sütun üç satırda da tam
**1,0000**'dır. İstem Mühendisliği kursunun ölçtüğü sayı budur ve burada aynen çıkıyor: üretim
şemanın dışına çıkamıyorsa, tamamlanan her yanıt şemaya uyar.

Aynı satırların uyum sütunu ise **0,9000**'dır. Aradaki **0,1000**, modelin değil **ağın**
payıdır: 120 çağrının 12'si hız sınırına, zaman aşımına ya da yarıda kesilmeye takılıyor ve
yarım bir kayıt şemadan geçmiyor. Kursun kuralı burada doğrudan görünür hâle gelir. Bir işlev
çağrısı olarak ölçüldüğünde şema zorunluluğunun uyumu 1,0000'dır; bir **ağ işlemi** olarak
ölçüldüğünde 0,9000. Başarısızlığı yazılmayan çağrı ölçülmemiş sayılır ve aradaki fark tam
olarak yazılmayan o başarısızlıktır.

İki koşum farkı en çok **0,0583**'tür (istemle dayatma, dört alan). Arayüzün dört alandaki
kazancı 0,1417, on iki alandaki kazancı 0,2917; ikisi de bu farkın üstünde ve **ölçülmüştür**.
Doğru kayıt başına belirteç dört alanda **125,8'den 65,7'ye**, on iki alanda **287,1'den
123,0'a** iniyor.

Son sütun bir uyarı taşıyor. Arayüzle dayatmada doğru kayıt oranı üç büyüklükte de **0,7583**'te
sabit; uyum 0,9000 ile arasındaki 0,1417, şemadan geçen ama **konusu yanlış** olan kayıtlardır.
Alan eklemek çıkış belirtecini üç katına çıkardı ve doğru kayıt oranını **hiç** değiştirmedi.
Biçimin garantisi içeriğin garantisi değildir; bu ayrım İstem Mühendisliği kursunda ölçüldü ve
burada bir kez daha, arayüz düzeyinde, aynı yerde duruyor.

#### Özet

- Aynı şemanın isteme yazılan tarifi dört alanda 35, on iki alanda 74 belirteç eder; istek alanı
  olarak taşınan biçimi 7 ve 21 belirteçtir.
- İstemle dayatmanın uyumu şema büyüdükçe 0,7583'ten 0,6083'e iner, çünkü her alan bağımsız bir
  risktir; arayüzle dayatma üç büyüklükte de 0,9000'da kalır.
- Giriş belirteci istemle 7654'ten 12334'e, arayüzle 4294'ten 5974'e çıkar; tasarruf dört alanda
  3360, on iki alanda 6360 belirteçtir.
- Arayüzle dayatmanın ağsız uyumu tam 1,0000'dır; ağ hesaba katıldığında 0,9000'e iner ve aradaki
  0,1000 modelin değil ağın payıdır.
- Doğru kayıt başına belirteç dört alanda 125,8'den 65,7'ye, on iki alanda 287,1'den 123,0'a
  düşer; iki koşum farkı en çok 0,0583 olduğu için bu kazançlar ölçülmüştür.
- Alan eklemek çıkış belirtecini 1688'den 5219'a çıkarır ama doğru kayıt oranını 0,7583'te sabit
  bırakır: biçim garantisi içerik garantisi değildir.

#### Sonraki Adım

Dört derste arayüzün dört yeteneği ölçüldü ve her birinin bedeli belirteçle yazıldı: konuşma
durumunun taşınması, yanıtın parça parça alınması, çıktının bir çağrıya bağlanması ve çıktının
bir şemaya oturtulması. Dördünün ortak bir varsayımı vardı ve hiç sorgulanmadı: **girdi hep
metindi**. Talep bir cümleydi, durum bir dökümdü, şema bir alan listesiydi ve hepsi aynı
belirteçleyiciden geçti.

Bir destek talebinin yanında bir sayaç fotoğrafı, bir sesli mesaj ya da bir kısa görüntü
geldiğinde bu sayıların hiçbiri olduğu gibi kalmaz. Aynı bilgi metin olarak da verilebiliyorsa
hangisi kaç belirteç ediyor ve biçim değiştiğinde isabet ne oluyor. Sonraki ders girdinin
biçimini bir değişken hâline getirir ve bedelini aynı ölçekte sayar.

### Çok Kipli Girdi

Source: https://academia.sh/tr/kurslar/model-apileri/cok-kipli-girdi

Aynı saha denetim kaydının altı girdi biçiminde ölçülmesi: metin özeti 21, kırpık ince ızgara 42, kaba ızgara 59, ince ızgara 183 belirteç ve dizi kayıt başına 195 ile 330 arasında. Kullanılabilir kayıt oranı kaba ızgarada 0,0833, ince ızgarada 0,8167, kırpık ızgarada 0,7000; kırpık biçim ince ızgaranın kullanılabilir kayıtlarının yüzde seksen altısını dörtte bir belirteçle veriyor ve kayıt başına bedel 224,1'den 60,0'a düşüyor. Dizi biçimi en yüksek görünürlüğe sahip olduğu hâlde altmış kaydın otuz dördünde bağlam penceresini aştığı için 0,3667'de kalıyor ve en pahalı biçim oluyor. Ses kipi endeksi 0,8833 ile okuyor ama gövde durumuna kör olduğu için kullanılabilir kayıt üretmiyor.

Önceki dört ders arayüzün ne sunduğunu ölçtü: rol ve içerikten oluşan bir mesaj dizisi, parça
parça gelen bir yanıt, kod yürütmeye bağlanan bir çağrı ve üretimi kısıtlayan bir çıktı kipi.
Dördünde de modele giren şey **metindi**. Belirteç sayımı metnin üzerinde yapıldı, bağlam
penceresi metinle doldu, kısaltma kararları metinden budandı.

Saha ekibinin elindeki denetim kaydı metin değil. Sayacın yüzünün bir görüntüsü var, bazen bir
ses notu, bazen birkaç karelik bir çekim. Çok kipli bir arayüz bunları kabul eder; kabul etmesi
bedava değildir. Bu ders aynı denetim kaydını altı ayrı biçimde gönderir ve iki sayıyı yan yana
basar: **girdinin belirteç bedeli** ve **okumanın isabeti**. Ölçülen şey modelin görme yeteneği
değil, biçim seçiminin faturasıdır.

- **AK41.** Kod bir **benzeticidir**; gerçek bir çok kipli uç nokta çağrılmaz. Denetim kayıtları,
  sayaç yüzü ve bütün kip görünürlükleri **kurgudur**, tohum **20260218**.
- **AK42.** Çok kipli bir uç noktanın faturaladığı birim yine **belirteçtir**. Görüntü ızgara
  hücrelerine, ses parçalara, dizi karelere ayrılır ve **her hücre bir belirteç** sayılır. Bu
  dersin bütün bedel sütunu bu birimle yazılır.
- **AK43.** Altı biçim şunlardır: elle yazılmış **metin** özeti, **kaba ızgara** (4x10), **ince
  ızgara** (8x20), **kırpık** ince ızgara (3x8), **dizi** (kayıt başına dört ile yedi kare, her
  kare bir kaba ızgara) ve **ses** (on sekiz ile otuz parça).
- **AK44.** Her kip iki **görünürlük** payı taşır: endeksin ve gövde durumunun doğru okunma payı.
  Bu paylar benzeticinin kurgu sabitleridir; çözünürlük arttıkça yükselirler.
- **AK45.** Ses kipinin gövde durumu görünürlüğü **sıfırdır**. Bir kip bir alana **kör** olabilir
  ve bu bir hata değil, o kipin taşıdığı bilginin sınırıdır.
- **AK46.** **Kullanılabilir kayıt**, hem endeksi hem gövde durumu doğru okunan kayıttır; bu
  dersin ürün ölçütü budur. Tek alanı doğru okunan kayıt saha ekibinin işine yaramaz.
- **AK47.** Bağlam penceresi **240 belirteç**, hız sınırı **otuz yedi çağrıda bir**. Yapay Zekâ
  Mühendisliğine Giriş kursunda kurulan yüzey aynen sürer.
- **AK48.** Makine Öğrenmesi ve Veri Bilimi müfredatının Doğal Dil İşleme ve Bilgisayarla Görme
  kursu çok kipli modelin **ortak temsilini** ölçtü; o yordam burada tekrarlanmaz. Ölçülen tek
  şey **girdi biçiminin bedelidir**.

#### Bir Kaydın Altı Biçimi

Bir görüntü arayüzden geçerken bir sayı dizisine, o dizi de belirteçlere çevrilir. Bu dersin
benzeticisi çevrimi görünür kılmak için ızgarayı doğrudan istem metnine yazar: her hücre bir
damga, her damga bir belirteç. Gerçek bir uç noktada ara adımlar farklıdır, **fatura aynı yerden
çıkar** — çözünürlük yükseldikçe belirteç sayısı hücre sayısıyla birlikte büyür.

Aşağıdaki blok altmış kurgu denetim kaydını üretir, altı biçimi kurar ve çok kipli çağrıyı
tanımlar. Görünürlük paylarının kipe göre değişmesi benzeticinin tek varsayımıdır.

```python
# BENZETICI -- KURGUDUR. Gercek bir cok kipli uc nokta cagrilmaz. Denetim
# kayitlari, sayac yuzu ve butun kip gorunurlukleri kurgudur.
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE = 240


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


DURUM = ["saglam", "catlak", "muhursuz"]
KAYIT = []
for i in range(60):                     # 60 KURGU saha denetim kaydi
    r = uretec(TOHUM + 900 + i)
    KAYIT.append({"no": 7001 + i,
                  "endeks": "".join(str(int(r() * 10)) for _ in range(5)),
                  "durum": DURUM[ayrik(r(), [0.58, 0.27, 0.15])],
                  "kare": 4 + int(r() * 4), "sure": 18 + int(r() * 13)})
HUCRE = ".:-=+*#"


def izgara(kayit, satir, sutun):
    """Sayac yuzunun KURGU izgarasi: her hucre ayri bir belirtec olarak yazilir."""
    r = uretec(izno(kayit["endeks"] + kayit["durum"]) ^ (satir * 31 + sutun))
    out = []
    for y in range(satir):
        out.append(f"s{y}")
        out += [HUCRE[int(r() * 7)] for _ in range(sutun)]
    return " ".join(out)


def govde(kayit, kip):
    """Ayni kaydin alti girdi bicimi. Tasinan bilgi ayni, uzunluk degil."""
    if kip == "metin":
        return f"endeks {kayit['endeks']} govde {kayit['durum']}"
    if kip == "izgara kaba":
        return izgara(kayit, 4, 10)
    if kip == "izgara ince":
        return izgara(kayit, 8, 20)
    if kip == "izgara kirpik":
        return izgara(kayit, 3, 8)
    if kip == "ses":
        r = uretec(izno(kayit["endeks"]) ^ 7717)
        return " ".join(f"d{int(r() * 9)}" for _ in range(kayit["sure"]))
    return " ".join(f"k{j} " + izgara(kayit, 4, 10)
                    for j in range(kayit["kare"]))          # dizi: kare kare


GORUNUR = {"metin": (1.00, 1.00), "izgara kaba": (0.62, 0.16),
           "izgara ince": (0.93, 0.85), "izgara kirpik": (0.91, 0.80),
           "dizi": (0.88, 0.95), "ses": (0.90, 0.00)}
ONEK = "Sayac yuzunu oku . Endeks ve govde durumunu yaz . Kayit: "
SAYAC = [0]


def cagir_kipli(kayit, kip, tohum=TOHUM):
    """Cok kipli benzetici: her kip her alani kendi gorunurluk payiyla tasir."""
    SAYAC[0] += 1
    bel = belirtecle(ONEK + govde(kayit, kip))
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0}
    if SAYAC[0] % 37 == 0:
        return {"durum": "hiz_siniri", "giris": len(bel), "cikis": 0}
    r = uretec(tohum ^ izno(" ".join(bel)))
    ge, gd = GORUNUR[kip]
    e, d = kayit["endeks"], kayit["durum"]
    if r() >= ge:                       # okunamayan basamak komsusuna kayar
        j = int(r() * 5)
        e = e[:j] + str((int(e[j]) + 1 + int(r() * 8)) % 10) + e[j + 1:]
    if r() >= gd:
        d = DURUM[(DURUM.index(d) + 1 + int(r() * 2)) % 3]
    return {"durum": "tamam", "giris": len(bel), "endeks": e, "govde": d,
            "cikis": len(belirtecle(f"endeks {e} govde {d}"))}


k = KAYIT[0]
print(f"kayit {k['no']} : endeks {k['endeks']} , govde {k['durum']} ,"
      f" {k['kare']} kare , {k['sure']} ses parcasi")
for kip in GORUNUR:
    print(f"  {kip:<14} giris belirteci {len(belirtecle(ONEK + govde(k, kip))):>4}")
print("kaba izgaranin ilk iki satiri:")
print(" ", " ".join(izgara(k, 4, 10).split()[:22]))
uzun = next(x for x in KAYIT if x["kare"] == 7)
for kayit, kip in ((k, "metin"), (k, "izgara kaba"), (k, "izgara ince"),
                   (uzun, "dizi")):
    s = cagir_kipli(kayit, kip)
    bilgi = (f"endeks {s['endeks']} govde {s['govde']}" if s["durum"] == "tamam"
             else f"{s['giris']} belirtec , pencere {PENCERE}")
    print(f"{kayit['no']} {kip:<14} {s['durum']:<13} {bilgi}")
```

```
kayit 7001 : endeks 17328 , govde saglam , 5 kare , 21 ses parcasi
  metin          giris belirteci   21
  izgara kaba    giris belirteci   59
  izgara ince    giris belirteci  183
  izgara kirpik  giris belirteci   42
  dizi           giris belirteci  240
  ses            giris belirteci   36
kaba izgaranin ilk iki satiri:
  s0 . * : - = * - : : + s1 = . : + = + : * + .
7001 metin          tamam         endeks 17328 govde saglam
7001 izgara kaba    tamam         endeks 17328 govde catlak
7001 izgara ince    tamam         endeks 17328 govde saglam
7005 dizi           baglam_asimi  330 belirtec , pencere 240
```

Tek kaydın altı biçimi arasındaki fark **21 belirteç ile 240 belirteç** arasında geziniyor.
Taşınan bilgi her satırda aynı: beş basamaklı bir endeks ve üç değerli bir gövde durumu. Aradaki
on bir katlık fark bilgiden değil, **bilginin sarıldığı kaptan** geliyor.

Son dört satır iki ayrı başarısızlık gösteriyor. Kaba ızgara endeksi doğru okuyor ama gövde
durumunu `saglam` yerine `catlak` diye veriyor: çözünürlük mührün ve çatlağın ayırt edilmesine
yetmiyor. Yedi kareli 7005 numaralı kayıtta ise okuma hiç gerçekleşmiyor; 330 belirteçlik dizi
240 belirteçlik pencereye girmiyor ve çağrı `baglam_asimi` ile dönüyor. **En zengin girdi, hiç
girdi olmayan girdidir.**

#### Altı Biçimin Bedel ve İsabet Tablosu

Altmış kaydın tamamı altı biçimde ayrı ayrı koşturulur. Her satırda toplam giriş belirteci,
toplam çıkış belirteci, başarısız çağrı sayısı, iki alanın ayrı isabetleri, kullanılabilir kayıt
oranı ve **kullanılabilir kayıt başına belirteç** basılır. Son sütun ikinci koşumdur: tohum
20260219 ile alınan kullanılabilir kayıt oranı, bir farkın gürültüden ayırt edilip
edilemeyeceğini söyler.

```python
def olc(kip, tohum=TOHUM):
    SAYAC[0] = 0
    g = c = hata = ie = idr = kul = 0
    for x in KAYIT:
        s = cagir_kipli(x, kip, tohum)
        g, c = g + s["giris"], c + s["cikis"]
        if s["durum"] != "tamam":
            hata += 1
            continue
        e, d = s["endeks"] == x["endeks"], s["govde"] == x["durum"]
        ie, idr, kul = ie + e, idr + d, kul + (e and d)
    return g, c, hata, ie / 60, idr / 60, kul / 60


print("kip             giris  cikis  basarisiz  endeks   durum  kullanilabilir"
      "  bel/kayit  ikinci kosum")
for kip in GORUNUR:
    a, b = olc(kip), olc(kip, TOHUM + 1)
    bk = f"{a[0] / (a[5] * 60):.1f}" if a[5] else "-"
    print(f"{kip:<14} {a[0]:>6} {a[1]:>6} {a[2]:>10} {a[3]:>7.4f} {a[4]:>7.4f}"
          f" {a[5]:>15.4f} {bk:>10} {b[5]:>13.4f}")
```

```
kip             giris  cikis  basarisiz  endeks   durum  kullanilabilir  bel/kayit  ikinci kosum
metin            1260    354          1  0.9833  0.9833          0.9833       21.4        0.9833
izgara kaba      3540    354          1  0.6500  0.1333          0.0833      708.0        0.0833
izgara ince     10980    354          1  0.9500  0.8500          0.8167      224.1        0.7833
izgara kirpik    2520    354          1  0.8833  0.7833          0.7000       60.0        0.6833
dizi            16155    150         35  0.3667  0.4167          0.3667      734.3        0.2833
ses              2300    354          1  0.8833  0.0000          0.0000          -        0.0000
```

Çıkış belirteci sütunu beş satırda aynı: 354; dizide 150, çünkü otuz beş çağrı hiç yanıt üretmiyor. Yanıt her biçimde altı belirteçlik tek bir
kayıttır. Değişen şey yalnız girdidir ve bu, çok kipli bir arayüzün faturasının **hangi tarafta
şiştiğini** gösteren en sade satırdır. Metin özetinin toplam bedeli 1260 belirteç; ince ızgaranın
bedeli 10980, yani sekiz buçuk katı. Aynı bilgi, aynı yanıt.

Birinci satır bir sınır durumudur ve dürüstçe okunmalıdır. Metin özeti hem en ucuz hem en
isabetlidir, ama o özeti **birisi zaten okumuş** olmalıdır. Kullanılabilir kayıt oranının
0,9833'te kalmasının sebebi de okuma değil, otuz yedinci çağrıda gelen hız sınırı reddidir. Bu
satır bir kip seçeneği değil, işin insan tarafında çözülmüş hâlidir; tablodaki işlevi diğer beş
satırın **ne kadarını geri kazanmaya çalıştığını** göstermektir.

#### Kırpma, Kör Kip ve Pencereye Sığmayan Dizi

Kaba ızgara ile ince ızgara arasındaki fark, çözünürlüğün hangi alanı kurtardığını söylüyor.
Endeks isabeti 0,6500'den 0,9500'e çıkıyor, ama asıl sıçrama gövde durumundadır: 0,1333'ten
0,8500'e. Bir çatlak beş basamaklı bir sayıdan **daha ince bir ayrıntıdır** ve kaba ızgarada
görünmez. Kullanılabilir kayıt bu iki alanın çarpımı gibi davranıyor ve 0,0833'ten 0,8167'ye
çıkıyor. Bedel üç katına çıkıyor: 3540 belirteçten 10980 belirtece.

Kırpık ızgara satırı bu dersin asıl bulgusudur. Kırpma çözünürlüğü değil **alanı** küçültür: aynı
ince ayrıntı düzeyi, sayacın yalnız endeks ve mühür bölgesine uygulanır. Sonuç 2520 belirteç ve
0,7000 kullanılabilir kayıt. İnce ızgaranın kullanılabilir kayıtlarının yaklaşık yüzde seksen
altısını, onun **dörtte biri kadar** belirteçle veriyor. Kullanılabilir kayıt başına bedel
224,1'den 60,0'a düşüyor. İki koşum sütunu bu okumayı destekliyor: ince ızgara 0,8167 ve 0,7833,
kırpık ızgara 0,7000 ve 0,6833 veriyor, yani aradaki 0,1167'lik fark koşum farkından büyüktür ve
gerçektir. Gerçek olan şey ince ızgaranın üstünlüğüdür; tartışmalı olan, o üstünlüğün **kayıt
başına 164 belirtece değip değmediğidir**.

Dizi satırı en yüksek görünürlüğe sahip biçimdir ve tablonun en kötü satırlarından biridir. Kare
kare bakmak gövde durumunu 0,95 payla görünür kılar, çünkü hareket çatlağı ele verir. Ne var ki
altmış kaydın otuz dördü altı ya da yedi kare taşıyor ve 240 belirteçlik pencereye girmiyor.
Başarısız çağrı sayısı 35 (otuz dört bağlam aşımı ve bir hız sınırı), kullanılabilir kayıt
0,3667, toplam bedel 16155 belirteçle tablonun en yükseği. Görünürlüğü en yüksek kip, teslim
ettiği kayıt bakımından kırpık ızgaranın yarısı kadar. Bu, bu müfredatın ikinci iddiasının çok
kipli girdideki karşılığıdır: **eklenen zenginlik ölçüyü düşürebilir.**

Ses satırı bir başka sınırı gösteriyor. Endeks isabeti 0,8833 ile ince ızgaraya yakın, gövde
durumu isabeti **0,0000**. Ses kaydı endeksi okuyan bir insanı taşıyor, çatlağı taşımıyor.
Kullanılabilir kayıt bu yüzden sıfırdır ve kayıt başına bedel hesaplanamaz. Bir kipin bir alanı
taşımaması ortalama bir isabet sayısında görünmez; ancak alanlar **ayrı ayrı** sayıldığında
ortaya çıkar. Bir kip seçimi bir çözünürlük kararı değil, **hangi alanların taşınacağı**
kararıdır.

#### Özet

- Çok kipli bir arayüzün faturası yine belirteçle yazılır: ızgara hücresi, ses parçası ve dizi
  karesi girdi belirtecine dönüşür, çıkış belirteci beş biçimde 354'te sabit kalır.
- Aynı kaydın bedeli metin özetinde 21, kırpık ızgarada 42, kaba ızgarada 59, ince ızgarada 183
  belirteç; taşınan bilgi değişmez, kap değişir.
- Çözünürlük artışı gövde durumu isabetini 0,1333'ten 0,8500'e çıkarır; ince ayrıntı kaba
  ızgarada görünmez ve kullanılabilir kayıt 0,0833'te kalır.
- Kırpma çözünürlüğü değil alanı küçültür: ince ızgaranın kullanılabilir kayıtlarının yüzde
  seksen altısını dörtte bir belirteçle verir, kayıt başına bedel 224,1'den 60,0'a düşer.
- Dizi biçimi en yüksek görünürlüğe sahiptir ama altmış kaydın otuz dördü pencereye sığmadığı
  için 0,3667'de kalır ve 16155 belirteçle en pahalı satırdır.
- Ses kipi endeksi 0,8833 ile okur, gövde durumuna kördür ve kullanılabilir kayıt üretmez; bir
  kipin taşımadığı alan ancak alanlar ayrı sayıldığında görünür.

#### Sonraki Adım

Bu derste girdi hep **bir kayıt hakkında** gönderildi ve model onu okudu. Sorulmayan soru şu:
altmış kaydın hangisinin şu anki talebe benzediğini bulmak gerekseydi, hepsini isteme koymak
mümkün olmadığına göre benzerlik neyin üzerinden hesaplanırdı. Arayüz bunun için ayrı bir yüzey
sunar: metni bir sayı dizisine çeviren ve yanıt olarak metin değil **vektör** döndüren bir uç
nokta. Sonraki ders bu yüzeyi ölçer ve tek bir karara odaklanır: vektörün kaç boyutlu olacağı.
Boyut düştükçe saklanan sayı ve karşılaştırma maliyeti düşer, komşuluk isabeti de düşer; ikisinin
hangi noktada ayrıştığı sayılır.

### Gömme Arayüzleri

Source: https://academia.sh/tr/kurslar/model-apileri/gomme-apileri

Yanıt olarak metin değil vektör döndüren bir uç noktanın ve tek bir kararın ölçülmesi: gömmenin kaç boyutlu isteneceği. Yetmiş iki kurgu kayıtta çağrı maliyeti boyuttan bağımsızdır ve 1814 giriş belirtecinde sabit kalır; değişen saklanan sayı (10368'den 648'e) ve karşılaştırma çarpması (368064'ten 23004'e) olur. Üç en yakın komşunun aynı konudan olma payı 144 boyutta 0,9259, 72'de 0,9028, 36'da 0,8102, 9'da 0,6389. Boyutu yarıya indirmenin kaybı 0,0231, aynı boyuttaki ikinci gömme modeliyle fark 0,0232: yarıya indirme ölçülemez bir kayıpla saklamayı yarıya düşürüyor. Boyut düştükçe iki model arasındaki fark 0,0232'den 0,1018'e büyüyor ve istemci tarafında katlamanın kazancı bu farkı aşmıyor.

Önceki ders girdinin biçimini ölçtü ve her biçimin faturasını belirteçle yazdı. Sonunda kalan
soru şuydu: altmış kaydın hangisinin eldeki talebe benzediğini bulmak gerekse, hepsini isteme
koymak mümkün olmadığına göre benzerlik neyin üzerinden hesaplanır.

Arayüz bunun için ayrı bir yüzey sunar. **Gömme arayüzü** bir metin alır ve yanıt olarak metin
değil, sabit uzunlukta bir **sayı dizisi** döndürür. Bu yüzeyin ölçülecek bir tek ayarı vardır ve
bu ders onu ölçer: **vektörün kaç boyutlu olacağı**. Boyut düştükçe saklanan sayı ve karşılaştırma
maliyeti düşer, komşuluk isabeti de düşer. İkisinin hangi noktada ayrıştığı sayılır.

- **AK49.** Kod bir **benzeticidir**; gerçek bir gömme uç noktası çağrılmaz. Kayıtlar, parça
  dağarcığı ve gömme yordamının kendisi **kurgudur**, tohum **20260218**.
- **AK50.** Benzetici belirtecin izinden koordinat üretir ve **bilgiyi ilk koordinatlara ağırlıklı
  yerleştirir**. `boyut` parametresi baştan o kadar koordinat döndürmek demektir. Bu, boyut
  parametresi sunan bir uç noktanın yapısal karşılığıdır.
- **AK51.** Gömme arayüzü **belirlenmiştir**: aynı metin her çağrıda aynı vektörü verir. Bu dersin
  koşumdan bağımsız ölçüsü budur ve blokta gösterilir.
- **AK52.** Bu yüzden ikinci koşum ayrı bir tabandan okunur: **aynı aileden ikinci bir gömme
  modeli** (tohum 20260219 ile kurulan benzetici). Bir boyut kararının taşınabilir sayılması için
  kaybın **iki model arasındaki farkı aşması** gerekir.
- **AK53. Komşuluk isabeti**, her kaydın **üç en yakın komşusunun** aynı konudan olma payıdır.
  Ölçü tek komşu yerine üç komşu üzerinden alınır, çünkü tek komşu tek bir çiftin oynamasıyla
  değişir.
- **AK54. Erişim hattı bu derste kurulmaz.** Hangi belgenin isteme gireceği, kaç belge
  getirileceği ve yanlış getirmenin bedeli Gömme Vektörleri ve Erişim Artırılmış Üretim kursuna
  bırakılır. Burada yalnız vektörlerin **birbirine göre** durumu ölçülür.
- **AK55.** Gömme, açı benzerliği ve boyut azaltma Makine Öğrenmesi ve Veri Bilimi müfredatının
  Denetimsiz Öğrenme ile Doğal Dil İşleme ve Bilgisayarla Görme kurslarında ölçüldü; o yordamlar
  burada tekrarlanmaz. Eklenen tek şey **arayüz düzeyindeki boyut kararıdır**.
- **AK56.** Karşılaştırma maliyeti, yetmiş iki kaydın bütün çiftleri için gereken **çarpma
  sayısıyla** yazılır. Saklama maliyeti **tutulan sayı adedidir**.

#### Vektör Döndüren Uç Nokta

Aşağıdaki blok yetmiş iki kurgu kaydı üretir, gömme arayüzünü kurar ve iki şey gösterir. Birincisi
uç noktanın belirlenmiş olduğu: aynı metin iki çağrıda aynı vektörü verir, yani bu dersin bütün
sayıları koşum farkı taşımaz. İkincisi mekanizma: aynı konudan bir kayda olan benzerlik ile başka
konudan bir kayda olan benzerlik arasındaki **aralık**, boyut düştükçe ne oluyor.

```python
# BENZETICI -- KURGUDUR. Gercek bir gomme uc noktasi cagrilmaz. Kayitlar,
# parca dagarcigi ve gomme yordami kurgudur.
TOHUM, M32 = 20260218, 0xFFFFFFFF
BOYUT = 144                             # uc noktanin en buyuk gomme boyutu


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
PARCA = {
    "fatura": ["fatura tutari cok yuksek geldi", "odemeyi yaptim borc gorunuyor",
               "fatura ayrintisini goremiyorum", "son odeme tarihi gecmis",
               "gecmis donem dokumu lazim", "tutar gecen aya gore artmis"],
    "ariza": ["evde su akmiyor bir ariza var", "baglanti bozuk hic calismiyor",
              "ariza kaydi actim ekip gelmedi", "vana kapali kalmis",
              "boru patlamis sokak su icinde", "servis ekibi randevuyu kacirdi"],
    "sayac": ["sayac okumasi yanlis girilmis", "endeks tutmuyor gibi",
              "sayac degisimi randevusu istiyorum", "sayac cami buharlanmis",
              "muhur kopmus gorunuyor", "endeks fotografini gonderdim"],
    "tarife": ["hangi tarife basamagindayim", "tarife degisikligi nasil olur",
               "birim ucret abone tipine gore degisiyor", "indirimli tarife sarti nedir",
               "kademeli hesap anlasilmiyor", "abone tipim yanlis kayitli"],
    "kesinti": ["mahallede kesinti var", "planli kesinti duyurusu nerede",
                "aksamdan beri kesinti yasiyoruz", "kesinti suresi uzadi",
                "bakim calismasi ne zaman biter", "sokak boyunca su yok"]}
KUYRUK = ["abone numaram kayitli", "bolge merkez ilce", "daha once de yazdim",
          "acil degil ama takipteyim", "telefonla ulasilamiyor", "ek belge gonderdim"]
KAYIT = []
for i in range(72):                     # 72 KURGU kayit: 2-4 kendi parcasi , bazen bir yabanci
    r = uretec(TOHUM + 400 + i)
    k = KONU[int(r() * 5)]
    p = list(PARCA[k])
    sec = [p.pop(int(r() * len(p))) for _ in range(2 + int(r() * 3))]
    if r() < 0.35:
        y = KONU[(KONU.index(k) + 1 + int(r() * 4)) % 5]
        sec.append(PARCA[y][int(r() * 6)])
    sec.append(KUYRUK[int(r() * 6)])
    KAYIT.append({"no": 5001 + i, "konu": k, "metin": " ".join(sec)})
CAGRI = [0]


def gom(metin, boyut=BOYUT, tohum=TOHUM):
    """KURGU gomme uc noktasi. Bilgi ilk koordinatlara agirlikli yerlestirilir;
    boyut parametresi bastan bu kadar koordinat dondurmek demektir."""
    CAGRI[0] += 1
    bel = belirtecle(metin)
    v = [0.0] * BOYUT
    for t in bel:
        r = uretec(izno(t) ^ tohum)
        for _ in range(10):             # her belirtec on koordinata dokunur
            i = int(r() ** 2 * BOYUT)   # kare alma agirligi ilk koordinatlara toplar
            v[i] += 1.0 if r() < 0.5 else -1.0
    v = v[:boyut]
    n = sum(x * x for x in v) ** 0.5 or 1.0
    return [x / n for x in v], len(bel)


def katla(v, d):
    """Istemci tarafinda boyut dusurme: koordinatlar toplanarak katlanir."""
    k = [0.0] * d
    for i, x in enumerate(v):
        k[i % d] += x
    n = sum(x * x for x in k) ** 0.5 or 1.0
    return [x / n for x in k]


def benzerlik(u, v):
    return sum(a * b for a, b in zip(u, v))


x = KAYIT[0]
ayni = next(y for y in KAYIT[1:] if y["konu"] == x["konu"])
baska = next(y for y in KAYIT[1:] if y["konu"] != x["konu"])
tam, bel = gom(x["metin"])
print(f"kayit {x['no']} ({x['konu']}) : {x['metin'][:56]}")
print(f"giris belirteci {bel} , donen sayi {len(tam)} , ikinci cagri ayni vektor:"
      f" {gom(x['metin'])[0] == tam}")
print("ilk sekiz koordinat:", " ".join(f"{c:+.3f}" for c in tam[:8]))
print("son sekiz koordinat:", " ".join(f"{c:+.3f}" for c in tam[-8:]))
print(f"\nboyut  {x['no']}-{ayni['no']} ({ayni['konu']})  "
      f"{x['no']}-{baska['no']} ({baska['konu']})  aralik")
for d in (144, 36, 9):
    a, b = gom(x["metin"], d)[0], gom(ayni["metin"], d)[0]
    c = gom(baska["metin"], d)[0]
    ab, ac = benzerlik(a, b), benzerlik(a, c)
    print(f"{d:>5} {ab:>17.4f} {ac:>19.4f} {ab - ac:>8.4f}")
```

```
kayit 5001 (sayac) : muhur kopmus gorunuyor sayac cami buharlanmis endeks fot
giris belirteci 37 , donen sayi 144 , ikinci cagri ayni vektor: True
ilk sekiz koordinat: -0.329 +0.094 +0.094 +0.235 +0.047 +0.047 +0.141 -0.094
son sekiz koordinat: +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.047

boyut  5001-5002 (sayac)  5001-5003 (tarife)  aralik
  144            0.5074              0.1790   0.3284
   36            0.3991              0.3544   0.0447
    9            0.4423              0.3922   0.0501
```

İlk çıktı satırı bu yüzeyin metin döndüren yüzeyden farkını gösteriyor: otuz yedi belirteçlik bir
girdi, yüz kırk dört sayılık bir çıktıya dönüşüyor ve ikinci çağrı **aynı vektörü** veriyor. Metin
üreten çağrıda aynı istem iki koşumda iki ayrı yanıt verebiliyordu; burada veremez. Bu dersin
bütün farkları bu yüzden gerçek farklardır, koşum oynaması değildir.

Koordinat satırları benzeticinin varsayımını görünür kılıyor. İlk sekiz koordinat dolu, son sekiz
koordinatın yedisi sıfır. Bilgi baştaki koordinatlara toplanmış durumda; boyut parametresi de bu
yüzden **baştan kesmek** anlamına geliyor.

Aralık tablosu asıl mekanizmadır. Yüz kırk dört boyutta aynı konudan komşuya benzerlik 0,5074,
başka konudan komşuya 0,1790 ve aralık **0,3284**. Otuz altı boyutta iki benzerlik de birbirine
yaklaşıyor ve aralık **0,0447**'ye iniyor. Boyut düşünce vektörler birbirinden uzaklaşmıyor,
**birbirine yaklaşıyor**; ayırt etmeyi zorlaştıran şey mesafenin kendisi değil, mesafeler
arasındaki aralığın kapanmasıdır. Dokuz boyuttaki 0,0501 aralığın yeniden açıldığını göstermez;
tek bir çift tek bir çekilişten fazlasını söylemez ve karar tablodan okunur.

#### Beş Boyutun Bedel ve İsabet Tablosu

Yetmiş iki kayıt beş boyutta ayrı ayrı gömülür. Her satırda saklanan sayı adedi, bütün çiftleri
karşılaştırmak için gereken çarpma sayısı, komşuluk isabeti, aynı boyutta ikinci gömme modelinin
isabeti ve tam vektörü istemci tarafında katlayarak elde edilen isabet basılır.

```python
N, K = len(KAYIT), 3
CAGRI[0] = 0
TAM = [gom(y["metin"])[0] for y in KAYIT]
IKINCI = [gom(y["metin"], BOYUT, TOHUM + 1)[0] for y in KAYIT]
GIRIS = sum(gom(y["metin"])[1] for y in KAYIT)


def kirp(v, d):
    u = v[:d]
    n = sum(a * a for a in u) ** 0.5 or 1.0
    return [a / n for a in u]


def komsuluk(vek):
    """Uc en yakin komsunun ayni konudan olma payi. Erisim hatti kurulmaz."""
    en = [[] for _ in range(N)]
    for i in range(N):
        for j in range(i + 1, N):
            s = benzerlik(vek[i], vek[j])
            en[i].append((s, j))
            en[j].append((s, i))
    d = 0
    for i in range(N):
        for _, j in sorted(en[i], reverse=True)[:K]:
            d += KAYIT[j]["konu"] == KAYIT[i]["konu"]
    return d / (N * K)


print(f"{N} kayit , {CAGRI[0]} gomme cagrisi , toplam giris {GIRIS} belirtec"
      f" -- bu sayi boyuttan bagimsizdir")
print("boyut  saklanan  karsilastirma  uc nokta  ikinci model  istemci katlamasi")
for d in (144, 72, 36, 18, 9):
    u = komsuluk([kirp(v, d) for v in TAM])
    m = komsuluk([kirp(v, d) for v in IKINCI])
    kt = komsuluk([katla(v, d) for v in TAM])
    print(f"{d:>5} {N * d:>9} {N * (N - 1) // 2 * d:>14} {u:>9.4f}"
          f" {m:>13.4f} {kt:>18.4f}")
```

```
72 kayit , 216 gomme cagrisi , toplam giris 1814 belirtec -- bu sayi boyuttan bagimsizdir
boyut  saklanan  karsilastirma  uc nokta  ikinci model  istemci katlamasi
  144     10368         368064    0.9259        0.9491             0.9259
   72      5184         184032    0.9028        0.9259             0.9120
   36      2592          92016    0.8102        0.9120             0.9120
   18      1296          46008    0.7685        0.8611             0.8148
    9       648          23004    0.6389        0.7176             0.7315
```

Başlık satırı bu tablonun en kolay gözden kaçan sayısını taşıyor. Toplam giriş **1814 belirteç**
ve bu sayı beş boyutta da aynı. Boyut kararı **çağrı maliyetini değiştirmez**: aynı metinler,
aynı belirteçler, aynı çağrı sayısı. Değişen şey çağrıdan sonra başlar. Saklanan sayı 10368'den
648'e, karşılaştırma çarpması 368064'ten 23004'e iniyor. Bir uç noktanın faturası ile bir
sistemin maliyeti aynı yerde durmuyor ve boyut kararı ikincisine ait.

#### Kaybın Hangi Tabana Karşı Okunacağı

Uç nokta sütunu tek başına okunursa karar kolay görünür: boyut düştükçe isabet düşüyor, o hâlde
en büyük boyut alınır. İkinci model sütunu bu okumayı bozar. Yüz kırk dört boyutta iki model
0,9259 ve 0,9491 veriyor; aradaki fark **0,0232**. Boyutu yarıya, yetmiş ikiye indirmenin
maliyeti ise 0,9259'dan 0,9028'e, yani **0,0231**. Kayıp, aynı boyuttaki iki gömme modeli
arasındaki farkla aynı büyüklüktedir. Bu kararın **ölçülmüş bir kaybı yoktur**, buna karşılık
saklamayı ve karşılaştırmayı tam yarıya düşürür. Tablodaki en açık kazanç budur ve sezgiye
aykırıdır.

Otuz altı boyuta inildiğinde durum değişir. Uç nokta 0,8102 veriyor; yüz kırk dörde göre kayıp
0,1157 ve bu, iki model arasındaki farkın beş katıdır. Dokuz boyutta kayıp 0,2870'e çıkıyor.
Kırılma yetmiş iki ile otuz altı arasındadır: saklamanın dörtte üçü kazanılıncaya kadar bedel
ölçülemez düzeyde kalıyor, sonra hızla ödeniyor.

İkinci model sütununun kendisi de bir şey söylüyor. İki model arasındaki fark yüz kırk dörtte
0,0232 iken otuz altıda **0,1018**'e çıkıyor. Boyut düştükçe **hangi modeli kullandığın daha çok
önemli hâle geliyor**: yüksek boyutta iki model neredeyse aynı komşulukları kuruyor, düşük boyutta
ayrışıyorlar. Düşük boyutlu bir kurulumda model değiştirmenin bedeli, yüksek boyutlu bir
kurulumdakinin dört katından fazladır.

Son sütun boyutu kimin indirdiğini soruyor. Tam vektörü alıp koordinatları katlamak, otuz altı
boyutta 0,9120 veriyor; uç noktadan otuz altı boyut istemenin 0,8102'sinden 0,1018 yüksek. Ne var
ki bu kazanç tam olarak iki model arasındaki farka eşittir ve on sekiz boyutta 0,0463'e, yani o
satırın model farkının yarısına iniyor. Bu tabana göre **ölçülmüş bir üstünlük değildir**.
Üstelik bedeli vardır: katlama tam vektörü gerektirir, yani her çağrıda yüz kırk dört sayı almak
ve taşımak gerekir. Saklama kazancı korunur, aktarım kazancı kaybedilir. Soyutlamanın hangi
tarafta durduğu burada da belirleyicidir: uç noktanın boyut parametresi bir kararı senin yerine
verir ve o kararın bedelini ancak iki tabanı yan yana koyduğunda görebilirsin.

#### Özet

- Gömme arayüzü metin yerine sabit uzunlukta bir sayı dizisi döndürür ve belirlenmiştir: aynı
  metin her çağrıda aynı vektörü verir, bu yüzden bu dersin farkları koşum oynaması değildir.
- Boyut kararı çağrı maliyetini değiştirmez; yetmiş iki kaydın toplam giriş belirteci beş boyutta
  da 1814'tür. Değişen saklanan sayı (10368'den 648'e) ve karşılaştırma çarpmasıdır (368064'ten
  23004'e).
- Boyut düştükçe aynı konu ile başka konu arasındaki benzerlik aralığı kapanır: tek bir çiftte
  0,3284'ten 0,0447'ye iner, komşuluk isabeti 0,9259'dan 0,6389'a düşer.
- Boyutu yarıya indirmenin kaybı 0,0231, aynı boyuttaki ikinci modelle fark 0,0232: saklama ve
  karşılaştırma yarıya inerken ölçülmüş bir kayıp yoktur. Kırılma yetmiş iki ile otuz altı
  arasındadır.
- İki model arasındaki fark boyut düştükçe 0,0232'den 0,1018'e büyür; düşük boyutta model seçimi
  daha ağır basar.
- Tam vektörü istemcide katlamak otuz altı boyutta 0,1018 kazandırır ama bu kazanç model farkının
  düzeyindedir ve her çağrıda yüz kırk dört sayı taşımayı gerektirir.

#### Sonraki Adım

Bu dersteki gömme uç noktası ile önceki derslerdeki metin uç noktası aynı sağlayıcıdan gelmek
zorunda değil. Boyut parametresinin adı, dağılım sıcaklığının ölçeği, hata alanının biçimi ve
yanıtın hangi anahtarla döndüğü sağlayıcıdan sağlayıcıya değişir. Bir uygulama bu farkları her
çağrı yerine tek bir yerde ele almak ister ve ortak bir arayüz yazar. Sonraki ders iki sağlayıcıyı
benzetici düzeyinde kurar ve o ortak arayüzün ne yaptığını sayar: kaç alan taşınıyor, kaç alan
kayboluyor ve kaybolan alanların hangisi bir ölçüyü görünmez kılıyor.

### Uyumlu Arayüz Katmanları

Source: https://academia.sh/tr/kurslar/model-apileri/uyumlu-api-katmanlari

İki kurgu sağlayıcının ve aralarındaki ortak arayüzün alan alan sayılması: sağlayıcı A on iki alan sunuyor, sekizi taşınıyor ve dördü kayboluyor; sağlayıcı B on alan sunuyor, sekizi taşınıyor ve ikisi kayboluyor. Durdurma dizisi alanı yalnız A'da olduğu için kesişimde yer bulamıyor ve çıkış belirteci 773'ten 1638'e çıkıyor. Yüz yirmi çağrının 117'si uzunluk sınırında kesiliyor; iki sağlayıcı da bunu kendi arayüzünde bildiriyor, ortak arayüzden okunabilen kesilme sayısı 0. Aynı ortak çağrıda sıcaklık 0,6 A'da 0,5500, B'de 0,5000 isabet veriyor; sıcaklık 0,4 ile 0,6 B'de aynı ayara yuvarlandığı için ikisi de 0,5000 verirken A 0,7583 ile 0,5500 arasında ayrışıyor.

Önceki dersteki gömme uç noktası ile daha önceki derslerdeki metin uç noktası aynı sağlayıcıdan
gelmek zorunda değil. Bir uygulama büyüdükçe ikinci bir sağlayıcı eklenir, bir görev ucuz olana
taşınır, bir başkası elde tutulur. O noktada her çağrı yerinde ayrı ayrı yazılmış alan adlarıyla
uğraşmak istenmez ve **ortak bir arayüz** yazılır: tek bir işlev, tek bir ad kümesi, altında
sağlayıcıya göre değişen bir eşleme.

Bu ders o katmanın ne yaptığını sayar. İki sağlayıcı **benzetici düzeyinde** kurulur, ikisi de
kurgudur ve ikisi de altta aynı motoru çağırır. Ölçülen şey **soyutlamanın taşıdığı ve kaybettiği
alanlardır**: kaç alan geçiyor, kaç alan düşüyor ve düşen alanların hangisi bir ölçüyü görünmez
kılıyor. Veri Analitiği müfredatının Python ile Veri Analizi kursunda kurulan kural burada aynen
geçerlidir: **bir soyutlama altındaki kararı gizler.**

- **AK57.** Kod bir **benzeticidir**. **İki sağlayıcı da kurgudur** ve benzetici düzeyinde
  kurulur; gerçek bir uç nokta çağrılmaz. Tohum **20260218**, ikinci koşum **20260219**.
- **AK58.** İki sağlayıcı **tek bir motoru** paylaşır. Böylece aralarındaki bütün farklar
  **arayüz farkıdır**, model farkı değil.
- **AK59.** Sağlayıcı A **on iki alan**, sağlayıcı B **on alan** sunar; adlar blokta listelidir.
  B'de **durdurma dizisi alanı yoktur** ve B'nin `cesit` ayarı sıfır ile dört arasında **tam
  sayıdır**, yani kendi ölçeğine oturur.
- **AK60.** Ortak arayüz iki sağlayıcının **kesişimidir**: yalnız her ikisinde de karşılığı olan
  alan taşınabilir. Bir alan tek sağlayıcıda varsa ortak arayüzde yeri yoktur.
- **AK61. Durdurma dizisi** üretimi belirli bir belirteçte kesen alandır; bu derste üç yanıt
  kalıbının da içindeki ortak bir sözcükte devreye girer.
- **AK62.** Benzetici her çağrının **gerçek bitiş nedenini** kendi kaydına yazar; ortak arayüzü
  kullanan bir uygulamanın böyle bir kaydı olmaz.

#### İki Sağlayıcı ve Aradaki Kesişim

Aşağıdaki blok motoru, iki sağlayıcıyı, alan envanterini ve ortak arayüzü kurar. Envanter bir
düzyazı iddiası değil, kod içinde tutulan bir listedir; taşınan ve kaybedilen alanlar küme
işlemiyle sayılır.

```python
# BENZETICI -- KURGUDUR. Iki saglayici da kurgudur ve benzetici duzeyinde
# kurulur. Gercek bir model uc noktasi cagrilmaz.
import math
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE = 240


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                    # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "ariza": "ariza",
      "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza", "sayac": "sayac",
      "endek": "sayac", "okuma": "sayac", "tarif": "tarife", "birim": "tarife",
      "abone": "tarife", "basam": "tarife", "kesin": "kesinti", "duyur": "kesinti",
      "mahal": "kesinti"}
KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
SERBEST = [                             # ucuncu kalip hicbir etiket tasimaz
    "talebiniz {} konusunda kaydedildi ayrica ekibimiz sizinle iletisime gececek"
    " ve sonuc size bildirilecektir",
    "{} kaydiniz acilmistir ayrica islem numaraniz kisa mesajla tarafiniza"
    " gonderilecek ve surec takip edilebilecektir",
    "kaydiniz alinmistir ayrica ilgili birim inceleyip size donus yapacak"
    " ve gerekirse ek belge istenecektir"]
SAYAC, GERCEK = [0], []          # GERCEK: benzeticinin kendi kaydi


def motor(istem, en_uzun, sicaklik, dur, tohum):
    """Iki saglayicinin da altinda calisan tek KURGU motor."""
    SAYAC[0] += 1
    bel = belirtecle(istem)
    bos = {"metin": "", "hal": "hata", "giris": len(bel), "cikis": 0}
    if len(bel) > PENCERE or SAYAC[0] % 37 == 0:
        n = "baglam_asimi" if len(bel) > PENCERE else "hiz_siniri"
        GERCEK.append(n)
        return dict(bos, bitis=n)
    r = uretec(tohum ^ izno(istem))
    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:
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    if sicaklik <= 0.0:
        secim = max(sorted(p), key=lambda a: p[a])
    else:
        ad = sorted(p)
        w = [math.exp(p[a] / sicaklik) for a in ad]
        secim = ad[ayrik(r(), [q / sum(w) for q in w])]
    kalip = SERBEST[ayrik(r(), [0.40, 0.36, 0.24])]
    cb, bitis = belirtecle(kalip.format(secim)), "dogal"
    for i, t in enumerate(cb):
        if t in dur:                    # durdurma dizisi: uretim burada kesilir
            cb, bitis = cb[:i], "durdurma"
            break
    if len(cb) > en_uzun:
        cb, bitis = cb[:en_uzun], "uzunluk"
    GERCEK.append(bitis)
    tam = kalip.format(secim)
    return {"metin": tam if bitis == "dogal" else " ".join(cb), "hal": "tamam",
            "giris": len(bel), "cikis": len(cb), "bitis": bitis}


def saglayici_a(istem, en_cok=14, dagilim=0.6, dur=(), kip="serbest", tohum=TOHUM):
    """KURGU saglayici A. Alan adlari ve yanit bicimi kendisine ozgudur."""
    s = motor(istem, en_cok, dagilim, dur, tohum)
    return {"metin": s["metin"], "hal": s["hal"], "giris_bel": s["giris"],
            "cikis_bel": s["cikis"], "bitis": s["bitis"],
            "kesildi": s["bitis"] == "uzunluk"}


def saglayici_b(mesaj, sinir=14, cesit=2, sema=None, anahtar=TOHUM):
    """KURGU saglayici B. cesit 0-4 arasi tam sayidir ve kendi olcegine oturur."""
    s = motor(mesaj, sinir, cesit / 4 * 1.6, (), anahtar)
    return {"cikti": s["metin"], "durum": s["hal"], "neden": s["bitis"],
            "kullanim": {"g": s["giris"], "c": s["cikis"]}}


ALAN = {"A": ["istem", "en_cok", "dagilim", "dur", "kip", "tohum",
              "metin", "hal", "giris_bel", "cikis_bel", "bitis", "kesildi"],
        "B": ["mesaj", "sinir", "cesit", "sema", "anahtar",
              "cikti", "durum", "kullanim.g", "kullanim.c", "neden"]}
ESLEME = {"istem": ("istem", "mesaj"), "en_uzun": ("en_cok", "sinir"),
          "sicaklik": ("dagilim", "cesit"), "tohum": ("tohum", "anahtar"),
          "yanit": ("metin", "cikti"), "durum": ("hal", "durum"),
          "giris": ("giris_bel", "kullanim.g"), "cikis": ("cikis_bel", "kullanim.c")}


def ortak(saglayici, istem, en_uzun=14, sicaklik=0.6, tohum=TOHUM):
    """Ortak arayuz: yalnizca ESLEME'deki sekiz alan tasinir."""
    if saglayici == "A":
        y = saglayici_a(istem, en_cok=en_uzun, dagilim=sicaklik, tohum=tohum)
        return {"yanit": y["metin"], "durum": y["hal"],
                "giris": y["giris_bel"], "cikis": y["cikis_bel"]}
    y = saglayici_b(istem, sinir=en_uzun, cesit=round(sicaklik * 4), anahtar=tohum)
    return {"yanit": y["cikti"], "durum": y["durum"],
            "giris": y["kullanim"]["g"], "cikis": y["kullanim"]["c"]}


ONEK5 = {k[:5]: k for k in KONU}        # kesilen yanitta etiket parcalanmis olabilir


def oku(y):
    return next((ONEK5[s[:5]] for s in y.split() if s[:5] in ONEK5), None)


YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife ,"
           " kesinti . Talep: ")


print("ortak arayuzun alanlari :", " , ".join(ESLEME))
for i, ad in enumerate(ALAN):
    tasinan = [e[i] for e in ESLEME.values()]
    kayip = [a for a in ALAN[ad] if a not in tasinan]
    print(f"saglayici {ad}: {len(ALAN[ad])} alan , tasinan {len(tasinan)} ,"
          f" kaybedilen {len(kayip)} -> {' , '.join(kayip)}")
istem = YONERGE + TALEP[2]["metin"]
print("\nayni istem , dort yol -- metin disindaki alanlar:")
for ad, y in (("A kendi + dur", saglayici_a(istem, dur=("ayric",))),
              ("B kendi", saglayici_b(istem)),
              ("ortak -> A", ortak("A", istem)),
              ("ortak -> B", ortak("B", istem))):
    alan = " , ".join(f"{k}={v}" for k, v in y.items()
                      if k not in ("metin", "cikti", "yanit"))
    print(f" {ad:<14} {alan}")
```

```
ortak arayuzun alanlari : istem , en_uzun , sicaklik , tohum , yanit , durum , giris , cikis
saglayici A: 12 alan , tasinan 8 , kaybedilen 4 -> dur , kip , bitis , kesildi
saglayici B: 10 alan , tasinan 8 , kaybedilen 2 -> sema , neden

ayni istem , dort yol -- metin disindaki alanlar:
 A kendi + dur  hal=tamam , giris_bel=33 , cikis_bel=5 , bitis=durdurma , kesildi=False
 B kendi        durum=tamam , neden=uzunluk , kullanim={'g': 33, 'c': 14}
 ortak -> A     durum=tamam , giris=33 , cikis=14
 ortak -> B     durum=tamam , giris=33 , cikis=14
```

Envanter satırları soyutlamanın aritmetiğini veriyor. Sağlayıcı A on iki alan sunuyor, sekizi
taşınıyor, dördü kayboluyor. Sağlayıcı B on alan sunuyor, sekizi taşınıyor, ikisi kayboluyor.
Kaybın sebebi ortak arayüzün kötü tasarlanmış olması değil: `dur` ve `kip` yalnız A'da,
`sema` yalnız B'de var. **Kesişim ancak iki tarafta da karşılığı olanı taşıyabilir** ve bir
sağlayıcı ne kadar çok alan sunarsa ortak arayüzde o kadar çok alanını kaybeder.

Dört yanıt biçimi aynı istemde yan yana duruyor. A kendi arayüzüyle çağrıldığında durdurma dizisi
işini yapıyor: çıkış beş belirteç ve `bitis` alanı `durdurma` diyor. B kendi arayüzüyle
çağrıldığında çıkış on dört belirteç ve `neden` alanı `uzunluk` diyor, yani yanıt kesildi. Ortak
arayüzden bakan iki satır ise ayırt edilemez: ikisi de `durum: tamam` ve `cikis: 14`. Yanıtın
tamamlanıp tamamlanmadığı **bu iki satırda yazmıyor**.

#### Kaybolan Alanların Bedeli

Yüz yirmi kurgu talep beş yoldan geçirilir. İlk ikisi A'nın kendi arayüzü (durdurma dizisiz ve
dizili), üçüncüsü B'nin kendi arayüzü, son ikisi ortak arayüz. Her satırda giriş ve çıkış
belirteci, etiket isabeti, ikinci koşum isabeti, benzeticinin kaydettiği **gerçek** kesilme sayısı
ve o yoldan **okunabilen** kesilme sayısı basılır.

```python
YOL = ("A kendi", "A kendi + dur", "B kendi", "ortak -> A", "ortak -> B")


def kosum(yol, sicaklik=0.6, tohum=TOHUM):
    SAYAC[0], GERCEK[:] = 0, []
    g = c = dg = gor = 0
    for x in TALEP:
        istem = YONERGE + x["metin"]
        if yol.startswith("A kendi"):
            y = saglayici_a(istem, dagilim=sicaklik, tohum=tohum,
                            dur=("ayric",) if "dur" in yol else ())
            m, gi, ci = y["metin"], y["giris_bel"], y["cikis_bel"]
            gor += y["kesildi"]                     # bitis alani okunabiliyor
        elif yol == "B kendi":
            y = saglayici_b(istem, cesit=2, anahtar=tohum)
            m, gi, ci = y["cikti"], y["kullanim"]["g"], y["kullanim"]["c"]
            gor += y["neden"] == "uzunluk"          # neden alani okunabiliyor
        else:
            y = ortak(yol[-1], istem, sicaklik=sicaklik, tohum=tohum)
            m, gi, ci = y["yanit"], y["giris"], y["cikis"]   # bitis nedeni yok
        g, c = g + gi, c + ci
        dg += oku(m) == x["konu"]
    return g, c, dg / 120, GERCEK.count("uzunluk"), gor


print("yol             giris  cikis  isabet  ikinci kosum  gercek kesilme  okunan")
for yol in YOL:
    a, b = kosum(yol), kosum(yol, tohum=TOHUM + 1)
    print(f"{yol:<14} {a[0]:>6} {a[1]:>6} {a[2]:>7.4f} {b[2]:>13.4f}"
          f" {a[3]:>15} {a[4]:>7}")
print("\nayni ortak cagri , iki saglayici:")
print("sicaklik  B'ye giden cesit  ortak -> A  ortak -> B  fark")
for s in (0.0, 0.2, 0.4, 0.6, 0.8, 1.0):
    a, b = kosum("ortak -> A", s)[2], kosum("ortak -> B", s)[2]
    print(f"{s:>8.1f} {round(s * 4):>17} {a:>11.4f} {b:>11.4f} {b - a:>+6.4f}")
```

```
yol             giris  cikis  isabet  ikinci kosum  gercek kesilme  okunan
A kendi          4054   1638  0.5500        0.5000             117     117
A kendi + dur    4054    773  0.5500        0.5000               0       0
B kendi          4054   1638  0.5000        0.3917             117     117
ortak -> A       4054   1638  0.5500        0.5000             117       0
ortak -> B       4054   1638  0.5000        0.3917             117       0

ayni ortak cagri , iki saglayici:
sicaklik  B'ye giden cesit  ortak -> A  ortak -> B  fark
     0.0                 0      0.8417      0.8417 +0.0000
     0.2                 1      0.7583      0.7583 +0.0000
     0.4                 2      0.7583      0.5000 -0.2583
     0.6                 2      0.5500      0.5000 -0.0500
     0.8                 3      0.5000      0.3167 -0.1833
     1.0                 4      0.4500      0.3167 -0.1333
```

İkinci satır kaybolan `dur` alanının bedelidir. Durdurma dizisi kullanıldığında çıkış belirteci
**773**, kullanılmadığında **1638**: iki katından fazla. İsabet iki satırda da 0,5500, yani bu
belirteçlerin hiçbiri işe yaramıyor; kalıbın gövdesinden sonra gelen kibar kapanış cümlesi
ödeniyor ve atılıyor. Ortak arayüz bu alanı **sunamaz**, çünkü B'de karşılığı yoktur. Kesişimin
bedeli burada doğrudan belirteçle yazılıdır.

Son iki sütun kaybolan `bitis` ve `neden` alanlarının bedelidir ve bu dersin en sert satırıdır.
Yüz yirmi çağrının **117'si** uzunluk sınırında kesiliyor. A kendi arayüzünde bunu `kesildi`
alanıyla, B kendi arayüzünde `neden` alanıyla bildiriyor: iki sağlayıcı da dürüst. Ortak arayüzden
okunabilen kesilme sayısı ise **0**. Kesilme ortadan kalkmadı, **sayılamaz hâle geldi**. Kursun
kuralı tam buraya oturuyor: başarısızlığı yazılmayan çağrı ölçülmemiş sayılır. Ortak arayüzü
kullanan bir uygulama yüz on yedi yarım yanıtı kayıt sistemine yazar ve hiçbir sayacı kıpırdamaz.

Kaybolan alanın yerine konabilecek tek şey bir çıkarımdır: `cikis` sınıra eşitse yanıt kesilmiş
sayılır. Bu çıkarım sınıra tam denk gelerek doğal biten yanıtları da kesilmiş sayar, yani bir
ölçüm alanının yerine yeni bir hata sınıfı geçer.

#### Aynı Düğme, İki Ayrı Anlam

Alan sayısı soyutlamanın yalnız bir yüzüdür. Taşınan sekiz alanın **aynı şeyi ifade ettiği**
varsayımı ikinci ve daha sinsi yüzüdür. Ortak arayüzün `sicaklik` alanı A'ya olduğu gibi gider;
B'ye giderken sıfır ile dört arasında bir tam sayıya yuvarlanır, çünkü B'nin ölçeği odur.

Alt tablo bunun iki ayrı sonucunu gösteriyor. Birincisi: aynı ayar iki ayrı davranış demek.
Sıcaklık 0,4'te A 0,7583, B 0,5000 veriyor; fark **0,2583**. Aynı satırdaki iki sayı aynı işlevin
aynı argümanıyla üretildi. İkincisi: iki ayrı ayar aynı davranış demek. Sıcaklık 0,4 ile 0,6 B'de
aynı `cesit` değerine yuvarlanıyor ve ikisi de **0,5000** veriyor, oysa A'da 0,7583 ile 0,5500
arasında **0,2083**'lük bir ayrım var. Ortak arayüzün sürekli görünen düğmesi B üzerinde beş
konumludur ve aradaki konumlar sessizce yutulur.

Bu okumaların hangisinin ölçülmüş sayıldığı ikinci koşum sütunundan çıkar. A'nın iki koşum farkı
0,0500, B'nin 0,1083. Sıcaklık 0,6 satırındaki 0,0500'lük sağlayıcı farkı koşum farkının tam
kendisidir ve **ölçülmemiş sayılır**; o değerde iki sağlayıcı arasında bir seçim yapılamaz.
Sıcaklık 0,4 satırındaki 0,2583 ise koşum farkının beş katıdır ve gerçektir. Ortak arayüzü
kullanan bir uygulama sağlayıcı değiştirdiğinde bu farkı hiçbir yerde görmez: alan adları aynı
kalır, çağrı aynı kalır, yalnız sayı değişir.

#### Özet

- Ortak arayüz iki sağlayıcının kesişimidir: A'nın on iki alanından sekizi taşınır ve dördü
  düşer, B'nin on alanından sekizi taşınır ve ikisi düşer.
- Yalnız bir sağlayıcıda bulunan alan kesişime giremez; `dur` ve `kip` A'da, `sema` B'de kalır.
- Durdurma dizisinin kaybı belirteçle ödenir: çıkış 773'ten 1638'e çıkar, isabet 0,5500'de sabit
  kalır, yani eklenen belirteçler işe yaramaz.
- Yüz yirmi çağrının 117'si uzunluk sınırında kesilir; iki sağlayıcı da bunu kendi alanında
  bildirir, ortak arayüzden okunabilen kesilme sayısı 0'dır.
- Taşınan bir alan da aynı anlama gelmeyebilir: sıcaklık 0,4'te iki sağlayıcı 0,2583 ayrışır,
  0,4 ile 0,6 ise B'de aynı ayara yuvarlandığı için tek bir değere çöker.
- Sağlayıcı farkının ölçülmüş sayılması koşum farkını aşmasına bağlıdır: 0,6 satırındaki 0,0500
  koşum farkının kendisidir, 0,4 satırındaki 0,2583 onun beş katıdır.

#### Sonraki Adım

Bu derse kadar her ölçü **istek başına bir çağrı** varsayımıyla yazıldı: yüz yirmi talep, yüz
yirmi çağrı. Oysa yönerge her çağrıda yeniden gönderiliyor ve tabloda giriş belirtecinin 4054'te
sabit kalmasının sebebi budur. Talepler bir kerede biriktirilip tek çağrıda gönderilseydi bu
tekrar ödenmezdi. Sonraki ders toplu çağrıyı ölçer ve tek bir soruya bağlar: toplu boyut
büyüdükçe çağrı sayısı ve belirteç düşerken, **tek bir başarısızlığın etkilediği istek sayısı**
ne oluyor.

### Toplu ve Eşzamansız Çağrılar

Source: https://academia.sh/tr/kurslar/model-apileri/toplu-ve-eszamansiz-cagrilar

Yüz yirmi kurgu talebin yedi ayrı toplu boyutta işlenmesi ve toplu boyutun üç ayrı sayıyı ters yönde oynatması: giriş belirteci 5854'ten 1784'e, çağrı sayısı 120'den 10'a, dörtlü eşzamanlılıkta tur sayısı 30'dan 3'e iniyor. Yönergenin tekrarı dışındaki yük yedi satırda da tam 1414 belirteç; bütün tasarruf yinelenen yönergeden geliyor. Buna karşılık tek bir başarısızlığın etkilediği istek sayısı toplu boyuta eşittir ve 1'den 12'ye çıkar; boyut 18'de istem bağlam penceresini aşar, yedi çağrının altısı düşer ve isabet 0,0667'ye çöker. İsabetin toplu boyutla oynaması iki koşum farkını aşmaz, yani ölçülmemiş sayılır. Çıktı sınırı toplu boyutla büyütülmezse boyut 12'de 26 istek yanıtsız kalır ve isabet 0,5333'e iner.

Önceki derse kadar her ölçü **istek başına bir çağrı** varsayımıyla yazıldı: yüz yirmi talep, yüz
yirmi çağrı. Bu varsayımın görünmeyen bir bedeli var. Her çağrının başına aynı yönerge konuyor ve
her seferinde yeniden ödeniyor. Bir gecelik toplu işte yüz yirmi değil binlerce kayıt olduğunda bu
tekrar tek başına faturanın çoğunu oluşturur.

Toplu çağrı bunu ortadan kaldırır: yönerge bir kez yazılır, arkasına numaralanmış istekler dizilir
ve yanıt tek seferde okunur. Bu ders toplu boyutu bir ayar olarak ele alır ve üç sayıyı yan yana
basar: **çağrı ve belirteç**, **bekleme** ve **tek bir başarısızlığın etkilediği istek sayısı**.
İlk ikisi toplu boyut büyüdükçe düşer, üçüncüsü büyür.

- **AK63.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler ve bütün başarısızlık
  kuralları **kurgudur**, tohum **20260218**, ikinci koşum **20260219**.
- **AK64. Başarısızlık çağrı düzeyindedir.** Bir çağrı hangi sebeple reddedilirse içindeki
  isteklerin **tamamı** reddedilir. Toplu arayüzün tanımı budur ve bu dersin ölçtüğü asıl şeydir.
- **AK65.** Üç ret kaynağı vardır: **bağlam penceresi** (240 belirteç), **hız sınırı** (otuz yedi
  çağrıda bir) ve **biçim bozukluğu**. Sonuncusu **istek başına** yüzde bir buçuk paydır; bir
  istek bozarsa yanıtın tamamı düşer.
- **AK66.** Biçim bozukluğu payının **istek başına** olması bu dersin kilit varsayımıdır. Altta
  yatan kusur oranı toplu boyuttan bağımsızdır; değişen tek şey **bir kusurun kaç isteği
  götürdüğüdür**.
- **AK67. Bekleme tur sayısıyla yazılır.** Dört çağrı eşzamanlı gönderilir; tur sayısı çağrı
  sayısının dörde bölümünün yukarı yuvarlanmışıdır. **Ham süre yazılmaz**; tur koşumdan koşuma
  değişmeyen bir sayımdır.
- **AK68.** Çıktı sınırı öntanımlı olarak toplu boyutla birlikte büyür (istek başına üç belirteç
  ve iki paylık boşluk). Büyütülmediğinde ne olduğu ayrıca ölçülür.
- **AK69.** Yanıt sıralara **çözücüyle** ayrılır: numara, ardından etiket. Bir sıra okunamazsa o
  istek **yanıtsız** sayılır; çağrı başarılı olsa bile.
- **AK70.** Kuyruk, geri çekilme ve eşzamansız iş yönetimi yordamı Backend Geliştirme müfredatının
  Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda ölçüldü; **tekrarlanmaz**. Bu ders yalnız
  **toplu boyutun** üç sayıya ne yaptığını ekler.

#### Bir Çağrıya Kaç İstek Sığar

Toplu çağrının istemi tek parçadır: yönerge bir kez, ardından numaralanmış istekler. Yanıt da tek
parçadır ve okunabilmesi için sıraya ayrılması gerekir. Aşağıdaki blok bu iki ucu kurar ve üç
toplu boyutta ne olduğunu gösterir.

```python
# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz. Talepler ve
# butun basarisizlik kurallari kurgudur.
import math
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, ESZAMAN = 240, 4               # baglam penceresi , eszamanli cagri sayisi


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                    # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "ariza": "ariza",
      "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza", "sayac": "sayac",
      "endek": "sayac", "okuma": "sayac", "tarif": "tarife", "birim": "tarife",
      "abone": "tarife", "basam": "tarife", "kesin": "kesinti", "duyur": "kesinti",
      "mahal": "kesinti"}
ONEK = ("Her talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife ,"
        " kesinti . Her satir icin once numara sonra tek etiket yaz . Talepler: ")
ONEK5 = {k[:5]: k for k in KONU}
SAYAC = [0]


def toplu(parti, tohum=TOHUM, en_uzun=None, sicaklik=0.6):
    """k istegi tek cagrida gonderir. Basarisizlik cagri duzeyindedir:
    kim reddedilirse partinin tamami reddedilir."""
    SAYAC[0] += 1
    k = len(parti)
    istem = ONEK + " ".join(f"{i + 1} {x['metin']} ;" for i, x in enumerate(parti))
    bel = belirtecle(istem)
    en_uzun = 3 * k + 2 if en_uzun is None else en_uzun
    bos = {"giris": len(bel), "cikis": 0, "yanit": []}
    if len(bel) > PENCERE:
        return dict(bos, durum="baglam_asimi")
    if SAYAC[0] % 37 == 0:
        return dict(bos, durum="hiz_siniri")
    r = uretec(tohum ^ izno(istem))
    for _ in parti:                      # her istek kendi bozukluk payini tasir
        if r() < 0.015:                 # bir istek bozarsa yanit tumuyle duser
            return dict(bos, durum="bicim_bozuk")
    cb = []
    for i, x in enumerate(parti):
        p = {c: 0.15 for c in KONU}
        for t in belirtecle(x["metin"]):
            if IZ.get(t) in p:
                p[IZ[t]] += 1.0
        ad = sorted(p)
        w = [math.exp(p[a] / sicaklik) for a in ad]
        cb += [str(i + 1)] + belirtecle(ad[ayrik(r(), [q / sum(w) for q in w])])
    kesik = len(cb) > en_uzun
    return {"durum": "tamam", "giris": len(bel), "cikis": min(len(cb), en_uzun),
            "yanit": cb[:en_uzun], "kesik": kesik}


def coz(cb, k):
    """Toplu yanittan sira basina etiket okur. Okunamayan sira None kalir."""
    out, i = [None] * k, 0
    while i < len(cb):
        if cb[i].isdigit():
            n, j = int(cb[i]), i + 1
            parca = []
            while j < len(cb) and not cb[j].isdigit():
                parca.append(cb[j])
                j += 1
            e = "".join(parca)
            if 1 <= n <= k and e[:5] in ONEK5:
                out[n - 1] = ONEK5[e[:5]]
            i = j
        else:
            i += 1
    return out


for k in (1, 6, 18):
    s = toplu(TALEP[:k])
    print(f"toplu boyut {k:>2} : giris {s['giris']:>3} , cikis {s['cikis']:>2} ,"
          f" durum {s['durum']}")
s = toplu(TALEP[:6])
print("\nalti istekli tek cagrinin yaniti:", " ".join(s["yanit"]))
print("cozulmus:", coz(s["yanit"], 6))
print("gercek  :", [x["konu"] for x in TALEP[:6]])
d = toplu(TALEP[:6], en_uzun=8)         # cikti siniri toplu boyutla buyutulmezse
print(f"\nen_uzun 8 ile ayni cagri: cikis {d['cikis']} , kesik {d['kesik']} ,"
      f" cozulen {sum(e is not None for e in coz(d['yanit'], 6))} / 6")
```

```
toplu boyut  1 : giris  50 , cikis  3 , durum tamam
toplu boyut  6 : giris 107 , cikis 16 , durum tamam
toplu boyut 18 : giris 247 , cikis  0 , durum baglam_asimi

alti istekli tek cagrinin yaniti: 1 kesin ti 2 kesin ti 3 kesin ti 4 ariza 5 sayac 6 fatur a
cozulmus: ['kesinti', 'kesinti', 'kesinti', 'ariza', 'sayac', 'fatura']
gercek  : ['kesinti', 'fatura', 'ariza', 'ariza', 'sayac', 'tarife']

en_uzun 8 ile ayni cagri: cikis 8 , kesik True , cozulen 3 / 6
```

İlk üç satır toplu boyutun tavanını gösteriyor. Yönerge otuz yedi belirteç; tek istekli bir çağrı
elli belirteç ediyor, yani girişin dörtte üçü yönergedir. Altı istekli çağrıda giriş 107'ye
çıkıyor ama istek başına düşen pay on sekize iniyor. On sekiz istekte istem 247 belirtece ulaşıyor
ve 240 belirteçlik pencereyi aşıyor: çağrı hiç kurulmadan reddediliyor. **Toplu boyutun üst
sınırını hız sınırı değil bağlam penceresi koyuyor.**

Çözücü satırları toplu yanıtın ikinci yüzünü gösteriyor. Yanıt tek bir belirteç dizisidir ve
sıralar ancak numaralarla ayrılabilir. Altı sıranın hepsi okunuyor, üçü doğru. Son blok ise
çıktı sınırı toplu boyutla büyütülmediğinde ne olduğunu gösteriyor: sekiz belirteçlik sınır yanıtı
ortadan kesiyor, çağrı **başarılı dönüyor** ve altı isteğin yalnız üçü çözülüyor. Kesilme çağrı
durumunda yazmaz; ancak çözücünün boş bıraktığı sıralar sayılırsa görünür.

#### Toplu Boyutun Üç Sayısı

Yüz yirmi talep yedi ayrı toplu boyutta baştan sona işlenir. Her satırda çağrı sayısı, giriş ve
çıkış belirteci, başarısız çağrı, o başarısızlıkların **etkilediği istek sayısı**, teslim edilen
isabet, ikinci koşum isabeti ve dörtlü eşzamanlılıkta tur sayısı basılır.

```python
def kosum(k, tohum=TOHUM, en_uzun=None):
    SAYAC[0] = 0
    cagri = g = c = hata = etkilenen = dogru = yanitsiz = 0
    for i in range(0, 120, k):
        parti = TALEP[i:i + k]
        s = toplu(parti, tohum, en_uzun)
        cagri, g, c = cagri + 1, g + s["giris"], c + s["cikis"]
        if s["durum"] != "tamam":
            hata, etkilenen = hata + 1, etkilenen + len(parti)
            continue
        for x, e in zip(parti, coz(s["yanit"], len(parti))):
            dogru, yanitsiz = dogru + (e == x["konu"]), yanitsiz + (e is None)
    return cagri, g, c, hata, etkilenen, dogru / 120, -(-cagri // ESZAMAN), yanitsiz


print("boyut  cagri  giris  cikis  basarisiz  etkilenen  isabet  ikinci kosum  tur")
for k in (1, 2, 3, 6, 12, 18, 24):
    a, b = kosum(k), kosum(k, TOHUM + 1)
    print(f"{k:>5} {a[0]:>6} {a[1]:>6} {a[2]:>6} {a[3]:>10} {a[4]:>10}"
          f" {a[5]:>7.4f} {b[5]:>13.4f} {a[6]:>4}")
for k in (6, 12):
    a = kosum(k, en_uzun=24)
    print(f"cikti siniri 24 sabit , boyut {k:>2} : yanitsiz istek {a[7]:>2} ,"
          f" isabet {a[5]:.4f}")
```

```
boyut  cagri  giris  cikis  basarisiz  etkilenen  isabet  ikinci kosum  tur
    1    120   5854    300          3          3  0.8250        0.7083   30
    2     60   3634    300          3          6  0.7667        0.7250   15
    3     40   2894    291          3          9  0.7167        0.6667   10
    6     20   2154    299          1          6  0.7833        0.7583    5
   12     10   1784    284          1         12  0.7083        0.6833    3
   18      7   1673     30          6        108  0.0667        0.0750    2
   24      5   1599      0          5        120  0.0000        0.0000    2
cikti siniri 24 sabit , boyut  6 : yanitsiz istek  0 , isabet 0.7833
cikti siniri 24 sabit , boyut 12 : yanitsiz istek 26 , isabet 0.5333
```

Giriş sütunundaki düşüşün tamamı tek bir kalemden geliyor ve bunu tam olarak ayırmak mümkün.
Yönerge otuz yedi belirteç; tek tek gönderimde 120 kez, on ikili toplu gönderimde 10 kez ödeniyor,
yani 4440 belirteçten 370'e iniyor. Geriye kalan yük yedi satırın hepsinde **tam 1414
belirteçtir**: taleplerin kendisi, numaraları ve ayraçları. Toplu çağrı isteğin yükünü değil,
**yönergenin tekrarını** ortadan kaldırır. Çıkış sütunu bu okumayı doğruluyor: istek başına üç
belirteç ve toplam üç yüz civarı, toplu boyuttan bağımsız. Toplu çağrı çıkıştan tasarruf
ettirmez.

Tur sütunu beklemenin ölçüsüdür. Yüz yirmi ayrı çağrı dörderli gönderildiğinde otuz tur sürüyor;
on ikili partilerde üç tur. Gecikme sınıfı **tek çağrıdan toplu çağrıya** geçiyor ve aradaki fark
onlu bir çarpandır. Ham süre yazılmaz, ama tur sayısı koşumdan koşuma değişmez ve karşılaştırma
için yeter.

#### Kazanan Giriş, Büyüyen Yarıçap

Etkilenen istek sütunu bu dersin asıl bulgusudur ve tek satırda okunur: **etkilenen istek sayısı,
başarısız çağrı sayısı ile toplu boyutun çarpımıdır.** Tek tek gönderimde üç başarısızlık üç isteği
götürüyor. Altılı partilerde tek bir başarısızlık altı isteği, on ikili partilerde on iki isteği
götürüyor. Altta yatan kusur oranı değişmedi; her istek aynı yüzde bir buçukluk payı taşıyor.
Değişen tek şey **bir kusurun yarıçapıdır**.

Başarısız çağrı sayısının toplu boyut büyüdükçe düşmesi bu okumayı gizleyebilir. Üçten bire iniyor
ve tek başına iyi bir haber gibi duruyor. Oysa bu düşüşün bir kısmı yalnız **çağrı sayısı
azaldığı** içindir: hız sınırı otuz yedi çağrıda bir devreye giriyor, on çağrı yapan bir
kurulumda hiç devreye girmiyor. Aynı işi daha az çağrıyla yapmak hız sınırını gerçekten
seyreltir, ama biçim bozukluğunu seyreltmez; onun payı isteğe bağlıdır ve istek sayısı sabittir.

On sekiz ve yirmi dört satırları bir eşiğin ötesidir. On sekizde istem pencereye sığmıyor; yedi
çağrının altısı hiç kurulmadan düşüyor ve 108 istek yanıtsız kalıyor. Ayakta kalan tek çağrı son
kalan on iki istektir ve isabet 0,0667'ye iniyor. Yirmi dörtte hiçbir çağrı kurulmuyor, isabet
sıfır. **Eklenen düzeneğin işi kötüleştirmesi** bu tabloda bir eğri değil bir uçurumdur: toplu
boyutu on ikiden on sekize çıkarmak giriş belirtecinden yalnız yüz on bir belirteç kazandırıyor
ve karşılığında işin tamamını götürüyor.

İsabet sütununu okurken ölçüt gerekiyor. İlk beş satırda isabet 0,7083 ile 0,8250 arasında
geziniyor; aradaki fark 0,1167. İkinci koşum sütununun aynı satırdaki farkı ise en büyük 0,1167
(tek tek gönderimde 0,8250 ve 0,7083). **Toplu boyutun isabete etkisi koşum farkını aşmıyor**,
yani ölçülmemiş sayılır. Bu şaşırtıcı değildir: etiket kararı istek başına verilir ve toplu
göndermek o kararı değiştirmez. Toplu boyut bir kalite ayarı değil, bir **maliyet ve risk**
ayarıdır. Onu kalite üzerinden savunmak da suçlamak da tabloya aykırıdır.

Son iki satır çıktı sınırının unutulduğu durumu ölçüyor. Sınır yirmi dörtte sabit tutulduğunda
altılı partiler etkilenmiyor, çünkü altı sıra yirmi belirtece sığıyor. On ikili partilerde ise
yanıtın kuyruğu kesiliyor ve **26 istek yanıtsız kalıyor**; isabet 0,7083'ten 0,5333'e düşüyor.
Bu kayıp başarısız çağrı sütununda görünmez: çağrılar başarıyla döndü. Toplu boyutu büyütmek,
çıktı sınırını da onunla birlikte büyütmeyi zorunlu kılar.

#### Özet

- Toplu çağrı yönergenin tekrarını ortadan kaldırır: giriş belirteci 5854'ten 1784'e iner, çünkü
  otuz yedi belirteçlik yönerge 120 kez yerine 10 kez ödenir. Kalan yük yedi satırda da tam 1414
  belirteçtir ve çıkış belirteci toplu boyuttan bağımsızdır.
- Bekleme tur sayısıyla yazılır: dörtlü eşzamanlılıkta 30 turdan 3 tura iner.
- Tek bir başarısızlığın etkilediği istek sayısı toplu boyuta eşittir; aynı kusur oranı 3 isteği
  değil 12 isteği götürür hâle gelir.
- Toplu boyutun üst sınırını bağlam penceresi koyar: boyut 18'de istem 247 belirtece çıkar, yedi
  çağrının altısı hiç kurulmadan düşer ve isabet 0,0667'ye, boyut 24'te 0,0000'a iner.
- İsabetin ilk beş satırdaki 0,1167'lik oynaması iki koşum farkının içindedir: toplu boyut bir
  kalite ayarı değil, maliyet ve risk ayarıdır.
- Çıktı sınırı toplu boyutla büyütülmezse boyut 12'de 26 istek yanıtsız kalır ve isabet 0,5333'e
  düşer; bu kayıp başarısız çağrı sütununda hiç görünmez.

#### Sonraki Adım

Sekiz derste mesaj tabanlı arayüzün ne sunduğu tek tek ölçüldü: konuşma durumunun bedeli, yanıt
akışının değiştirdiği, araç çağrısının geçerlilik oranı, arayüz düzeyinde şema zorunluluğu, girdi
biçiminin belirteç faturası, gömme boyutunun takası, ortak arayüzün kaybettiği alanlar ve toplu
boyutun üç sayısı. Sekizinin de altında aynı varsayım duruyordu: **çağrı başarılı oluyor.**

O varsayımın tutmadığı bu derste sayıldı ama karşılığı verilmedi. Reddedilen çağrılar yeniden
denenmedi, penceresi aşan parti bölünmedi, yanıtsız kalan yirmi altı istek kurtarılmadı, yinelenen
yönerge önbelleğe alınmadı. Sayıldılar ve öylece bırakıldılar. Sonraki konu tam buradan başlar ve
ilk dersinde bu kursun ikinci iddiasını kurar: bir isteği yeniden denemek onu kurtarabilir, ama
belirteci de katlar ve hız sınırını daha da zorlar. Dayanıklılık eklemek bedava değildir ve
bazen düzeltmeye çalıştığı sayıyı bozar.

## Üretim Kalitesi

Çağrının gecikmesi, reddedilmesi ve yarıda kesilmesi karşısında kurulan dayanıklılık düzeneğinin kendi bedelinin ve bozduğu yerin ölçülmesi: sabit aralıklı ile geri çekilmeli yeniden denemenin yük altında karşılaştırılması ve yeniden denemenin belirteci de katlaması, önbellek isabeti yükselirken büyüyen bayat yanıt payı, küçük bağlam, büyük bağlam ve iki aşamalı kurulumun gecikme sınıfı ile isabet takası, istek başına belirtecin ortalaması ile en pahalı yüzde birin toplam içindeki payı, yedek modele düşen isteklerin isabetinin sessizce düşmesi ve ölçülmediğinde görünmez kalması, aynı girdinin farklı çıktı vermesini durduran kalemlerin sayılması.

### Hız Sınırları ve Yeniden Deneme

Source: https://academia.sh/tr/kurslar/model-apileri/hiz-sinirlari-ve-yeniden-deneme

Aynı 160 kurgu talebin iki yük düzeyinde üç politikayla koşturulması: düzeneksiz istemci her iki yükte de 0,8562 tamamlıyor ve hiç hız sınırına takılmıyor. Hafif yükte yeniden deneme tamamlamayı 1,0000'a çıkarıyor, bedeli 25 ek çağrı ve 1209 belirteç. Ağır yükte aynı düzenek işi bozuyor: sabit aralıklı deneme 0,8000'e düşüyor ve 151 hız sınırı reddi üretiyor, geri çekilmeli deneme 0,8750 ile düzeneksizin 0,0188 üstünde kalıyor ama iki koşum farkı da 0,0188. Aynı sınırı paylaşan etkileşimli akış 0,9500'den 0,8667'ye iniyor: yeniden deneme kendi işini kurtarırken başkasının işini bozuyor.

Önceki sekiz derste arayüzün ne sunduğu ölçüldü: konuşma durumunun taşınması, yanıt akışı,
araç çağrısı, yapılandırılmış çıktı kipi, çok kipli girdi, gömme arayüzü, uyumlu arayüz katmanı
ve toplu çağrı. Hepsinin ortak bir sessiz varsayımı vardı: **çağrı başarılı oldu.** Sayılan her
belirteç, ödenen ve karşılığı alınan bir belirteçti.

Bir üretim hattında bu varsayım tutmaz. Çağrı reddedilir, yarıda kesilir, hiç yanıt vermez.
Bunların karşılığı bilinen bir yordamdır: yeniden dene. Yeniden deneme M16'nın gözlemlenebilirlik
kursunda ve M19'un dayanıklılık kursunda ölçüldü; yordamı burada tekrarlanmaz. Bu derste
eklenen tek şey, çağrının **pahalı ve belirsiz** olmasından gelir: her deneme girişi bir kez daha
öder, her deneme aynı hız sınırına bir çağrı daha yükler ve yarıda kesilen bir çıktı hiçbir işe
yaramadan belirteç harcamıştır. Sorunun kendisi budur — yeniden deneme, düzelttiği şeyin
kaynağını besler.

- **UK1.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, kalıplar ve ağ
  davranışı **kurgudur**, tohum **20260218**.
- **UK2.** Zaman **adım** ile sayılır, ham süre yazılmaz. Bir adım istemcinin bir gönderim turudur.
- **UK3. Hız sınırı kayan pencerede okunur ve reddedilen çağrılar da sayılır:** son üç adımda
  yapılan toplam çağrı yirmi dördü aşarsa çağrı reddedilir. Reddi saymayan bir uç noktada aşağıda
  ölçülen fark küçülür; bu davranış bir varsayımdır ve sonucu belirler.
- **UK4.** Reddedilen çağrı **belirteç harcamaz**. Kabul edilen her çağrı girişini tam öder.
- **UK5.** İki içerik başarısızlığı vardır: **zaman aşımı** (çıktı başlamadan kesilir, giriş
  ödenir) ve **yarım çıktı** (giriş ile bir belirteç çıkış ödenir, yanıt okunamaz).
- **UK6.** İstemci bir adımda en çok on iki çağrı gönderir; bir istek en çok dört kez denenir.
- **UK7. İki iş yükü aynı sınırı paylaşır:** 160 kayıtlık toplu sınıflandırma ve iki adımda bir
  gelen **etkileşimli** durum sorgusu. Etkileşimli sorgunun gecikme bütçesi bir adımdır.
- **UK8.** Yük, patlama sırasında adım başına gelen istek sayısıdır: **hafif üç, ağır altı**.

#### Çağrının Üç Başarısızlığı ve Bedeli

Benzetici bu konuda bir şey daha taşır: **ağ davranışı**. Aynı istem, pencerenin doluluğuna göre
reddedilebilir; kabul edilse bile yanıt yarıda kesilebilir. Üç sınıfın ayrı ayrı sayılması
gerekir, çünkü **bedelleri farklıdır**.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz; ag davranisi da ders
# icinde yazilir. Talepler ve kaliplar kurgudur, tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF
KOTA, KADIM = 24, 3          # kayan pencerede sayilan cagri / pencere adimi
ESZAMAN, BUTCE, EN_COK = 12, 140, 4


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 belirtecle(m):           # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
EK = ["ayrica gecen ay tarife degisikligi de yapilmisti",
      "kayit numarasini ekliyorum ekip hala gelmedi",
      "odeme gorunmuyor ama dekont elimde duruyor",
      "duyurulari takip ediyorum yine de bilgi alamadim"]
TALEP = []
for i in range(160):         # 160 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = [x for x in KALIP if x[1] == k][int(r() * 3)][0]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": m + (" " + EK[int(r() * 4)] if r() < 0.34 else "")})

KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "odeme",
      "ariza": "ariza", "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza",
      "sayac": "sayac", "endek": "sayac", "okuma": "sayac", "tarif": "tarife",
      "birim": "tarife", "abone": "tarife", "basam": "tarife", "kesin": "kesinti",
      "duyur": "kesinti", "mahal": "kesinti", "dekon": "odeme", "sikay": "sikayet"}
YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife , "
           "kesinti . Yanit olarak tek etiket yaz . ")
SUNUCU = {"gecmis": []}


def istemi(t):
    return YONERGE + f"Talep {t['no']} : {t['metin']}"


def etiketle(bel):           # en olasi secim; adayi daraltan sey etiket kumesidir
    aday = [k for k in KAVRAM if k[:5] in bel]
    p = {k: 0.15 for k in (aday if len(aday) >= 3 else KAVRAM)}
    for t in bel:
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    return max(sorted(p), key=lambda a: p[a])


def cagir(istem, adim, deneme=0, tohum=TOHUM):
    """KURGU uc nokta. Hiz siniri kayan pencerede REDDEDILENLER DAHIL sayar."""
    g = SUNUCU["gecmis"]
    while len(g) <= adim:
        g.append(0)
    g[adim] += 1
    if sum(g[max(0, adim - KADIM + 1):adim + 1]) > KOTA:
        return {"durum": "hiz_siniri", "giris": 0, "cikis": 0, "yanit": ""}
    bel = belirtecle(istem)
    r = uretec((tohum ^ izno(istem)) + 7919 * deneme)
    if r() < 0.03 + 0.0006 * len(bel):                  # cikti baslamadan kesildi
        return {"durum": "zaman_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    k = etiketle(bel)
    if r() < 0.09:                                      # yarida kesilen cikti
        return {"durum": "yarim_cikti", "giris": len(bel), "cikis": 1, "yanit": k[:2]}
    return {"durum": "tamam", "giris": len(bel), "cikis": len(belirtecle(k)),
            "yanit": k}


SUNUCU["gecmis"] = []
print("tek cagri :", cagir(istemi(TALEP[0]), 0))
SUNUCU["gecmis"] = [KOTA]                               # pencere doldurulmus durumda
print("dolu pencere :", cagir(istemi(TALEP[1]), 0))
SUNUCU["gecmis"] = []
sinif = {}
for t in TALEP:
    SUNUCU["gecmis"] = []
    y = cagir(istemi(t), 0)
    a, b = sinif.get(y["durum"], (0, 0))
    sinif[y["durum"]] = (a + 1, b + y["giris"] + y["cikis"])
print("\nsinif        adet  belirtec  sonuc")
for d in ("tamam", "zaman_asimi", "yarim_cikti"):
    a, b = sinif[d]
    print(f"{d:<12} {a:>4}  {b:>8}  {'kullanilir' if d == 'tamam' else 'atilir'}")
```

```
tek cagri : {'durum': 'tamam', 'giris': 44, 'cikis': 2, 'yanit': 'kesinti'}
dolu pencere : {'durum': 'hiz_siniri', 'giris': 0, 'cikis': 0, 'yanit': ''}

sinif        adet  belirtec  sonuc
tamam         137      6523  kullanilir
zaman_asimi     9       436  atilir
yarim_cikti    14       655  atilir
```

Son tabloda pencere her çağrıdan önce boşaltıldı, yani hız sınırı devre dışı ve geriye yalnız
içerik başarısızlıkları kaldı. Yirmi üç istek düşüyor ve bu isteklerin **1091 belirteci ödenmiş,
karşılığı alınmamıştır**. Toplamın 7614 belirteç olduğu düşünülürse boşa giden pay **0,1433**.
Bu, hiçbir yeniden deneme yapılmadan, tek denemeli bir istemcide ödenen bedeldir.

İki başarısızlık sınıfının bedeli eşit değildir. Zaman aşımı dokuz istekte 436 belirteç yakıyor;
yarım çıktı on dört istekte 655. Reddedilen çağrı ise sıfır belirteç harcıyor — ödeme açısından
en ucuz başarısızlık odur. Bu sıralama, yeniden deneme politikasının niçin körlemesine
kurulamayacağını söylüyor: reddedilmiş bir çağrıyı tekrar göndermek yalnız bir çağrıya mal olur,
yarıda kesilmiş bir çağrıyı tekrar göndermek girişin tamamını ikinci kez ödetir.

#### Yük Altında Üç Politika

Şimdi aynı 160 talep bir zaman ekseninde koşturulur. İlk yüz adımda adım başına bir istek gelir;
otuzuncu adımda bir **patlama** başlar ve altmış istek ya üçerli ya altışarlı olarak yığılır.
Aynı hız sınırını, saha uygulamasından iki adımda bir gelen etkileşimli durum sorgusu da kullanır.
Üç politika karşılaştırılır: yeniden deneme yok, **sabit aralıklı** (her başarısızlıktan bir adım
sonra) ve **geri çekilmeli** (bir, iki, dört adım sonra).

```python
def kosum(politika, yuk, tohum=TOHUM):
    """politika: yok | sabit | geri . yuk: patlama sirasinda adim basina istek."""
    SUNUCU["gecmis"] = []
    varis = [[] for _ in range(BUTCE)]
    for i in range(len(TALEP)):
        varis[i if i < 100 else 30 + (i - 100) // yuk].append(i)
    kuyruk, etkin = [], []
    s = dict.fromkeys(("cagri", "hiz", "icerik", "bel", "bos", "tamam", "dogru",
                       "etamam", "etoplam"), 0)
    for adim in range(BUTCE):
        if adim % 2 == 0 and adim < 120:                # etkilesimli akis
            etkin.append({"a": adim, "d": 0})
            s["etoplam"] += 1
        for i in varis[adim]:
            kuyruk.append({"i": i, "hazir": adim, "deneme": 0})
        for x in list(etkin):
            if x["a"] + 1 < adim:                       # gecikme butcesi doldu
                etkin.remove(x)
                continue
            y = cagir(f"Saha uygulamasi sorgusu {x['a']} : acik kayit sayisi",
                      adim, x["d"], tohum)
            s["bel"] += y["giris"] + y["cikis"]
            if y["durum"] == "tamam":
                s["etamam"] += 1
                etkin.remove(x)
            else:
                s["bos"] += y["giris"] + y["cikis"]
                x["d"] += 1
        for x in [x for x in kuyruk if x["hazir"] <= adim][:ESZAMAN]:
            kuyruk.remove(x)
            t = TALEP[x["i"]]
            y = cagir(istemi(t), adim, x["deneme"], tohum)
            s["cagri"] += 1
            s["bel"] += y["giris"] + y["cikis"]
            if y["durum"] == "tamam":
                s["tamam"] += 1
                s["dogru"] += y["yanit"] == t["konu"]
                continue
            s["bos"] += y["giris"] + y["cikis"]
            s["hiz" if y["durum"] == "hiz_siniri" else "icerik"] += 1
            x["deneme"] += 1
            if politika == "yok" or x["deneme"] >= EN_COK:
                continue
            x["hazir"] = adim + (1 if politika == "sabit" else 2 ** (x["deneme"] - 1))
            kuyruk.append(x)
    n = len(TALEP)
    return (s["tamam"] / n, s["etamam"] / s["etoplam"], s["cagri"], s["hiz"],
            s["icerik"], s["bel"], s["bos"], s["dogru"] / n)


print("yuk  politika  tamamlanan  etkilesimli  cagri  hiz reddi  icerik hatasi"
      "  belirtec  bosa giden  isabet")
for yuk, ad in ((3, "hafif"), (6, "agir ")):
    for p in ("yok", "sabit", "geri"):
        a = kosum(p, yuk)
        print(f"{ad}  {p:<8} {a[0]:>10.4f}  {a[1]:>11.4f}  {a[2]:>5}  {a[3]:>9}"
              f"  {a[4]:>13}  {a[5]:>8}  {a[6]:>10}  {a[7]:>6.4f}")
print("\nikinci kosum (tohum 20260219), tamamlanan / etkilesimli:")
for yuk, ad in ((3, "hafif"), (6, "agir ")):
    b = [kosum(p, yuk, TOHUM + 1) for p in ("yok", "sabit", "geri")]
    print(f"  {ad} " + "  ".join(f"{p}: {x[0]:.4f} / {x[1]:.4f}"
                                 for p, x in zip(("yok", "sabit", "geri"), b)))
```

```
yuk  politika  tamamlanan  etkilesimli  cagri  hiz reddi  icerik hatasi  belirtec  bosa giden  isabet
hafif  yok          0.8562       0.9500    160          0             23      8425        1218  0.8438
hafif  sabit        1.0000       0.9500    185          0             25      9634        1311  0.9875
hafif  geri         1.0000       0.9500    185          0             25      9634        1311  0.9875
agir   yok          0.8562       0.9500    160          0             23      8425        1218  0.8438
agir   sabit        0.8000       0.8667    295        151             16      7658         873  0.7937
agir   geri         0.8750       0.8833    289        129             20      8389        1038  0.8625

ikinci kosum (tohum 20260219), tamamlanan / etkilesimli:
  hafif yok: 0.8750 / 1.0000  sabit: 1.0000 / 1.0000  geri: 1.0000 / 1.0000
  agir  yok: 0.8750 / 1.0000  sabit: 0.6813 / 0.8667  geri: 0.7188 / 0.8833
```

Tablonun okunması gereken ilk satırı, düzeneksiz istemcinin **iki yükte de aynı** olmasıdır:
0,8562 tamamlanma, **sıfır hız sınırı reddi**. Patlamanın adım başına üçten altıya çıkması
düzeneksiz istemci için hiçbir şeyi değiştirmiyor, çünkü gelen yük hâlâ sınırın altında kalıyor.
Sınır, iş yükü tarafından değil, **düzenek tarafından** aşılacak.

Hafif yükte yeniden deneme tam olarak beklendiği gibi çalışıyor: tamamlanma 0,8562'den
**1,0000'a** çıkıyor ve iki politika **birbirinin aynısı** — çünkü hiç red olmadığında geri
çekilmenin geciktirecek bir şeyi yoktur. Bedel açık: 25 ek çağrı, 1209 ek belirteç ve boşa giden
belirteç 1218'den 1311'e. Yani kurtarılan yirmi üç isteğin karşılığında ödenen belirtecin bir
kısmı yine boşa gitti, çünkü kimi yeniden deneme de düştü.

#### Yeniden Denemenin Kimin İşini Bozduğu

Ağır yük satırları kursun ikinci iddiasının en açık örneğidir. Sabit aralıklı yeniden deneme
tamamlanmayı **0,8562'den 0,8000'e düşürüyor**. Düzenek eklendi, sayı geriledi. Nedeni sütunlarda
duruyor: çağrı 160'tan 295'e çıkıyor ve bu çağrıların **151'i hız sınırından reddediliyor**.
Reddedilen çağrılar da pencerede sayıldığı için her red bir sonraki reddi kolaylaştırıyor;
düzeltmek için gönderilen çağrı, düzeltilecek sorunu büyütüyor. İçerik hatası 23'ten 16'ya
düşerken toplam tamamlanma da düşüyor: istekler artık içerik yüzünden değil, **kendi
denemelerinin yarattığı tıkanıklık** yüzünden kaybediliyor.

Geri çekilmeli deneme aynı yükte 0,8750 veriyor, yani düzeneksize göre **0,0188** üstünde. Bu
sayının yanına ikinci koşum konmalıdır: düzeneksiz istemci tohum 20260219'da 0,8750 veriyor ve iki
koşum farkı da tam **0,0188**. Kazanç, koşum farkını aşmıyor, dolayısıyla **ölçülmemiş sayılır**.
Buna karşılık sabit aralıklının kaybı 0,0562, yani koşum farkının üç katı — kayıp ölçülmüştür.
İkinci koşumun ağır yük satırları bunu doğruluyor: orada iki politika da düzeneksizin altına
düşüyor (0,6813 ve 0,7188).

Son sütun, çoğu ölçümde hiç bakılmayan yerdedir. Etkileşimli akış aynı hız sınırını paylaşıyor ve
kendi yeniden denemesi yok; gecikme bütçesi bir adım. Düzeneksiz istemcide bu akış 0,9500
tamamlıyor. Toplu işe yeniden deneme eklendiğinde **0,8667'ye** düşüyor. Etkileşimli akış hiçbir
şey değiştirmedi, isteği artmadı, istemi büyümedi; yalnız **komşusu dayanıklı hâle geldi**.
Bu, dayanıklılık düzeneğinin en sinsi bedelidir: kendi ölçütünü kurtarırken paylaşılan bir kaynağı
tüketir ve zararı **başka bir ölçütte** görünür. Bir yeniden deneme politikası yalnız kendi
başarısızlık payıyla değerlendirilirse bu satır hiç görülmez.

#### Özet

- Bir çağrının üç başarısızlığı ayrı bedeller taşır: hız sınırı reddi belirteç harcamaz, zaman
  aşımı girişi öder, yarım çıktı giriş ile kısmi çıkışı öder; tek denemeli istemcide boşa giden
  belirteç payı 0,1433'tür.
- Düzeneksiz istemci hafif ve ağır yükte aynı sonucu veriyor (0,8562) ve hiç hız sınırına
  takılmıyor; sınırı iş yükü değil, eklenen düzenek aşıyor.
- Hafif yükte yeniden deneme tamamlanmayı 1,0000'a çıkarıyor ve sabit aralıklı ile geri çekilmeli
  arasında fark yok; bedel 25 ek çağrı ve 1209 belirteçtir.
- Ağır yükte sabit aralıklı deneme tamamlanmayı 0,8000'e düşürüyor ve 151 hız sınırı reddi
  üretiyor: düzeltmek için gönderilen çağrı, düzeltilecek sorunu büyütüyor.
- Geri çekilmeli denemenin ağır yükteki kazancı 0,0188, iki koşum farkı da 0,0188; kazanç
  ölçülmemiş sayılır, buna karşılık sabit aralıklının 0,0562'lik kaybı ölçülmüştür.
- Aynı sınırı paylaşan etkileşimli akış 0,9500'den 0,8667'ye iniyor; dayanıklılık düzeneği kendi
  ölçütünü kurtarırken zararı başka bir ölçütte bırakıyor.

#### Sonraki Adım

Bu derste her çağrı sıfırdan gönderildi. Oysa tabloya giren 160 istemin hepsi aynı yönergeyle
başlıyor ve o yönerge her seferinde yeniden belirteçleniyor, yeniden ödeniyor. Yeniden deneme bu
tekrarı bir kat daha büyütüyor: ağır yükte 295 çağrının hepsi aynı ortak metni taşıyor. Tekrarın
kendisi bir bedeldir ve bu bedel, yanıtın veya ortak bağlamın saklanmasıyla düşürülebilir.
Ama saklanan bir yanıtın bir yaşı vardır: dayandığı belge değişmişse yanıt hâlâ hızlıdır, hâlâ
ucuzdur ve artık yanlıştır. Sonraki ders iki sayıyı yan yana koyar: önbellek isabeti yükseldikçe
belirteç ne kadar düşüyor ve **bayat yanıt payı** ne kadar büyüyor.

### İstem Önbellekleme

Source: https://academia.sh/tr/kurslar/model-apileri/istem-onbellekleme

Aynı 240 kurgu isteğin yedi önbellek kurulumunda ölçülmesi: istemin 186 belirtecinin 175'i bütün isteklerde ortaktır. İçeriğe göre anahtarlanan önek önbelleği 0,9792 isabetle giriş belirtecini 44367'den 7472'ye indiriyor ve doğru yanıt payını hiç değiştirmiyor. Soruya göre anahtarlanan yanıt önbelleğinde ömür uzadıkça isabet 0,4708'den 0,8792'ye çıkıyor, çağrı 240'tan 29'a düşüyor, ama bayat yanıt payı 0,0208'den 0,4417'ye tırmanıyor ve doğru yanıt payı 0,9333'ten 0,5542'ye iniyor. İki önbellek birlikte girişi 2946'ya indiriyor, yani on beş kat ve yanıt önbelleği açıldığında önek isabeti 0,9792'den 0,9359'a düşüyor.

Önceki derste ağır yükte 295 çağrı yapıldı ve bu çağrıların hepsi aynı yönergeyle başlıyordu.
Yeniden deneme o tekrarı bir kat daha büyüttü: düzeltmek için gönderilen her çağrı, ortak metni
bir kez daha belirteçledi ve bir kez daha ödedi. Tekrarın kendisi ölçülmemişti.

Bir destek yardımcısında bu tekrar iki katmanlıdır. Birincisi **istemin öneki**: yönerge ve saha
ekibinin kurgu belge dağarcığı her istekte aynıdır ve istemin büyük bölümünü kaplar. İkincisi
**sorunun kendisi**: birkaç soru bütün trafiğin yarısını üretir ve aynı soru gün boyunca onlarca
kez sorulur. İki tekrarın da bir çaresi vardır ve **iki çare aynı şey değildir**. Bu ders ikisini
ayrı ayrı kurar ve yan yana ölçer: önbellek isabeti yükseldikçe belirteç düşer, ama saklanan
yanıtın bir **yaşı** olur ve dayandığı belge değiştiğinde yanıt hâlâ hızlı, hâlâ ucuz ve artık
yanlıştır.

- **UK9.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Dağarcık, sorular ve
  güncelleme takvimi **kurgudur**, tohum **20260218**.
- **UK10.** Dağarcık **on kurgu belgedir**; her belgenin bir **sürümü** vardır ve dört ayrı adımda
  ikişer belge güncellenir.
- **UK11.** İstem iki parçalıdır: bütün isteklerde aynı olan **önek** (yönerge ile dağarcık) ve
  sorunun kendisi.
- **UK12. Önek önbelleği içeriğe göre anahtarlanır.** Önek bir önceki çağrıdakiyle birebir aynıysa
  isabet sayılır ve önek belirteçlerinin **yüzde onu** ödenir. Dağarcık değişirse önek de değişir.
- **UK13. Yanıt önbelleği soruya göre anahtarlanır** ve bir **ömrü** vardır. Ömür içindeki isabet
  çağrı yapmaz, hiç belirteç harcamaz.
- **UK14. Bayat yanıt**, önbellekten dönen ve dayandığı belgenin sürümü artık geçerli olmayan
  yanıttır.
- **UK15. Doğru yanıt**, etiketi doğru olan **ve** bayat olmayan yanıttır; bu dersin ürün ölçütü
  budur.
- **UK16.** İş yükü 120 adımda 240 istektir, adım başına iki; soru dağılımı çarpıktır.

#### İki Ayrı Önbellek, İki Ayrı Anahtar

Önce dağarcık ve sorular kurulur, sonra bir belge güncellenip aynı sorunun yanıtının ne olduğuna
bakılır. Ayrım burada görünür hâle gelir: önek, dağarcık değişince **kendiliğinden** değişir;
saklanmış bir yanıt ise değişmez.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz. Belge dagarcigi, sorular
# ve guncelleme takvimi kurgudur, tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF
ADIM, ONEK_INDIRIM = 120, 0.10     # kosum uzunlugu, isabetli onegin odenen payi


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 belirtecle(m):
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
BELGE = [{"kod": "FT1", "konu": "fatura", "anahtar": "fatura tutari",
          "metin": "fatura tutari hesap donemi ve gecikme farki kurallari"},
         {"kod": "FT2", "konu": "fatura", "anahtar": "fatura odemesi",
          "metin": "fatura odemesi yontemleri ve borc gorunumu kurallari"},
         {"kod": "AR1", "konu": "ariza", "anahtar": "ariza kaydi",
          "metin": "ariza kaydi acma ve ekip yonlendirme yordami"},
         {"kod": "AR2", "konu": "ariza", "anahtar": "baglanti bozuklugu",
          "metin": "baglanti bozuk oldugunda uygulanan denetim adimlari"},
         {"kod": "SY1", "konu": "sayac", "anahtar": "sayac endeksi",
          "metin": "sayac endeks okumasi ve duzeltme yordami"},
         {"kod": "SY2", "konu": "sayac", "anahtar": "sayac degisimi",
          "metin": "sayac degisimi randevu kurallari ve sure taahhudu"},
         {"kod": "TA1", "konu": "tarife", "anahtar": "tarife basamagi",
          "metin": "tarife basamaklari ve abone tipine gore birim ucret"},
         {"kod": "TA2", "konu": "tarife", "anahtar": "tarife degisikligi",
          "metin": "tarife degisikligi basvurusu ve gecerlilik kosullari"},
         {"kod": "KS1", "konu": "kesinti", "anahtar": "planli kesinti",
          "metin": "planli kesinti duyurusu yayimlama ve takip kurallari"},
         {"kod": "KS2", "konu": "kesinti", "anahtar": "mahalle kesintisi",
          "metin": "mahallede kesinti bildirimi ve tahmini donus suresi"}]
for b in BELGE:
    b["surum"] = 1
SORU = [{"b": i, "konu": b["konu"], "metin": k.format(a=b["anahtar"])}
        for i, b in enumerate(BELGE)
        for k in ("{a} konusunda ne yapmam gerekiyor",
                  "{a} icin gecerli kural nedir",
                  "{a} ile ilgili son durum ne")]
AGIRLIK = [1.0 / (i + 1) ** 1.0 for i in range(len(SORU))]
AGIRLIK = [w / sum(AGIRLIK) for w in AGIRLIK]
GUNCELLEME = {24: [6, 1], 48: [0, 8], 72: [2, 6], 96: [4, 7]}   # adim -> belge
IZ = {"fatur": "fatura", "tutar": "fatura", "borc": "fatura", "odeme": "fatura",
      "ariza": "ariza", "bozuk": "ariza", "bagla": "ariza", "kayit": "ariza",
      "sayac": "sayac", "endek": "sayac", "okuma": "sayac", "tarif": "tarife",
      "birim": "tarife", "abone": "tarife", "basam": "tarife", "kesin": "kesinti",
      "duyur": "kesinti", "mahal": "kesinti"}
YONERGE = ("Asagidaki dagarcigi kullanarak soruyu yanitla . Yanitta once etiket , "
           "sonra dayandigin belge kodu ve surumu yaz . Dagarcik: ")
SAYAC = [0]


def onek():
    return YONERGE + " ; ".join(f"{b['kod']} s{b['surum']} {b['metin']}"
                                for b in BELGE) + " . Soru: "


def cagir(soru, tohum=TOHUM):
    """KURGU uc nokta. Dagarcigin o andaki surumunu okur."""
    SAYAC[0] += 1
    istem = onek() + soru["metin"]
    bel = belirtecle(istem)
    p = {k: 0.15 for k in KONU}
    for t in belirtecle(soru["metin"]):
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    r = uretec((tohum ^ izno(soru["metin"])) + 7919 * SAYAC[0])
    e = max(sorted(p), key=lambda a: p[a]) if r() > 0.10 else KONU[int(r() * 5)]
    b = BELGE[soru["b"]]
    return {"etiket": e, "kod": b["kod"], "surum": b["surum"],
            "giris": len(bel), "onek": len(belirtecle(onek())),
            "cikis": len(belirtecle(f"{e} {b['kod']} s{b['surum']}"))}


def akis(tohum=TOHUM):
    """Her adimda iki istek; soru dagilimi carpiktir (birkac soru baskin)."""
    r = uretec(tohum + 991)
    return [(a, SORU[ayrik(r(), AGIRLIK)]) for a in range(ADIM) for _ in range(2)]


for b in BELGE:
    b["surum"] = 1
ilk = cagir(SORU[0])
print("ilk cagri  :", {k: ilk[k] for k in ("etiket", "kod", "surum", "giris", "onek")})
BELGE[0]["surum"] += 1                      # dagarcik guncellendi
ikinci = cagir(SORU[0])
print("guncelleme sonrasi:", {k: ikinci[k] for k in ("kod", "surum", "giris")})
print("saklanan yanit    :", ilk["kod"], "s" + str(ilk["surum"]),
      "-> bayat" if ilk["surum"] != BELGE[0]["surum"] else "-> taze")
BELGE[0]["surum"] = 1
ist = akis()
sik = {}
for _, s in ist:
    sik[s["metin"][:26]] = sik.get(s["metin"][:26], 0) + 1
print(f"\nistek {len(ist)} , benzersiz soru {len(sik)} , onek {ilk['onek']} belirtec")
print("en sik uc soru:", [(a, n) for a, n in sorted(sik.items(), key=lambda x: -x[1])[:3]])
```

```
ilk cagri  : {'etiket': 'fatura', 'kod': 'FT1', 'surum': 1, 'giris': 186, 'onek': 175}
guncelleme sonrasi: {'kod': 'FT1', 'surum': 2, 'giris': 186}
saklanan yanit    : FT1 s1 -> bayat

istek 240 , benzersiz soru 29 , onek 175 belirtec
en sik uc soru: [('fatura tutari konusunda ne', 56), ('fatura tutari icin gecerli', 41), ('fatura tutari ile ilgili s', 23)]
```

İlk satır tekrarın büyüklüğünü veriyor: istem 186 belirteç, bunun **175'i önek**. Yani her
isteğin ödediği belirtecin **0,9409'u** bir önceki istekle birebir aynıdır. İkinci satır
güncellemeden sonraki çağrının aynı belgeyi ikinci sürümüyle okuduğunu gösteriyor. Üçüncü satır
ise ayrımın kendisidir: saklanmış yanıt hâlâ birinci sürüme dayanıyor ve **bayat** olmuş.

Soru dağılımı da önemlidir. 240 istek yalnız 29 farklı soruya karşılık geliyor ve en sık üç soru
tek başına 120 isteği kaplıyor. Bir yanıt önbelleğinin işe yaraması bu çarpıklığa bağlıdır;
her isteğin farklı olduğu bir yükte yanıt önbelleğinin isabeti sıfır kalır.

#### İsabet Yükselirken Bayat Yanıt Payı

Yedi kurulum aynı akışta koşturulur: önbelleksiz taban, yalnız önek önbelleği, dört farklı ömürle
yanıt önbelleği ve ikisi birlikte.

```python
def kosum(onek_ac, omur=0, tohum=TOHUM):
    """onek_ac: onek onbellegi acik mi . omur: yanit onbelleginin adim omru."""
    for b in BELGE:
        b["surum"] = 1
    SAYAC[0] = 0
    onbellek, izi, gecen = {}, [None], [-1]
    s = dict.fromkeys(("oi", "yi", "giris", "cikis", "bayat", "dogru", "istek"), 0)
    for adim, soru in akis(tohum):
        if adim != gecen[0]:
            gecen[0] = adim
            for i in GUNCELLEME.get(adim, []):
                BELGE[i]["surum"] += 1
        s["istek"] += 1
        kayit = onbellek.get(soru["metin"])
        if omur and kayit and adim - kayit["adim"] <= omur:
            s["yi"] += 1
            bayat = kayit["surum"] != BELGE[soru["b"]]["surum"]
            s["bayat"] += bayat
            s["dogru"] += kayit["etiket"] == soru["konu"] and not bayat
            continue
        y = cagir(soru, tohum)
        s["cikis"] += y["cikis"]
        if onek_ac and izi[0] == onek():           # onek icerige gore anahtarlanir
            s["oi"] += 1
            s["giris"] += round(y["onek"] * ONEK_INDIRIM) + y["giris"] - y["onek"]
        else:
            s["giris"] += y["giris"]
        izi[0] = onek()
        onbellek[soru["metin"]] = {"etiket": y["etiket"], "surum": y["surum"],
                                   "adim": adim}
        s["dogru"] += y["etiket"] == soru["konu"]
    n, c = s["istek"], max(SAYAC[0], 1)
    return (s["yi"] / n, s["oi"] / c, s["giris"], s["giris"] + s["cikis"],
            SAYAC[0], s["bayat"] / n, s["dogru"] / n)


DUZEN = [("onbelleksiz", 0, 0), ("onek onbellegi", 1, 0), ("yanit omur 8", 0, 8),
         ("yanit omur 24", 0, 24), ("yanit omur 64", 0, 64),
         ("yanit omur sinirsiz", 0, 10 ** 6), ("onek + yanit omur 24", 1, 24)]
print("duzenek               yanit isb  onek isb   giris  toplam  cagri   bayat"
      "   dogru")
for ad, o, m in DUZEN:
    a = kosum(o, m)
    print(f"{ad:<21} {a[0]:>8.4f}  {a[1]:>8.4f}  {a[2]:>6}  {a[3]:>6}  {a[4]:>5}"
          f"  {a[5]:>6.4f}  {a[6]:>6.4f}")
print("\nikinci kosum (tohum 20260219), yanit isb / bayat / dogru:")
for ad, o, m in DUZEN:
    a = kosum(o, m, TOHUM + 1)
    print(f"  {ad:<21} {a[0]:.4f} / {a[5]:.4f} / {a[6]:.4f}")
```

```
duzenek               yanit isb  onek isb   giris  toplam  cagri   bayat   dogru
onbelleksiz             0.0000    0.0000   44367   45263    240  0.0000  0.9333
onek onbellegi          0.0000    0.9792    7472    8368    240  0.0000  0.9333
yanit omur 8            0.4708    0.0000   23456   23917    127  0.0208  0.9208
yanit omur 24           0.6750    0.0000   14407   14686     78  0.0500  0.9292
yanit omur 64           0.8000    0.0000    8870    9042     48  0.1333  0.8625
yanit omur sinirsiz     0.8792    0.0000    5357    5461     29  0.4417  0.5542
onek + yanit omur 24    0.6750    0.9359    2946    3225     78  0.0500  0.9292

ikinci kosum (tohum 20260219), yanit isb / bayat / dogru:
  onbelleksiz           0.0000 / 0.0000 / 0.9083
  onek onbellegi        0.0000 / 0.0000 / 0.9083
  yanit omur 8          0.5292 / 0.0292 / 0.8667
  yanit omur 24         0.6958 / 0.0833 / 0.8250
  yanit omur 64         0.8208 / 0.2167 / 0.6833
  yanit omur sinirsiz   0.9000 / 0.5000 / 0.4042
  onek + yanit omur 24  0.6958 / 0.0833 / 0.8250
```

İkinci satır bu dersin en ucuz kazancıdır ve tuzağı yoktur. Önek önbelleği 0,9792 isabetle giriş
belirtecini **44367'den 7472'ye** indiriyor, yani **5,94 kat**. Bayat yanıt payı **0,0000**,
doğru yanıt payı **değişmiyor**. Nedeni anahtardadır: önek **içeriğe göre** anahtarlanır.
Dağarcık güncellendiği anda önek metni de değişir, eşleşme kırılır ve bir sonraki çağrı tam
ödenir. Bir önbelleğin bayatlaması, anahtarının içerikten kopmasıyla başlar.

Yanıt önbelleği satırları bunun tersidir. Anahtar **soru** metnidir ve soru değişmez; değişen
şey, sorunun dayandığı belgedir. Ömür sekiz adımken isabet 0,4708 ve bayat pay 0,0208; ömür
sınırsız olduğunda isabet 0,8792'ye çıkıyor ve bayat pay **0,4417'ye** tırmanıyor. Çağrı sayısı
240'tan 29'a düşüyor, giriş belirteci 5357'ye iniyor. Maliyet tarafından bakıldığında
son satır en iyi satırdır. Ürün tarafından bakıldığında ise doğru yanıt payı **0,9333'ten
0,5542'ye** düşmüştür: her iki isteğin yaklaşık birinde kullanıcıya artık geçerli olmayan bir
kural anlatılıyor.

#### Ömrün Seçimi Bir Doğruluk Kararıdır

Kaybın hangi ömürde ölçülebilir hâle geldiği, iki koşum farkına bakılarak söylenir. Önbelleksiz
taban ikinci tohumda 0,9083 veriyor, yani koşum farkı **0,0250**. Ömür sekizde kayıp 0,0125,
ömür yirmi dörtte 0,0041 — ikisi de koşum farkının altında ve **ölçülmemiş sayılır**. Ömür
altmış dörtte kayıp 0,0708, sınırsızda 0,3791; bunlar sırasıyla koşum farkının yaklaşık üç ve on
beş katı, yani **ölçülmüştür**. Karar buradan okunur: bu güncelleme takviminde ömrü yirmi dörde
kadar uzatmak bedelsizdir, altmış dörde çıkarmak değildir.

Bu okumanın bir uyarısı var. İkinci koşumda ömür yirmi dördün kaybı 0,0833'e çıkıyor, yani kendi
tabanına göre koşum farkının üç katı. Aynı ayar bir koşumda gürültünün altında, ötekinde ölçülür
durumda. Bu, yirmi dört adımın **güncelleme aralığına yakın** olmasından gelir: dağarcık her yirmi
dört adımda bir değiştiği için, ömrü tam o aralığa oturtmak kararı belge güncellemesinin zamanlama
şansına bırakır. Önbellek ömrü, verinin değişme sıklığından **bağımsız** seçilemez.

Son satır iki önbelleğin birlikte çalıştığı kurulumdur ve tek başına hiçbirinin vermediği bir sayı
üretiyor: giriş belirteci **2946**, yani tabana göre **15,06 kat** düşüş, bayat pay ise ömür yirmi
dördünkiyle aynı, 0,0500. Aynı satırda daha ince bir etki de var: önek isabeti 0,9792'den
**0,9359'a** düşüyor. Yanıt önbelleği çağrı sayısını 240'tan 78'e indirdiği için, dört
güncellemenin kırdığı eşleşme artık çok daha küçük bir bölene bölünüyor. Bir önbellek, öbürünün
isabet oranını **düşürerek** iyileştirir; iki düzeneğin sayısı ayrı ayrı ölçülüp toplanamaz.

#### Özet

- İstemin 186 belirtecinin 175'i bütün isteklerde ortaktır; tekrarın büyüklüğü ölçülmeden hangi
  önbelleğin işe yarayacağı bilinemez.
- Önek önbelleği içeriğe göre anahtarlandığı için bayatlamaz: 0,9792 isabetle girişi 44367'den
  7472'ye indiriyor ve doğru yanıt payını hiç değiştirmiyor.
- Yanıt önbelleğinde ömür uzadıkça isabet 0,4708'den 0,8792'ye çıkarken bayat yanıt payı
  0,0208'den 0,4417'ye tırmanıyor ve doğru yanıt payı 0,9333'ten 0,5542'ye iniyor.
- İki koşum farkı 0,0250'dir: ömür sekiz ve yirmi dördün kaybı bu farkın altında kalıp ölçülmemiş
  sayılırken, altmış dört ve sınırsız ömrün kaybı ölçülmüştür.
- Ömür, güncelleme aralığına yakın seçildiğinde karar kararsızlaşır; aynı ayar bir koşumda
  gürültünün altında, ötekinde onun üç katı kayıp veriyor.
- İki önbellek birlikte girişi 2946'ya indiriyor, ama yanıt önbelleği önek isabetini 0,9792'den
  0,9359'a düşürüyor: düzeneklerin sayıları ayrı ölçülüp toplanamaz.

#### Sonraki Adım

Bu derste kazanılan şey belirteçtir. Önbellekten dönen bir yanıt hiç çağrı yapmadığı için
kullanıcının beklemesini de kısaltır, ama bu ders o tarafı hiç saymadı: tablo yalnız belirteç,
çağrı ve doğruluk sütunları taşıyor. Oysa bir destek yardımcısında en görünür ölçüt bekleme
süresidir ve onu belirleyen şey yalnız önbellek değildir. Bağlamın büyüklüğü, çağrının tek başına
mı yoksa bir zincirin parçası olarak mı yapıldığı ve pahalı adımın her istekte mi yoksa yalnız
gerekli olduğunda mı çalıştırıldığı beklemeyi ayrı ayrı değiştirir. Sonraki ders bu üç kurulumu
karşılaştırır: küçük bağlam, büyük bağlam ve iki aşamalı çağrı hangi **gecikme sınıfında** duruyor
ve her birinin isabeti ne.

### Gecikme Eniyilemesi

Source: https://academia.sh/tr/kurslar/model-apileri/gecikme-eniyilemesi

Aynı 240 kurgu isteğin beş kurulumda gecikme sınıfı ve doğruluk olarak karşılaştırılması: küçük bağlam tek çağrı sınıfında 1,0000 adım bekletiyor ama doğruluğu 0,7750, büyük bağlam aynı sınıfta 3,0000 adım bekletip 0,9292 veriyor. İki aşamalı kurulum isteklerin 0,2500'ünü zincire taşıyarak beklemeyi 1,7500'e, giriş belirtecini 19716'ya indiriyor ve doğruluğun yalnız 0,0125'ini kaybediyor. Paralel kurulum beklemeyi 1,5000'e çekiyor ama 47352 belirteçle büyük bağlamdan pahalıya geliyor. İkinci aşamayı yığın hâlinde göndermek doğruluğu ve belirteci değiştirmeden beklemeyi 3,5542'ye çıkarıyor: toplu çağrı bir gecikme düzeneği değildir.

Önceki ders belirteci saydı ve önbelleğin onu on beş kata kadar düşürebildiğini gösterdi.
Tablonun hiçbir sütunu kullanıcının **beklediği** şeyi ölçmüyordu. Oysa bir destek yardımcısında
en görünür ölçüt budur ve onu belirleyen tek kaldıraç önbellek değildir.

Bekleme, ham süre olarak yazılamaz: aynı kod başka bir makinede başka bir sayı verir. Yazılabilen
şey **yapı**dır. Bir isteğin yanıtı kaç ardışık çağrı bekliyor, o çağrılar aynı anda mı yoksa
peş peşe mi yapılıyor ve her çağrının giriş belirteci ne kadar. Bu ders üç kurulumu — küçük
bağlam, büyük bağlam ve iki aşamalı çağrı — bu iki eksende karşılaştırır ve her birinin
**doğruluğunu** yanına yazar. Sonra iki kurulum daha ekler, çünkü gecikmeyi düşürmenin iki ayrı
yolu daha vardır ve ikisi de bedelsiz değildir.

- **UK17.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Dağarcık, sorular ve
  yanıltıcı ek cümleler **kurgudur**, tohum **20260218**.
- **UK18.** Bekleme **adım** ile sayılır. Bir çağrı `1 + giriş // 60` adım tutar: uzun giriş
  daha uzun bekletir.
- **UK19. Dört gecikme sınıfı vardır.** **Tek çağrı**: bir istek için tek bir çağrı beklenir.
  **Zincir**: ikinci çağrı birincinin yanıtını bekler. **Paralel**: iki çağrı aynı anda gönderilir,
  bekleme geç bitenindir. **Toplu**: çağrı bir yığının parçasıdır ve yığın dolana kadar beklenir.
- **UK20.** Ucuz **ön süzgeç** modelin dışındadır, hiç belirteç harcamaz ve dağarcıktan tek bir
  belge seçer. Parça sayımı yaptığı için yanıltıcı ek cümlelere takılır.
- **UK21.** Dağarcığın tamamı isteme konduğunda model belgeleri karşılaştırabildiği için anahtar
  öbeğini bütün olarak eşleştirir; bu, büyük bağlamın doğruluk üstünlüğünün kaynağıdır.
- **UK22.** İki aşamalı kurulumda birinci aşama, verilen belgenin **yeterli olup olmadığını** da
  bildirir. Bu bildirim **onda bir** yanılır; yalnız yetersiz denen istekler ikinci aşamaya
  tırmanır.
- **UK23. Doğru yanıt**, hem doğru belgeye dayanan hem etiketi doğru olan yanıttır.
- **UK24.** İş yükü 120 adımda 240 istektir, adım başına iki; otuz soru sırayla dolaşılır.
- **UK25.** Toplu kurulumda yığın boyu sekizdir; koşum sonunda eksik kalan yığın son adımda
  gönderilir.

#### Bağlamın Boyutu Hem Beklemeyi Hem Doğruluğu Belirler

Önce dağarcık, sorular ve iki seçim yordamı kurulur: ucuz ön süzgeç ile dağarcığın tamamının
istemde olduğu durum. Ardından bir kolay ve bir yanıltıcı soru üzerinde ikisi yan yana konur.

```python
# BENZETICI -- KURGUDUR. Gercek bir uc nokta cagrilmaz. Dagarcik, sorular ve
# yaniltici ek cumleler kurgudur, tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF
BIRIM = 60                       # bir adimin tasidigi giris belirteci


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 belirtecle(m):
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
BELGE = [("FT1", "fatura tutari", "fatura tutari hesap donemi ve gecikme farki"),
         ("FT2", "fatura odemesi", "fatura odemesi yontemleri ve borc gorunumu"),
         ("AR1", "ariza kaydi", "ariza kaydi acma ve ekip yonlendirme yordami"),
         ("AR2", "baglanti bozuklugu", "baglanti bozuk oldugunda uygulanan denetim"),
         ("SY1", "sayac endeksi", "sayac endeks okumasi ve duzeltme yordami"),
         ("SY2", "sayac degisimi", "sayac degisimi randevu kurallari ve sure taahhudu"),
         ("TA1", "tarife basamagi", "tarife basamaklari ve abone tipine gore ucret"),
         ("TA2", "tarife degisikligi", "tarife degisikligi basvurusu ve gecerlilik"),
         ("KS1", "planli kesinti", "planli kesinti duyurusu ve takip kurallari"),
         ("KS2", "mahalle kesintisi", "mahallede kesinti bildirimi ve donus suresi")]
BELGE = [{"kod": k, "konu": KONU[i // 2], "anahtar": a, "metin": m}
         for i, (k, a, m) in enumerate(BELGE)]
KALIP = ["{a} konusunda ne yapmam gerekiyor",
         "{a} icin gecerli kural nedir",
         "{a} ile ilgili son durum ne"]
SORU = []
for i, b in enumerate(BELGE):
    for j, k in enumerate(KALIP):
        m = k.format(a=b["anahtar"])
        if (i + j) % 3 == 1:                       # yaniltici ek cumle
            m += " " + BELGE[(i + 4) % 10]["metin"].split(" ve ")[-1]
        SORU.append({"b": i, "konu": b["konu"], "metin": m})
TAM = " ; ".join(f"{b['kod']} {b['metin']}" for b in BELGE)
YON = "Soruyu verilen belgeye dayanarak yanitla . Etiket ve belge kodu yaz . Belge: "


def sec(soru, tam):
    """tam=False: ucuz on suzgec (parca sayimi). tam=True: dagarcik istemde
    oldugundan model anahtar obegini butun olarak eslestirebilir."""
    st, p = belirtecle(soru["metin"]), []
    for b in BELGE:
        x = sum(t in belirtecle(b["metin"]) for t in st)
        if tam and all(t in st for t in belirtecle(b["anahtar"])):
            x += 8.0
        p.append(x)
    e = sorted(range(10), key=lambda i: (-p[i], i))
    return e[0], p[e[0]] - p[e[1]]


def cagir(soru, baglam, tohum=TOHUM, sira=0):
    """KURGU uc nokta. Verilen baglami okur; giris belirteci baglamla buyur."""
    bel = belirtecle(YON + baglam + " . Soru: " + soru["metin"])
    r = uretec((tohum ^ izno(soru["metin"])) + 7919 * sira)
    return (soru["konu"] if r() > 0.08 else KONU[int(r() * 5)]), len(bel)


def adim(g):
    return 1 + g // BIRIM


print("belge", len(BELGE), ", soru", len(SORU), ", tam dagarcik",
      len(belirtecle(TAM)), "belirtec")
z = sum(sec(s, False)[0] == s["b"] for s in SORU)
g = sum(sec(s, True)[0] == s["b"] for s in SORU)
print(f"dogru belgeye ulasan: on suzgec {z}/{len(SORU)} , tam dagarcik {g}/{len(SORU)}")
for j in (0, 8):
    s0 = SORU[j]
    i0, i1 = sec(s0, False)[0], sec(s0, True)[0]
    gk, gb = cagir(s0, BELGE[i0]["metin"])[1], cagir(s0, TAM)[1]
    print(f"\nsoru : {s0['metin']}")
    print(f"  dogru {BELGE[s0['b']]['kod']} , on suzgec {BELGE[i0]['kod']} , "
          f"tam dagarcik {BELGE[i1]['kod']}")
    print(f"  kucuk baglam {gk} belirtec -> {adim(gk)} adim ; "
          f"buyuk baglam {gb} belirtec -> {adim(gb)} adim")
```

```
belge 10 , soru 30 , tam dagarcik 121 belirtec
dogru belgeye ulasan: on suzgec 25/30 , tam dagarcik 30/30

soru : fatura tutari konusunda ne yapmam gerekiyor
  dogru FT1 , on suzgec FT1 , tam dagarcik FT1
  kucuk baglam 44 belirtec -> 1 adim ; buyuk baglam 154 belirtec -> 3 adim

soru : ariza kaydi ile ilgili son durum ne abone tipine gore ucret
  dogru AR1 , on suzgec TA1 , tam dagarcik AR1
  kucuk baglam 46 belirtec -> 1 adim ; buyuk baglam 156 belirtec -> 3 adim
```

İki sorunun karşılaştırılması ödünleşimin kaynağını gösteriyor. Kolay soruda iki yol da aynı
belgeye ulaşıyor ve küçük bağlam **üçte bir** beklemeyle aynı işi yapıyor. Yanıltıcı sorudaysa ek
cümle bir tarife belgesinin sözcüklerini taşıyor; parça sayan ön süzgeç `TA1` diyor, oysa doğru
belge `AR1`. Dağarcığın tamamı istemdeyken bu yanılma olmuyor, çünkü model anahtar öbeğini bütün
olarak eşleştirebiliyor. Otuz soruda ön süzgeç 25'ini, tam dağarcık 30'unu doğru belgeye
bağlıyor.

Bekleme tarafında da tablo nettir: küçük bağlam 44 belirteçle bir adım, büyük bağlam 154
belirteçle üç adım. **İkisi de aynı gecikme sınıfındadır** — tek çağrı — ama bekleme üç katıdır.
Sınıf tek başına bir ölçü değildir; sınıfın içindeki bekleme giriş belirteciyle büyür.

#### Beş Kurulumun Sınıf ve Doğruluk Tablosu

Beş kurulum aynı akışta koşturulur. İki aşamalı kurulumda birinci aşama ucuz çağrıdır ve verilen
belgenin yeterli olup olmadığını da bildirir; yetersiz diyenler ikinci aşamaya tırmanır. Paralel
kurulumda iki çağrı aynı anda gönderilir. Sonuncusunda tırmanan istekler sekizli yığınlarda
toplanır.

```python
def akis():
    """120 adimda 240 istek, adim basina iki; sorular sirayla dolasilir."""
    return [(a, SORU[(2 * a + j) % len(SORU)]) for a in range(120) for j in (0, 1)]


def asama1(soru, tohum, sira):
    """Ucuz asama: on suzgecin verdigi tek belge . Model belgenin yeterli olup
    olmadigini da bildirir; bu bildirim onda bir yaniliyor."""
    i, _ = sec(soru, False)
    e, g = cagir(soru, BELGE[i]["metin"], tohum, sira)
    r = uretec((tohum ^ izno(soru["metin"])) + 31 * sira + 5)
    yeterli = (i == soru["b"]) != (r() < 0.10)
    return i, e, g, yeterli


def asama2(soru, tohum, sira):
    i, _ = sec(soru, True)
    e, g = cagir(soru, TAM, tohum, sira)
    return i, e, g


def kosum(kurulum, tohum=TOHUM):
    s = dict.fromkeys(("dogru", "giris", "cagri", "bekle", "tirman"), 0)
    sinif, yigin, n = {}, [], 0
    for a, soru in akis():
        n += 1
        i, e, g, yeterli = asama1(soru, tohum, n)
        if kurulum == "kucuk":
            s["giris"] += g
            s["cagri"] += 1
            s["bekle"] += adim(g)
            sinif["tek cagri"] = sinif.get("tek cagri", 0) + 1
            s["dogru"] += i == soru["b"] and e == soru["konu"]
            continue
        if kurulum == "buyuk":
            i2, e2, g2 = asama2(soru, tohum, n)
            s["giris"] += g2
            s["cagri"] += 1
            s["bekle"] += adim(g2)
            sinif["tek cagri"] = sinif.get("tek cagri", 0) + 1
            s["dogru"] += i2 == soru["b"] and e2 == soru["konu"]
            continue
        if kurulum == "paralel":                       # iki cagri ayni anda
            i2, e2, g2 = asama2(soru, tohum, n)
            s["giris"] += g + g2
            s["cagri"] += 2
            if yeterli:
                s["bekle"] += adim(g)
                sinif["paralel-erken"] = sinif.get("paralel-erken", 0) + 1
                s["dogru"] += i == soru["b"] and e == soru["konu"]
            else:
                s["bekle"] += max(adim(g), adim(g2))
                sinif["paralel"] = sinif.get("paralel", 0) + 1
                s["dogru"] += i2 == soru["b"] and e2 == soru["konu"]
            continue
        s["giris"] += g                                # iki asamali kurulumlar
        s["cagri"] += 1
        if yeterli:
            s["bekle"] += adim(g)
            sinif["tek cagri"] = sinif.get("tek cagri", 0) + 1
            s["dogru"] += i == soru["b"] and e == soru["konu"]
            continue
        s["tirman"] += 1
        i2, e2, g2 = asama2(soru, tohum, n)
        s["giris"] += g2
        s["cagri"] += 1
        s["dogru"] += i2 == soru["b"] and e2 == soru["konu"]
        if kurulum == "iki":
            s["bekle"] += adim(g) + adim(g2)
            sinif["zincir"] = sinif.get("zincir", 0) + 1
        else:                                          # ikinci asama yigin halinde
            yigin.append((a, adim(g), adim(g2)))
            if len(yigin) == 8:
                for a0, b1, b2 in yigin:
                    s["bekle"] += b1 + (a - a0) + b2
                sinif["toplu"] = sinif.get("toplu", 0) + 8
                yigin = []
    for a0, b1, b2 in yigin:                           # kosum sonunda kalan yigin
        s["bekle"] += b1 + (119 - a0) + b2
        sinif["toplu"] = sinif.get("toplu", 0) + 1
    return (s["dogru"] / n, s["bekle"] / n, s["giris"], s["cagri"], s["tirman"] / n,
            " , ".join(f"{k} {v / n:.4f}" for k, v in sorted(sinif.items())))


KURULUM = (("kucuk baglam", "kucuk"), ("buyuk baglam", "buyuk"),
           ("iki asamali", "iki"), ("paralel", "paralel"),
           ("iki asamali + toplu", "toplu"))
print("kurulum              dogru  bekleme  giris  cagri  tirmanan")
for ad, k in KURULUM:
    a = kosum(k)
    print(f"{ad:<19} {a[0]:.4f}  {a[1]:>7.4f}  {a[2]:>5}  {a[3]:>5}  {a[4]:>8.4f}")
print("\ngecikme sinifi dagilimi:")
for ad, k in KURULUM:
    print(f"  {ad:<19} {kosum(k)[5]}")
print("\nikinci kosum (tohum 20260219), dogru / bekleme / tirmanan:")
for ad, k in KURULUM:
    a = kosum(k, TOHUM + 1)
    print(f"  {ad:<19} {a[0]:.4f} / {a[1]:.4f} / {a[4]:.4f}")
```

```
kurulum              dogru  bekleme  giris  cagri  tirmanan
kucuk baglam        0.7750   1.0000  10376    240    0.0000
buyuk baglam        0.9292   3.0000  36976    240    0.0000
iki asamali         0.9167   1.7500  19716    300    0.2500
paralel             0.9167   1.5000  47352    480    0.0000
iki asamali + toplu 0.9167   3.5542  19716    300    0.2500

gecikme sinifi dagilimi:
  kucuk baglam        tek cagri 1.0000
  buyuk baglam        tek cagri 1.0000
  iki asamali         tek cagri 0.7500 , zincir 0.2500
  paralel             paralel 0.2500 , paralel-erken 0.7500
  iki asamali + toplu tek cagri 0.7500 , toplu 0.2500

ikinci kosum (tohum 20260219), dogru / bekleme / tirmanan:
  kucuk baglam        0.7792 / 1.0000 / 0.0000
  buyuk baglam        0.9250 / 3.0000 / 0.0000
  iki asamali         0.9083 / 1.6375 / 0.2125
  paralel             0.9083 / 1.4250 / 0.0000
  iki asamali + toplu 0.9083 / 3.3583 / 0.2125
```

İlk iki satır takasın uçlarıdır. Küçük bağlam en hızlı, en ucuz ve en yanlış olandır: bekleme
1,0000 adım, giriş 10376, doğruluk **0,7750**. Büyük bağlam doğruluğu **0,9292**'ye çıkarıyor ve
karşılığında beklemeyi üçe, giriş belirtecini **3,56 kata** katlıyor. İki koşum farkı her iki
satırda da 0,0042; aradaki 0,1542'lik doğruluk farkı bu farkın otuz katından fazla, yani
tartışmasız ölçülmüştür.

Üçüncü satır iki aşamalı kurulumdur ve tablonun en dengeli satırıdır. İsteklerin **0,2500**'ü
ikinci aşamaya tırmanıyor; geri kalan dörtte üç tek çağrıda bitiyor. Sonuç: bekleme 1,7500,
yani büyük bağlamın **0,5833**'ü; giriş belirteci 19716, yani **0,5332**'si. Ödenen bedel iki
kalemdir. Birincisi 60 ek çağrıdır (240'tan 300'e). İkincisi doğruluktur: 0,9292'den 0,9167'ye,
yani **0,0125**. Bu kayıp iki koşum farkının yaklaşık üç katıdır ve ölçülmüş sayılır, ama
küçük bağlamın 0,1542'lik kaybının yanında küçük kalır. Tırmanma bildiriminin onda bir yanılması
tam olarak buraya düşüyor.

#### Gecikmeyi Neyle Satın Aldığın

Dördüncü satır aynı doğruluğa daha kısa beklemeyle ulaşıyor: 1,5000 adım. Nedeni sınıf
dağılımında yazılı — burada zincir yok, iki çağrı **aynı anda** gidiyor, dolayısıyla tırmanan
istek ucuz çağrının bir adımını ikinci kez ödemiyor. Kazanç 0,2500 adımdır. Bedel sütununda
duruyor: 480 çağrı ve **47352** giriş belirteci. Bu, iki aşamalının 2,40 katı ve **büyük
bağlamın bile 1,28 katı**. Paralel kurulum, en pahalı kurulumun da üstüne çıkarak, hiçbir
doğruluk kazanmadan yalnız bekleme satın alıyor. Gecikmeyi kısaltmanın bir yolu her zaman
vardır; sorulacak soru, hangi sütunun karşılığında.

Son satır kursun ikinci iddiasının bu konudaki üçüncü örneğidir. Tırmanan istekleri sekizli
yığınlarda göndermek doğruluğu değiştirmiyor (0,9167) ve giriş belirtecini de değiştirmiyor
(19716) — çağrı sayısı bile aynı. Değişen tek şey beklemedir ve **1,7500'den 3,5542'ye**
çıkmıştır. Toplu kurulum, tabloda en yavaş satırdır; büyük bağlamın tek çağrısından bile yavaştır.
Nedeni açıktır: yığının dolması beklenirken ilk giren istek boşuna oturur. Toplu çağrı bir
verim düzeneğidir, bir gecikme düzeneği değildir; gecikme ölçütüne bakılmadan açıldığında ölçütü
iki katına çıkarır.

İkinci koşum satırları bu okumayı doğruluyor. Tırmanan pay 0,2500'den 0,2125'e düşüyor ve bekleme
sayıları onunla birlikte iniyor (1,7500 yerine 1,6375, 3,5542 yerine 3,3583). Yani iki aşamalı
kurulumun bekleme kazancı **tırmanma payına bağlıdır** ve o pay koşumdan koşuma oynar. Sabit
olan tek şey sıralamadır: paralel her koşumda en kısa, toplu her koşumda en uzun beklemeyi
veriyor.

#### Özet

- Bekleme ham süre olarak değil, gecikme sınıfı ve adım sayısı olarak yazılır; küçük ve büyük
  bağlam aynı sınıftadır (tek çağrı) ama beklemeleri 1,0000 ve 3,0000 adımdır.
- Ucuz ön süzgeç otuz sorunun 25'ini doğru belgeye bağlıyor, dağarcığın tamamı 30'unu; küçük
  bağlamın doğruluğu 0,7750, büyük bağlamınki 0,9292.
- İki aşamalı kurulum isteklerin 0,2500'ünü zincire taşıyarak beklemeyi büyük bağlamın 0,5833'üne,
  giriş belirtecini 0,5332'sine indiriyor ve doğruluktan 0,0125 veriyor.
- Paralel kurulum beklemeyi 1,5000'e çekiyor ama 47352 giriş belirteciyle büyük bağlamın 1,28
  katına çıkıyor: doğruluk kazanmadan yalnız bekleme satın alınıyor.
- İkinci aşamayı yığın hâlinde göndermek doğruluğu, belirteci ve çağrı sayısını hiç değiştirmeden
  beklemeyi 1,7500'den 3,5542'ye çıkarıyor; toplu çağrı bir gecikme düzeneği değildir.
- İki aşamalı kurulumun bekleme kazancı tırmanma payına bağlıdır ve o pay koşumdan koşuma
  0,2500 ile 0,2125 arasında oynuyor.

#### Sonraki Adım

Üç derste dayanıklılık, önbellek ve gecikme ayrı ayrı ölçüldü ve her birinin yanına bir belirteç
toplamı yazıldı: 10376, 19716, 47352. Bu sayılar bir kurulumu öbürüyle karşılaştırmaya yetiyor,
ama tek bir soruyu yanıtlamıyor — **bu toplam kimin arasında paylaşıldı.** İki yüz kırk isteğin
hepsi ortalama kadar mı harcadı, yoksa toplamın önemli bir bölümünü birkaç istek mi yuttu.
Bir bütçe ortalamayla tutulmaz: ortalamanın altında kalan bir hattın en pahalı yüzde biri, tek
başına bütçeyi aşabilir ve bu, toplamlara bakan hiçbir tabloda görünmez. Sonraki ders maliyeti
**istek başına** yazar ve dağılımın kuyruğuna bakar.

### Maliyet İzleme

Source: https://academia.sh/tr/kurslar/model-apileri/maliyet-izleme

Dört yüz isteklik kurgu bir iş yükünde istek başına belirtecin defterinin tutulması ve dağılımın kuyruğunun sayılması: ortalama 81,6 belirteç iken ortanca 69, yüzde 99 dilimi 224 ve en büyük istek 303. En pahalı yüzde bir toplam belirtecin 0,0299'unu, en pahalı yüzde on ise 0,2124'ünü harcıyor. İki koşumda ortalama 81,6'dan 83,0'a çıkarken en pahalı yüzde birin payı 0,0299'dan 0,0409'a gidiyor, yani kararlı olan ortalama, oynayan kuyruktur. Faturanın kalemleri ayrıldığında yönerge 0,3921, konuşma durumu 0,3658 ve yeni bilgi taşıyan talep metni yalnız 0,1190 tutuyor. Konuşma durumunu kısaltan üç politika istek başına belirteci 81,6'dan 50,5'e indiriyor ama doğru etiket başına okunduğunda aradaki fark daralıyor.

Önceki üç ders çağrının ağ tarafını ölçtü: hız sınırına takılan istek yeniden denendi, yinelenen
bağlam önbelleğe alındı, bağlam boyutu ve kurulum değiştirilerek gecikme sınıfı düşürüldü. Üçü de
bir şeyi ucuzlattı ve hiçbirinde **ne kadara** ucuzladığı sorulmadı. Gecikme sınıfı kullanıcının
ölçüsüdür; faturanın birimi değildir.

Bu dersin birimi **belirteçtir**. Para birimi yazılmaz, çünkü fiyat sağlayıcıya ve zamana bağlıdır;
belirteç sayısı ise düzeneğin kendi ürettiği bir sayıdır ve koşumdan koşuma taşınır. Ölçülecek iki
şey vardır: bir isteğin kaç belirtece mal olduğu ve bu sayının istekler arasında **nasıl
dağıldığı**. İkincisi olmadan birincisi yanıltır.

- **UK31.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, konuşmalar ve
  belgeler **kurgudur**, tohum **20260218**.
- **UK32. Maliyet muhasebesinin yordamı tekrarlanmaz.** Ölçüt toplama, gösterge tablosu ve birim
  maliyet dağıtımı M16'nın gözlemlenebilirlik kursunda, M22'de ve M23'ün bulut yönetişimi ve
  maliyet kursunda ölçüldü. Buraya eklenen tek şey **birimdir**: bir isteğin bedeli belirteçle yazılır.
- **UK33. İş yükü bu derste tekil talep değil konuşmadır.** Durum istemcide taşınır ve her istekte
  yeniden gönderilir; bir konuşmanın üçüncü isteği birinci isteğin metnini de içerir. Bu, kuyruğun
  kaynağıdır.
- **UK34.** Konuşma uzunlukları `[1, 2, 3, 5, 8, 12]` kümesinden ağırlıklı seçilir. En uzun
  konuşmanın en son isteği bile bağlam penceresinin altında kalır, bu yüzden bu derste kırpma
  kararı devreye girmez; kırpmanın bedeli M28/K01'de ölçüldü.
- **UK35.** Bir istek bir ya da birkaç çağrıdan oluşur. Yeniden deneme yordamı tekrarlanmaz;
  deftere yalnız **kaç çağrı yapıldığı** ve her çağrının giriş ile çıkış belirteci yazılır.
- **UK36.** Yeniden denemede benzeticinin tohumu bir artırılır. Aynı istem aynı tohumla aynı yanıtı
  verdiği için ikinci deneme ancak böyle başka bir sonuç verebilir.
- **UK37.** Bir isteğin bedeli **giriş artı çıkış belirtecidir**; başarısız çağrının girişi de
  sayılır, çünkü gönderilmiştir.

#### İstek Başına Defter

Toplam belirtecin tek bir sayı olarak raporlanması bir muhasebe değil bir toplamdır. Muhasebe,
bedelin **hangi isteğe** ait olduğunu yazmayı gerektirir. Aşağıdaki defter her istek için bir satır
tutar: kaç çağrı yapıldı, kaç belirteç girdi, kaç belirteç çıktı.

```python
# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz; talepler, konusmalar
# ve belgeler kurgudur, tohum 20260218.
import math
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, EN_UZUN = 240, 24


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
KALIP = {"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"]}
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "odeme",
      "odedi": "odeme", "ariza": "ariza", "bozuk": "ariza", "calis": "ariza",
      "akmiy": "ariza", "sayac": "sayac", "endek": "sayac", "okuma": "sayac",
      "tarif": "tarife", "birim": "tarife", "abone": "tarife", "basam": "tarife",
      "kesin": "kesinti", "duyur": "kesinti", "mahal": "kesinti",
      "yardi": "bilgi", "nered": "bilgi", "kayit": "sikayet", "bekle": "sikayet"}
SERBEST = ["talebiniz {k} konusunda kaydedildi ve ekibe iletildi",
           "{k} ile ilgili kaydiniz olusturuldu en kisa surede donulecek",
           "kaydiniz alindi ilgili birim sizinle iletisime gececek"]
SAYAC = [0]


def cagir(istem, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN):
    SAYAC[0] += 1
    bel = belirtecle(istem)
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    if SAYAC[0] % 37 == 0:                          # hiz siniri cagri sayisina bagli
        return {"durum": "hiz_siniri", "giris": len(bel), "cikis": 0, "yanit": ""}
    r = uretec(tohum ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return {"durum": "zaman_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    aday = [k for k in KAVRAM if k[:5] in bel]      # etiket kumesi adayi daraltir
    p = {k: 0.15 for k in (aday if len(aday) >= 3 else KAVRAM)}
    for t in bel:
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    if sicaklik <= 0.0:
        k = max(sorted(p), key=lambda a: p[a])
    else:
        w = [math.exp(p[a] / sicaklik) for a in sorted(p)]
        k = sorted(p)[ayrik(r(), [x / sum(w) for x in w])]
    y = k if "tek" in bel else SERBEST[int(r() * 3)].format(k=k)
    cb = belirtecle(y)
    if len(cb) > en_uzun:                           # durdurma kosulu
        cb, y = cb[:en_uzun], " ".join(cb[:en_uzun])
    return {"durum": "tamam", "giris": len(bel), "cikis": len(cb), "yanit": y}


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


YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife , "
           "kesinti . Yanit olarak tek etiket yaz . Talep: ")
BELGE = ["TR1 tarife basamaklari abone tipine gore belirlenir ve yilda bir guncellenir",
         "FT2 fatura itirazi kayit acildiktan sonra on is gunu icinde sonuclanir",
         "SY3 sayac degisimi randevusu saha ekibinin bolge programina baglidir",
         "AR4 ariza kaydi acilan adreste ekip ayni gun icinde yonlendirilir",
         "KS5 planli kesinti duyurulari bir hafta once ilan panosuna asilir"]
KONUS, i = [], 0
while sum(len(c["tur"]) for c in KONUS) < 400:      # KURGU is yuku: konusmalar
    r = uretec(TOHUM + 900 + i)
    i += 1
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    u = [1, 2, 3, 5, 8, 12][ayrik(r(), [0.46, 0.24, 0.14, 0.09, 0.05, 0.02])]
    KONUS.append({"no": i, "belge": ayrik(r(), [0.74, 0.16, 0.07, 0.03]),
                  "tur": [{"konu": k, "metin": KALIP[k][(i + t) % 3]} for t in range(u)]})
ISTEK = [{"kon": c, "sira": t, "talep": c["tur"][t]}
         for c in KONUS for t in range(len(c["tur"]))][:400]


def baglam(x, kip="tam"):
    t = x["kon"]["tur"][:x["sira"]]
    t = [] if kip == "durumsuz" else (t[-2:] if kip == "iki tur" else t)
    if kip == "ozet durum":
        g = "".join(f"Onceki konu: {o['konu']} . " for o in t)
    else:
        g = "".join(f"Onceki: {o['metin']} Yanit: {o['konu']} . " for o in t)
    return g + "".join(BELGE[(x["kon"]["no"] + j) % 5] + " . "
                       for j in range(x["kon"]["belge"]))


def defter(kip="tam", tohum=TOHUM):
    """Her istek icin ayri satir: cagri, giris belirteci, cikis belirteci."""
    SAYAC[0] = 0
    d = []
    for x in ISTEK:
        c = g = ci = 0
        ist = YONERGE + baglam(x, kip) + x["talep"]["metin"]
        for a in range(3):
            s = cagir(ist, tohum + a)               # yeniden denemede tohum artar
            c, g, ci = c + 1, g + s["giris"], ci + s["cikis"]
            if s["durum"] == "tamam":
                break
        d.append({"top": g + ci, "cagri": c, "cikis": ci,
                  "dogru": oku(s["yanit"]) == x["talep"]["konu"]})
    return d


k = defter()
t = sorted(z["top"] for z in k)
top = sum(t)
print("konusma", len(KONUS), " istek", len(k), " cagri", sum(z["cagri"] for z in k),
      " toplam belirtec", top)
print("ortalama %.1f  ortanca %d  yuzde 75 %d  yuzde 90 %d  yuzde 99 %d  en buyuk %d"
      % (top / 400, t[200], t[300], t[360], t[396], t[-1]))
for p, d in ((1, 4), (5, 20), (10, 40)):
    print("en pahali %%%-3d %5d belirtec, toplamin %.4f'i"
          % (p, sum(t[-d:]), sum(t[-d:]) / top))
k2 = defter(tohum=TOHUM + 1)
t2 = sorted(z["top"] for z in k2)
print("2. kosum  ortalama %.1f  ortanca %d  en pahali %%1 payi %.4f"
      % (sum(t2) / 400, t2[200], sum(t2[-4:]) / sum(t2)))
print("isabet %.4f / %.4f" % (sum(z["dogru"] for z in k) / 400,
                              sum(z["dogru"] for z in k2) / 400))
```

```
konusma 154  istek 400  cagri 414  toplam belirtec 32642
ortalama 81.6  ortanca 69  yuzde 75 100  yuzde 90 139  yuzde 99 224  en buyuk 303
en pahali %1     975 belirtec, toplamin 0.0299'i
en pahali %5    3892 belirtec, toplamin 0.1192'i
en pahali %10   6932 belirtec, toplamin 0.2124'i
2. kosum  ortalama 83.0  ortanca 69  en pahali %1 payi 0.0409
isabet 0.9125 / 0.8925
```

#### Ortalamanın Sakladığı Kuyruk

Tek sayıya indirilmiş bir rapor şunu söylerdi: dört yüz istek, otuz iki bin altı yüz kırk iki
belirteç, istek başına **81,6**. Bu sayıya bakan bir plan, istek sayısını iki katına çıkarmanın
bedelini de iki katı olarak yazar ve yanılır.

Ortanca **69**'dur, yani isteklerin yarısı 69'un altındadır. Ortalamayı yukarı çeken şey
üst dilimlerdir: yüzde 75 dilimi 100, yüzde 90 dilimi 139, yüzde 99 dilimi **224** ve en pahalı
istek **303** belirteç. En pahalı istek ortancanın dört katından fazlasıdır. Bu, bir bozukluk değildir;
uzun konuşmaların kaçınılmaz sonucudur. Durum istemcide taşındığı için bir konuşmanın on ikinci
isteği, o konuşmanın on bir turunu da yeniden gönderir.

Kuyruğun ağırlığı payla okunur. **En pahalı yüzde bir**, yani dört yüz isteğin dördü, toplamın
**0,0299**'unu harcıyor: kendi payının üç katı. En pahalı yüzde on ise **0,2124**'ünü, yani
payının iki katından fazlasını. Bir bütçe aşımı araştırmasında bakılacak yer bu kırk istektir;
kalan üç yüz altmışın hepsini bir belirteç ucuzlatmak, aynı kazancı vermez.

Son iki satır ölçünün kendi kararlılığını sınıyor. İkinci koşumda ortalama **81,6'dan 83,0'a**
çıkıyor, yani binde on yedi oynuyor; ortanca **69'da sabit**. Buna karşılık en pahalı yüzde birin
payı **0,0299'dan 0,0409'a** gidiyor, yani üçte birden fazla oynuyor. Kuyruk az sayıda isteğin
üzerinde durduğu için gürültülüdür. Bunun doğrudan bir sonucu vardır: kuyruk payı **tek bir
koşumdan** okunmaz, bir pencere boyunca biriktirilip okunur. Ortalamanın kararlı, kuyruğun oynak
olması, ortalamaya güvenmek için değil, kuyruğu daha uzun ölçmek için bir gerekçedir.

#### Faturanın Kalemleri

Toplam belirtecin nereye gittiği, isteğin içindeki metin parçalarının ayrı ayrı sayılmasıyla
bulunur. Aşağıdaki blok aynı defteri kalemlere ayırır ve ardından konuşma durumunu kısaltan üç
politikayı aynı iş yükünde koşturur.

```python
kalem = {"yonerge": 400 * len(belirtecle(YONERGE)),
         "konusma durumu": sum(len(belirtecle(baglam(x)))
                               - len(belirtecle(baglam(x, "durumsuz"))) for x in ISTEK),
         "belge": sum(len(belirtecle(baglam(x, "durumsuz"))) for x in ISTEK),
         "talep metni": sum(len(belirtecle(x["talep"]["metin"])) for x in ISTEK),
         "cikis": sum(z["cikis"] for z in k)}
kalem["yeniden deneme"] = top - sum(kalem.values())
print("kalem            belirtec     pay")
for a, v in kalem.items():
    print(f"{a:<16} {v:>8}  {v / top:>7.4f}")
print("\npolitika      toplam  istek basi  yuzde 99  en pahali %1  isabet  dogru basi")
for kip in ("tam", "iki tur", "ozet durum", "durumsuz"):
    d = defter(kip)
    s = sorted(z["top"] for z in d)
    tt, dg = sum(s), sum(z["dogru"] for z in d)
    print(f"{kip:<12} {tt:>7} {tt / 400:>11.1f} {s[396]:>9} {sum(s[-4:]) / tt:>13.4f}"
          f" {dg / 400:>7.4f} {tt / dg:>11.1f}")
```

```
kalem            belirtec     pay
yonerge             12800   0.3921
konusma durumu      11939   0.3658
belge                2344   0.0718
talep metni          3885   0.1190
cikis                 625   0.0191
yeniden deneme       1049   0.0321

politika      toplam  istek basi  yuzde 99  en pahali %1  isabet  dogru basi
tam            32642        81.6       224        0.0299  0.9125        89.4
iki tur        27401        68.5       198        0.0314  0.9125        75.1
ozet durum     24355        60.9       120        0.0259  0.9075        67.1
durumsuz       20198        50.5        95        0.0276  0.7975        63.3
```

Kalem tablosunun ilk okuması şudur: bu faturanın **yalnız 0,1190'ı yeni bilgi taşıyor**. Talep
metni, yani abonenin o istekte yazdığı cümle, üç bin sekiz yüz seksen beş belirteçtir. Geri kalanın
en büyük iki kalemi yinelenen metindir — yönerge **0,3921**, konuşma durumu **0,3658** — ve ikisi
birlikte toplamın dörtte üçüne yakınını tutar. Çıkış belirteci ise **0,0191**, yani ihmal
edilebilir; bu düzenekte model tek bir etiket yazıyor ve yazdığı şeyin bedeli, okuduğu şeyin
bedelinin yanında görünmüyor.

Bu ayrım, hangi düzeneğin nereye dokunduğunu da söylüyor. Yönerge kalemi her istekte birebir
aynıdır ve önbelleklemenin hedefi odur; konuşma durumu kalemi istekten isteğe büyür ve
kısaltmanın hedefi odur. İkisi ayrı sayılmadan hangi düzeneğin ne kazandıracağı bilinemez.

#### Hangi Birimle Bakıldığı

Politika tablosu dört kurulumu aynı iş yükünde karşılaştırıyor. **İstek başına** sütununa bakan
bir okuma nettir: durumu tamamen atmak 81,6'yı **50,5**'e indiriyor, yani üçte birden fazla
kazandırıyor. Aynı satırın isabeti **0,7975**'tir; tam durumun **0,9125**'ine göre 0,1150 düşük.
İki koşum farkı 0,0200 olduğuna göre bu düşüş gerçektir ve dört yüz istekte kırk altı yanlış
etiket demektir.

Son sütun aynı dört satırı **doğru yanıt başına** okuyor ve aradaki farkı daraltıyor: 89,4 / 75,1 /
67,1 / **63,3**. Durumsuz kurulum, isabeti en düşük olduğu hâlde doğru yanıt başına en ucuz
olanıdır. İki birim aynı kazananı gösteriyor ama farkı ayrı büyüklükte yazıyor, çünkü ilki
yanlış yanıtın bedelini sıfır sayıyor. Bir destek hattında yanlış etiket bedelsiz değildir; yanlış yönlendirilmiş kırk altı
talep, elle düzeltme işi doğurur. Hangi birimin doğru olduğu ölçümün değil ürünün kararıdır, ama
**hangi birimle bakıldığının yazılması** ölçümün sorumluluğudur.

Üçüncü satır ise ölçülemeyen bir kazançtır. Özet durum kurulumu isabeti 0,9125'ten **0,9075**'e
indiriyor; fark 0,0050, iki koşum farkının dörtte biri. Bu satır "isabeti düşürmüyor" diye
okunabilir, ama doğrusu "**düşürüp düşürmediği bu ölçümle bilinemez**" olmalıdır. Karşılığında
kazandırdığı 8287 belirteç ise ölçülmüştür.

Kuyruk sütunu ayrıca ters bir davranış gösteriyor. İki tur kurulumu toplamı 32642'den 27401'e
indirdiği hâlde en pahalı yüzde birin payı **0,0299'dan 0,0314'e çıkıyor**. Kısaltma toplamı,
kuyruğu kestiğinden daha çok kestiği için pay büyüyor. Kuyruk payı bir oran olduğundan tek başına
okunamaz; yanında toplam yazmalıdır.

#### Özet

- Maliyetin birimi belirteçtir; para birimi yazılmaz, çünkü fiyat sağlayıcıya bağlıdır, belirteç
  sayısı düzeneğin kendi ürettiği bir sayıdır.
- Ortalama 81,6, ortanca 69, yüzde 99 dilimi 224 ve en büyük istek 303 belirteçtir; ortalamaya
  bakan bir plan uzun konuşmaların bedelini göremez.
- En pahalı yüzde bir toplamın 0,0299'unu, en pahalı yüzde on 0,2124'ünü harcıyor: bütçe
  araştırması kırk isteğe bakarak yapılır.
- Ortalama iki koşumda 81,6'dan 83,0'a oynarken kuyruk payı 0,0299'dan 0,0409'a gidiyor; kuyruk
  tek koşumdan değil bir pencereden okunur.
- Faturanın 0,3921'i yönerge, 0,3658'i konuşma durumu, yalnız 0,1190'ı yeni bilgi taşıyan talep
  metnidir; çıkış belirteci 0,0191'dir.
- Aynı dört politika iki birimde de aynı sıralanır ama aradaki fark daralır (50,5'e karşı 63,3);
  hangi birimle bakıldığı yazılmadan bu fark okunamaz.

#### Sonraki Adım

Bu dersin defteri her isteği aynı sayıyor: bir istek gitti, bir yanıt geldi, şu kadar belirteç
tutuldu. Defterin göremediği bir sütun var. Dört yüz isteğin bir bölümü, uç nokta yanıt vermediği
için başka bir yoldan geçtiğinde de aynı satırı yazacaktır: çağrı sayısı, belirteç, hatta bir
etiket. Yanıtın **nereden geldiği** deftere yazılmıyor. Sonraki ders kesinti karşısında ikinci bir
yola düşen isteklerin payını sayar ve o isteklerin isabetini ayrı basar: kesinti kapatıldığında
kullanıcıya görünen hata neredeyse sıfıra iner, toplam isabet neredeyse hiç oynamaz ve düşüş yalnız yanıtın
kaynağı deftere yazıldığında görünür.

### Hata ve Kesinti Yönetimi

Source: https://academia.sh/tr/kurslar/model-apileri/hata-ve-kesinti-yonetimi

Birincil uç nokta yanıt vermediğinde isteğin yedek bir katmana düşürülmesinin kaliteye ne yaptığının ölçülmesi: yedeksiz kurulumda kesinti 26 isteği hataya çevirirken yedekli kurulumda hata 2'ye iniyor ve toplam isabet 0,8450'den 0,8850'ye çıkıyor, yani yedek bir iyileşme gibi görünüyor. Kesintisiz tabana göre okunduğunda aynı sayı 0,8975'ten 0,8850'ye düşmüştür ve düşüş 0,0125, iki koşum farkı olan 0,0200'ün altındadır. Defter yanıtın kaynağını yazdığında düşüş görünür oluyor: ana katman 0,9037, yedek katman 0,6667. Kesinti payı 0,00'dan 0,35'e çıkarıldığında toplam isabetin düşüşü ancak 0,18'de koşum farkını aşıyor; ana katmanın isabeti dört satırda da oynamıyor, oynayan karışımdır.

Önceki dersin defteri her isteğe bir satır yazdı: kaç çağrı, kaç belirteç, doğru mu. O defterde
olmayan tek şey yanıtın **nereden geldiğiydi**. Bir uç nokta yanıt vermediğinde isteğin
kaybolmaması için ikinci bir yol açılır ve bu yol, defterde birincisiyle aynı görünen bir satır
yazar.

Devre kesici, zarif bozulma ve yedeğe geçiş M19'un dayanıklılık kursunda kuruldu: anahtarın ne
zaman çevrileceği, açık devrenin ne kadar açık kalacağı ve yarı açık denemenin yordamı orada
ölçüldü. Burada tekrarlanmaz. Bu derse eklenen tek şey şudur: bir dil modeli için yedek, **aynı
işi yapan başka bir sunucu değildir**. Daha küçük, daha dar ve daha az isabetli bir bileşendir; ve
bunu kimseye söylemeden yapar.

- **UK38.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, konuşmalar ve
  kesinti penceresi **kurgudur**, tohum **20260218**.
- **UK39.** İş yükü önceki dersinkiyle aynıdır: 154 kurgu konuşmadan gelen 400 istek.
- **UK40. Yedek katman üç yerde farklıdır:** bağlam penceresi 240 yerine **120**, iz tablosunun
  yirmi üç girdisinden **on biri** onda yoktur ve isteme yazılan etiket kümesi onun aday
  kümesini **daraltmaz**. Üçü de gerçek bir küçük modelin bilinen sınırlarıdır.
- **UK41.** Kesinti bir **pencere** olarak kurgulanır: 160. istekten başlayarak iş yükünün belirli
  bir payı boyunca birincil katman isteklerin 0,70'ini reddeder.
- **UK42.** Kesinti dışında da birincil katman bir pay isteği yanıtlamaz: hız sınırı, zaman aşımı
  ve bağlam aşımı. Bunlar **kesinti olmadan da** yedeği devreye sokar.
- **UK43. Üç kurulum karşılaştırılır:** düşen isteği hataya çeviren, insan hattına yönlendiren ve
  yedeğe düşüren. Üçü de **aynı birincil koşumun** çıktısı üzerinde çalışır, böylece düşen istek
  kümesi üçünde de birebir aynıdır.
- **UK44.** İsabet üç yerde ayrı sayılır: bütün isteklerin üzerinden **toplam**, birincil katmanın
  yanıtladıkları üzerinden **ana**, yedeğin yanıtladıkları üzerinden **yedek**.

#### Yedeğin Sessiz Bedeli

```python
# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz; talepler, konusmalar
# ve kesinti penceresi kurgudur, tohum 20260218.
import math
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE, EN_UZUN = 240, 24


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
KALIP = {"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"]}
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "odeme",
      "odedi": "odeme", "ariza": "ariza", "bozuk": "ariza", "calis": "ariza",
      "akmiy": "ariza", "sayac": "sayac", "endek": "sayac", "okuma": "sayac",
      "tarif": "tarife", "birim": "tarife", "abone": "tarife", "basam": "tarife",
      "kesin": "kesinti", "duyur": "kesinti", "mahal": "kesinti",
      "yardi": "bilgi", "nered": "bilgi", "kayit": "sikayet", "bekle": "sikayet"}
SERBEST = ["talebiniz {k} konusunda kaydedildi ve ekibe iletildi",
           "{k} ile ilgili kaydiniz olusturuldu en kisa surede donulecek",
           "kaydiniz alindi ilgili birim sizinle iletisime gececek"]
SAYAC = [0]


def cagir(istem, tohum=TOHUM, sicaklik=0.6, en_uzun=EN_UZUN):
    SAYAC[0] += 1
    bel = belirtecle(istem)
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    if SAYAC[0] % 37 == 0:                          # hiz siniri cagri sayisina bagli
        return {"durum": "hiz_siniri", "giris": len(bel), "cikis": 0, "yanit": ""}
    r = uretec(tohum ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return {"durum": "zaman_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    aday = [k for k in KAVRAM if k[:5] in bel]      # etiket kumesi adayi daraltir
    p = {k: 0.15 for k in (aday if len(aday) >= 3 else KAVRAM)}
    for t in bel:
        if IZ.get(t) in p:
            p[IZ[t]] += 1.0
    if sicaklik <= 0.0:
        k = max(sorted(p), key=lambda a: p[a])
    else:
        w = [math.exp(p[a] / sicaklik) for a in sorted(p)]
        k = sorted(p)[ayrik(r(), [x / sum(w) for x in w])]
    y = k if "tek" in bel else SERBEST[int(r() * 3)].format(k=k)
    cb = belirtecle(y)
    if len(cb) > en_uzun:                           # durdurma kosulu
        cb, y = cb[:en_uzun], " ".join(cb[:en_uzun])
    return {"durum": "tamam", "giris": len(bel), "cikis": len(cb), "yanit": y}


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


YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife , "
           "kesinti . Yanit olarak tek etiket yaz . Talep: ")
BELGE = ["TR1 tarife basamaklari abone tipine gore belirlenir ve yilda bir guncellenir",
         "FT2 fatura itirazi kayit acildiktan sonra on is gunu icinde sonuclanir",
         "SY3 sayac degisimi randevusu saha ekibinin bolge programina baglidir",
         "AR4 ariza kaydi acilan adreste ekip ayni gun icinde yonlendirilir",
         "KS5 planli kesinti duyurulari bir hafta once ilan panosuna asilir"]
KONUS, i = [], 0
while sum(len(c["tur"]) for c in KONUS) < 400:      # KURGU is yuku: konusmalar
    r = uretec(TOHUM + 900 + i)
    i += 1
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    u = [1, 2, 3, 5, 8, 12][ayrik(r(), [0.46, 0.24, 0.14, 0.09, 0.05, 0.02])]
    KONUS.append({"no": i, "belge": ayrik(r(), [0.74, 0.16, 0.07, 0.03]),
                  "tur": [{"konu": k, "metin": KALIP[k][(i + t) % 3]} for t in range(u)]})
ISTEK = [{"kon": c, "sira": t, "talep": c["tur"][t]}
         for c in KONUS for t in range(len(c["tur"]))][:400]


def baglam(x):
    return "".join(f"Onceki: {o['metin']} Yanit: {o['konu']} . "
                   for o in x["kon"]["tur"][:x["sira"]]) \
        + "".join(BELGE[(x["kon"]["no"] + j) % 5] + " . "
                  for j in range(x["kon"]["belge"]))


IZ_YEDEK = {a: b for a, b in IZ.items() if a not in
            ("tutar", "ayrin", "bozuk", "akmiy", "endek", "okuma", "basam",
             "abone", "duyur", "mahal", "calis")}
PENCERE_YEDEK = 120


def yedege_sor(istem, tohum=TOHUM):
    """Yedek katman: dar pencere, az iz, etiket kumesini daraltmiyor."""
    SAYAC[0] += 1
    bel = belirtecle(istem)
    if len(bel) > PENCERE_YEDEK:
        return {"durum": "baglam_asimi", "giris": len(bel), "cikis": 0, "yanit": ""}
    p = {a: 0.15 for a in KAVRAM}
    for t in bel:
        if IZ_YEDEK.get(t) in p:
            p[IZ_YEDEK[t]] += 1.0
    w = [math.exp(p[a] / 1.3) for a in sorted(p)]
    r = uretec((tohum + 5) ^ izno(istem))
    return {"durum": "tamam", "giris": len(bel), "cikis": 1,
            "yanit": sorted(p)[ayrik(r(), [x / sum(w) for x in w])]}


def birincil(pay=0.06, tohum=TOHUM):
    """Kesinti penceresi: 160. istekten baslayarak is yukunun pay kadari."""
    SAYAC[0] = 0
    kes, cikti = int(400 * pay), []
    for i, x in enumerate(ISTEK):
        ist = YONERGE + baglam(x) + x["talep"]["metin"]
        if 160 <= i < 160 + kes and uretec(tohum ^ izno(ist))() < 0.70:
            s = {"durum": "kesinti", "giris": len(belirtecle(ist)), "cikis": 0, "yanit": ""}
            SAYAC[0] += 1
        else:
            s = cagir(ist, tohum)
        cikti.append((x, ist, s))
    return cikti


def kurul(kip, ham):
    """Defter yanitin kaynagini da yazar: ana katman ve yedek ayri sayilir."""
    say = dict(dusen=0, yedek=0, hata=0, insan=0, ad=0, an=0, yd=0, yn=0, bel=0)
    for x, ist, s in ham:
        say["bel"] += s["giris"] + s["cikis"]
        if s["durum"] == "tamam":
            say["an"] += 1
            say["ad"] += oku(s["yanit"]) == x["talep"]["konu"]
            continue
        say["dusen"] += 1
        if kip == "yedeksiz":
            say["hata"] += 1
        elif kip == "insana":
            say["insan"] += 1
        else:
            y = yedege_sor(ist)
            say["bel"] += y["giris"] + y["cikis"]
            if y["durum"] != "tamam":
                say["hata"] += 1
            else:
                say["yedek"] += 1
                say["yn"] += 1
                say["yd"] += oku(y["yanit"]) == x["talep"]["konu"]
    say["toplam"] = (say["ad"] + say["yd"]) / 400
    say["ana"] = say["ad"] / max(say["an"], 1)
    say["yed"] = say["yd"] / max(say["yn"], 1)
    return say


print("kurulum              dusen  hata  yedege  insana  toplam    ana   yedek  belirtec")
for ad, kip, ham in (("kesintisiz yedeksiz", "yedeksiz", birincil(0.0)),
                     ("kesintili yedeksiz", "yedeksiz", birincil()),
                     ("kesintili insana", "insana", birincil()),
                     ("kesintili yedekli", "yedekli", birincil()),
                     ("kesintisiz yedekli", "yedekli", birincil(0.0))):
    a = kurul(kip, ham)
    print(f"{ad:<20} {a['dusen']:>5} {a['hata']:>5} {a['yedek']:>7} {a['insan']:>7}"
          f" {a['toplam']:>7.4f} {a['ana']:>6.4f} {a['yed']:>6.4f} {a['bel']:>9}")
```

```
kurulum              dusen  hata  yedege  insana  toplam    ana   yedek  belirtec
kesintisiz yedeksiz     13    13       0       0  0.8750 0.9044 0.0000     31569
kesintili yedeksiz      26    26       0       0  0.8450 0.9037 0.0000     31548
kesintili insana        26     0       0      26  0.8450 0.9037 0.0000     31548
kesintili yedekli       26     2      24       0  0.8850 0.9037 0.6667     33775
kesintisiz yedekli      13     1      12       0  0.8975 0.9044 0.7500     32726
```

İkinci ve dördüncü satır yan yana okunduğunda yedek bir kazanç gibi görünüyor. Kesinti sırasında
yedeksiz kurulum yirmi altı isteği hataya çeviriyor ve toplam isabeti **0,8450**'de bırakıyor;
yedekli kurulumda hata **2**'ye iniyor ve toplam isabet **0,8850**'ye çıkıyor. Fark **0,0400**,
bedeli **2227 belirteç**. Bir gösterge tablosunda bu satır, düzeneğin işe yaradığının kanıtı diye
okunur.

Beşinci satır aynı sayıyı başka bir tabana karşı koyuyor. Kesinti hiç olmasaydı toplam isabet
**0,8975** olacaktı. Kesinti oldu ve sayı **0,8850**'ye indi: düşüş **0,0125**. Bir sonraki bölümde
görüleceği gibi bu ölçünün iki koşum farkı **0,0200**'dür. Yani düşüş, ölçüm gürültüsünün altında
kaldı. Kesinti yaşandı, yirmi dört istek başka bir modelden yanıtlandı ve toplam isabet bunu
göstermedi.

Düşüşün nerede olduğunu yalnız son iki sütun söylüyor. Birincil katmanın isabeti **0,9037**, yedeğe
düşen isteklerinki **0,6667**. Aradaki **0,2371** küçük bir fark değildir; her üç istekten birinde
etiket yanlıştır. Bu sayının görünmesi için tek gereken, deftere bir alan eklemekti: yanıtın
**hangi katmandan** geldiği. O alan sıfır belirteç tutuyor.

Üçüncü satır başka bir seçeneği ölçüyor. Düşen istek yedeğe verilmek yerine insan hattına
yönlendirildiğinde toplam isabet **0,8450**'de kalıyor, yani yedeksiz kurulumla aynı; ama
kullanıcıya dönen hata **sıfır** ve maliyet yirmi altı isteklik insan işi olarak **sayılabilir bir
yere** yazılıyor. Yedek gizler, insan hattı sayar. Zarif bozulmanın bu iki biçimi arasındaki
seçim, gizlenen bedeli görünür kılmaya değer verip vermemekle ilgilidir.

Son olarak yedeğin dar penceresi iki isteği hiç yanıtlanamaz bırakıyor. Bunlar en uzun
konuşmalardır: yedek katmanın penceresi 120 belirteç olduğu için birincil katmanın taşıyabildiği
bağlamı taşıyamıyor. Yedeğe düşen istekler rastgele değildir; **en uzun bağlamı olanlar en çok
zorlanır**.

#### Kesinti Payı Büyüdükçe

Bir düşüşün görünmemesi, düşüşün küçük olduğu anlamına gelmez. Aşağıdaki blok kesinti payını
sıfırdan 0,35'e çıkarıyor ve her adımda toplam isabeti iki tohumla ölçüyor.

```python
taban = kurul("yedekli", birincil(0.0))["toplam"]
print("kesinti  yedek payi  toplam A  toplam B  kosum farki  dusus  gorunur"
      "   ana   yedek  orneklem")
for pay in (0.0, 0.06, 0.18, 0.35):
    a = kurul("yedekli", birincil(pay))
    b = kurul("yedekli", birincil(pay, TOHUM + 1))
    f, d = abs(a["toplam"] - b["toplam"]), taban - a["toplam"]
    print(f"{pay:<8.2f} {a['yedek'] / 400:>10.4f} {a['toplam']:>9.4f} {b['toplam']:>9.4f}"
          f" {f:>12.4f} {d:>6.4f}  {'evet' if d > f else 'hayir':<7}"
          f" {a['ana']:>6.4f} {a['yed']:>6.4f} {a['yn']:>9}")
```

```
kesinti  yedek payi  toplam A  toplam B  kosum farki  dusus  gorunur   ana   yedek  orneklem
0.00         0.0300    0.8975    0.8725       0.0250 0.0000  hayir   0.9044 0.7500        12
0.06         0.0600    0.8850    0.8650       0.0200 0.0125  hayir   0.9037 0.6667        24
0.18         0.1275    0.8500    0.8325       0.0175 0.0475  evet    0.9032 0.6275        51
0.35         0.2350    0.7850    0.7750       0.0100 0.1125  evet    0.8927 0.5957        94
```

Görünürlük sütunu ikinci satırla üçüncü satır arasında dönüyor. Kesinti payı 0,06 iken düşüş
0,0125, koşum farkı 0,0200: toplam isabete bakan bir uyarı eşiği **hiçbir şey görmez**. Kesinti
payı 0,18'e çıktığında düşüş 0,0475 olur ve koşum farkını aşar. Yani toplam isabet bir kalite
göstergesi değil, **kesinti payına bağlı bir gösterge**dir; kaliteyi ancak kesinti yeterince
büyüdüğünde bildirir.

İlk satır bunun uç hâlidir. Kesinti hiç yokken bile on iki istek yedekten yanıtlanıyor, çünkü hız
sınırı ve zaman aşımı her koşumda bir pay üretiyor. Bu on iki isteğin isabeti **0,7500**; olağan
işleyişte, hiçbir olay kaydı düşmeden, isteklerin **0,0300**'ü daha kötü bir modelden
yanıtlanıyor.

Ana isabet sütunu dört satırda da yerinde duruyor: **0,9044 / 0,9037 / 0,9032 / 0,8927**. Birincil
model bozulmadı; bozulan **karışımdır**. Yedek katmanın isabeti ise payla birlikte düşüyor
(0,7500'den 0,5957'ye), çünkü kesinti büyüdükçe yedeğe düşen istekler arasında uzun bağlamlıların
oranı artıyor. Son sütun bu okumanın sınırını da yazıyor: 0,06 satırındaki 0,6667 yalnız yirmi
dört istekten hesaplandı. Az örneklemli bir sayıdır ve tek başına bir eşiğe bağlanamaz; buna
karşılık toplam isabetten **çok daha bilgilendiricidir**, çünkü ölçmek istediği şeyi ölçüyor.

#### Özet

- Yedek katman aynı işi yapan başka bir sunucu değildir: penceresi dar, iz tablosu eksik ve etiket
  kümesi onun aday kümesini daraltmıyor.
- Kesinti sırasında yedek, hatayı 26'dan 2'ye indirip toplam isabeti 0,8450'den 0,8850'ye
  çıkarıyor ve 2227 belirteç ekliyor; kesintisiz tabana göre ise 0,8975'ten 0,8850'ye düşürüyor.
- Düşüş 0,0125, iki koşum farkı 0,0200: toplam isabete bakan bir gösterge kesintiyi hiç görmez.
- Defter yanıtın kaynağını yazdığında düşüş görünür olur: ana katman 0,9037, yedek katman 0,6667,
  fark 0,2371; bu alanın bedeli sıfır belirteçtir.
- Toplam isabet bir kalite göstergesi değil kesinti payına bağlı bir göstergedir: düşüş ancak
  kesinti payı 0,18'e çıktığında koşum farkını aşıyor.
- Ana katmanın isabeti dört payda da oynamıyor (0,9044 ile 0,8927 arası); bozulan model değil
  karışımdır ve kesinti yokken bile isteklerin 0,0300'ü yedekten yanıtlanıyor.

#### Sonraki Adım

Bu derste iki koşum farkı bir eşik olarak kullanıldı: 0,0200'ün altındaki her fark ölçülmemiş
sayıldı. Bu eşiğin kendisi hiç sorgulanmadı. Aynı iş yükü, aynı istem ve aynı kod iki koşumda
niçin başka sayılar veriyor, hangi kalem serbest bırakıldığında oynuyor ve hepsi sabitlenirse
oynama duruyor mu. Sonraki ders bir model çağrısının kalemlerini tek tek sayar, her birini yalnız
başına serbest bırakıp kaç yanıtın değiştiğini ölçer ve bu kalemlerin kaçının **bizim elimizde**
olduğunu ayırır.

### Belirsizlik ve Yeniden Üretilebilirlik

Source: https://academia.sh/tr/kurslar/model-apileri/belirsizlik-ve-yeniden-uretilebilirlik

Bir model çağrısının çıktısını belirleyen kalemlerin sayılması ve her birinin tek başına serbest bırakılması: on iki kalemin 11'i yanıtları oynatıyor, en büyük oynama yönergenin biçim sözcüğünde (bütün yanıtlar değişiyor, isabet 0,9125'ten 0,5525'e iniyor). Anlamı hiç değiştirmeyen boşluk düzeni yanıtların 0,0700'ünü, istemci normalleştirmesi 0,1300'ünü oynatıyor. Tek başına hiçbir şey oynatmayan en büyük çıktı uzunluğu, yönerge sözcüğüyle birlikte serbest bırakıldığında isabeti 0,5525'ten 0,2675'e indiriyor. Kalemlerin 9'u istemcide, 3'ü sağlayıcıdadır ve üçü birlikte serbest kaldığında yanıtların 0,1150'si oynuyor, isabet 0,0200 düşüyor: önceki iki dersin eşiği budur.

Önceki iki derste bir eşik tekrar tekrar kullanıldı: iki koşum arasındaki fark. Maliyet defterinde
0,0200 çıktı, kesinti tablosunda yine 0,0200 çıktı ve bu sayının altında kalan her kazanç
ölçülmemiş sayıldı. Eşiğin kendisi hiç sorulmadı. Aynı kod, aynı iş yükü ve aynı istem iki koşumda
niçin iki ayrı sayı veriyor.

Sorunun bir bölümü daha önce kapandı. Görselleştirme, Raporlama ve Ölçekli Analiz kursu bir
raporun yeniden üretilmesini elli dokuz kalem olarak yazdı: hazırlama defterinin otuz dokuz
kararı, çalışma ortamının dokuz kalemi ve raporun kendi on bir kalemi. Derin Öğrenme kursu aynı hesabı bir eğitim
için yaptı, eğitime özgü sekiz kalemi ekledi ve altmış yediye çıkardı. Bu hesap burada
tekrarlanmaz. Eklenen soru şudur: bir **model çağrısının** kendi kalemleri nelerdir ve kaçı bizim
elimizdedir.

- **UK45.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, konuşmalar ve
  belgeler **kurgudur**, tohum **20260218**.
- **UK46.** İş yükü önceki iki dersinkiyle aynıdır: 154 kurgu konuşmadan gelen 400 istek.
- **UK47. Kalem**, çağrının çıktısını belirleyebilecek ve koşumdan koşuma taşınması gereken her
  karardır. Her kalem **eşit ölçüde savunulabilir** bir alternatife geçirilir; yanlış bir değere
  değil.
- **UK48.** İki ölçü basılır: **değişen yanıt payı** (400 yanıttan kaçı taban koşumdakinden farklı)
  ve **isabet**. İkisi ayrı şeylerdir.
- **UK49. Kalemler iki tarafa ayrılır.** Dokuzu istemcide, üçü sağlayıcıdadır. Sağlayıcı kalemleri
  benzeticide sabitlenebilir ama gerçek bir uç noktada sabitlenemez; bu derste **sabitlenemez**
  sayılırlar.
- **UK50.** Devralınan kalemler: hazırlama defterinin **39** kararı ve çalışma ortamının **9**
  kalemi. Eğitime özgü sekiz kalem devralınmaz, çünkü model verilmiştir ve eğitilmez.
- **UK51.** Yönergenin biçim sözcüğü kalemi listenin uç noktasıdır: benzetici yanıtın biçimini
  istemdeki `tek` sözcüğüne bağlar. Bu, biçim uyumunun **yüzey sözcüğüne** bağlı olmasının
  modellenmiş hâlidir.
- **UK52.** Sağlayıcının sürüm değişikliği, iz tablosuna iki girdi eklenmesiyle modellenir.

#### Bir Çağrının Kalemleri

```python
# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz; talepler, konusmalar
# ve belgeler kurgudur, tohum 20260218.
import math
TOHUM, M32 = 20260218, 0xFFFFFFFF
PENCERE = 240


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"]
KALIP = {"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"]}
IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "borc": "odeme",
      "odedi": "odeme", "ariza": "ariza", "bozuk": "ariza", "calis": "ariza",
      "akmiy": "ariza", "sayac": "sayac", "endek": "sayac", "okuma": "sayac",
      "tarif": "tarife", "birim": "tarife", "abone": "tarife", "basam": "tarife",
      "kesin": "kesinti", "duyur": "kesinti", "mahal": "kesinti",
      "yardi": "bilgi", "nered": "bilgi", "kayit": "sikayet", "bekle": "sikayet"}
SERBEST = ["talebiniz {k} konusunda kaydedildi ve ekibe iletildi",
           "{k} ile ilgili kaydiniz olusturuldu en kisa surede donulecek",
           "kaydiniz alindi ilgili birim sizinle iletisime gececek"]
SAYAC = [0]


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


BELGE = ["TR1 tarife basamaklari abone tipine gore belirlenir ve yilda bir guncellenir",
         "FT2 fatura itirazi kayit acildiktan sonra on is gunu icinde sonuclanir",
         "SY3 sayac degisimi randevusu saha ekibinin bolge programina baglidir",
         "AR4 ariza kaydi acilan adreste ekip ayni gun icinde yonlendirilir",
         "KS5 planli kesinti duyurulari bir hafta once ilan panosuna asilir"]
KONUS, i = [], 0
while sum(len(c["tur"]) for c in KONUS) < 400:      # KURGU is yuku: konusmalar
    r = uretec(TOHUM + 900 + i)
    i += 1
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    u = [1, 2, 3, 5, 8, 12][ayrik(r(), [0.46, 0.24, 0.14, 0.09, 0.05, 0.02])]
    KONUS.append({"no": i, "belge": ayrik(r(), [0.74, 0.16, 0.07, 0.03]),
                  "tur": [{"konu": k, "metin": KALIP[k][(i + t) % 3]} for t in range(u)]})
ISTEK = [{"kon": c, "sira": t, "talep": c["tur"][t]}
         for c in KONUS for t in range(len(c["tur"]))][:400]
VAR = dict(tohum=TOHUM, sicaklik=0.6, en_uzun=24, soz="tek", etiket="kurgu",
           bosluk="tek", durum="tam", parca="belge sonra", normal="ham",
           deneme=3, iz="surum a", esik=37)
IZ_B = dict(IZ, gecen="fatura", ekip="kesinti")     # saglayicinin surum degisikligi


def cagir3(istem, a):
    """Ayar sozlugu ile cagri: her kalem ayri bir anahtardir."""
    SAYAC[0] += 1
    bel = belirtecle(istem)
    if len(bel) > PENCERE:
        return {"durum": "baglam_asimi", "yanit": ""}
    if SAYAC[0] % a["esik"] == 0:
        return {"durum": "hiz_siniri", "yanit": ""}
    r = uretec(a["tohum"] ^ izno(istem))
    if len(bel) > 90 and r() < 0.04:
        return {"durum": "zaman_asimi", "yanit": ""}
    iz = IZ if a["iz"] == "surum a" else IZ_B
    aday = [k for k in KAVRAM if k[:5] in bel]
    p = {k: 0.15 for k in (aday if len(aday) >= 3 else KAVRAM)}
    for t in bel:
        if iz.get(t) in p:
            p[iz[t]] += 1.0
    w = [math.exp(p[q] / a["sicaklik"]) for q in sorted(p)]
    k = sorted(p)[ayrik(r(), [x / sum(w) for x in w])]
    y = k if "tek" in bel else SERBEST[int(r() * 3)].format(k=k)
    cb = belirtecle(y)
    return {"durum": "tamam",
            "yanit": " ".join(cb[:a["en_uzun"]]) if len(cb) > a["en_uzun"] else y}


def istem_kur(x, a):
    et = KONU if a["etiket"] == "kurgu" else sorted(KONU)
    yon = ("Talebi su etiketlerden birine ata: " + " , ".join(et) + " . Yanit olarak "
           + ("tek" if a["soz"] == "tek" else "yalnizca") + " etiket yaz . Talep: ")
    t = x["kon"]["tur"][:x["sira"]]
    g = "".join(f"Onceki: {o['metin']} Yanit: {o['konu']} . "
                for o in (t[-2:] if a["durum"] == "iki tur" else t))
    b = "".join(BELGE[(x["kon"]["no"] + j) % 5] + " . " for j in range(x["kon"]["belge"]))
    s = yon + (b + g if a["parca"] == "belge once" else g + b) + x["talep"]["metin"]
    if a["bosluk"] == "cift":
        s = s.replace(" ", "  ")
    if a["normal"] == "sadelesmis":
        s = " ".join(s.lower().split())
    return s


def kos(**d):
    a = dict(VAR, **d)
    SAYAC[0] = 0
    cikti = []
    for x in ISTEK:
        ist = istem_kur(x, a)
        for i in range(a["deneme"]):
            s = cagir3(ist, dict(a, tohum=a["tohum"] + i))
            if s["durum"] == "tamam":
                break
        cikti.append(s["yanit"])
    return cikti


def isabet(c):
    return sum(oku(y) == x["talep"]["konu"] for y, x in zip(c, ISTEK)) / 400


def degisen(c, ref):
    return sum(a != b for a, b in zip(ref, c)) / 400


KALEM = [("saglayici", "ornekleme durumu", dict(tohum=TOHUM + 1)),
         ("saglayici", "model surumu", dict(iz="surum b")),
         ("saglayici", "hiz siniri esigi", dict(esik=31)),
         ("istemci", "dagilim sicakligi", dict(sicaklik=0.8)),
         ("istemci", "en buyuk cikti uzunlugu", dict(en_uzun=10)),
         ("istemci", "yonerge bicim sozcugu", dict(soz="yalnizca")),
         ("istemci", "etiket kumesi sirasi", dict(etiket="alfabetik")),
         ("istemci", "bosluk duzeni", dict(bosluk="cift")),
         ("istemci", "konusma durumu", dict(durum="iki tur")),
         ("istemci", "baglam parcasi sirasi", dict(parca="belge once")),
         ("istemci", "istemci normallestirmesi", dict(normal="sadelesmis")),
         ("istemci", "yeniden deneme sayisi", dict(deneme=1))]
REF = kos()
print("taban isabet %.4f , kalem sayisi %d" % (isabet(REF), len(KALEM)))
print("taraf      kalem                     degisen  isabet     fark")
for taraf, ad, d in KALEM:
    c = kos(**d)
    print(f"{taraf:<10} {ad:<25} {degisen(c, REF):>7.4f} {isabet(c):>7.4f}"
          f" {isabet(c) - isabet(REF):>+8.4f}")
print("oynatan kalem", sum(degisen(kos(**d), REF) > 0 for _, _, d in KALEM), "/", len(KALEM))
```

```
taban isabet 0.9125 , kalem sayisi 12
taraf      kalem                     degisen  isabet     fark
saglayici  ornekleme durumu           0.1200  0.8925  -0.0200
saglayici  model surumu               0.0150  0.9175  +0.0050
saglayici  hiz siniri esigi           0.0050  0.9075  -0.0050
istemci    dagilim sicakligi          0.0600  0.8575  -0.0550
istemci    en buyuk cikti uzunlugu    0.0000  0.9125  +0.0000
istemci    yonerge bicim sozcugu      1.0000  0.5525  -0.3600
istemci    etiket kumesi sirasi       0.1100  0.9100  -0.0025
istemci    bosluk duzeni              0.0700  0.9325  +0.0200
istemci    konusma durumu             0.0050  0.9125  +0.0000
istemci    baglam parcasi sirasi      0.0025  0.9150  +0.0025
istemci    istemci normallestirmesi   0.1300  0.8775  -0.0350
istemci    yeniden deneme sayisi      0.0375  0.8750  -0.0375
oynatan kalem 11 / 12
```

On iki kalemin **on biri** tek başına serbest bırakıldığında yanıtları oynatıyor. Listenin en
öğretici satırları, oynatması beklenmeyenlerdir. **Boşluk düzeni** istemin anlamına hiç dokunmuyor,
aynı sözcükleri aynı sırada gönderiyor ve yanıtların **0,0700**'ünü değiştiriyor. **İstemci
normalleştirmesi** aynı biçimde anlamı korurken **0,1300**'ünü değiştiriyor. **Etiket kümesinin
sırası** beş etiketi başka sırada yazıyor ve **0,1100** oynatıyor. Bir istemin metni, anlamıyla
değil **birebir kendisiyle** bir girdidir.

Değişen yanıt ile bozulan yanıt aynı şey değildir ve tablo bunu ayrı sütunlarda tutuyor. Boşluk
düzeni yanıtların yüzde yedisini değiştiriyor ama isabeti **0,9125'ten 0,9325'e yükseltiyor**;
kazanç tesadüfidir ve bir sonraki koşumda tersine dönebilir. Etiket sırası 0,1100 oynatıp isabeti
yalnız 0,0025 düşürüyor. Buna karşılık **dağılım sıcaklığı** yalnız 0,0600 oynatıp isabeti
**0,0550** düşürüyor: az sayıda yanıt değişiyor ama değişenlerin neredeyse tamamı doğrudan yanlışa
gidiyor. Oynama payı tek başına bir zarar ölçüsü değildir.

İki satır beklenenden küçük çıkıyor. **Konuşma durumu** yalnız 0,0050 oynatıyor, oysa 400 isteğin
113'ünde istem metni değişti; **bağlam parçası sırası** 0,0025 oynatıyor, oysa 60 istekte iki parça
birden vardı. Uzun konuşmalar en kararlı isteklerdir, çünkü aynı konudan gelen izler birikince
seçim tek bir kavramda toplanır ve çekiliş onu bozamaz. Kararlılık isteğe göre değişir; tek bir
oynama payı bütün iş yükünü anlatmaz.

En büyük satır ise ölçek olarak diğerlerinden ayrılır. **Yönergenin biçim sözcüğü** eşanlamlısıyla
değiştirildiğinde yanıtların **tamamı** değişiyor ve isabet 0,9125'ten **0,5525**'e iniyor. Bu
kalem çekilişi değil **görevi** değiştiriyor: biçim kısıtı kalkınca model tek etiket yerine cümle
yazmaya başlıyor ve cümlelerin bir bölümü hiçbir etiket taşımıyor. Eşanlamlı bir sözcük, ölçüyü
0,3600 düşürdü.

#### Birlikte Serbest Bırakılan Kalemler

```python
ikili = kos(en_uzun=10, soz="yalnizca")
tek_kalem = kos(soz="yalnizca")
print("yalniz en buyuk cikti uzunlugu     degisen %.4f  isabet %.4f"
      % (degisen(kos(en_uzun=10), REF), isabet(kos(en_uzun=10))))
print("yalniz yonerge bicim sozcugu       degisen %.4f  isabet %.4f"
      % (degisen(tek_kalem, REF), isabet(tek_kalem)))
print("ikisi birlikte                     degisen %.4f  isabet %.4f"
      % (degisen(ikili, REF), isabet(ikili)))
uc = kos(tohum=TOHUM + 1, iz="surum b", esik=31)
print("dokuz istemci kalemi sabit, uc saglayici kalemi serbest:"
      " degisen %.4f  isabet %.4f" % (degisen(uc, REF), isabet(uc)))
print("sabitlenebilir kalem 39 + 9 + 9 =", 39 + 9 + 9,
      ", sabitlenemeyen 3 , toplam", 39 + 9 + 12)
```

```
yalniz en buyuk cikti uzunlugu     degisen 0.0000  isabet 0.9125
yalniz yonerge bicim sozcugu       degisen 1.0000  isabet 0.5525
ikisi birlikte                     degisen 1.0000  isabet 0.2675
dokuz istemci kalemi sabit, uc saglayici kalemi serbest: degisen 0.1150  isabet 0.8925
sabitlenebilir kalem 39 + 9 + 9 = 57 , sabitlenemeyen 3 , toplam 60
```

Tablonun tek sıfırı **en büyük çıktı uzunluğuydu**. Sınır yirmi dörtten ona indirildiğinde hiçbir
yanıt değişmiyor, çünkü tek etiketlik yanıtlar iki belirteçten uzun değil. Bir sabitleme listesi
hazırlarken bu kalemi atmak akla yatkın görünür.

İkinci ve üçüncü satır bunun niçin yanlış olduğunu gösteriyor. Biçim sözcüğü tek başına serbest
bırakıldığında isabet 0,5525'e iniyor; **ikisi birlikte** serbest bırakıldığında **0,2675**'e
iniyor. Aradaki **0,2850**, tek başına hiçbir şey oynatmayan kalemin hesabıdır: cümleye dönen
yanıtlar on belirteçte kesiliyor ve kesilen metinde etiket okunamıyor. Aynı sonuca iki kurs daha
varmıştı: Görselleştirme, Raporlama ve Ölçekli Analiz kursu tek başına raporu oynatmayan bir
kalemin başka bir kalemle birlikte oranı 87,168'den 94,432'ye taşıdığını, Derin Öğrenme kursu tek
başına sıfır oynatan tur sayısının toplu boyla birlikte iki aboneyi kaydırdığını ölçtü. **Tek başına oynatmayan
kalem, sabitlenmesi gerekmeyen kalem değildir.**

#### Sabitlenemeyen Üç Kalem

Son iki satır bu konunun kapanış sayısını veriyor. Bir model çağrısının yeniden üretilmesi **60**
kalemin sabitlenmesini ister: hazırlama defterinin 39 kararı, çalışma ortamının 9 kalemi ve bu
derste sayılan 12 kalem. Bunların **57'si** bizim elimizdedir. Kalan **üçü** — örnekleme durumu,
model sürümü ve hız sınırı eşiği — sağlayıcının elindedir ve hiçbir dosyaya yazılarak
sabitlenemez.

Dokuz istemci kalemi sabitken bu üçü birlikte serbest bırakıldığında yanıtların **0,1150**'si
oynuyor ve isabet 0,9125'ten **0,8925**'e iniyor. Düşüş **0,0200**. Önceki iki dersin eşiği tam
olarak budur: maliyet defterindeki 0,0200 ve kesinti tablosundaki 0,0200, bir gürültü değil, bu üç
kalemin **adıdır**. Eşik keyfi seçilmiş bir sayı değil, sabitlenemeyen kalemlerin ölçülmüş
payıdır.

Buradan çıkan sonuç, önceki iki kursunkinden yapıca farklıdır. Bir rapor 59 kalemin 59'uyla, bir
eğitim 67 kalemin 67'siyle sabitlenebilir; ikisi de eksiksiz yeniden üretilebilir. Bir model
çağrısı sabitlenemez. Bu yüzden belirlenimcilik bir hedef değil bir **sınırdır** ve ulaşılabilecek
en iyi şey oynamanın **ölçülmüş** olmasıdır. Bunun uygulamadaki karşılığı tek bir kuraldır: her
ölçüm raporunun yanına iki koşum farkı yazılır ve o farkın altındaki hiçbir kazanç kazanç sayılmaz.

#### Özet

- Bir model çağrısının yeniden üretilmesi 60 kalem ister: devralınan 39 hazırlama kararı, 9 ortam
  kalemi ve çağrıya özgü 12 kalem.
- On iki kalemin 11'i tek başına serbest bırakıldığında yanıtları oynatıyor; en büyüğü yönergenin
  biçim sözcüğüdür ve isabeti 0,9125'ten 0,5525'e indiriyor.
- Anlamı hiç değiştirmeyen kalemler de oynatıyor: boşluk düzeni 0,0700, istemci normalleştirmesi
  0,1300, etiket kümesi sırası 0,1100.
- Değişen yanıt ile bozulan yanıt ayrı sayılır: boşluk düzeni 0,0700 oynatıp isabeti yükseltirken
  dağılım sıcaklığı 0,0600 oynatıp 0,0550 düşürüyor.
- Tek başına 0,0000 oynatan en büyük çıktı uzunluğu, biçim sözcüğüyle birlikte serbest
  bırakıldığında isabeti 0,5525'ten 0,2675'e indiriyor.
- Üç kalem sağlayıcıdadır ve sabitlenemez; birlikte serbest kaldıklarında yanıtların 0,1150'si
  oynuyor ve isabet 0,0200 düşüyor, yani önceki iki dersin eşiği ölçülmüş olur.

#### Sonraki Adım

On dört derste çağrı bir **ürünün içinde** ele alındı. Mesaj tabanlı arayüzün ne sunduğu, akışın
ne değiştirdiği, bir araç çağrısının kaçının geçerli olduğu, hız sınırının ne kadara mal olduğu,
önbelleğin ne kazandırdığı, gecikmenin hangi sınıfa indiği, faturanın hangi kalemlerden oluştuğu,
kesintinin kaliteyi nasıl sessizce düşürdüğü ve aynı girdinin niçin iki çıktı verdiği sayıldı.
Bütün bu ölçümlerde çağrıyı yapan bir uygulamaydı ve o uygulamayı yazan kişi ölçümün dışında
durdu. Oysa aynı model geliştiricinin kendi masasında da çalışıyor: kod tamamlarken, var olan bir
işlevi açıklarken, bir dosyayı dönüştürürken, hatta çok adımlı bir görevi devralırken. Sonraki
konu ölçüyü oraya taşır ve aynı soruyu sorar: kurgu bir kod tabanında hangi görev sınıfında
düzeneksiz çağrı çöküyor, hangi bağlam kaç belirtece mal oluyor ve kabul edilen önerinin kaçı
gerçekten doğru.

## Geliştirme Akışında Yapay Zekâ

Kurgu bir kod tabanı üzerinde kod yardımcısının ne kazandırdığının ve neyi kaçırdığının savunma tarafından sayılması: tamamlama, açıklama ve dönüştürme kullanımlarında görev sınıfına göre kabul oranı ve düzeneksiz çağrının çöktüğü yer, dosya sayısı arttıkça belirteç ile isabet ve ilgisiz bağlamın isabeti düşürdüğü nokta, çok adımlı devirde kaç adımda bir durulduğunda hatanın yayılmadan yakalandığı, sınama koşumu, örüntü taraması ve uydurma bağımlılık varlık denetiminin her birinin yakaladığı kusur ile hiçbirinin yakalamadığı kalıntı, üretilen sınamaların konan hataları yakalama oranı ve hep geçen boş sınama payı, bağlama giren metinde sır sınıfına giren alan sayısı ile süzgecin çıkardığı ve kabul edilen ama yanlış öneri payı.

### Kod Yardımcıları

Source: https://academia.sh/tr/kurslar/model-apileri/kod-yardimcilari

Kurgu bir kod tabanı üzerinde tamamlama, açıklama ve dönüştürme kullanımlarının kabul oranıyla ölçülmesi: bağlamsız çağrı yirmi dört görevin yalnız yedisini kabule götürüyor ve çöküş tamamlama (1/8) ile dönüştürmede (2/8); ayakta kalan tek sınıf açıklama (4/8). Açık dosya bağlamı 10/24 veriyor ama aynı kurulumun iki koşum farkı 2/24 olduğu için kazanç dar. Bütün kod tabanı 18/24'e çıkarıyor, bedeli 1104 belirteçten 4224 belirtece; bin belirteç başına kabul 6,34'ten 4,26'ya düşüyor. Koşumdan bağımsız beklenen kabul sütununda dönüştürme, bütün kod tabanıyla bile (0,4675) hiç bağlamsız açıklamanın (0,6450) altında kalıyor.

Bu kursun buraya kadarki dersleri çağrıyı hep bir ürünün içinde ele aldı: bir abone kısa bir
destek talebi yazıyor, bir istemci onu bir model uç noktasına gönderiyor ve ölçülen şey o hattın
belirteci, yeniden denemesi, önbellek isabeti ve kesinti payı oluyordu. Aynı çağrının bir yerde
daha yapıldığı hiç sayılmadı: **geliştiricinin kendi masasında**, henüz hiçbir aboneye ulaşmamış
bir kodun üzerinde.

Oradaki ölçü farklıdır. Yanıtı okuyan bir abone değil, kodu yazan kişidir; ve o kişi yanıtı ya
olduğu gibi kullanıma alır ya da atıp kendi yazar. Bu dersin ölçütü budur: **kabul**. Ders kurgu
bir kod tabanı kurar, üç kullanım sınıfını aynı görev kümesinde ölçer ve **düzeneksiz çağrının
hangi sınıfta çöktüğünü** sayar.

- **YG1.** Kod tabanı **kurgudur**: ölçüm ağının kendi yardımcı betikleri. Hiçbir gerçek depo,
  paket, çerçeve ya da ürün değildir. **Beş modül, 53 satır.**
- **YG2.** Kod yardımcısı bir **benzeticidir**; gerçek bir yardımcı, düzenleyici ya da eklenti
  çağrılmaz. Tohum **20260218**, `random` kullanılmaz.
- **YG3.** Ölçüt **kabuldür**: geliştirici öneriyi kullanıma alıyorsa kabul, yeniden yazıyorsa
  ret. Önerinin gerçekten doğru olup olmadığı ayrı bir sorudur ve bu derste sorulmaz.
- **YG4.** Üç kullanım sınıfı: **tamamlama** (eksik bir gövdeyi yazmak), **açıklama** (var olan
  bir parçanın ne yaptığını söylemek), **dönüştürme** (var olan bir parçayı başka bir biçime
  çevirmek). Sınıf başına sekiz kurgu görev, toplam **yirmi dört**.
- **YG5.** Taban kabul olasılığı sınıfa göre farklıdır: açıklama **0,72**, tamamlama **0,34**,
  dönüştürme **0,18**. Gerekçe yapısaldır: açıklamanın girdisi istemin **içindedir**; tamamlama
  ile dönüştürme kod tabanının **geri kalanına** uymak zorundadır.
- **YG6.** Bağlam örtüşmesi kabulü yükseltir, **ilgisiz dosya düşürür**, görev zorluğu düşürür.
  Üçü tek bir puanda toplanır ve puan sıfır ile bir arasına kırpılır.
- **YG7.** Bedel belirteçtir: taban **40**, bağlamdaki dosya başına **26**, dönüştürmeye **18**
  ek. Gecikme sınıfı üç kurulumda da aynıdır: **tek çağrı**, görev başına bir tane.
- **YG8.** Koşumdan bağımsız ölçü **beklenen kabuldür** (puanların ortalaması); sayılan kabul iki
  koşumda ayrı basılır (tohum **20260218** ve **20260219**).

#### Kurgu Kod Tabanı

Ölçüm ağının saha ekibi, sayaç okumalarını rapora çeviren bir avuç yardımcı betik taşıyor. Bu
betikler bir ürün değil, bir ekibin kendi işini gördüğü kısa dosyalardır ve **kurgudur**. Beş
modül bir sözlükte tutulur; böylece hem tek blokta gösterilebilir hem de bağlam seçimi
**dosya adıyla** yapılabilir.

```python
# KURGU KOD TABANI -- gercek bir depo, paket ya da urun degildir. Olcum aginin
# kendi yardimci betikleri: bes modul. Tohum 20260218.
KOD = {
    "okuma.py": """
def ayristir(satir):
    p = satir.split(";")
    if len(p) != 4:
        return None
    if not p[3].lstrip("-").isdigit():
        return None
    return {"abone": p[0], "bolge": p[1], "donem": p[2], "endeks": int(p[3])}

def tuketim(onceki, simdiki):
    fark = simdiki - onceki
    if fark < 0:
        fark = fark + 100000
    return fark
""",
    "tarife.py": """
BASAMAK = ((10, 4), (25, 7), (40, 11))
USTU = 16

def bedel(m3):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    return top + kalan * USTU
""",
    "denetim.py": """
GECERLI_BOLGE = ("dogu", "bati", "kuzey", "guney", "merkez")

def gecerli(kayit):
    if kayit is None:
        return False
    if kayit["endeks"] < 0:
        return False
    return kayit["bolge"] in GECERLI_BOLGE

def ayikla(kayitlar):
    return [k for k in kayitlar if gecerli(k)]
""",
    "ozet.py": """
def bolge_toplam(kayitlar, tuketimler):
    top = {}
    for k, t in zip(kayitlar, tuketimler):
        top[k["bolge"]] = top.get(k["bolge"], 0) + t
    return top

def bolge_sayi(kayitlar):
    say = {}
    for k in kayitlar:
        say[k["bolge"]] = say.get(k["bolge"], 0) + 1
    return say
""",
    "bicim.py": """
def satir(bolge, m3, tutar):
    return bolge.ljust(8) + str(m3).rjust(7) + str(tutar).rjust(9)

def rapor(baslik, satirlar):
    return "\\n".join([baslik] + satirlar)
""",
}


def yukle(kod):
    ad = {}
    for dosya, kaynak in kod.items():
        alan = {}
        exec(kaynak, alan)
        ad[dosya] = alan
    return ad


AD = yukle(KOD)
BOY = {d: len(k.strip().split("\n")) for d, k in KOD.items()}
print("modul       satir")
for d in KOD:
    print(f"  {d:<10}{BOY[d]:>4}")
print(f"  {'toplam':<10}{sum(BOY.values()):>4}")

OKUMA = [                                   # KURGU sayac okumalari
    "A017;dogu;2026-01;41250", "A017;dogu;2026-02;41312",
    "B204;bati;2026-02;99800", "B204;bati;2026-03;300",
    "C088;kuzey;2026-02;7130", "C088;kuzey;2026-03;7166",
    "D311;disari;2026-03;5000", "E402;guney;2026-03;bozuk",
]
kayitlar = [AD["okuma.py"]["ayristir"](s) for s in OKUMA]
temiz = AD["denetim.py"]["ayikla"](kayitlar)
print("\nokunan", len(kayitlar), "gecerli", len(temiz))

esler = [(temiz[i], temiz[i + 1]) for i in range(0, len(temiz) - 1, 2)]
tuk = [AD["okuma.py"]["tuketim"](a["endeks"], b["endeks"]) for a, b in esler]
sonraki = [b for _, b in esler]
toplam = AD["ozet.py"]["bolge_toplam"](sonraki, tuk)
satirlar = [AD["bicim.py"]["satir"](b, m, AD["tarife.py"]["bedel"](m))
            for b, m in sorted(toplam.items())]
print(AD["bicim.py"]["rapor"]("bolge        m3    tutar", satirlar))
```

```
modul       satir
  okuma.py    13
  tarife.py   13
  denetim.py  11
  ozet.py     11
  bicim.py     5
  toplam      53

okunan 8 gecerli 6
bolge        m3    tutar
bati        500     7670
dogu         62      662
kuzey        36      266
```

Beş modül birbirine bağlıdır ve tek bir hat kurar: `okuma.py` satırı kayda çevirir, `denetim.py`
geçersizleri atar, `ozet.py` bölgeye toplar, `tarife.py` basamaklı bedeli hesaplar, `bicim.py`
hizalı satırı yazar. Sekiz okumanın ikisi elenmiştir: biri tanınmayan bir bölge taşıyor, birinin
endeksi sayı değil. Batı bölgesinin 500 metreküpü de bir kural sonucudur; sayaç 99800'den 300'e
dönmüştür ve `tuketim` bu dönüşü telafi eder.

**53 satırın tamamı bir istemin içine sığar.** Kod tabanının küçük tutulması kasıtlıdır: burada
"bağlamı büyütmek" gerçekten bir seçenektir ve bedeli sayılabilir. Büyük bir depoda bu seçenek
zaten yoktur, ama ölçünün yönü aynıdır.

#### Üç Kullanım Sınıfı ve Kabul

Yirmi dört kurgu görev üç sınıfa bölünür. **Tamamlama** bir gövdeyi yazmayı ister: bölge sayımı
alan yeni bir işlev, eksik bir dal, bir kenar durumu. **Açıklama** var olan bir parçanın ne
yaptığını sorar: `tuketim` niçin 100000 ekliyor, `BASAMAK` demeti neyi kodluyor. **Dönüştürme**
var olan bir parçayı başka bir biçime çevirir: sözlük yerine demet döndürmek, döngüyü kavramaya
çevirmek, iki modülü ortak bir imzada birleştirmek.

Bu üç sınıfın kabul oranı aynı olmaz ve nedeni benzeticiye taban olasılık olarak yazılmıştır.
Açıklamanın **girdisi istemin içindedir**: açıklanacak parça zaten gönderilmiştir, dışarıdan bir
şey bilmek gerekmez. Tamamlama ile dönüştürme ise kod tabanının **görülmeyen kısmına** uymak
zorundadır — hangi anahtar adları kullanılıyor, hangi işlev neyi döndürüyor, hangi geçersizlik
kuralı nerede uygulanıyor.

```python
# YARDIMCI BENZETICISI -- KURGUDUR. Gercek bir kod yardimcisi cagrilmaz.
# Kabul, gorev sinifi ile baglam ortusmesinden hesaplanir; random kullanilmaz.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py")
GEREKEN = {                                 # gorev numarasi -> gereken dosyalar
    0: ("okuma.py",),
    1: ("tarife.py",),
    2: ("denetim.py", "okuma.py"),
    3: ("ozet.py", "denetim.py"),
    4: ("bicim.py", "ozet.py"),
    5: ("tarife.py", "okuma.py"),
    6: ("ozet.py", "okuma.py", "tarife.py"),
    7: ("denetim.py", "bicim.py"),
}
GOREV = [                                   # 24 KURGU gorev: 3 sinif x 8
    {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)}
    for s in SINIF
    for i in range(8)
]
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def yardimci(gorev, baglam, tohum=TOHUM):
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam))))
    ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    kabul = r() < puan
    belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0)
    return {"kabul": kabul, "puan": puan, "belirtec": belirtec}


KURULUM = (("yok", ()), ("acik dosya", ("okuma.py",)), ("butun kod tabani", DOSYA))


def olc(baglam, sinif, tohum=TOHUM):
    g = [x for x in GOREV if x["sinif"] == sinif]
    s = [yardimci(x, baglam, tohum) for x in g]
    return (sum(x["kabul"] for x in s), sum(x["puan"] for x in s) / len(s),
            sum(x["belirtec"] for x in s))


print("gorev sayisi", len(GOREV), " ornek:",
      ", ".join(g["ad"] + " -> " + "+".join(g["gereken"]) for g in GOREV[:2]))
print("\nbaglam            sinif       beklenen  kabul A  kabul B")
for ad, b in KURULUM:
    for s in SINIF:
        ka, p, _ = olc(b, s)
        kb, _, _ = olc(b, s, TOHUM + 1)
        print(f"{ad:<18}{s:<12}{p:>8.4f}{ka:>7}/8{kb:>7}/8")

print("\nbaglam            toplam A  toplam B  belirtec  kabul/1000 belirtec")
for ad, b in KURULUM:
    ta = sum(olc(b, s)[0] for s in SINIF)
    tb = sum(olc(b, s, TOHUM + 1)[0] for s in SINIF)
    bel = sum(olc(b, s)[2] for s in SINIF)
    print(f"{ad:<18}{ta:>7}/24{tb:>8}/24{bel:>10}{1000 * ta / bel:>17.2f}")
```

```
gorev sayisi 24  ornek: tamamlama-1 -> okuma.py, tamamlama-2 -> tarife.py

baglam            sinif       beklenen  kabul A  kabul B
yok               tamamlama     0.2650      1/8      1/8
yok               aciklama      0.6450      4/8      6/8
yok               donusturme    0.1050      2/8      0/8
acik dosya        tamamlama     0.3954      3/8      1/8
acik dosya        aciklama      0.7417      5/8      6/8
acik dosya        donusturme    0.2429      2/8      1/8
butun kod tabani  tamamlama     0.6275      6/8      7/8
butun kod tabani  aciklama      0.9813      8/8      8/8
butun kod tabani  donusturme    0.4675      4/8      5/8

baglam            toplam A  toplam B  belirtec  kabul/1000 belirtec
yok                     7/24       7/24      1104             6.34
acik dosya             10/24       8/24      1728             5.79
butun kod tabani       18/24      20/24      4224             4.26
```

#### Düzeneksiz Çağrının Çöktüğü Yer

İlk üç satır çıplak çağrının tablosudur: bağlam yok, yalnız görev tarifi gönderiliyor. Yirmi dört
görevin **yedisi** kabul ediliyor ve ikinci koşumda da **yedisi**. Toplam sabit görünse de dağılım
sabit değildir ve asıl bilgi dağılımdadır.

Çöküş iki sınıftadır. **Tamamlama 1/8**, iki koşumda da aynı; beklenen kabul **0,2650**.
**Dönüştürme 2/8** ve ikinci koşumda **0/8**; beklenen kabul **0,1050**, tablonun en düşük
sayısı. Ayakta kalan tek sınıf **açıklamadır**: 4/8 ve 6/8, beklenen kabul **0,6450**. Bir
geliştirici bağlamsız bir yardımcıya "bu işlev ne yapıyor" diye sorabilir ve yanıtın yarısından
fazlasını kullanabilir; aynı yardımcıdan "bu işlevi tamamla" istediğinde sekiz denemenin yedisini
atacaktır.

Neden yapısaldır ve sayı onu doğrular. Açıklama görevinde bilinmesi gereken her şey isteme
konulmuştur. Tamamlama görevinde ise yazılacak gövdenin döndüreceği sözlüğün anahtarları,
çağıracağı işlevin adı ve uyacağı geçersizlik kuralı **başka dosyalardadır**. Yardımcı onları
göremediği için makul ama uymayan bir kod üretir; makul kod da reddedilen koddur.

Sınıf içinde de dağılım vardır ve tek sayı onu gizler. Her sınıfın sekiz görevi dört ayrı zorluk
kademesine dağılır ve zorluk kabul puanından doğrudan düşülür; sınıfın ortalaması, en kolay
görevle en zor görevin arasında bir yerdedir. İki koşum farkı ise ayrı bir şeyi ölçer: aynı görev,
aynı bağlam ve aynı puan, iki tohumda iki ayrı karara varabilir. Bu yüzden tabloda sayılan kabulün
yanına **beklenen kabul** sütunu konulmuştur; sayılan kabul koşuma bağlıdır, beklenen kabul
kurulumun kendisine.

#### Bağlamın Kattığı ve Ödettiği

İkinci kurulum bir geliştiricinin en kolay yaptığı şeydir: o an açık olan dosyayı da göndermek.
Burada bu dosya `okuma.py` ve her görev için aynı. Toplam **7/24'ten 10/24'e** çıkıyor, kazanç
**3/24**. Aynı kurulumun iki koşum farkı ise **2/24** (10'a karşı 8). Kazanç, farkın ancak bir
buçuk katıdır; üstelik tamamlama sütununda yön **tersine dönüyor** (3/8 ve 1/8). Sabit tek bir
dosya bir düzenek değildir; görevle ilgisi olduğunda yardım eder, olmadığında ilgisiz bağlam
olarak sayılır.

Üçüncü kurulum belirsiz değildir. Bütün kod tabanı gönderildiğinde toplam **18/24** ve ikinci
koşumda **20/24**; tabana göre kazanç **11/24**, iki koşum farkının beş katından fazla. Üç sınıf
da yükseliyor: tamamlama 1/8'den 6/8'e, açıklama 4/8'den 8/8'e, dönüştürme 2/8'den 4/8'e.

Bedel sütunu bu kazancın fiyatını yazıyor. Çağrı sayısı üç kurulumda da **24**'tür ve gecikme
sınıfı **tek çağrı** olarak aynı kalır; değişen yalnız belirteçtir: **1104'ten 4224'e**, yaklaşık
**3,8 kat**. Bin belirteç başına kabul ise **6,34'ten 5,79'a, oradan 4,26'ya** düşüyor. Düzenek
işi iyileştirdi ve **birim başına verimi düşürdü**; ikisi aynı anda doğrudur ve ikisi de yazılmak
zorundadır.

Son olarak koşumdan bağımsız sütun bir sıralamayı sabitliyor. Dönüştürme, **bütün kod tabanı**
verildiğinde bile **0,4675**'te kalıyor; açıklama **hiç bağlam olmadan 0,6450**. Bağlam eklemek
sınıfların yerini değiştirmiyor, hepsini birlikte yukarı taşıyor. Bir kod yardımcısını "iyi" ya da
"kötü" diye tek sayıyla anmak bu yüzden yanıltıcıdır: sayı görev sınıfına göre değişir ve en çok
bağlam alan zor sınıf, en az bağlam alan kolay sınıfın gerisinde kalabilir.

#### Özet

- Kurgu kod tabanı beş modül ve 53 satırdır; okuma, denetim, özet, tarife ve biçim tek bir rapor
  hattı kurar ve tamamı bir istemin içine sığar.
- Ölçüt kabuldür ve üç kullanım sınıfına göre ayrı sayılır; sınıflar arası fark yapısaldır,
  çünkü açıklamanın girdisi istemin içinde, tamamlama ile dönüştürmenin girdisi dışarıdadır.
- Bağlamsız çağrı 7/24 kabul veriyor; çöküş tamamlama (1/8) ile dönüştürmede (2/8), ayakta kalan
  tek sınıf açıklama (4/8, beklenen 0,6450).
- Tek bir sabit dosya eklemek 10/24 veriyor ama aynı kurulumun iki koşum farkı 2/24'tür ve
  tamamlama sütununda yön tersine döner: sabit bağlam bir düzenek değildir.
- Bütün kod tabanı 18/24'e çıkarıyor; bedel 1104 belirteçten 4224 belirtece, bin belirteç başına
  kabul 6,34'ten 4,26'ya iniyor. Çağrı sayısı ve gecikme sınıfı değişmiyor.
- Bağlam sınıfların sırasını değiştirmiyor: tam bağlamlı dönüştürme (0,4675) bağlamsız
  açıklamanın (0,6450) altında kalır.

#### Sonraki Adım

Bu derste bağlam üç kez **sabit** verildi: hiç, hep aynı dosya, ya da hepsi. Üçü de bir seçim
değildir. Gerçek bir masada bağlam her görev için yeniden kurulur ve iki soru sorulur: hangi
dosyalar ve kaç tane. Yukarıdaki tablo bu soruların ikisini de yanıtsız bırakıyor; yalnız uçları
gösteriyor. Sonraki ders arayı doldurur: dosya sayısı bir bir artarken belirteç nasıl büyüyor,
kabul nerede tepe yapıyor ve **görevle ilgisi olmayan bir dosya** kabule ne yapıyor. Orada
ölçülecek olan bağlamın **boyu** değil, **seçimidir**.

### Bağlam Sağlama

Source: https://academia.sh/tr/kurslar/model-apileri/baglam-saglama

Aynı kurgu kod tabanında bağlamı büyütmekle bağlamı seçmenin yan yana ölçülmesi: bütün dosyaları göndermek beklenen kabulü 0,6921'e çıkarıyor ve 4224 belirteç ile 120 dosya harcıyor, yalnız gereken dosyaları göndermek 0,8233'e çıkarıyor ve 2274 belirteç ile 45 dosya harcıyor. İlgisiz her dosya beklenen kabulden 0,0400 götürüyor ve 624 belirteç ekliyor; eşiği yoktur, ilk dosyadan başlar. Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274'te sabittir, ama beklenen kabul 0,4960 ile 0,8233 arasında değişir; sağlayıcının bütün kod tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

Önceki ders bağlamı üç kez **sabit** verdi: hiç, hep aynı dosya, ya da hepsi. Uçlar arasındaki
mesafe büyüktü — yirmi dört görevin yedisinden on sekizine — ama üçü de bir seçim değildi. Bir
geliştirici masasında bağlam her görev için yeniden kurulur ve iki ayrı soru sorulur: **hangi
dosyalar** ve **kaç tane**.

Bu ders o iki soruyu ayırır. Önce bağlam **büyütülür**: aynı dosya kümesi herkese verilir ve boyu
bir bir artar. Sonra bağlam **seçilir**: her göreve yalnız o görevin gerektirdiği dosyalar gider.
İki eğri belirteç ekseninde yan yana konur ve üzerine üçüncü bir sayı eklenir: **görevle ilgisi
olmayan bir dosyanın kabule ne yaptığı**.

- **YG9.** Kod tabanı önceki derste gövdeleriyle kurulan aynı **kurgu** kod tabanıdır: beş modül,
  **53 satır**. Burada yalnız yapısı gerekir, çünkü bağlam **dosya adıyla** seçilir.
- **YG10.** Görev kümesi ve yardımcı benzeticisi de aynıdır: yirmi dört kurgu görev, üç sınıf,
  tohum **20260218**, `random` yok.
- **YG11.** Bağlamın kabule etkisi iki terimlidir: **örtüşme** (gereken dosyaların kaçı bağlamda)
  kabulü yükseltir, **ilgisizlik** (bağlamdaki dosyaların kaçı gereksiz) düşürür.
- **YG12.** Bedel dosya başına düz **26 belirteçtir**; dosya boyu bedele girmez. Gerçek bir
  bağlamda büyük dosya pahalıdır, yani buradaki bedel eğrisi **iyimserdir**.
- **YG13.** Gönderilen dosya sayısı ayrıca sayılır; yirmi dört görev için toplamdır ve belirteçten
  bağımsız bir hacim ölçüsüdür.
- **YG14. Bağlam sağlayıcı kurgudur** ve tek bir ayarı vardır: **isabet**, yani gereken kümeyi
  doğru bulduğu görev payı. Kaçırdığında bir gereken dosyayı düşürür, yerine ilgisiz bir dosya
  koyar; **dosya sayısı değişmez**, yalnız hangi dosya olduğu değişir.
- **YG15.** Sağlayıcının kendi çekilişi **tohumla sabittir**; ikinci koşumda yalnız yardımcının
  belirsizliği değişir. Böylece iki koşum farkı seçime değil, yalnız modele yazılır.
- **YG16.** Koşumdan bağımsız ölçü yine **beklenen kabuldür**; sayılan kabul iki tohumda ayrı
  basılır. Gecikme sınıfı bütün kurulumlarda **tek çağrıdır**, görev başına bir tane.

#### Kod Tabanının Yapısı ve Sağlayıcı

Bağlam seçimi için kod tabanının gövdeleri değil **yapısı** gerekir: hangi modül var, ne kadar
uzun ve dışarıya hangi adları veriyor. Bir bağlam sağlayıcının çalıştığı düzlem de budur.

```python
# AYNI KURGU KOD TABANI -- bes modul, 53 satir; govdeleri onceki derste kuruldu.
# Burada yalniz yapisi gerekiyor: boy ve disa verilen adlar.
BOY = {"okuma.py": 13, "tarife.py": 13, "denetim.py": 11, "ozet.py": 11, "bicim.py": 5}
DISA = {
    "okuma.py": ("ayristir", "tuketim"),
    "tarife.py": ("BASAMAK", "USTU", "bedel"),
    "denetim.py": ("GECERLI_BOLGE", "gecerli", "ayikla"),
    "ozet.py": ("bolge_toplam", "bolge_sayi"),
    "bicim.py": ("satir", "rapor"),
}
DOSYA = tuple(BOY)

TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
GEREKEN = {
    0: ("okuma.py",),
    1: ("tarife.py",),
    2: ("denetim.py", "okuma.py"),
    3: ("ozet.py", "denetim.py"),
    4: ("bicim.py", "ozet.py"),
    5: ("tarife.py", "okuma.py"),
    6: ("ozet.py", "okuma.py", "tarife.py"),
    7: ("denetim.py", "bicim.py"),
}
GOREV = [                                   # 24 KURGU gorev: 3 sinif x 8
    {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)}
    for s in SINIF
    for i in range(8)
]
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def yardimci(gorev, baglam, tohum=TOHUM):   # BENZETICI -- KURGUDUR
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam))))
    ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    kabul = r() < puan
    belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0)
    return {"kabul": kabul, "puan": puan, "belirtec": belirtec}


def saglayici(gorev, isabet, tohum=TOHUM):
    """KURGU baglam saglayici. Isabet ettiginde gereken kumeyi bulur; kacirdiginda
    bir gereken dosyayi dusurur ve yerine ilgisiz bir dosya koyar. Dosya sayisi ayni."""
    r = uretec(tohum ^ izno("saglayici|" + gorev["ad"]))
    if r() < isabet:
        return tuple(gorev["gereken"])
    ek = tuple(d for d in DOSYA if d not in gorev["gereken"])[:1]
    return tuple(gorev["gereken"][1:]) + ek


print("modul       satir  disa verilen")
for d in DOSYA:
    print(f"  {d:<10}{BOY[d]:>4}   {', '.join(DISA[d])}")
dagilim = {}
for g in GOREV:
    dagilim[len(g["gereken"])] = dagilim.get(len(g["gereken"]), 0) + 1
print(f"\ngorev {len(GOREV)}, gereken dosya sayisi dagilimi {dict(sorted(dagilim.items()))}"
      f", toplam gereken dosya {sum(len(g['gereken']) for g in GOREV)}")
print("ornek gorev:", GOREV[6]["ad"], "->", "+".join(GOREV[6]["gereken"]),
      " belirtec", yardimci(GOREV[6], GOREV[6]["gereken"])["belirtec"],
      "/ butun kod tabaniyla", yardimci(GOREV[6], DOSYA)["belirtec"])
```

```
modul       satir  disa verilen
  okuma.py    13   ayristir, tuketim
  tarife.py   13   BASAMAK, USTU, bedel
  denetim.py  11   GECERLI_BOLGE, gecerli, ayikla
  ozet.py     11   bolge_toplam, bolge_sayi
  bicim.py     5   satir, rapor

gorev 24, gereken dosya sayisi dagilimi {1: 6, 2: 15, 3: 3}, toplam gereken dosya 45
ornek gorev: tamamlama-7 -> ozet.py+okuma.py+tarife.py  belirtec 118 / butun kod tabaniyla 170
```

Görevlerin yarısından çoğu **iki** dosya istiyor, altısı bir, üçü üç. Yirmi dört görevin toplam
ihtiyacı **45 dosyadır**. Bütün kod tabanını her göreve göndermek ise 120 dosya demektir, yani
gereğinin **iki katından fazlası**. Örnek görevde fark tek başına küçük görünüyor: 118 belirteçe
karşı 170. Yirmi dört görev boyunca aynı fark birikir.

#### Büyütmek ile Seçmek

İki eğri aynı tabloda basılır. **Toplu** satırlar herkese aynı ilk `k` dosyayı verir; **seçili**
satırlar her göreve yalnız kendi gereken dosyalarını verir ve üzerine sırayla ilgisiz dosya
eklenir.

```python
def olc(sec, tohum=TOHUM):
    kabul = bel = dosya = 0
    puan = 0.0
    for g in GOREV:
        b = sec(g)
        s = yardimci(g, b, tohum)
        kabul += s["kabul"]
        puan += s["puan"]
        bel += s["belirtec"]
        dosya += len(b)
    return kabul, puan / len(GOREV), bel, dosya


def yaz(ad, sec):
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    print(f"{ad:<26}{a[3]:>7}{a[1]:>11.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")


print("kurulum                    dosya   beklenen  kabul A  kabul B  belirtec")
for k in range(6):
    yaz(f"toplu {k}", lambda g, b=DOSYA[:k]: b)
yaz("secili (yalniz gereken)", lambda g: g["gereken"])
for n in (1, 2, 3):
    def sec(g, n=n):
        ek = tuple(d for d in DOSYA if d not in g["gereken"])[:n]
        return tuple(g["gereken"]) + ek
    yaz(f"secili + {n} ilgisiz", sec)

print("\nsaglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec")
for isb in (0.00, 0.25, 0.50, 0.75, 1.00):
    def sec(g, i=isb):
        return saglayici(g, i)
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    bulunan = sum(sum(1 for d in g["gereken"] if d in sec(g)) for g in GOREV)
    print(f"{isb:>13.2f}{bulunan / 45:>22.4f}{a[1]:>10.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")
```

```
kurulum                    dosya   beklenen  kabul A  kabul B  belirtec
toplu 0                         0     0.3383       7/24       7/24      1104
toplu 1                        24     0.4600      10/24       8/24      1728
toplu 2                        48     0.5402      12/24      13/24      2352
toplu 3                        72     0.6013      15/24      13/24      2976
toplu 4                        96     0.6608      15/24      15/24      3600
toplu 5                       120     0.6921      18/24      20/24      4224
secili (yalniz gereken)        45     0.8233      19/24      19/24      2274
secili + 1 ilgisiz             69     0.7833      19/24      18/24      2898
secili + 2 ilgisiz             93     0.7433      20/24      18/24      3522
secili + 3 ilgisiz            114     0.7029      17/24      20/24      4068

saglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec
         0.00                0.4667    0.4960      13/24      10/24      2274
         0.25                0.6222    0.5796      15/24      12/24      2274
         0.50                0.7333    0.6404      15/24      14/24      2274
         0.75                0.8222    0.7050      17/24      15/24      2274
         1.00                1.0000    0.8233      19/24      19/24      2274
```

#### Eğrinin Okunması

Toplu satırlar sezgiyi doğruluyor: dosya eklemek beklenen kabulü **0,3383'ten 0,6921'e** çıkarıyor
ve hiçbir adımda düşürmüyor. Bedel de düzgündür — her adım tam **624 belirteç**, çünkü yirmi dört
görevin her birine bir dosya daha giriyor. Eğri, bağlamı büyütmenin işe yaradığı iddiasının
sayısıdır ve doğrudur.

Eğrinin bir zayıflığı var ve tabloda görünmüyor: **sıra**. Toplu satırlar dosyaları modül
demetindeki sırayla ekliyor, yani ikinci satırın hangi dosyayı taşıdığı bir karar değil bir
tesadüftür. Başka bir sırayla aynı iki uç nokta arasında başka bir eğri çıkarırdı. Seçili kurulumun
böyle bir bağımlılığı yoktur, çünkü sıra sorusunu hiç sormaz. Bir kurulumun sayısı, listelenmemiş
bir keyfî karara duyarlıysa o sayı tek başına okunmamalıdır.

İkinci zayıflık bedel tarafındadır ve **seçimin lehinedir**. Bu ölçümde her dosya boyundan bağımsız
olarak 26 belirteç ediyor; oysa kod tabanının en uzun modülü en kısasının iki buçuk katından
uzundur.
Gerçek bir bağlamda toplu gönderim uzun dosyaların bedelini de öder, seçili gönderim çoğu zaman
ödemez. Yani aşağıdaki fark bir **alt sınırdır**.

Seçili satır aynı iddiayı yerinden ediyor. Yalnız gereken dosyalar gönderildiğinde beklenen kabul
**0,8233**; bütün kod tabanının **0,6921**'inden **0,1312** yüksek. Bunu **45 dosya** ve **2274
belirteç** ile yapıyor: dosya hacminin **üçte birinden biraz fazlası**, belirtecin **yüzde elli
dördü**.
İki eksende birden kazanan bir kurulum ender görülür ve buradaki nedeni açıktır: bütün kod
tabanını göndermek gereken dosyaları da gönderir, ama yanında **ortalama üç ilgisiz dosya**
taşır.

Aynı bedelde karşılaştırma bunu daha keskin yapıyor. **Toplu 2** kurulumu 2352 belirteç harcayıp
**0,5402** veriyor; seçili kurulum 2274 belirteçle, yani biraz daha azıyla, **0,8233**. Neredeyse
aynı bütçede **0,2831** fark. Belirteç bütçesi bir tasarım kısıtıysa, o bütçeyi nereye harcadığın
ne kadar harcadığından daha çok belirliyor.

Sayılan kabul sütunları bir uyarı taşıyor. Seçili satır **19/24** ve bütün kod tabanı **18/24**;
aradaki fark tek görev. Ama ikinci koşumda sıralama tersine dönüyor: 19/24'e karşı **20/24**.
Sayılan kabulle bakıldığında bu iki kurulum **ayırt edilemez**, çünkü fark iki koşum farkının
içinde kalıyor. Ayrımı yapan şey koşumdan bağımsız sütundur. Bu, kursun ölçü kuralının doğrudan
uygulanmasıdır: iki koşumda oynayan bir sayı, tek koşumda okunduğunda karar verdirmez.

#### İlgisiz Dosyanın Eşiği Yoktur

Son üç seçili satır tek bir soruyu yanıtlıyor: doğru dosyalar zaten gönderildikten sonra
**fazladan bir dosya** ne yapar. Yanıt düzgün ve tek yönlüdür. Beklenen kabul **0,8233'ten
0,7833'e, 0,7433'e ve 0,7029'a** iniyor; her ilgisiz dosya tam **0,0400** götürüyor. Bedel aynı
anda **2274'ten 4068'e** çıkıyor; adım başına 624, 624 ve 546 belirteç.

Burada aranan "isabetin düştüğü nokta" bir eşik değildir: **ilk ilgisiz dosyadan başlar**. Bedava
bir ilgisiz dosya yoktur, çünkü ilgisizlik terimi doğrusaldır ve örtüşme terimi zaten
doyurulmuştur. Üç ilgisiz dosya eklemek belirteci **yüzde yetmiş dokuz** artırıp beklenen kabulden
**0,1204** götürüyor — eklenen düzeneğin işi kötüleştirdiği en yalın satır budur.

Sayılan kabul burada da yanıltıcıdır ve niçin olduğu görülüyor: 19, 19, 20, 17 diye gidiyor,
ikinci koşumda 19, 18, 18, 20. Tek koşuma bakan biri "iki ilgisiz dosya kabulü yükseltti"
diyebilir. Beklenen kabul sütunu bu yorumu kapatıyor. Yirmi dört görevlik bir kümede tek bir
kabulün ağırlığı 0,0417'dir, yani ilgisiz bir dosyanın gerçek etkisinden büyüktür; sayılan kabul
bu ayrıntıyı gösterecek çözünürlükte değildir ve daha büyük bir görev kümesi gerektirir.

#### Sağlayıcının İsabeti Bedelden Bağımsızdır

İkinci tablo bağlam seçimini bir yeteneğe çeviriyor. Sağlayıcı her isabet düzeyinde **aynı sayıda
dosya** gönderir, dolayısıyla belirteç sütunu beş satırda da **2274**'tür. Değişen tek şey
**hangi** dosyaların gönderildiğidir ve beklenen kabul **0,4960 ile 0,8233 arasında** oynuyor.
Bağlam kalitesi burada belirteçle satın alınmıyor; ölçülen fark tamamen seçimin kendisinden
geliyor.

Bu tablonun son satırı, bir önceki tablonun seçili satırıyla aynıdır ve aynı olması gerekir:
**1,00 isabet**, gereken kümeyi her görevde bilen bir sağlayıcıdır. Böyle bir sağlayıcı bir ölçüm
kurgusudur, bir kurulum değil. Hangi dosyaların gerektiğini bilmek, görevin çözülmüş olmasına çok
yakın bir bilgidir; gerçek bir sağlayıcı bunu ad benzerliği, çağrı ilişkisi ya da geçmiş
değişikliklerden **tahmin eder**. Bu yüzden 0,8233 bir hedef değil bir **üst sınırdır** ve tablo
o sınıra ne kadar yaklaşıldığının bedelini değil, yaklaşamamanın bedelini gösterir.

Sıfır isabette bile bulunan gereken dosya payı **0,4667**'dir, çünkü iki dosyalık bir görevden
biri düşürüldüğünde öbürü yerinde kalır. Yani kötü bir sağlayıcı sıfır değildir, sadece
zayıftır — ve 0,4960 beklenen kabul, hiç bağlam göndermemenin (0,3383) üzerindedir.

Asıl karar noktası ortadadır. Bütün kod tabanını göndermek **0,6921** veriyor. Sağlayıcı bunu
0,50 isabette geçemiyor (**0,6404**), 0,75 isabette geçiyor (**0,7050**). Yani bir bağlam
sağlayıcısı, gereken dosyaları **dört görevin yaklaşık üçünde** bulabiliyorsa her şeyi göndermekten
iyidir; bulamıyorsa daha kötüdür ve üstelik bunu ucuz olduğu için fark etmek zordur. Bedel sütunu
sabit olduğu için sağlayıcının kötülüğü faturada görünmez, yalnız kabulde görünür.

#### Özet

- Bağlamı büyütmek beklenen kabulü 0,3383'ten 0,6921'e çıkarır ve her adım tam 624 belirteç eder;
  eğri düzgündür ve hiçbir adımda düşmez.
- Bağlamı seçmek aynı görev kümesinde 0,8233 verir; bunu 45 dosya ve 2274 belirteçle yapar, yani
  bütün kod tabanından hem 0,1312 yüksek hem yaklaşık yarı bedelde.
- Neredeyse eşit bütçede fark daha da büyüktür: toplu iki dosya 2352 belirteçle 0,5402, seçili
  bağlam 2274 belirteçle 0,8233.
- İlgisiz her dosya beklenen kabulden tam 0,0400 götürür ve 624 belirteç ekler; eşiği yoktur,
  ilk dosyadan başlar ve üç dosyada 0,1204 kayıp eder.
- Sayılan kabul bu kararların ikisinde de ayrım yapmaz (19/24'e karşı 18/24, ikinci koşumda
  tersine döner); ayrımı koşumdan bağımsız beklenen kabul sütunu yapar.
- Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274'te sabittir; bütün kod
  tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

#### Sonraki Adım

Bu iki derste her görev **tek bir çağrıydı**: bağlam gitti, öneri geldi, geliştirici kabul etti ya
da etmedi. Karar noktası tekti ve hemen oradaydı. Bir geliştirme işi çoğu zaman böyle durmaz —
bir dosyayı okumak, bir işlevi değiştirmek, çağıranları güncellemek ve raporu yeniden biçimlemek
tek bir istekle devredildiğinde ortaya **çok adımlı** bir iş çıkar ve geliştirici artık her adımda
değil, durduğu yerde bakar. Sonraki ders bu durma yerini ölçer: kaç adımda bir durulduğunda bir
hata **yayılmadan** yakalanıyor, kaç adım boşa gidiyor ve durmanın kendisi kaç çağrıya mal oluyor.

### Ajanlı Kodlama

Source: https://academia.sh/tr/kurslar/model-apileri/ajanli-kodlama

Çok adımlı bir işin devredilmesinde denetim noktası aralığının ölçülmesi: altmış kurgu işin 480 adımı altı ayrı aralıkta koşturulunca her adımda durmak 478/480 doğru adım veriyor ama 479 durma istiyor, sekiz adımda bir durmak 60 durmaya iniyor ve 355/480'e düşüyor. Yakalanan hata başına boşa giden adım 1,00'den 5,64'e çıkıyor; kaçan hata 1'den 21'e. Çağrı sayısı altı aralıkta neredeyse sabit (549 ile 598 arası), yani durmanın bedeli çağrı değil insan bakışıdır. Doğru adım başına belirteç iki koşumda da üç adımlık aralıkta en düşüktür (146,8 ve 144,9), yani en doğru aralık ile en ucuz aralık aynı değildir.

Önceki iki derste her görev **tek bir çağrıydı**: bağlam gitti, öneri geldi, geliştirici kabul
etti ya da etmedi. Karar noktası tekti ve öneriyle aynı yerdeydi. Bir dosyayı okumak, bir işlevi
değiştirmek, çağıranları güncellemek ve raporu yeniden biçimlemek tek bir istekle devredildiğinde
bu düzen bozulur: araç arka arkaya adım atar, her adım bir öncekinin **üstüne** kurulur ve
geliştirici artık her adımda değil, **durduğu yerde** bakar.

Bu ders o durma yerini ölçer ve başka bir şey ölçmez. Aracın nasıl planladığı, neyi hatırladığı ve
döngüsünü nasıl kapattığı burada ele alınmaz; bunlar bu müfredatın Yapay Zekâ Ajanları kursunun
konusudur. Buradaki tek soru şudur: **kaç adımda bir durulduğunda hata yayılmadan yakalanıyor ve
bunun bedeli ne.**

- **YG17.** Kurulum önceki iki dersle aynıdır: **kurgu** kod tabanı (beş modül, 53 satır), yirmi
  dört kurgu görev ve yardımcı **benzeticisi**. Gerçek bir ajanlı kodlama aracı çalıştırılmaz.
- **YG18.** Çok adımlı iş: **60 kurgu iş, her biri 8 adım**, toplam **480 adım**. Her adımın
  bağlamı **seçilidir**, yani yalnız o adımın gerektirdiği dosyalar gönderilir.
- **YG19. Yayılma kuralı:** reddedilen bir adım fark edilmezse sonraki adımlar onun üstüne
  kurulur ve **bulaşık** sayılır. Bu dersin ölçtüğü tek yapısal olgu budur.
- **YG20. Denetim noktası** her `d` adımda bir ve işin sonunda konur; durakta o pencere insana
  bakılır.
- **YG21. Görme payı pencere büyüdükçe düşer:** `0,95 - 0,07 x (d - 1)`, alt sınır `0,40`. Sekiz
  adımlık bir değişikliği tek seferde okumak, tek adımı okumaktan zordur.
- **YG22.** Yakalanan hata **yeniden koşulur**: hatalı adımdan durağa kadarki adımlar yeniden
  çağrılır ve düzeldiği varsayılır. Bunlar **boşa giden adımdır**.
- **YG23.** Yakalanmayan hata **tabana girer**: işin kalan adımları bulaşıktır ve sonraki duraklar
  onu göremez, çünkü bakılan şey kabul edilmiş taban değil yeni iştir.
- **YG24.** Bedel üç ayrı kalemdir: **durma sayısı** (insanın baktığı kez), **çağrı** ve
  **belirteç**; her durak ayrıca **50 belirteç** durum özeti ekler.
- **YG25.** Teslim ölçüsü **doğru adımdır**: kaçan hatası olan bir işte doğru adım sayısı hatanın
  bulunduğu yere kadardır.
- **YG26.** Adım sonuçları aralıktan bağımsız olarak aynı tohumla üretilir; aralıklar arasında
  değişen tek şey **nerede durulduğudur**. İkinci koşum tohum **20260219**.

#### Bir İşin İzi

Önce tek bir iş iki ayrı aralıkla koşturulur. Aynı sekiz adım, aynı sonuçlar; değişen yalnız
durakların yeri.

```python
# AYNI KURGU KURULUM -- bes modullu kod tabani (53 satir), 24 kurgu gorev,
# yardimci benzeticisi. Gercek bir ajanli kodlama araci calistirilmaz.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py")
GEREKEN = {
    0: ("okuma.py",), 1: ("tarife.py",), 2: ("denetim.py", "okuma.py"),
    3: ("ozet.py", "denetim.py"), 4: ("bicim.py", "ozet.py"),
    5: ("tarife.py", "okuma.py"), 6: ("ozet.py", "okuma.py", "tarife.py"),
    7: ("denetim.py", "bicim.py"),
}
GOREV = [
    {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)}
    for s in SINIF
    for i in range(8)
]
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def yardimci(gorev, baglam, tohum=TOHUM):   # BENZETICI -- KURGUDUR
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam))))
    ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    kabul = r() < puan
    belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0)
    return {"kabul": kabul, "puan": puan, "belirtec": belirtec}


IS_SAYI, ADIM, DURUM_BEL = 60, 8, 50


def gorme(d):
    """Denetim penceresi buyudukce insanin hatayi gorme payi duser."""
    return max(0.95 - 0.07 * (d - 1), 0.40)


def devir(j, d, tohum=TOHUM, ayrinti=False):
    """Tek bir cok adimli isin d adimda bir durdurularak kosturulmasi."""
    say = {"cagri": 0, "belirtec": 0, "durma": 0, "yakalanan": 0,
           "kacan": 0, "bosa": 0, "dogru": 0}
    hatali, kacti = None, False
    for k in range(ADIM):
        g = GOREV[(j * ADIM + k) % len(GOREV)]
        s = yardimci(g, g["gereken"], tohum ^ izno("adim|" + str(j) + "|" + str(k)))
        say["cagri"] += 1
        say["belirtec"] += s["belirtec"]
        if kacti:
            if ayrinti:
                print(f"  adim {k}  {g['ad']:<14} bulasik (kacan hatanin ustune)")
            continue
        if hatali is None and not s["kabul"]:
            hatali = k
        if ayrinti:
            d_ad = "kabul" if s["kabul"] else "RET"
            if hatali is not None and hatali < k:
                d_ad = "bulasik"
            print(f"  adim {k}  {g['ad']:<14} {d_ad}")
        if (k + 1) % d == 0 or k == ADIM - 1:
            say["durma"] += 1
            say["belirtec"] += DURUM_BEL
            if hatali is None:
                if ayrinti:
                    print(f"  DURMA adim {k}: temiz")
                continue
            r = uretec(tohum ^ izno("denetim|" + str(j) + "|" + str(k)))
            if r() < gorme(d):
                yeniden = k - hatali + 1
                say["yakalanan"] += 1
                say["bosa"] += yeniden
                say["cagri"] += yeniden
                say["belirtec"] += yeniden * s["belirtec"]
                if ayrinti:
                    print(f"  DURMA adim {k}: hata adim {hatali} noktasinda"
                          f" gorundu, {yeniden} adim yeniden")
                hatali = None
            else:
                say["kacan"] += 1
                kacti = True
                if ayrinti:
                    print(f"  DURMA adim {k}: gorulmedi, hata tabana girdi")
    say["dogru"] = hatali if kacti else ADIM
    return say


print("is 0, adim araligi 4:")
a = devir(0, 4, ayrinti=True)
print("  ->", {x: a[x] for x in ("dogru", "bosa", "durma", "cagri", "belirtec")})
print("\nis 0, adim araligi 8:")
b = devir(0, 8, ayrinti=True)
print("  ->", {x: b[x] for x in ("dogru", "bosa", "durma", "cagri", "belirtec")})
```

```
is 0, adim araligi 4:
  adim 0  tamamlama-1    kabul
  adim 1  tamamlama-2    kabul
  adim 2  tamamlama-3    RET
  adim 3  tamamlama-4    bulasik
  DURMA adim 3: hata adim 2 noktasinda gorundu, 2 adim yeniden
  adim 4  tamamlama-5    kabul
  adim 5  tamamlama-6    kabul
  adim 6  tamamlama-7    RET
  adim 7  tamamlama-8    bulasik
  DURMA adim 7: hata adim 6 noktasinda gorundu, 2 adim yeniden
  -> {'dogru': 8, 'bosa': 4, 'durma': 2, 'cagri': 12, 'belirtec': 1178}

is 0, adim araligi 8:
  adim 0  tamamlama-1    kabul
  adim 1  tamamlama-2    kabul
  adim 2  tamamlama-3    RET
  adim 3  tamamlama-4    bulasik
  adim 4  tamamlama-5    bulasik
  adim 5  tamamlama-6    bulasik
  adim 6  tamamlama-7    bulasik
  adim 7  tamamlama-8    bulasik
  DURMA adim 7: hata adim 2 noktasinda gorundu, 6 adim yeniden
  -> {'dogru': 8, 'bosa': 6, 'durma': 1, 'cagri': 14, 'belirtec': 1312}
```

İki iz aynı sekiz adımı taşıyor ve altta yatan sonuçlar da aynı: `2` ve `6` numaralı adımlar
reddediliyor. Değişen tek şey durakların yeridir, ama iz aynı değildir. Dört adımlık aralıkta
ilk hata iki adım yayıldıktan sonra yakalanıyor, ikinci hata da öyle; toplam dört adım yeniden
koşuluyor. Sekiz adımlık aralıkta ilk hata **altı adım** yayıyor ve ikinci hata **hiç
görünmüyor** — `6` numaralı adım o noktada zaten bulaşık olduğu için ayrı bir hata olarak
sayılmıyor. İkisi de sonunda sekiz doğru adım teslim ediyor, ama biri 12 çağrı ve 1178 belirteç,
öbürü 14 çağrı ve 1312 belirteç harcıyor.

Bu tek iş iyi bir örnek ama bir sayı değildir: burada denetim ikisinde de gördü. Görmediğinde ne
olacağı ancak yeterince iş üzerinde okunur.

#### Aralığın Süpürülmesi

Altmış iş, dört yüz seksen adım, altı ayrı denetim aralığı. Adım sonuçları aralıktan bağımsızdır;
değişen tek şey durakların yeridir.

```python
def kosum(d, tohum=TOHUM):
    top = {"cagri": 0, "belirtec": 0, "durma": 0, "yakalanan": 0,
           "kacan": 0, "bosa": 0, "dogru": 0}
    for j in range(IS_SAYI):
        for a, v in devir(j, d, tohum).items():
            top[a] += v
    return top


ADIMLAR = IS_SAYI * ADIM
BASLIK = ("aralik  gorme  durma  yakalanan  kacan  bosa  dogru adim"
          "  cagri  belirtec  bel/dogru")


def yaz(d, tohum):
    a = kosum(d, tohum)
    print(f"{d:>6}{gorme(d):>7.2f}{a['durma']:>7}{a['yakalanan']:>11}{a['kacan']:>7}"
          f"{a['bosa']:>6}{a['dogru']:>8}/{ADIMLAR}{a['cagri']:>7}{a['belirtec']:>10}"
          f"{a['belirtec'] / a['dogru']:>11.1f}")


print("kosum A (tohum 20260218)")
print(BASLIK)
for d in (1, 2, 3, 4, 6, 8):
    yaz(d, TOHUM)
print("\nkosum B (tohum 20260219)")
print(BASLIK)
for d in (1, 2, 3, 4, 6, 8):
    yaz(d, TOHUM + 1)
```

```
kosum A (tohum 20260218)
aralik  gorme  durma  yakalanan  kacan  bosa  dogru adim  cagri  belirtec  bel/dogru
     1   0.95    479         90      1    90     478/480    570     78648      164.5
     2   0.88    233         69      8   109     455/480    589     67790      149.0
     3   0.81    172         52     11   104     441/480    584     64746      146.8
     4   0.74    117         45     11   118     430/480    598     63320      147.3
     6   0.60    104         23     23    69     367/480    549     57784      157.4
     8   0.46     60         14     21    79     355/480    559     56414      158.9

kosum B (tohum 20260219)
aralik  gorme  durma  yakalanan  kacan  bosa  dogru adim  cagri  belirtec  bel/dogru
     1   0.95    467         71      4    71     463/480    551     76070      164.3
     2   0.88    224         52     11    79     430/480    559     64318      149.6
     3   0.81    168         44     12    78     428/480    558     62010      144.9
     4   0.74    107         29     14    85     392/480    565     59550      151.9
     6   0.60    105         24     17    79     393/480    559     58790      149.6
     8   0.46     60         18     16   101     393/480    581     59032      150.2
```

#### Yayılmanın Ölçüsü

Sorunun ilk yarısı — hata yayılmadan yakalanıyor mu — tabloda iki sütunun bölümüdür. Boşa giden
adım, yakalanan hata sayısına bölündüğünde **yakalandığı ana kadar kaç adım yayıldığını** verir.
Birinci koşumda bu sayı sırayla **1,00 / 1,58 / 2,00 / 2,62 / 3,00 / 5,64**; ikinci koşumda
**1,00 / 1,52 / 1,77 / 2,93 / 3,29 / 5,61**. İki koşum ayrı ayrı aynı şeyi söylüyor: her adımda
durulduğunda hata **yayılmıyor**, sekiz adımda bir durulduğunda ortalama **beş buçuk adım**
yayıldıktan sonra yakalanıyor.

Kaçan hata sütunu ikinci yarıyı veriyor. Her adımda durmak birinci koşumda **1**, ikinci koşumda
**4** hatayı kaçırıyor; sekiz adımda bir durmak **21** ve **16**. Bunun nedeni tabloda yazılı:
görme payı 0,95'ten 0,46'ya iniyor, çünkü sekiz adımlık bir değişikliği tek seferde okumak
zordur.

Bir sütun burada yanıltıcıdır ve okunmamalıdır: **yakalanan hata sayısı**. Aralık büyüdükçe 90'dan
14'e iniyor, sanki hata azalmış gibi. Azalan şey hata değil, **hata sayabildiğimiz iş**tir; kaçan
bir hata işin kalanını bulaştırdığı için o işte başka hata sayılmaz. Devredilen işin kalitesi
"kaç hata bulundu" ile ölçülemez. Ölçülebilen tek şey **teslim edilen doğru adımdır**: 478/480'den
355/480'e, ikinci koşumda 463/480'den 393/480'e.

Aynı bağlılık durma sütununda da görünüyor. Her adımda durulan koşumda durak sayısı 480 değil
**479**; ikinci koşumda **467**. Eksik duraklar, hatası kaçmış işlerin kalanıdır: taban artık
bulaşık olduğu için o duraklarda bakılacak temiz bir iş kalmamıştır ve sayılmazlar. Tablodaki
sütunlar birbirinden bağımsız değildir, çünkü devredilen iş de bağımsız adımlardan oluşmuyor.

#### Durmanın Bedeli

Bedel üç kalemdir ve üçü aynı yöne gitmiyor. **Çağrı sayısı** altı aralıkta 549 ile 598 arasında,
ikinci koşumda 551 ile 581 arasında kalıyor — yani neredeyse sabit. Sık durmak yeniden koşum
doğurur, seyrek durmak daha uzun yeniden koşum doğurur; ikisi birbirini götürür. **Durmak bir
çağrı meselesi değildir.**

**Belirteç** düzenli düşüyor: 78648'den 56414'e, yani seyrek durmak toplam belirtecin yaklaşık
**yüzde yirmi sekizini** kurtarıyor. Bunun büyük kısmı durak başına eklenen 50 belirteçlik durum
özetinden gelir; 479 durak ile 60 durak arasındaki fark tek başına 20950 belirteçtir.

Asıl bedel üçüncü kalemdedir ve belirteçle ödenmez: **durma sayısı**. Her adımda durmak insanı
479 kez masaya çağırıyor, sekiz adımda bir durmak 60 kez. Aradaki fark **sekiz kattır** ve
karşılığında kazanılan 123 doğru adımdır. Kurtarılan her doğru adım için insan yaklaşık **3,4 kez**
fazladan bakmıştır. Bu takas bir mühendislik kararıdır ve tabloda yazılıdır; hangi tarafın
seçileceği adımın ne kadar geri alınabilir olduğuna bağlıdır.

Son sütun üçüncü bir eniyileme noktası gösteriyor. Doğru adım başına belirteç iki koşumda da
**üç adımlık aralıkta** en düşüktür: **146,8** ve **144,9**. Bu, en çok doğru adım veren aralık
(bir) değildir; en az durma isteyen aralık (sekiz) de değildir. Üç ayrı ölçüt, üç ayrı kazanan.
Bir denetim aralığı seçmek bu yüzden bir eniyileme değil bir **beyandır**: hangi maliyeti
düşürdüğünü söylemeden seçilmiş bir aralık, ölçülmüş sayılmaz.

#### Özet

- Çok adımlı bir devirde yakalanmayan bir hata sonraki adımlara bulaşır; denetim noktası bu
  bulaşmayı kestiği yerdir ve tek ölçtüğü şey **nerede durulduğudur**.
- Yakalanana kadar yayılan adım sayısı her adımda durulduğunda 1,00, sekiz adımda bir durulduğunda
  5,64'tür; ikinci koşumda 1,00 ve 5,61.
- Kaçan hata 1'den 21'e çıkar (ikinci koşumda 4'ten 16'ya), çünkü pencere büyüdükçe görme payı
  0,95'ten 0,46'ya iner.
- Yakalanan hata sayısı bir kalite ölçüsü değildir: aralık büyüdükçe düşer, çünkü kaçan hata işin
  kalanını sayılamaz kılar. Ölçülebilen tek şey teslim edilen doğru adımdır (478/480'e karşı
  355/480).
- Bedelin üç kalemi ayrışır: çağrı sayısı neredeyse sabittir (549 ile 598 arası), belirteç yüzde
  yirmi sekiz düşer, durma sayısı sekiz kat düşer. Sık durmanın asıl fiyatı insan bakışıdır.
- Doğru adım başına belirteç iki koşumda da üç adımlık aralıkta en düşüktür (146,8 ve 144,9); en
  doğru aralık, en ucuz aralık ve en az durduran aralık üç ayrı satırdır.

#### Sonraki Adım

Bu derste denetim noktası bir **yer** olarak ele alındı ve görme payı tek bir sayıya sıkıştırıldı:
duran insan hatayı bir olasılıkla görüyor, görmüyorsa hata tabana giriyor. O sayının içinde ne
olduğu hiç açılmadı. Durakta tam olarak neye bakılıyor — kod koşuyor mu, doğru sonucu mu veriyor,
var olmayan bir bağımlılığı mı çağırıyor, bağlama giren metinde ne taşındı. Denetim noktası
koyuldu, ama **neyin denetleneceği** söylenmedi. Sonraki ders bu boşluğu doldurur ve görme payını
bir varsayım olmaktan çıkarıp ölçülen bir sayıya çevirir: birbirinden bağımsız denetimler aynı
üretilmiş kod üzerinde koşturulur, her birinin yakaladığı kusur ayrı sayılır ve **hiçbirinin
yakalamadığı** kalıntı adıyla yazılır.

### Üretilen Kodun İncelenmesi

Source: https://academia.sh/tr/kurslar/model-apileri/uretilen-kodun-incelenmesi

Kurgu bir kod tabanına gelen yirmi dört üretilmiş yamanın üç savunma denetiminden geçirilmesi: kabul sınaması altı davranış kusurunun beşini yakalıyor, örüntü taraması sekiz bulgunun sekizini, bağımlılık varlık denetimi dokuz uydurma adın dokuzunu. Yirmi sekiz kusurun yirmi altısı yakalanıyor, ikisi biçim hatası olarak kaçıyor ve kaçanlardan biri hiçbir uyarı almadan kod tabanına giriyor.

Önceki ders çok adımlı bir devirde **denetim noktasının** nereye konacağını ölçtü: kaç adımda
bir durulduğunda hata yayılmadan yakalanıyor ve durmanın bedeli ne. Denetim noktası bir yerdir.
Orada **ne yapılacağı** söylenmedi. Duran insanın önünde bir yama durur ve o yamaya bakmanın
kendi kapsamı, kendi maliyeti ve kendi kör noktası vardır.

Bu ders o bakışı üç ayrı denetime böler ve her birinin **eriştiği kusur sınıfını** sayar: kod
tabanının **sınama koşumu**, üretilen metnin **örüntü taraması** ve alınan bağımlılıkların
**varlık denetimi**. Kod incelemesinin genel yordamı Yazılım Kalitesi ve Test müfredatında,
güvenlik denetiminin yordamı Siber Güvenlik ve Uygulama Güvenliği müfredatlarında ölçüldü;
burada tekrarlanmaz. Eklenen tek şey **üreticinin kimliğidir**: incelenen yama bir insandan
değil belirsiz bir bileşenden geliyor, bu yüzden kusurların **dağılımı** başkadır ve denetimlerin
kapsadığı alanın sınırı sayılmalıdır.

- **YG31.** Kod tabanı **kurgudur**: ölçüm ağının kendi yardımcı betikleri. Hiçbir gerçek depo,
  paket ya da ürün değildir. **Beş modül, 53 satır.** Tohum **20260218**.
- **YG32.** Bu ders bir saldırı dersi değildir. **Koşan kod her zaman savunma tarafındadır**:
  sınama, tarama, sayım, doğrulama. Hiçbir sömürü kodu, yük ya da atlatma yordamı yazılmaz.
- **YG33.** Üretilen yama iki parçadır: değişen bir **modül** ve yeni bir **yardımcı dosya**.
  Yardımcı dosyayı hiçbir sınama çağırmaz; kod tabanına henüz bağlanmamıştır.
- **YG34.** Kod tabanına konan altı **davranış kusuru** kaynak metinde tek dizge değişimidir;
  altıncısı bir **biçim** kusurudur ve çıktının hizasını bozar.
- **YG35.** Kabul sınaması **on maddedir** ve ders içinde yazılır. Kod tabanının kendi
  sınamasıdır, üretilen bir sınama değildir.
- **YG36.** Örüntü taraması dört dizge arar. Bulgu bir kanıt değil bir **işarettir**; insanın
  bakması gereken satırı gösterir.
- **YG37.** Varlık denetimi: bir `import` satırındaki ad kod tabanının modülleri arasında ya da
  izinli standart kitaplık adları arasında değilse **uydurmadır**. Uydurma adlar kurgudur.
- **YG38.** Sayılan birim **kusurdur, aday değildir**. Bir aday birden çok kusur taşıyabilir;
  **işaretli aday** en az bir denetimden uyarı alandır.

#### Kurgu Kod Tabanı ve İncelemenin Konusu

İnceleme, üzerinde durulacak bir gövde ister. Gövde şudur: ölçüm ağının okuma, tarife hesabı,
kayıt denetimi, bölge özeti ve çıktı biçimlendirmesi için yazılmış beş küçük modülü. Modüller
metin olarak tutulur ve çalıştırılmak istendiğinde ayrı bir ad alanına yüklenir; bu, aynı kod
tabanının **bozulmuş bir sürümünü** yan yana koşturmayı ucuzlatır.

```python
# KURGU kod tabani: olcum aginin kendi yardimci betikleri. Gercek bir depo,
# paket ya da urun degildir. Bes modul, 53 satir. Tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KOD = {
    "okuma.py": """
def ayristir(satir):
    p = satir.split(";")
    if len(p) != 4:
        return None
    if not p[3].lstrip("-").isdigit():
        return None
    return {"abone": p[0], "bolge": p[1], "donem": p[2], "endeks": int(p[3])}

def tuketim(onceki, simdiki):
    fark = simdiki - onceki
    if fark < 0:
        fark = fark + 100000
    return fark
""",
    "tarife.py": """
BASAMAK = ((10, 4), (25, 7), (40, 11))
USTU = 16

def bedel(m3):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    return top + kalan * USTU
""",
    "denetim.py": """
GECERLI_BOLGE = ("dogu", "bati", "kuzey", "guney", "merkez")

def gecerli(kayit):
    if kayit is None:
        return False
    if kayit["endeks"] < 0:
        return False
    return kayit["bolge"] in GECERLI_BOLGE

def ayikla(kayitlar):
    return [k for k in kayitlar if gecerli(k)]
""",
    "ozet.py": """
def bolge_toplam(kayitlar, tuketimler):
    top = {}
    for k, t in zip(kayitlar, tuketimler):
        top[k["bolge"]] = top.get(k["bolge"], 0) + t
    return top

def bolge_sayi(kayitlar):
    say = {}
    for k in kayitlar:
        say[k["bolge"]] = say.get(k["bolge"], 0) + 1
    return say
""",
    "bicim.py": """
def satir(bolge, m3, tutar):
    return bolge.ljust(8) + str(m3).rjust(7) + str(tutar).rjust(9)

def rapor(baslik, satirlar):
    return "\\n".join([baslik] + satirlar)
""",
}


def yukle(kod):
    ad = {}
    for dosya, kaynak in kod.items():
        alan = {}
        exec(kaynak, alan)
        ad[dosya] = alan
    return ad


SINIF = ("tamamlama", "aciklama", "donusturme")
DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py")
GEREKEN = {0: ("okuma.py",), 1: ("tarife.py",), 2: ("denetim.py", "okuma.py"),
           3: ("ozet.py", "denetim.py"), 4: ("bicim.py", "ozet.py"),
           5: ("tarife.py", "okuma.py"), 6: ("ozet.py", "okuma.py", "tarife.py"),
           7: ("denetim.py", "bicim.py")}
GOREV = [{"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i],
          "zorluk": 0.05 * (i % 4)} for s in SINIF for i in range(8)]

BOY = {d: len(k.strip().split("\n")) for d, k in KOD.items()}
AD = yukle(KOD)
print("kod tabani:", BOY, "toplam", sum(BOY.values()), "satir")
print("gorev sayisi:", len(GOREV), "-", " , ".join(SINIF))
print("bedel(0,10,25,40,60):", [AD["tarife.py"]["bedel"](m) for m in (0, 10, 25, 40, 60)])
print("tuketim(99800,300):", AD["okuma.py"]["tuketim"](99800, 300))
```

```
kod tabani: {'okuma.py': 13, 'tarife.py': 13, 'denetim.py': 11, 'ozet.py': 11, 'bicim.py': 5} toplam 53 satir
gorev sayisi: 24 - tamamlama , aciklama , donusturme
bedel(0,10,25,40,60): [0, 40, 145, 310, 630]
tuketim(99800,300): 500
```

Son iki satır kod tabanının **doğru davranışını** sabitliyor. Kademeli tarifede altmış metreküp
**630** ediyor; sayaç doksan dokuz binden üç yüze döndüğünde tüketim **500** çıkıyor. Bu iki sayı
bundan sonra ölçüt olacak: bir yama bunları değiştiriyorsa yama yanlıştır. İnceleme yordamının
ilk kuralı budur — doğruluk bir izlenim değil, **önceden yazılmış bir beklentidir**.

Yirmi dört kurgu görev üç sınıfa ayrılmıştır ve her görev belirli modülleri ilgilendirir. Bir
görevin yanıtı olarak gelen yama, o modüllerden birini değiştirir ve yanına bir yardımcı dosya
bırakır. Denetimlerin erişimi bu iki parça arasında bölünecektir.

#### Üç Denetimin Erişimi

Üç denetim üç ayrı yere bakar. **Sınama koşumu** yalnız değişen modülü görür ve yalnız
sınamaların ölçtüğü davranışı görür. **Örüntü taraması** metne bakar, çalıştırmaz. **Varlık
denetimi** yalnız `import` satırlarına bakar. Üçünün birleşimi kod tabanının tamamı değildir ve
bu dersin ölçtüğü şey tam olarak aradaki boşluktur.

```python
HATA = [("H1", "tarife.py", "USTU = 16", "USTU = 11"),
        ("H2", "okuma.py", "if fark < 0:", "if fark < -100000:"),
        ("H3", "denetim.py", 'kayit["endeks"] < 0', 'kayit["endeks"] < -1'),
        ("H4", "ozet.py", 'top.get(k["bolge"], 0) + t', 'top.get(k["bolge"], 0) + 1'),
        ("H5", "okuma.py", "len(p) != 4", "len(p) < 4"),
        ("H6", "bicim.py", "rjust(9)", "rjust(7)")]
UYDURMA = ("olcum_araclari", "tarife_yardim", "bolge_ozet", "sayac_kit")
ORUNTU = ("eval(", "except:", "== None", "open(")
EK = {"eval(": "def cevir(ifade):\n    return eval(ifade)\n",
      "except:": "def tamsayi(s):\n    try:\n        return int(s)\n    except:\n        return 0\n",
      "== None": "def bos_mu(kayit):\n    return kayit == None\n",
      "open(": "def yedek(yol):\n    return open(yol).read()\n"}
STANDART = ("math", "json")


def bozuk(kod, hata):
    _, dosya, eski, yeni = hata
    yeni_kod = dict(kod)
    yeni_kod[dosya] = kod[dosya].replace(eski, yeni, 1)
    return yeni_kod


def uret(gorev, tohum=TOHUM):
    r = uretec(tohum ^ izno(gorev["ad"]))
    u = [r() for _ in range(6)]
    hata = HATA[int(u[1] * 6)] if u[0] < 0.46 else None
    ithal = UYDURMA[int(u[3] * 4)] if u[2] < 0.30 else "math"
    oru = ORUNTU[int(u[5] * 4)] if u[4] < 0.34 else None
    return {"kod": bozuk(KOD, hata) if hata else dict(KOD),
            "hata": hata[0] if hata else None, "ithal": ithal, "oru": oru,
            "yardim": "import " + ithal + "\n\n" + (EK[oru] if oru else "")}


KAYITLAR = [{"bolge": "dogu", "endeks": 120}, {"bolge": "yildiz", "endeks": 40},
            {"bolge": "bati", "endeks": 90}]


def sinama_kos(kod):
    a = yukle(kod)
    o, t, d, z, b = (a["okuma.py"], a["tarife.py"], a["denetim.py"],
                     a["ozet.py"], a["bicim.py"])
    dusen = []
    for ad, sonuc in (
            ("ayristir-alan", o["ayristir"]("A017;dogu;2026-01;41250") ==
             {"abone": "A017", "bolge": "dogu", "donem": "2026-01", "endeks": 41250}),
            ("ayristir-fazla", o["ayristir"]("A017;dogu;2026-01;41250;ek") is None),
            ("tuketim-donus", o["tuketim"](99800, 300) == 500),
            ("bedel-basamak", [t["bedel"](m) for m in (0, 10, 25, 40, 60)] ==
             [0, 40, 145, 310, 630]),
            ("gecerli-eksi", d["gecerli"]({"bolge": "dogu", "endeks": -1}) is False),
            ("ayikla-bolge", len(d["ayikla"](KAYITLAR)) == 2),
            ("toplam-bolge", z["bolge_toplam"](KAYITLAR, [12, 5, 8]) ==
             {"dogu": 12, "yildiz": 5, "bati": 8}),
            ("sayi-bolge", z["bolge_sayi"](KAYITLAR) ==
             {"dogu": 1, "yildiz": 1, "bati": 1}),
            ("bicim-satir", "dogu" in b["satir"]("dogu", 12, 48)),
            ("bicim-rapor", b["rapor"]("bas", ["a", "b"]).count("\n") == 2)):
        if not sonuc:
            dusen.append(ad)
    return dusen


def oruntu_tara(metin):
    return [o for o in ORUNTU if o in metin]


def bagimlilik_dene(metin, kod):
    yok = []
    for s in metin.split("\n"):
        if s.startswith("import "):
            a = s[7:].strip()
            if a + ".py" not in kod and a not in STANDART:
                yok.append(a)
    return yok


def olc(tohum=TOHUM):
    kusur = {"davranis": 0, "oruntu": 0, "uydurma": 0}
    yakalanan = {"sinama": 0, "oruntu": 0, "bagimlilik": 0}
    kacan, sessiz, isaretli = [], 0, 0
    for g in GOREV:
        a = uret(g, tohum)
        bayrak = 0
        if a["oru"]:
            kusur["oruntu"] += 1
            if oruntu_tara(a["yardim"]):
                yakalanan["oruntu"] += 1
                bayrak += 1
        if a["ithal"] in UYDURMA:
            kusur["uydurma"] += 1
            if bagimlilik_dene(a["yardim"], a["kod"]):
                yakalanan["bagimlilik"] += 1
                bayrak += 1
        if a["hata"]:
            kusur["davranis"] += 1
            if sinama_kos(a["kod"]):
                yakalanan["sinama"] += 1
                bayrak += 1
            else:
                kacan.append((g["ad"], a["hata"],
                              "isaretli" if bayrak else "temiz"))
                sessiz += bayrak == 0
        isaretli += bayrak > 0
    return kusur, yakalanan, kacan, sessiz, isaretli


print("taban ORUNTU bulgusu:", oruntu_tara("".join(KOD.values())) or "yok")
print("kusur  dosya        dusen sinama")
for h in HATA:
    print("%-6s %-12s %s" % (h[0], h[1], sinama_kos(bozuk(KOD, h)) or "yok"))
print()
print("tohum     | davranis oruntu uydurma | sinama oruntu bagimlilik"
      " | isaretli kacan sessiz")
sonuc = {}
for tohum in (TOHUM, TOHUM + 1):
    k, y, kc, ss, isr = olc(tohum)
    sonuc[tohum] = kc
    print("%d  | %8d %6d %7d | %6d %6d %10d | %8d %5d %6d"
          % (tohum, k["davranis"], k["oruntu"], k["uydurma"], y["sinama"],
             y["oruntu"], y["bagimlilik"], isr, len(kc), ss))
print("kacan kusur, tohum 20260218:", sonuc[TOHUM])
print("kacan kusur, tohum 20260219:", sonuc[TOHUM + 1] or "yok")
```

```
taban ORUNTU bulgusu: yok
kusur  dosya        dusen sinama
H1     tarife.py    ['bedel-basamak']
H2     okuma.py     ['tuketim-donus']
H3     denetim.py   ['gecerli-eksi']
H4     ozet.py      ['toplam-bolge']
H5     okuma.py     ['ayristir-fazla']
H6     bicim.py     yok

tohum     | davranis oruntu uydurma | sinama oruntu bagimlilik | isaretli kacan sessiz
20260218  |       11      8       9 |      9      8          9 |       16     2      1
20260219  |        6      9      12 |      6      9         12 |       17     0      0
kacan kusur, tohum 20260218: [('tamamlama-4', 'H6', 'isaretli'), ('aciklama-7', 'H6', 'temiz')]
kacan kusur, tohum 20260219: yok
```

İlk satır taramanın **temiz bir taban** üzerinde çalıştığını söylüyor: kod tabanının kendisinde
aranan dört dizgeden hiçbiri yok. Bulgu çıkarsa üretilen koddan çıkacak demektir; bu, tarama
sonuçlarını yorumlanabilir kılan önkoşuldur.

İkinci tablo bu dersin **koşumdan bağımsız** ölçüsüdür. Altı davranış kusuru tek tek kod tabanına
konur ve kabul sınaması koşturulur. Beşi tek bir sınamayı düşürüyor: kademeli bedel, sayaç
dönüşü, eksi endeks denetimi, bölge toplamı ve fazla alanlı satır. Altıncısı **hiçbir sınamayı
düşürmüyor**. Sebep sınamanın kendisindedir: biçim modülünü ölçen iki madde çıktının içinde bölge
adının geçmesine ve satır sayısına bakıyor, **sütun genişliğine** bakmıyor. Kusur oradadır ve
sınama oraya bakmaz. Bu sonuç tohumdan, görev dağılımından ve üretimden bağımsızdır.

#### Kalıntı ve İşaretin Yanıltıcılığı

Üçüncü tablo iki koşumu yan yana koyuyor. İlk koşumda yirmi dört yamada **11 davranış kusuru,
8 örüntü bulgusu ve 9 uydurma bağımlılık** var; toplam **28 kusur**. Örüntü taraması sekizin
sekizini, varlık denetimi dokuzun dokuzunu yakalıyor. Sınama koşumu on birin **dokuzunu**
yakalıyor. Toplamda 28 kusurun 26'sı görülüyor, **2'si kaçıyor** ve ikisi de biçim kusuru.

İkinci koşumda kaçan yoktur ve bu, denetimin iyileştiği anlamına gelmez. O koşumda hiç biçim
kusuru üretilmemiştir; üretilen altı davranış kusurunun altısı da sınamanın baktığı yerdedir.
Kaçan sayısı **kusurun dağılımına** bağlıdır, denetimin kapsamına değil. Kapsamı okuyan sayı
ikinci tablodadır ve orada altıda bir kusur örtüsüz durur. Bir denetimin gücü, iyi bir koşumda
verdiği sıfırla değil, **erişemediği sınıfın adıyla** ölçülür.

Son satır işaretin kendisini sorguluyor. Kaçan iki yamadan biri (`tamamlama-4`) aslında
**işaretlidir**: uydurma bir bağımlılık almış ve yardımcı dosyasında bir örüntü bulgusu var. Bu
yamaya bakan insan iki uyarı görür, ikisini de giderir ve yamayı kabul eder. Giderilenler
kusurdur, ama **kusurun tamamı değildir**; biçim hatası kabulle birlikte kod tabanına girer.
İkincisi (`aciklama-7`) hiç uyarı almaz ve doğrudan girer. Bedel sütunu da buradadır: ilk koşumda
**16 aday işaretlenir**, yani insanın bakması gereken yama sayısı yirmi dörtte on altıdır;
işaretsiz geçen sekiz yamanın **biri kusurludur**. İkinci koşumda işaretli sayı **17'ye** çıkar
ve elde edilen kazanç sıfırdır, çünkü o koşumda zaten kaçan yoktu. İnceleme yükü kusur sayısıyla
değil, **işaret sayısıyla** büyür.

#### Özet

- Kurgu kod tabanı beş modül ve 53 satırdır; doğru davranışı iki sayıyla sabitlenir, kademeli
  bedelde 630 ve sayaç dönüşünde 500.
- Üç denetim üç ayrı yere bakar: sınama koşumu değişen modülün davranışına, örüntü taraması
  metne, varlık denetimi yalnız içe aktarma satırlarına.
- Koşumdan bağımsız ölçü: altı davranış kusurunun beşi kabul sınamasını düşürür, biçim kusuru
  hiçbirini düşürmez, çünkü sınama sütun genişliğine bakmaz.
- İlk koşumda 28 kusurun 26'sı yakalanır, 2'si kaçar; ikinci koşumda kaçan sıfırdır ama bunun
  nedeni kapsamın değil kusur dağılımının değişmesidir.
- İşaretli aday sayısı yakalanan kusur sayısı değildir: kaçan iki yamadan biri başka bir kusur
  yüzünden işaretlidir ve uyarıları giderilerek kabul edilir.
- İnceleme bedeli işaret sayısıyla ölçülür; ilk koşumda 24 yamanın 16'sı insana gider ve
  işaretsiz geçen sekizden biri kusur taşır.

#### Sonraki Adım

Bu derste kabul sınaması **elle yazılmıştı** ve kapsamı bilinen bir büyüklüktü: on madde, beş
modül, bilinen bir kör nokta. Sınamayı yazmak da bir iştir ve aynı yardımcıya devredilebilecek
görevlerin en çok önerileni budur. Sonraki ders sınamayı üretilen tarafa geçirir ve aynı soruyu
sınamanın kendisine sorar: üretilen sınamalar kod tabanına konan altı kusurun kaçını yakalıyor,
kaç sınama bütün sürümlerde aynı sonucu verip hiçbir şey ayırt etmiyor ve üretilen belgede kaç
iddia makinece doğrulanabiliyor.

### Belge ve Test Üretimi

Source: https://academia.sh/tr/kurslar/model-apileri/belge-ve-test-uretimi

Üretilen sınama kümesinin ayırt etme gücünün ölçülmesi: kurgu kod tabanının altı bozuk sürümü üzerinde koşturulan on dört üretilmiş sınamanın ikisi temiz kodda düşüyor, kalan on ikinin dokuzu yedi sürümün hepsinde aynı sonucu veriyor ve yalnız üçü bir kusuru ayırt ediyor. Yakalama 3/6, havuzun tamamıyla ulaşılabilecek tavan 6/6, elle eklenen tek bir hiza maddesi 4/6 yapıyor. Üretilen belgede on iddia makinece denetlenebiliyor, altısı doğru, biri olmayan bir işlevi anlatıyor.

Önceki derste kabul sınaması **elle yazılmıştı**: on madde, bilinen bir kapsam, bilinen bir kör
nokta. Sınamanın kendisi de bir yazma işidir ve bir kod yardımcısına en sık devredilen görev
budur. Belge yazımı da öyledir. İkisinin ortak yanı, çıktının **doğrudan çalıştırılmaması**:
üretilen sınama koşulmadıkça, üretilen belge okunmadıkça yanlışlığı görünmez.

Bu ders o iki çıktıyı ölçülebilir kılar. Sınama için ölçüt **ayırt etme gücüdür**: kod tabanının
bozuk sürümlerini temiz sürümden ayırabiliyor mu. Belge için ölçüt **denetlenebilirliktir**:
iddianın doğruluğu koda bakılarak makinece sınanabiliyor mu. İki ölçüt de üretilen metnin
kendisine değil, onun **verdiği bilgiye** bakar.

- **YG39.** Kod tabanı **kurgudur** ve beş modül, **53 satırdır**. Hiçbir gerçek depo, paket ya
  da ürün değildir. Tohum **20260218**.
- **YG40.** Altı kusur kaynak metinde tek dizge değişimidir; her biri ayrı bir **sürüm** üretir.
  Temizle birlikte **yedi sürüm** vardır.
- **YG41.** Bir **sınama** (test) bir **gözlem noktası** ile bir **beklenen değerden** oluşur.
  Kümedeki gözlem havuzu yirmi bir noktadır.
- **YG42.** Üretilen küme, hiza noktası dışındaki **yirmiden on dört nokta** seçer ve beklenen değeri koddan okur.
  Okuma her zaman doğru değildir: bir pay **yanlış beklenti** taşır.
- **YG43. Yanlış beklentili sınama** temiz sürümde düşen sınamadır. Geçerlilik denetimi budur ve
  ayırt etme ölçümünden önce yapılır.
- **YG44. Hep geçen sınama**, yedi sürümün hepsinde aynı sonucu veren sınamadır. Bu, sınamanın
  değersiz olduğu anlamına gelmez; **bu altı kusura karşı bilgi taşımadığı** anlamına gelir.
- **YG45.** Üretilen küme çıktı biçimini **içerik ve satır sayısıyla** ölçer, **sütun
  genişliğiyle** ölçmez. Bu, önceki derste elle yazılan sınamanın da kör noktasıydı.
- **YG46.** Üretilen belge iki parçadır: işlev adı ve parametre sayısı taşıyan **denetlenebilir
  iddialar** ve modül başına bir **serbest cümle**. Serbest cümle makinece sınanamaz.
- **YG47.** Bu ders bir saldırı dersi değildir; koşan kod sınama, sayım ve doğrulamadır.

#### Yedi Sürüm ve Kusurun Göründüğü Yer

Ayırt etme gücünü ölçmek için ayırt edilecek bir şey gerekir. Kod tabanına konan altı kusur
bunu sağlar: her biri kaynak metinde tek bir dizgeyi değiştirir ve gözlemlenebilir bir sonucu
oynatır. Aşağıdaki blok altı sürümü kurar ve her kusurun **hangi gözlemde** göründüğünü basar.

```python
# KURGU kod tabani: olcum aginin kendi yardimci betikleri. Gercek bir depo,
# paket ya da urun degildir. Bes modul, 53 satir. Tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KOD = {
    "okuma.py": """
def ayristir(satir):
    p = satir.split(";")
    if len(p) != 4:
        return None
    if not p[3].lstrip("-").isdigit():
        return None
    return {"abone": p[0], "bolge": p[1], "donem": p[2], "endeks": int(p[3])}

def tuketim(onceki, simdiki):
    fark = simdiki - onceki
    if fark < 0:
        fark = fark + 100000
    return fark
""",
    "tarife.py": """
BASAMAK = ((10, 4), (25, 7), (40, 11))
USTU = 16

def bedel(m3):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    return top + kalan * USTU
""",
    "denetim.py": """
GECERLI_BOLGE = ("dogu", "bati", "kuzey", "guney", "merkez")

def gecerli(kayit):
    if kayit is None:
        return False
    if kayit["endeks"] < 0:
        return False
    return kayit["bolge"] in GECERLI_BOLGE

def ayikla(kayitlar):
    return [k for k in kayitlar if gecerli(k)]
""",
    "ozet.py": """
def bolge_toplam(kayitlar, tuketimler):
    top = {}
    for k, t in zip(kayitlar, tuketimler):
        top[k["bolge"]] = top.get(k["bolge"], 0) + t
    return top

def bolge_sayi(kayitlar):
    say = {}
    for k in kayitlar:
        say[k["bolge"]] = say.get(k["bolge"], 0) + 1
    return say
""",
    "bicim.py": """
def satir(bolge, m3, tutar):
    return bolge.ljust(8) + str(m3).rjust(7) + str(tutar).rjust(9)

def rapor(baslik, satirlar):
    return "\\n".join([baslik] + satirlar)
""",
}
HATA = [("H1", "tarife.py", "USTU = 16", "USTU = 11"),
        ("H2", "okuma.py", "if fark < 0:", "if fark < -100000:"),
        ("H3", "denetim.py", 'kayit["endeks"] < 0', 'kayit["endeks"] < -1'),
        ("H4", "ozet.py", 'top.get(k["bolge"], 0) + t', 'top.get(k["bolge"], 0) + 1'),
        ("H5", "okuma.py", "len(p) != 4", "len(p) < 4"),
        ("H6", "bicim.py", "rjust(9)", "rjust(7)")]
KAYITLAR = [{"bolge": "dogu", "endeks": 120}, {"bolge": "yildiz", "endeks": 40},
            {"bolge": "bati", "endeks": 90}]


def yukle(kod):
    ad = {}
    for dosya, kaynak in kod.items():
        alan = {}
        exec(kaynak, alan)
        ad[dosya] = alan
    return ad


def bozuk(kod, hata):
    _, dosya, eski, yeni = hata
    yeni_kod = dict(kod)
    yeni_kod[dosya] = kod[dosya].replace(eski, yeni, 1)
    return yeni_kod


def gozlem(kod):
    a = yukle(kod)
    return {"bedel60": a["tarife.py"]["bedel"](60),
            "donus": a["okuma.py"]["tuketim"](99800, 300),
            "eksi": a["denetim.py"]["gecerli"]({"bolge": "dogu", "endeks": -1}),
            "toplam": a["ozet.py"]["bolge_toplam"](KAYITLAR, [12, 5, 8])["dogu"],
            "fazla": a["okuma.py"]["ayristir"]("A017;dogu;2026-01;41250;ek") is None,
            "boy": len(a["bicim.py"]["satir"]("dogu", 12, 48))}


BOY = {d: len(k.strip().split("\n")) for d, k in KOD.items()}
TEMIZ = gozlem(KOD)
print("kod tabani:", BOY, "toplam", sum(BOY.values()), "satir")
print("temiz gozlem:", TEMIZ)
for h in HATA:
    b = gozlem(bozuk(KOD, h))
    print(h[0], h[1], {k: (TEMIZ[k], b[k]) for k in TEMIZ if TEMIZ[k] != b[k]})
```

```
kod tabani: {'okuma.py': 13, 'tarife.py': 13, 'denetim.py': 11, 'ozet.py': 11, 'bicim.py': 5} toplam 53 satir
temiz gozlem: {'bedel60': 630, 'donus': 500, 'eksi': False, 'toplam': 12, 'fazla': True, 'boy': 24}
H1 tarife.py {'bedel60': (630, 530)}
H2 okuma.py {'donus': (500, -99500)}
H3 denetim.py {'eksi': (False, True)}
H4 ozet.py {'toplam': (12, 1)}
H5 okuma.py {'fazla': (True, False)}
H6 bicim.py {'boy': (24, 22)}
```

Altı kusurun altısı da **gözlemlenebilir**. Hiçbiri gizli değildir, hiçbiri çalışma zamanında
hata fırlatmaz; her biri bir sayının ya da bir doğruluk değerinin yerini değiştirir. Bu, ölçümün
adil olmasını sağlar: bir kusur yakalanmıyorsa sebep kusurun görünmezliği değil, **sınamanın
oraya bakmamasıdır**.

Son satır bunun en açık örneğidir. Biçim kusuru yalnız **satır boyunda** görünür: yirmi dört
damgalık satır yirmi ikiye iner. Bölge adı yerindedir, sayılar doğrudur, satır sayısı aynıdır.
Bu kusuru yakalayan tek gözlem noktası satırın uzunluğunu ölçendir.

#### Üretilen Sınamanın Ayırt Etme Gücü

Yardımcıdan sınama istendiğinde ne gelir: yirmi gözlem noktasından on dördü ve her biri için
koddan okunmuş bir beklenen değer. Okuma çoğunlukla doğrudur, bir payı değildir. Üretilen küme
önce **geçerlilikten**, sonra **ayırt etme gücünden** geçirilir.

```python
def olcum(kod):
    a = yukle(kod)
    o, t, d, z, b = (a["okuma.py"], a["tarife.py"], a["denetim.py"],
                     a["ozet.py"], a["bicim.py"])
    return {"ayristir-tam": o["ayristir"]("A017;dogu;2026-01;41250")["endeks"],
            "ayristir-bos": o["ayristir"]("") is None,
            "ayristir-fazla": o["ayristir"]("A017;dogu;2026-01;41250;ek") is None,
            "ayristir-harf": o["ayristir"]("A017;dogu;2026-01;xx") is None,
            "tuketim-duz": o["tuketim"](100, 300),
            "tuketim-donus": o["tuketim"](99800, 300),
            "bedel-sifir": t["bedel"](0),
            "bedel-ilk": t["bedel"](10),
            "bedel-orta": t["bedel"](25),
            "bedel-ust": t["bedel"](60),
            "gecerli-yok": d["gecerli"](None),
            "gecerli-eksi": d["gecerli"]({"bolge": "dogu", "endeks": -1}),
            "gecerli-bolge": d["gecerli"]({"bolge": "yildiz", "endeks": 5}),
            "ayikla-bos": d["ayikla"]([]),
            "ayikla-uc": len(d["ayikla"](KAYITLAR)),
            "toplam-bolge": z["bolge_toplam"](KAYITLAR, [12, 5, 8]),
            "sayi-bos": z["bolge_sayi"]([]),
            "sayi-uc": z["bolge_sayi"](KAYITLAR),
            "satir-icerik": "dogu" in b["satir"]("dogu", 12, 48),
            "rapor-satir": b["rapor"]("bas", ["a", "b"]).count("\n"),
            "satir-boy": len(b["satir"]("dogu", 12, 48))}


HAVUZ = [a for a in olcum(KOD) if a != "satir-boy"]     # uretilen kume hizaya bakmaz
SURUM = [("temiz", KOD)] + [(h[0], bozuk(KOD, h)) for h in HATA]
TABLO = {ad: olcum(k) for ad, k in SURUM}


def saptir(v):
    if isinstance(v, bool):
        return not v
    if isinstance(v, int):
        return v + 30
    if isinstance(v, dict):
        return {}
    return [0]


def uret_sinama(tohum=TOHUM, n=14):
    r = uretec(tohum)
    kalan, secili = list(HAVUZ), []
    for _ in range(n):
        secili.append(kalan.pop(int(r() * len(kalan))))
    return [(ad, saptir(TABLO["temiz"][ad]) if r() < 0.14 else TABLO["temiz"][ad])
            for ad in secili]


def kos(kume, surum):
    return [ad for ad, bek in kume if TABLO[surum][ad] != bek]


def degerlendir(kume):
    yanlis = kos(kume, "temiz")
    saglam = [(ad, b) for ad, b in kume if ad not in yanlis]
    yakalanan = [h[0] for h in HATA if kos(saglam, h[0])]
    hep_gecen = [ad for ad, b in saglam
                 if not any(ad in kos(saglam, h[0]) for h in HATA)]
    return len(kume), len(yanlis), len(saglam), yakalanan, hep_gecen


print("surum sayisi:", len(SURUM), "| havuz:", len(HAVUZ), "olcum")
print("kume         | sinama yanlis saglam | yakalanan           | hep gecen")
for etiket, kume in (("tohum 218", uret_sinama(TOHUM)),
                     ("tohum 219", uret_sinama(TOHUM + 1)),
                     ("havuzun tumu", [(a, TABLO["temiz"][a]) for a in olcum(KOD)])):
    n, y, s_, yk, hg = degerlendir(kume)
    print("%-12s | %6d %6d %6d | %d/6 %-15s | %d"
          % (etiket, n, y, s_, len(yk), ",".join(yk), len(hg)))
kume = uret_sinama(TOHUM)
print("yanlis beklentili:", kos(kume, "temiz"))
print("hep gecen:", sorted(degerlendir(kume)[4]))
elle = kume + [("satir-boy", TABLO["temiz"]["satir-boy"])]
print("elle tek madde eklendikten sonra:", degerlendir(elle)[3])


def uret_belge(tohum=TOHUM):
    a = yukle(KOD)
    iddia = []
    for dosya in KOD:
        r = uretec(tohum ^ izno(dosya))
        for f in sorted(x for x in a[dosya]
                        if not x.startswith("__") and callable(a[dosya][x])):
            n = a[dosya][f].__code__.co_argcount
            iddia.append((dosya, f, n + 1 if r() < 0.22 else n))
        if r() < 0.40:
            iddia.append((dosya, "dogrula", 1))
    return iddia


def belge_dene(iddia):
    a = yukle(KOD)
    yok = [i[0] + ":" + i[1] for i in iddia if i[1] not in a[i[0]]]
    yanlis = [i[0] + ":" + i[1] for i in iddia if i[1] in a[i[0]]
              and a[i[0]][i[1]].__code__.co_argcount != i[2]]
    return yok, yanlis


print()
print("tohum     | denetlenir serbest | olmayan islev | yanlis sayi | dogru")
for tohum in (TOHUM, TOHUM + 1):
    ids = uret_belge(tohum)
    yok, yanlis = belge_dene(ids)
    print("%d  | %10d %7d | %13d | %11d | %5d"
          % (tohum, len(ids), len(KOD), len(yok), len(yanlis),
             len(ids) - len(yok) - len(yanlis)))
ids = uret_belge(TOHUM)
yok, yanlis = belge_dene(ids)
print("olmayan islev iddiasi:", yok, "| yanlis parametre sayisi:", yanlis)
```

```
surum sayisi: 7 | havuz: 20 olcum
kume         | sinama yanlis saglam | yakalanan           | hep gecen
tohum 218    |     14      2     12 | 3/6 H1,H2,H3        | 9
tohum 219    |     14      1     13 | 3/6 H1,H2,H4        | 10
havuzun tumu |     21      0     21 | 6/6 H1,H2,H3,H4,H5,H6 | 15
yanlis beklentili: ['bedel-sifir', 'ayikla-bos']
hep gecen: ['ayikla-uc', 'ayristir-bos', 'ayristir-harf', 'bedel-orta', 'gecerli-bolge', 'gecerli-yok', 'rapor-satir', 'satir-icerik', 'tuketim-duz']
elle tek madde eklendikten sonra: ['H1', 'H2', 'H3', 'H6']

tohum     | denetlenir serbest | olmayan islev | yanlis sayi | dogru
20260218  |         10       5 |             1 |           3 |     6
20260219  |         11       5 |             2 |           0 |     9
olmayan islev iddiasi: ['bicim.py:dogrula'] | yanlis parametre sayisi: ['denetim.py:ayikla', 'bicim.py:rapor', 'bicim.py:satir']
```

İlk satır on dört sınamanın **ikisinin temiz kodda düştüğünü** söylüyor: bedel hesabının sıfır
girdisi ve boş listeden süzme. Bunlar kusur bulmuyor, kusur **uyduruyor**. Kırmızı bir sınamayla
karşılaşan geliştirici için asıl tehlike buradadır: sınama yanlışken kodu ona uydurmak, çalışan
bir kodu bozmak demektir. Bu iki maddenin ayıklanması ölçümden önce gelen ve bedeli insan
zamanıyla ödenen bir iştir.

Kalan on iki sınamadan **dokuzu** yedi sürümün hepsinde aynı sonucu veriyor. Bunlar hatalı
değildir; boş liste süzmek, geçersiz bölge reddetmek ve rapor satır sayısını saymak akla
yatkın maddelerdir. Ama bu altı kusurun hiçbirine karşı bilgi taşımıyorlar. Bilgi taşıyan sınama
sayısı **üçtür** ve yakalama **3/6**'dır. On dört maddelik bir kümenin ayırt eden payı
**0,2143**, yani her yedi sınamadan biri buçuk.

İkinci koşum sayının kararlı olduğunu gösteriyor: on dört sınama, bir yanlış beklenti, on üç
sağlam, yine **3/6** yakalama ve on hep geçen. Yakalanan kusurların **kimliği** değişiyor
(ilk koşumda H3, ikincisinde H4), toplamı değişmiyor.

Üçüncü satır tavanı veriyor. Havuzun yirmi bir noktasının tamamı sınamaya çevrildiğinde yakalama
**6/6** olur ve hep geçen sayısı **15**'e çıkar. Bu, hep geçmenin bir kusur olmadığının kanıtıdır:
tam kapsamlı bir kümede bile maddelerin yedide beşi bu altı kusura karşı sessizdir. Ayırt etme
gücü **madde sayısıyla değil, doğru noktayla** gelir.

Son satır bunu tek bir hamlede gösteriyor. Üretilen kümeye elle **bir** madde eklenir — satırın
uzunluğunu ölçen madde — ve yakalama **3/6'dan 4/6'ya** çıkar. Bir sınamanın kattığı, on dört
sınamanın kattığından fazladır, çünkü o sınama hiçbirinin bakmadığı yere bakar.

#### Üretilen Belgenin Denetlenebilir Kısmı

Belge tarafında ölçüt farklıdır: doğruluk değil, **doğrulanabilirlik** önce gelir. Üretilen
belge modül başına bir serbest cümle ve işlev başına bir yapısal iddia içeriyor. Serbest cümleler
koda bakılarak sınanamaz; yapısal iddialar sınanabilir, çünkü işlevin var olup olmadığı ve kaç
parametre aldığı yüklenen ad alanından okunur.

İlk koşumda **on** denetlenebilir iddia ve **beş** serbest cümle var: on beş ifadenin
**0,6667**'si makinenin erişebildiği alanda. Denetlenen onun **altısı** doğru. Üçü işlevin
parametre sayısını bir fazla söylüyor, biri hiç var olmayan bir doğrulama işlevini anlatıyor.
İkinci koşumda on bir iddianın dokuzu doğru, ikisi olmayan işlev. İki koşumda da yanlış iddia
payı sıfır değildir ve yanlışın **iki ayrı türü** vardır: var olan bir şeyi yanlış anlatmak ve
**olmayan bir şeyi anlatmak**. İkincisi daha tehlikelidir, çünkü okuyucu belgede gördüğü işlevi
çağırmaya kalkar.

#### Özet

- Altı kusurun altısı da gözlemlenebilir; biçim kusuru yalnız satır boyunda görünür ve yirmi dört
  damgalık satırı yirmi ikiye indirir.
- Üretilen on dört sınamanın ikisi temiz kodda düşer: kusur bulmaz, kusur uydurur ve ayıklanması
  ölçümden önce gelen bir iştir.
- Kalan on iki sınamanın dokuzu yedi sürümün hepsinde aynı sonucu verir; bilgi taşıyan üç
  sınamayla yakalama 3/6'dır ve ikinci koşumda da 3/6 kalır.
- Havuzun tamamı 6/6 verir ama hep geçen sayısı 15'e çıkar: ayırt etme gücü madde sayısından
  değil, bakılan noktadan gelir.
- Elle eklenen tek bir hiza maddesi yakalamayı 4/6'ya çıkarır; bir doğru sınama on dört üretilmiş
  sınamadan fazla katar.
- Üretilen belgede on beş ifadenin onu makinece denetlenebilir, altısı doğrudur; yanlışın bir
  türü var olan işlevi yanlış anlatmak, diğeri olmayan bir işlevi anlatmaktır.

#### Sonraki Adım

İki derste de ölçülen şey **çıktının kalitesiydi**: yamanın doğruluğu, sınamanın ayırt etme gücü,
belgenin denetlenebilirliği. Bu ölçümlerin hepsi çıktı elde edildikten sonra yapılır ve hepsi
kusurun **kod tabanında** olduğunu varsayar. Oysa devrin iki ucunda daha sayılacak şey vardır.
Girdi ucunda modele gönderilen bağlamın içinde ne olduğu hiç sorulmadı: hangi alanlar sır
sınıfına giriyor ve bir süzgeç kaçını çıkarıyor. Çıktı ucunda ise kabul kararının kendisi hiç
sorgulanmadı: insan bir öneriyi kabul ettiğinde ne kadar sık haklı oluyor. Sonraki ders üç riski
tek tek sayar ve konuyu kapatır.

### Sınırlar ve Riskler

Source: https://academia.sh/tr/kurslar/model-apileri/sinirlar-ve-riskler

Yapay zekâ destekli geliştirmenin üç riskinin sayılması: yirmi dört istek paketindeki 456 bağlam satırının 168'i sır sınıfına giriyor, alan adına bakan süzgeç hepsini çıkarıyor ama serbest metinde kalan 12 ize erişemediği için kapsaması 0,9333'te kalıyor; üretilen kodun dokuzu var olmayan bir bağımlılık adı taşıyor; ve kabul edilen on dokuz önerinin onu kusurlu, yani kabul edilenlerdeki yanlış payı 0,5263 ile taban payı 0,4583'ün üzerinde.

Önceki iki ders üretilen çıktının kalitesini ölçtü: yamanın doğruluğu, sınamanın ayırt etme
gücü, belgenin denetlenebilirliği. Üçü de kusurun **kod tabanında** olduğunu varsayar ve
kusuru çıktı elde edildikten sonra arar. Devrin iki ucunda ise sayılmamış birer şey durur.
Girdi ucunda modele **ne gönderildiği**, çıktı ucunda ise **kabul kararının kendisi**.

Bu ders üç riski tek tek sayar: bağlama giren metinde kaç alan sır sınıfına giriyor ve bir
süzgeç kaçını çıkarıyor, üretilen kodda kaç bağımlılık adı var olmayan bir şeye işaret ediyor
ve kabul edilen önerilerin ne kadarı yanlış. Sır yönetiminin yordamı Uygulama Güvenliği ve
DevSecOps müfredatında, bağımlılık politikası ve bileşen analizi de aynı müfredatta ölçüldü;
ikisi de burada tekrarlanmaz. Eklenen tek şey **bu üç riskin sayısıdır**.

- **YG48.** Kod tabanı **kurgudur** ve beş modül, **53 satırdır**. Abone kayıtları, çalışma
  ayarları ve destek talepleri de kurgudur. Tohum **20260218**.
- **YG49.** Bu bir saldırı dersi değildir. **Koşan kod her zaman savunma tarafındadır**: sayım,
  sınıflandırma, süzgeç, varlık denetimi. Hiçbir sömürü kodu, yük, atlatma ya da yayımlama
  yordamı yazılmaz.
- **YG50. İstek paketi** bir göreve gönderilen bağlamın tamamıdır: görev satırı, dosya listesi,
  bir ila üç abone kaydı, çalışma ayarları ve bir destek talebi.
- **YG51.** Beş alan adı dört **sır sınıfına** eşlenir: kimlik, iletişim, konum ve erişim.
  Değerler kurgudur ve hiçbiri gerçek bir veri değildir.
- **YG52. Süzgeç alan adına bakar**: satırın anahtarı sır sınıfı tablosunda geçiyorsa satır
  çıkarılır. Yordam bundan ibarettir; anahtar yönetimi, maskeleme ve saklama ele alınmaz.
- **YG53. İz sözcüğü**, sır sınıfı alan adlarının ilk parçasıdır. Serbest metinde geçen iz,
  süzgecin göremediği sızıntıdır ve ayrı sayılır.
- **YG54. Uydurma bağımlılık**, `import` satırındaki adın kod tabanının modülleri arasında ya
  da izinli standart kitaplık adları arasında bulunmamasıdır. Uydurma adlar kurgudur ve hiçbir
  gerçek paket, depo ya da yayımlama yolu anılmaz.
- **YG55. Kusurlu öneri**, kod tabanının davranışını değiştiren bir öneridir. Kusur, tek bir
  karşılaştırma sınırının ya da tek bir sabitin değişmesidir.
- **YG56. Kabul**, geliştiricinin öneriyi olduğu gibi alma kararıdır. Karar bağlam örtüşmesine,
  görev sınıfına ve zorluğa bağlıdır; öneride kusur olup olmadığına **bakmaz**, çünkü bu kusurlar
  tek damgalık değişimlerdir. Bu varsayımın doğruluğu ölçümde ayrıca sınanır.
- **YG57.** Sayılar iki tohumda basılır; ikinci koşum tohumu **20260219**.

#### Bağlama Giren Sır Sınıfı Alanlar

Bir kod yardımcısına görev verirken gönderilen şey görev cümlesi değildir. Yanında dosya
listesi, örnek kayıtlar, çalışma ayarları ve çoğu zaman sorunun kaynağı olan bir kullanıcı metni
gider. Bu paket bir ağ üzerinden çıkar ve içinde ne olduğu **sayılmadıkça** bilinmez.

```python
# KURGU: olcum aginin bes modullu, 53 satirlik yardimci kod tabani ile abone
# kayitlari, calisma ayarlari ve destek talepleri. Hicbiri gercek degildir.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py")
GEREKEN = {0: ("okuma.py",), 1: ("tarife.py",), 2: ("denetim.py", "okuma.py"),
           3: ("ozet.py", "denetim.py"), 4: ("bicim.py", "ozet.py"),
           5: ("tarife.py", "okuma.py"), 6: ("ozet.py", "okuma.py", "tarife.py"),
           7: ("denetim.py", "bicim.py")}
GOREV = [{"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i],
          "zorluk": 0.05 * (i % 4)} for s in SINIF for i in range(8)]

SIR_ALAN = {"abone_kimlik": "kimlik", "iletisim": "iletisim", "adres": "konum",
            "erisim_dizgesi": "erisim", "oturum_anahtari": "erisim"}
IZ_SOZCUK = tuple(sorted({a.split("_")[0] for a in SIR_ALAN}))
ABONE = [{"abone_kimlik": "A0417", "iletisim": "hat-3", "adres": "dogu-12",
          "bolge": "dogu", "donem": "2026-01", "endeks": "41250"},
         {"abone_kimlik": "A0912", "adres": "bati-4",
          "bolge": "bati", "donem": "2026-01", "endeks": "38104"},
         {"abone_kimlik": "A1330", "iletisim": "hat-1",
          "bolge": "kuzey", "donem": "2026-01", "endeks": "50077"}]
AYAR = {"olcum_agi": "dogu", "zaman_asimi": "20", "kayit_yolu": "veri/olcum",
        "erisim_dizgesi": "ORNEK", "oturum_anahtari": "ORNEK"}
TALEP = ["adresim degisti yeni doneme kayit yapilsin",
         "iletisim bilgim sistemde yanlis gorunuyor",
         "sayac endeksi eksik girilmis duzeltilsin",
         "tarife basamagim yanlis hesaplanmis",
         "abone kaydim iki kere acilmis birlestirin",
         "kesinti sonrasi endeks okunmadi"]


def baglam(gorev, i):
    s = ["gorev: " + gorev["ad"], "dosya: " + ",".join(gorev["gereken"])]
    for k in ABONE[:1 + i % 3]:
        s += [a + ": " + d for a, d in k.items()]
    s += [a + ": " + d for a, d in AYAR.items()]
    s.append("talep: " + TALEP[i % len(TALEP)])
    return s


def sir_say(satirlar):
    say = {}
    for s in satirlar:
        sinif = SIR_ALAN.get(s.split(":")[0])
        if sinif:
            say[sinif] = say.get(sinif, 0) + 1
    return say


def suz(satirlar):
    return [s for s in satirlar if s.split(":")[0] not in SIR_ALAN]


def serbest_iz(satirlar):
    return sum(1 for s in satirlar if s.startswith("talep:")
               for w in IZ_SOZCUK if w in s)


toplam = {"satir": 0, "sir": 0, "kalan": 0, "iz": 0}
sinif_say = {}
for i, g in enumerate(GOREV):
    b = baglam(g, i)
    k = suz(b)
    toplam["satir"] += len(b)
    toplam["sir"] += len(b) - len(k)
    toplam["kalan"] += len(k)
    toplam["iz"] += serbest_iz(k)
    for s, n in sir_say(b).items():
        sinif_say[s] = sinif_say.get(s, 0) + n
print("iz sozcukleri:", IZ_SOZCUK)
print("baglam satiri:", toplam["satir"], "| suzuldukten sonra:", toplam["kalan"])
print("sir sinifi alan:", dict(sorted(sinif_say.items())), "toplam", toplam["sir"])
gecen = toplam["sir"] + toplam["iz"]
print("suzgecin cikardigi:", toplam["sir"], "| serbest metinde kalan iz:", toplam["iz"],
      "| kapsama: %.4f" % (toplam["sir"] / gecen))
print("ornek baglam (gorev 1), suzulmus:")
for s in suz(baglam(GOREV[0], 0)):
    print("  " + s)
```

```
iz sozcukleri: ('abone', 'adres', 'erisim', 'iletisim', 'oturum')
baglam satiri: 456 | suzuldukten sonra: 288
sir sinifi alan: {'erisim': 48, 'iletisim': 32, 'kimlik': 48, 'konum': 40} toplam 168
suzgecin cikardigi: 168 | serbest metinde kalan iz: 12 | kapsama: 0.9333
ornek baglam (gorev 1), suzulmus:
  gorev: tamamlama-1
  dosya: okuma.py
  bolge: dogu
  donem: 2026-01
  endeks: 41250
  olcum_agi: dogu
  zaman_asimi: 20
  kayit_yolu: veri/olcum
  talep: adresim degisti yeni doneme kayit yapilsin
```

Yirmi dört istek paketinde **456 bağlam satırı** var ve bunların **168'i** dört sır sınıfından
birine giriyor: kimlik 48, erişim 48, konum 40, iletişim 32. Yani gönderilen her üç satırdan
biraz fazlası, göreve hiçbir katkısı olmayan ama dışarı çıkan bir alandır. Bu oran **0,3684**
ve hiçbir yerde yazılı değildir; sayılmadan bilinmez.

Süzgeç yapısal alanların **hepsini** çıkarıyor: 168'in 168'i. Bu, kendi ölçütüne göre kusursuz
bir sonuçtur. Ama ölçüt yanlıştır. Süzgecin baktığı şey alan adıdır ve sır sınıfı bilgisi
yalnız alan adında durmaz. Serbest metinde kalan **12 iz** bunun kanıtıdır; süzgecin gerçek
kapsaması **0,9333**'tür. Örnek pakette bu apaçık görünüyor: `abone_kimlik`, `iletisim` ve
`adres` satırları temizlendikten sonra, en alttaki talep satırı hâlâ abonenin adresinden söz
ediyor. Yapısal alanı silmek, aynı bilgiyi taşıyan cümleyi silmez.

Süzgecin bedeli de aynı çıktıda okunuyor. Kalan kayıtta bölge, dönem ve endeks var, **abone
alanı yok**. Ayrıştırıcının dört sütunundan birincisi budur ve görev okuma modülünü
ilgilendiriyor. Sır sınıfı alanları çıkarmak, göreve gereken örneğin bir sütununu da götürür.

#### Uydurma Bağımlılık ve Kabul Kararı

İkinci ve üçüncü riskler çıktı tarafındadır. Üretilen kod bir bağımlılık adı taşıyabilir ve o
ad hiçbir şeye karşılık gelmeyebilir. Bunu görmenin yolu adı **denemek** değil, adın var olup
olmadığına bakmaktır: kod tabanının modülleri ve izinli standart kitaplık adları bilinen bir
kümedir, dışındaki her ad şüphelidir. Üçüncü risk ise ölçmesi en zor olanıdır, çünkü ölçülen
şey modelin çıktısı değil **insanın kararıdır**.

```python
UYDURMA = ("olcum_araclari", "tarife_yardim", "bolge_ozet", "sayac_kit")
ORUNTU = ("eval(", "except:", "== None", "open(")
STANDART = ("math", "json")
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def uret_kod(gorev, tohum=TOHUM):
    r = uretec(tohum ^ izno(gorev["ad"]))
    u = [r() for _ in range(6)]
    return {"kusurlu": u[0] < 0.46,
            "ithal": UYDURMA[int(u[3] * 4)] if u[2] < 0.30 else "math",
            "oru": ORUNTU[int(u[5] * 4)] if u[4] < 0.34 else None}


def varlik_denetimi(ad):
    return ad + ".py" not in DOSYA and ad not in STANDART


def yardimci(gorev, secim, tohum=TOHUM):
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(secim))))
    ortu = sum(1 for d in gorev["gereken"] if d in secim) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in secim if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    return {"kabul": r() < puan, "puan": puan,
            "belirtec": 40 + 26 * len(secim) + (18 if gorev["sinif"] == "donusturme" else 0)}


def olc(tohum=TOHUM):
    d = {"uydurma": 0, "ayri": set(), "oruntu": 0, "kusurlu": 0, "kabul": 0,
         "kabul_yanlis": 0, "ret_dogru": 0, "temiz_kabul": 0, "belirtec": 0}
    for g in GOREV:
        k = uret_kod(g, tohum)
        y = yardimci(g, g["gereken"], tohum)
        if varlik_denetimi(k["ithal"]):
            d["uydurma"] += 1
            d["ayri"].add(k["ithal"])
        d["oruntu"] += k["oru"] is not None
        d["kusurlu"] += k["kusurlu"]
        d["kabul"] += y["kabul"]
        d["belirtec"] += y["belirtec"]
        d["kabul_yanlis"] += y["kabul"] and k["kusurlu"]
        d["ret_dogru"] += (not y["kabul"]) and (not k["kusurlu"])
        d["temiz_kabul"] += y["kabul"] and not k["kusurlu"]
    return d


print("tohum     | uydurma ayri oruntu | kusurlu kabul kabul-yanlis"
      " | taban pay kabul pay | ret-dogru")
for tohum in (TOHUM, TOHUM + 1):
    d = olc(tohum)
    print("%d  | %7d %4d %6d | %7d %5d %12d | %9.4f %9.4f | %9d"
          % (tohum, d["uydurma"], len(d["ayri"]), d["oruntu"], d["kusurlu"],
             d["kabul"], d["kabul_yanlis"], d["kusurlu"] / 24,
             d["kabul_yanlis"] / d["kabul"], d["ret_dogru"]))
print("kabul orani | kusurlu oneride | temiz oneride")
for tohum in (TOHUM, TOHUM + 1):
    d = olc(tohum)
    ku, te = d["kusurlu"], 24 - d["kusurlu"]
    print("%d    | %-15s | %s"
          % (tohum, "%d/%d = %.4f" % (d["kabul_yanlis"], ku, d["kabul_yanlis"] / ku),
             "%d/%d = %.4f" % (d["temiz_kabul"], te, d["temiz_kabul"] / te)))
d = olc(TOHUM)
print("uydurma adlar:", sorted(d["ayri"]))
print("istek basina baglam belirteci:", d["belirtec"] // 24)
```

```
tohum     | uydurma ayri oruntu | kusurlu kabul kabul-yanlis | taban pay kabul pay | ret-dogru
20260218  |       9    4      8 |      11    19           10 |    0.4583    0.5263 |         4
20260219  |      12    4      9 |       6    19            5 |    0.2500    0.2632 |         4
kabul orani | kusurlu oneride | temiz oneride
20260218    | 10/11 = 0.9091  | 9/13 = 0.6923
20260219    | 5/6 = 0.8333    | 14/18 = 0.7778
uydurma adlar: ['bolge_ozet', 'olcum_araclari', 'sayac_kit', 'tarife_yardim']
istek basina baglam belirteci: 94
```

İkinci riskin sayısı ilk sütunlardadır. Yirmi dört üretilen parçanın **dokuzu** var olmayan bir
ada başvuruyor ve bunlar yalnız **dört ayrı ada** dağılıyor. İkinci koşumda sayı **12'ye**
çıkıyor, ayrı ad sayısı yine dört. Uydurma bağımlılık dağınık bir gürültü değildir: aynı küçük
ad kümesi tekrar tekrar üretilir, çünkü ad kod tabanının kendi adlandırma alışkanlığından
türetilir ve makul görünür. Varlık denetiminin ucuz olmasının nedeni de budur — karşılaştırılan
küme bellidir ve denetim bir dizge sınamasından ibarettir.

#### Aşırı Güvenin Sayısı

Üçüncü risk son sütunlarda okunur ve bu dersin en rahatsız edici sayısıdır. İlk koşumda yirmi
dört öneriden **11'i** kusurludur; taban pay **0,4583**. Geliştirici bu önerilerin **19'unu**
kabul eder. Kabul edilenlerin **10'u kusurludur**, yani kabul edilenlerdeki yanlış payı
**0,5263**. Kabul kararı, yanlış payını taban paya göre **düşürmemiştir**; hatta bu koşumda
biraz yükseltmiştir.

İkinci koşum aynı yapıyı daha düşük bir taban payla tekrarlıyor: kusurlu **6**, taban pay
**0,2500**, kabul yine **19**, kabul edilenlerdeki yanlış payı **0,2632**. İki koşumda da kabul
payı tabanın üzerinde ve iki sayı birbirine yakın. Buradan okunacak şey şudur: **kabul kararı
kusur hakkında bilgi taşımıyor.** Kabul edilenlerdeki yanlış oranı, öneri havuzundaki yanlış
oranıyla aynı yere düşüyor.

Son tablo bunu doğrudan sınıyor. Kusurlu önerilerde kabul oranı ilk koşumda **0,9091**, temiz
önerilerde **0,6923**; ikinci koşumda **0,8333** ve **0,7778**. Dört sayı da birbirine yakındır
ve kusurlu taraf hiçbir koşumda daha düşük değildir. Varsayım YG56 böylece sınanmış olur:
tek damgalık bir değişim hızlı bir okumada görülmüyor. Reddedilen beş öneriden **dördü** ise
temizdir; ret kararı da bilgi taşımaz, yalnız iş üretir.

Bedel üç yerde toplanır. Bağlam tarafında istek başına **94 belirteç** gider ve bunun bir payı
sır sınıfı alanlarıdır. Bağımlılık tarafında yirmi dört parçanın dokuzu incelemeye düşer.
Kabul tarafında ise bedel doğrudan kod tabanına yazılır: ilk koşumda **10 kusur** kabul edilmiş,
yani incelemeye giren yamaların içine geliştiricinin kendi kararıyla girmiştir. Önceki derste
kurulan üç denetim bu yüzden bir süs değildir; kabul kararının **arkasındaki** ikinci hattır.

#### Özet

- Yirmi dört istek paketinde 456 bağlam satırının 168'i dört sır sınıfına girer: kimlik 48,
  erişim 48, konum 40, iletişim 32.
- Alan adına bakan süzgeç yapısal alanların hepsini çıkarır ama serbest metindeki 12 ize
  erişemez; gerçek kapsama 0,9333'tür.
- Süzgecin bedeli görünürdür: abone alanı çıkarıldığında ayrıştırıcının dört sütunundan biri
  örnekten düşer.
- Üretilen yirmi dört parçanın dokuzu var olmayan bir bağımlılık adı taşır ve bunlar yalnız dört
  ayrı ada dağılır; ikinci koşumda sayı 12 olur, ayrı ad sayısı değişmez.
- Kabul edilen on dokuz önerinin onu kusurludur; kabul edilenlerdeki yanlış payı 0,5263, taban
  pay 0,4583, ikinci koşumda 0,2632 ve 0,2500.
- Kusurlu ve temiz önerilerde kabul oranları birbirine yakındır ve kusurlu taraf hiçbir koşumda
  daha düşük değildir: kabul kararı kusur hakkında bilgi taşımaz.

#### Sonraki Adım

Altı derste yardımcının kendisi ölçüldü: hangi görev sınıfında kabul edildiği, bağlamın neyi
kattığı ve nerede düşürdüğü, denetim noktasının hatayı nerede durdurduğu, üç denetimin neyi
yakaladığı, üretilen sınamanın neyi ayırt ettiği ve kabul kararının hiçbir şey ayırt etmediği.
Bu konu burada kapanır.

Kursun yirmi dersi boyunca sabit kalan bir şey vardı ve hiç sorgulanmadı: model her zaman
**uzakta** duran bir uç noktaydı. Çağrı ağa çıktı, sıraya girdi, hız sınırına takıldı, yarıda
kesildi, önbelleğe düştü ve belirteçle ödendi. Bağlam paketi de aynı yoldan çıktı ve içindeki
alanların sayılması gerekti. Uç noktayı **kendi donanımına** almak bütün bu sayıları başka bir
düzleme taşır: ağ gecikmesi ve hız sınırı gider, yerine bellek bütçesi, eşzamanlı istek sayısı
ve donanımın kendisi gelir. Sonraki konu bu takası ölçer ve ilk soruyu şöyle sorar: bir modeli
kendi barındırdığında bellekte tam olarak ne tutulur ve o bütçe kaç eşzamanlı isteğe yeter.

## Yerel Modeller ve Uyarlama

Modeli kendi donanımında çalıştırmanın ve uyarlamanın ödünleşimlerinin sayılması: parametre sayısı ile bağlam uzunluğunun bellekte tuttuğu sayı ve bütçenin yettiği eşzamanlı istek, basamak sayısı düştükçe düşen bellek ile isabetin düştüğü nokta ve hangi görevde önce düştüğü, aynı görevde istem düzeneği ile ince ayarın yan yana ölçülmesi ve ince ayarın kazanmadığı durum, tam güncelleme, katman dondurma ve düşük ranklı ekin güncellediği parametre payı ile isabet ve saklanan sayı adedi, büyük modelin çıktısıyla eğitilen küçük modelin kendi başına eğitilene göre kazandığı ve kapatamadığı açık, dört kullanım koşulu sınıfının bir senaryoda kapattığı dağıtım seçeneği.

### Kendi Barındırdığın Modeller

Source: https://academia.sh/tr/kurslar/model-apileri/kendi-barindirdigin-modeller

Modeli kendi donanımında çalıştırmanın biriminin belirteç değil bellek olması: üç kurgu ölçeğin ağırlık belleği 70,5 milyon, 367,5 milyon ve 2,14 milyar sayı, 960 belirteçlik bağlamda istek başına ara durum 11,8 milyon, 47,2 milyon ve 157,3 milyon sayı, üç milyar sayılık bütçenin yettiği eşzamanlı istek 248, 55 ve 5, aynı 120 kurgu talepte etiket isabeti 0,6333, 0,8167 ve 0,8667. Eşzamanlı istek ile isabetin çarpımı 157,1'den 4,3'e düşüyor, yani en büyük ölçek doğru yanıt kapasitesinin otuz altıda birini veriyor. Dağılım sıcaklığı sıfırken iki koşum aynı 0,8667'yi veriyor, 0,02'de 120 talebin 28'i koşumdan koşuma değişiyor.

Önceki yirmi derste model hep **uzakta** duran bir uç noktaydı. Ölçülen her şey o uç noktanın
yüzeyinden okundu: kaç çağrı gitti, kaç belirteç harcandı, kaç istek reddedildi, kaç yanıt yarıda
kesildi. Bütün bu sayıların ortak bir varsayımı vardı: modelin kendisi başkasının makinesinde
duruyor ve orada kaç isteğin aynı anda işlendiği **senin sorunun değil**.

Model kendi donanımına taşındığında bu varsayım düşer ve birim değişir. Artık harcanan şey belirteç
değil **bellek**tir ve bellek uzayan bir fatura değil **sabit bir tavan**dır. Bu ders o tavanı
sayar: bir ölçeğin ağırlıkları bellekte kaç sayı tutuyor, bir isteğin ara durumu kaç sayı ekliyor
ve verilmiş bir bütçe kaç **eşzamanlı isteğe** yetiyor. Eğitim tarafındaki bellek hesabı M27
Makine Öğrenmesi kursunun eğitim pratiği konusunda ölçüldü; o yordam burada tekrarlanmaz, yalnız
çıkarım tarafındaki karşılığı kurulur.

- **YM1.** Kod bir **benzeticidir**; gerçek bir model, çalışma zamanı ya da donanım çağrılmaz.
  Talepler ve ölçekler **kurgudur**, tohum **20260218**.
- **YM2.** Bellek **sayı adedi** olarak sayılır. Bir sayının kaç basamakla tutulduğu sonraki
  dersin konusudur ve burada sabit kabul edilir.
- **YM3.** Bir ölçek üç yapısal büyüklükle verilir: **katman sayısı**, **gizli genişlik** ve
  sözlük boyu. Parametre sayısı bunlardan hesaplanır.
- **YM4.** Benzeticinin kendi ağırlık tablosu küçüktür ve yalnız **isabet** üretmek içindir.
  Bellek hesabı ölçeklerin yapısal tarifinden yapılır, benzeticinin tablosundan değil.
- **YM5.** Ağırlık belleği isteklerden **bağımsızdır** ve tek kopyadır. **Ara durum** her istek
  için ayrıdır ve bağlam uzunluğuyla doğru orantılıdır.
- **YM6.** Ara durum her katmanda, bağlamdaki her belirteç için genişlik boyunda iki dizi tutar;
  yani istek başına iki çarpı katman çarpı genişlik çarpı bağlam sayı.
- **YM7.** Ölçek büyüdükçe benzeticinin **ayırt edici satır** sayısı artar (12, 26, 121). Bu,
  yeteneğin ölçekle arttığını modellemek içindir ve başka bir iddia taşımaz.
- **YM8.** Dağılım sıcaklığı sıfırken **en olası seçim** yapılır ve çıktı koşumdan koşuma aynıdır;
  sıfırın üstünde tohuma bağlı örnekleme yapılır.
- **YM9.** Bütçe üç milyar sayıdır; ağırlık ve ara durum **aynı** bütçeden karşılanır.
- **YM10.** Ölçülen birimler sayı adedi ve eşzamanlı istek sayısıdır; ham süre yazılmaz.

#### Üç Ölçek, Üç Yetenek

Benzetici bir metni beş damgalık parçalara böler ve her parça için bir **ağırlık satırı** tutar.
Satırın beş konu için de ortak bir tabanı vardır; ayırt edici olan, tabanın üstüne konu başına
eklenen **küçük farktır**. Model bir talebi okurken her konu için gördüğü en yüksek değeri alır ve
en yüksek puanlı konuyu seçer. Ölçek burada tek bir şeyi değiştirir: kaç parçanın ayırt edici bir
satırı olduğunu.

```python
# YEREL BENZETICI -- KURGUDUR. Gercek bir model, calisma zamani ya da donanim
# yoktur; bellek sayi adedi olarak sayilir.
import math

TOHUM, M32 = 20260218, 0xFFFFFFFF


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


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


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = {"fatura": ["bu ayki tutar gecen aya gore cok yuksek",
                    "odedim ama sistemde borc gorunuyor",
                    "ayrintili dokumu nereden gorebilirim"],
         "ariza": ["evde su akmiyor bir sorun var",
                   "baglanti bozuk oldu ve hic calismiyor",
                   "ariza kaydi actim ama ekip gelmedi"],
         "sayac": ["okuma yanlis girilmis endeks tutmuyor",
                   "cihaz degisimi icin randevu istiyorum",
                   "endeksi ile fatura ayni degil"],
         "tarife": ["hangi basamaktayim ogrenmek istiyorum",
                    "tarife degisikligi icin ne yapmaliyim",
                    "birim ucret abone tipine gore degisir mi"],
         "kesinti": ["mahallede elektrik yok ne zaman gelecek",
                     "planli duyuru nereden takip edilir",
                     "aksamdan beri kesinti yasiyoruz"]}
EK = ["ayrica gecen hafta da aradim", "kayit numarasi verildi",
      "ekip bilgi verecekti", "degisiklik talebim de var"]
TALEP = []                              # 120 KURGU destek talebi
for i in range(120):
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = KALIP[k][int(r() * 3)]
    if r() < 0.34:
        m += " " + EK[int(r() * 4)]
    TALEP.append({"no": 4001 + i, "konu": k, "metin": m})

GECIS = {}                              # parca hangi konunun kalibinda geciyor
for k, liste in KALIP.items():
    for m in liste:
        for t in set(belirtecle(m)):
            GECIS.setdefault(t, {})[k] = 1
for e in EK:
    for t in set(belirtecle(e)):
        GECIS.setdefault(t, {})

TABAN = 0.50                            # parcanin konudan bagimsiz ortak agirligi
AGIRLIK = {}
for i, t in enumerate(sorted(GECIS)):
    r = uretec(TOHUM + 7919 * (i + 1))
    satir = {k: TABAN for k in KONU}
    if GECIS[t]:
        for k in GECIS[t]:
            satir[k] = TABAN + 0.05 + 0.40 * r()    # ayirt edici kucuk fark
    else:
        satir[KONU[int(r() * 5)]] = TABAN + 0.02 + 0.10 * r()   # yaniltici bag
    AGIRLIK[t] = satir
SIRA = sorted(AGIRLIK, key=lambda t: (TABAN - max(AGIRLIK[t].values()), t))

OLCEK = {"kucuk": (12, 512, 12), "orta": (24, 1024, 26),
         "buyuk": (40, 2048, len(AGIRLIK))}         # katman, genislik, ayirt edici satir


def puan(metin, satir):
    ogrenilmis = set(SIRA[:satir])
    p = {k: TABAN for k in KONU}
    for t in belirtecle(metin):
        if t in ogrenilmis:
            for k in KONU:
                p[k] = max(p[k], AGIRLIK[t][k])
    return p


def yanitla(metin, olcek, sicaklik=0.0, tohum=TOHUM):
    p = puan(metin, OLCEK[olcek][2])
    if sicaklik <= 0.0:
        return max(sorted(p), key=lambda a: p[a])   # en olasi secim
    u = [math.exp((p[k] - max(p.values())) / sicaklik) for k in KONU]
    return KONU[ayrik(uretec(tohum ^ izno(metin))(), [x / sum(u) for x in u])]


print("sozluk", len(AGIRLIK), "parca ; ornek talep:", TALEP[0]["metin"])
print("olcek   isabet")
for ad in OLCEK:
    d = sum(yanitla(x["metin"], ad) == x["konu"] for x in TALEP)
    print(f"{ad:<7} {d / 120:.4f}")
print("\nsicaklik  tohum 20260218  tohum 20260219")
for s in (0.0, 0.02):
    a, b = (sum(yanitla(x["metin"], "buyuk", s, t) == x["konu"]
                for x in TALEP) / 120 for t in (TOHUM, TOHUM + 1))
    print(f"{s:>8.2f}  {a:>14.4f}  {b:>14.4f}")
```

```
sozluk 121 parca ; ornek talep: planli duyuru nereden takip edilir
olcek   isabet
kucuk   0.6333
orta    0.8167
buyuk   0.8667

sicaklik  tohum 20260218  tohum 20260219
    0.00          0.8667          0.8667
    0.02          0.8167          0.8583
```

İlk tablo ölçeğin ne satın aldığını söylüyor. Küçük ölçek yüz yirmi talebin **0,6333**'ünü doğru
konuya atıyor, orta **0,8167**, büyük **0,8667**. Aradaki fark yeteneğin kendisi değil, kaç ayrımın
öğrenilmiş olduğudur: küçük ölçek yalnız on iki parçanın hangi konuya işaret ettiğini biliyor,
kalan yüz dokuz parça onun için birbirinin aynı.

İkinci tablo, kendi barındırmanın uzak uç noktada bulunmayan bir yanını gösteriyor. Dağılım
sıcaklığı sıfırken iki ayrı tohum aynı **0,8667**'yi veriyor; hiçbir talebin yanıtı değişmiyor.
Sıcaklık 0,02'ye çıktığında aynı iki koşum **0,8167** ve **0,8583** veriyor. Örnekleme ayarı
sağlayıcının elinde değil senin elindedir; belirlenimcilik bir talep değil bir **yapılandırma**
olur. Bu, sonraki bölümlerdeki sayıların koşumdan koşuma sabit kalmasının da gerekçesidir.

#### Bellek Bütçesi ve Eşzamanlı İstek

Bellek iki ayrı kalemden oluşur ve ikisi çok farklı davranır. **Ağırlık belleği** modelin
parametrelerini tutar; kaç istek gelirse gelsin tek kopyadır ve değişmez. **Ara durum** her isteğin
kendi bağlamı için tutulur; istek sayısıyla ve bağlam uzunluğuyla birlikte büyür. Bütçe ikisini de
karşılamak zorundadır, yani eşzamanlı istek sayısı bütçeden ağırlık düşüldükten sonra kalanla
belirlenir.

```python
BUTCE, SOZLUK = 3_000_000_000, 32000    # bellek butcesi ve KURGU yapisal sozluk
BAGLAM = (240, 960, 3840)


def parametre(L, H):
    return 12 * L * H * H + 2 * SOZLUK * H


def ara_durum(L, H, baglam):
    return 2 * L * H * baglam


print("olcek   agirlik(sayi)  ara durum/istek  esz.istek  isabet  kapasite")
for ad, (L, H, satir) in OLCEK.items():
    a, d = parametre(L, H), ara_durum(L, H, 960)
    i = sum(yanitla(x["metin"], ad) == x["konu"] for x in TALEP) / 120
    e = max(0, (BUTCE - a) // d)
    print(f"{ad:<7} {a:>13} {d:>16} {e:>10} {i:>7.4f} {e * i:>9.1f}")
print("\nolcek   " + "  ".join(f"baglam {b:>4}" for b in BAGLAM))
for ad, (L, H, satir) in OLCEK.items():
    a = parametre(L, H)
    e = [max(0, (BUTCE - a) // ara_durum(L, H, b)) for b in BAGLAM]
    print(f"{ad:<7} " + "  ".join(f"{x:>11}" for x in e))
print("\n120 istegin tur sayisi (baglam 960):")
for ad, (L, H, satir) in OLCEK.items():
    e = max(0, (BUTCE - parametre(L, H)) // ara_durum(L, H, 960))
    print(f"  {ad:<7} esz.istek {e:>4}  tur {-(-120 // e):>3}")
print("butce 2000000000 sayiya inerse buyuk olcek yuklenemez:",
      parametre(40, 2048) > 2_000_000_000)
```

```
olcek   agirlik(sayi)  ara durum/istek  esz.istek  isabet  kapasite
kucuk        70516736         11796480        248  0.6333     157.1
orta        367525888         47185920         55  0.8167      44.9
buyuk      2144337920        157286400          5  0.8667       4.3

olcek   baglam  240  baglam  960  baglam 3840
kucuk           993          248           62
orta            223           55           13
buyuk            21            5            1

120 istegin tur sayisi (baglam 960):
  kucuk   esz.istek  248  tur   1
  orta    esz.istek   55  tur   3
  buyuk   esz.istek    5  tur  24
butce 2000000000 sayiya inerse buyuk olcek yuklenemez: True
```

İlk sütun ölçekler arasındaki mesafeyi veriyor: ağırlık belleği **70,5 milyon**, **367,5 milyon**
ve **2,14 milyar** sayı. Genişlik iki katına çıktığında katman parametreleri **dörde** katlanıyor,
çünkü her katmanın parametre sayısı genişliğin karesiyle büyüyor. Katman sayısının etkisi ise
doğrusaldır. Bu iki büyüme hızının farkı, ölçek seçiminin niçin kademeli değil sıçramalı olduğunu
açıklıyor.

İkinci sütun daha az sezgiseldir. Ara durum genişliğin **karesiyle değil kendisiyle** büyür, ama
bağlam uzunluğuyla doğru orantılıdır. Büyük ölçekte 960 belirteçlik bir bağlam istek başına
**157,3 milyon** sayı ister; bu, aynı ölçeğin ağırlıklarının on üçte biri kadardır. On üç eşzamanlı
istek, ikinci bir model yüklemekle aynı belleği tüketir.

#### Bütçenin Dayattığı Seçim

Eşzamanlı istek sütunu tabloyu bir tercihe dönüştürüyor. Üç milyar sayılık bütçe, 960 belirteçlik
bağlamda küçük ölçekte **248**, orta ölçekte **55**, büyük ölçekte **5** isteği aynı anda
taşıyabiliyor. Büyük ölçeğe geçmek isabeti 0,8167'den 0,8667'ye çıkarıyor; kazanç **0,0500**. Aynı
adımın bedeli eşzamanlı istekte **onda bire** düşmektir.

Son sütun bu iki sayıyı tek ölçüte indiriyor. Eşzamanlı istek ile isabetin çarpımı, bütçenin aynı
anda üretebildiği **doğru yanıt kapasitesidir**: küçük ölçekte **157,1**, ortada **44,9**, büyükte
**4,3**. En büyük ölçek en yüksek isabeti veriyor ve doğru yanıt kapasitesinin **otuz altıda
birini** üretiyor. Hangi sütunun kazandığı iş yüküne bağlıdır: gelen talep sayısı bütçenin
taşıyabileceğinin altındaysa isabet sütunu, üstündeyse kapasite sütunu belirleyicidir. Bu, uzak bir
uç noktada hiç sorulmayan bir sorudur, çünkü orada eşzamanlılık sağlayıcının bütçesinden karşılanır
ve fatura yalnız belirteç olarak görünür.

İkinci tablo aynı takası bağlam ekseninde gösteriyor. Bağlam 240'tan 3840'a çıktığında eşzamanlı
istek her ölçekte on altıda birine iniyor; büyük ölçekte **1**'e, yani sıraya girmeye. Bağlam
uzunluğu bir kalite ayarı gibi görünür ama yerel bir kurulumda **doğrudan bir kapasite ayarıdır**.

Son satır tavanın sert yanını yazıyor. Bütçe iki milyar sayıya inerse büyük ölçek yüklenemez;
eşzamanlı istek sayısı düşmez, **sıfır** olur. Uzak bir uç noktada aşırı yük bir hız sınırı yanıtı
üretir ve yeniden denemeyle karşılanır; yerel bir kurulumda karşılık **hiç başlamamaktır**. İki
başarısızlığın biçimi aynı değildir ve ikincisinin yeniden denemesi yoktur.

#### Eşzamanlılık Bir Gecikme Sınıfıdır

Eşzamanlı istek sayısı tek başına bir kapasite ölçüsüdür; bir iş yüküne uygulandığında bir
**gecikme sınıfına** dönüşür. Yüz yirmi kurgu talebin tamamı sıraya konduğunda küçük ölçek hepsini
**tek turda** karşılıyor, orta ölçek **üç**, büyük ölçek **yirmi dört** tur istiyor. Tur sayısı
ham süre değildir ve donanıma göre değişmez; bütçe ile ara durumun oranından çıkan, koşumdan
koşuma sabit bir sayıdır. Son sıradaki talebin ne kadar beklediğini ölçmek için ihtiyaç duyulan
şey de budur: yirmi dört turluk bir kuyruk, tek turluk bir kuyrukla aynı gecikme sınıfında değildir.

Çalışma zamanı seçimi bu tabloda hangi sütuna dokunur, hangisine dokunamaz sorusu da buradan
yanıtlanır. Ağırlık sütunu ölçeğin yapısal tarifinden gelir ve hangi çalışma zamanının seçildiğine
bağlı değildir. Çalışma zamanının değiştirebildiği tek kalem **ara durumun nasıl tutulduğudur**:
istekler arasında ortak olan bağlam parçasının paylaşılıp paylaşılmadığı, biten bir isteğin yerinin
hemen boşaltılıp boşaltılmadığı, bir turda kaç isteğin birlikte işlendiği. Bunların hepsi ikinci
sütunu, dolayısıyla eşzamanlı istek ve tur sayısını oynatır. Bir çalışma zamanını bir başkasıyla
karşılaştırmanın ölçülebilir biçimi de bu iki sayıyı aynı bütçe ve aynı bağlam uzunluğunda yan
yana koymaktır; ad değil, sütun karşılaştırılır.

#### Özet

- Kendi barındırmada birim belirteç değil **sayı adedi**dir; bellek uzayan bir fatura değil sabit
  bir tavandır.
- Ağırlık belleği tek kopyadır ve isteklerden bağımsızdır; ara durum her istek için ayrıdır ve
  bağlam uzunluğuyla doğru orantılı büyür.
- Üç kurgu ölçeğin ağırlığı 70,5 milyon, 367,5 milyon ve 2,14 milyar sayı; genişlik iki katına
  çıktığında katman parametreleri dörde katlanır.
- Üç milyar sayılık bütçe 960 belirteçlik bağlamda 248, 55 ve 5 eşzamanlı isteğe yetiyor; isabet
  0,6333, 0,8167 ve 0,8667.
- Eşzamanlı istek ile isabetin çarpımı 157,1'den 4,3'e düşüyor: en yüksek isabetli ölçek doğru
  yanıt kapasitesinin otuz altıda birini veriyor.
- Dağılım sıcaklığı sıfırken iki koşum aynı 0,8667'yi veriyor; belirlenimcilik yerel kurulumda bir
  yapılandırma kararıdır.

#### Sonraki Adım

Bu dersin bütün hesabı tek bir kabule dayanıyordu: bellek **sayı adedi** olarak sayıldı ve bir
sayının bellekte ne kadar yer tuttuğu sabit varsayıldı. Bu kabul kaldırılabilir. Bir sayı daha az
basamakla tutulursa aynı parametre sayısı daha az yer kaplar, aynı bütçeye daha büyük bir ölçek ya
da daha çok eşzamanlı istek sığar. Karşılığında modelin dayandığı **küçük farklar** kabalaşır ve
bu dersin ağırlık satırlarında ayırt edici olan şey tam olarak o küçük farklardı. Sonraki ders
basamak sayısını üç düzeyde düşürür ve iki sayıyı yan yana basar: bellek ne kadar düşüyor, isabet
hangi noktada ve **hangi görevde önce** düşüyor.

### Nicemleme

Source: https://academia.sh/tr/kurslar/model-apileri/nicemleme

Bir ağırlığın kaç basamakla tutulduğunun bellek ve isabet üzerindeki etkisinin aynı 120 kurgu talepte ölçülmesi: 16 basamakta ağırlık belleği 34,3 milyar basamak ve eşzamanlı istek 5, 8 basamakta 17,2 milyar ve 24, 4 basamakta 8,6 milyar ve 62. Beş sınıflı konu ataması 0,8667'den 8 basamakta 0,8750'de kalıyor, 4 basamakta 0,8000'e, 3 basamakta 0,6333'e, 2 basamakta 0,2083'e düşüyor; iki sınıflı aciliyet ayrımı aynı düzeylerde 0,9417, 0,9333, 0,8583 ve 0,3583. Ortalama karar farkı beş sınıfta 0,1597, iki sınıfta 0,2665 olduğu için ince ayrım önce gidiyor. 121 satırın ayırt edici farkı 4 basamakta 24 satırda, 3 basamakta 53 satırda tamamen siliniyor.

Önceki derste bellek **sayı adedi** olarak sayıldı ve bir sayının bellekte ne kadar yer tuttuğu
sabit kabul edildi. Bu kabul bir seçimdir, bir zorunluluk değil. Aynı ağırlık daha az basamakla
tutulabilir; o zaman parametre sayısı değişmeden bellek küçülür, aynı bütçeye daha çok eşzamanlı
istek sığar ve önceki dersin son tablosundaki tavan yükselir.

Karşılığı da aynı yerdedir. Önceki dersin ağırlık satırlarında ayırt edici olan şey ortak taban
değil, tabanın üstüne konu başına eklenen **küçük farktı**. Basamak sayısı düştükçe temsil
edilebilir değerler seyrekleşir ve bir noktadan sonra o küçük farklar aynı değere yuvarlanır. Bu
ders üç basamak düzeyini yan yana koyar ve iki soruyu ayrı ayrı yanıtlar: bellek ne kadar düşüyor,
**isabet hangi noktada** ve **hangi görevde önce** düşüyor.

- **YM11.** Kod bir **benzeticidir**; önceki dersin benzeticisi kısaltılarak yeniden kurulur.
  Talepler **kurgudur**, tohum **20260218**.
- **YM12. Nicemleme burada tek bir işlemdir:** sıfır ile iki arası, basamak sayısının verdiği eşit
  adıma bölünür ve her ağırlık en yakın adıma yuvarlanır. Ölçülen tek büyüklük **basamak
  sayısıdır**.
- **YM13.** Bellek **basamak** olarak sayılır: ağırlık belleği parametre sayısı çarpı basamak
  sayısıdır. Ara durum da aynı basamak sayısıyla tutulur.
- **YM14.** Bütçe 48 milyar basamaktır; bu, önceki dersin üç milyar sayılık bütçesinin 16
  basamaktaki karşılığıdır. Ölçek sabittir ve önceki dersin büyük ölçeğidir.
- **YM15.** Aynı yanıt **üç çözünürlükte** okunur: beş sınıflı konu ataması, üç sınıflı ekip
  yönlendirmesi (ücret, saha, sayaç) ve iki sınıflı aciliyet ayrımı. Eşlemeler **kurgudur**.
- **YM16. Fark**, bir kararın sağlamlığıdır: seçilen konunun puanı ile en yakın rakibin puanı
  arasındaki uzaklık. Üç görevde rakibin tanımı farklıdır, bu yüzden fark da farklıdır.
- **YM17.** Dağılım sıcaklığı sıfırdır; bütün sayılar koşumdan bağımsızdır. Belirsizliğin yerine
  **fark dağılımı** ölçülür.
- **YM18.** Eşitlik alfabetik sırayla çözülür. Bütün ağırlıklar aynı değere yuvarlandığında model
  tek bir etikete çöker.
- **YM19.** Basamak sayısı yalnız ağırlıkları etkiler; belirteçleme, sözlük ve görev tanımları
  değişmez.
- **YM20.** Eşzamanlı istek sayısı önceki dersin hesabıyla aynıdır; değişen tek girdi bir sayının
  kaç basamak tuttuğudur.

#### Basamak Sayısı Bellekte Neyi Serbest Bırakır

Nicemlemenin bellek tarafı doğrusaldır ve tartışmasızdır: basamak yarıya inerse ağırlık belleği
yarıya iner. İlginç olan ikinci etkidir. Ara durum da aynı basamak sayısıyla tutulduğu için bütçe
iki yerden birden serbest kalır ve eşzamanlı istek sayısı basamak sayısı düştükçe **basamağın
oranından daha hızlı** büyür: ağırlıklar bütçeden bir kere düşülür, kalanın tamamı isteklere gider.

```python
# YEREL BENZETICI -- KURGUDUR. Onceki dersin benzeticisi kisaltilarak kurulur.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = {"fatura": ["bu ayki tutar gecen aya gore cok yuksek",
                    "odedim ama sistemde borc gorunuyor",
                    "ayrintili dokumu nereden gorebilirim"],
         "ariza": ["evde su akmiyor bir sorun var",
                   "baglanti bozuk oldu ve hic calismiyor",
                   "ariza kaydi actim ama ekip gelmedi"],
         "sayac": ["okuma yanlis girilmis endeks tutmuyor",
                   "cihaz degisimi icin randevu istiyorum",
                   "endeksi ile fatura ayni degil"],
         "tarife": ["hangi basamaktayim ogrenmek istiyorum",
                    "tarife degisikligi icin ne yapmaliyim",
                    "birim ucret abone tipine gore degisir mi"],
         "kesinti": ["mahallede elektrik yok ne zaman gelecek",
                     "planli duyuru nereden takip edilir",
                     "aksamdan beri kesinti yasiyoruz"]}
EK = ["ayrica gecen hafta da aradim", "kayit numarasi verildi",
      "ekip bilgi verecekti", "degisiklik talebim de var"]
TALEP = []                              # 120 KURGU destek talebi
for i in range(120):
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = KALIP[k][int(r() * 3)]
    if r() < 0.34:
        m += " " + EK[int(r() * 4)]
    TALEP.append({"no": 4001 + i, "konu": k, "metin": m})

GECIS = {}
for k, liste in KALIP.items():
    for m in liste:
        for t in set(belirtecle(m)):
            GECIS.setdefault(t, {})[k] = 1
for e in EK:
    for t in set(belirtecle(e)):
        GECIS.setdefault(t, {})

TABAN, AGIRLIK = 0.50, {}
for i, t in enumerate(sorted(GECIS)):
    r = uretec(TOHUM + 7919 * (i + 1))
    satir = {k: TABAN for k in KONU}
    if GECIS[t]:
        for k in GECIS[t]:
            satir[k] = TABAN + 0.05 + 0.40 * r()
    else:
        satir[KONU[int(r() * 5)]] = TABAN + 0.02 + 0.10 * r()
    AGIRLIK[t] = satir

GRUP = {"fatura": "ucret", "tarife": "ucret", "ariza": "saha",     # ekip yonlendirmesi
        "kesinti": "saha", "sayac": "sayac"}
ACIL = {"fatura": "normal", "tarife": "normal", "sayac": "normal",  # aciliyet ayrimi
        "ariza": "acil", "kesinti": "acil"}


def nicem(x, b):
    """Sifir ile iki arasi, 2**b - 1 esit adima bolunur; en yakin adima yuvarlanir."""
    a = 2.0 / (2 ** b - 1)
    return round(x / a) * a


def puan(metin, b):
    p = {k: nicem(TABAN, b) for k in KONU}
    for t in belirtecle(metin):
        if t in AGIRLIK:
            for k in KONU:
                p[k] = max(p[k], nicem(AGIRLIK[t][k], b))
    return p


def sec(p):
    return max(sorted(p), key=lambda a: p[a])


PARAMETRE, ARA, BUTCE = 2144337920, 157286400, 48_000_000_000

print("bas    adim  agirlik(basamak)  esz.istek  bes sinif  uc sinif  iki sinif")
for b in (16, 12, 8, 6, 5, 4, 3, 2):
    a5 = a3 = a2 = 0
    for x in TALEP:
        s = sec(puan(x["metin"], b))
        a5 += s == x["konu"]
        a3 += GRUP[s] == GRUP[x["konu"]]
        a2 += ACIL[s] == ACIL[x["konu"]]
    e = max(0, (BUTCE // b - PARAMETRE) // ARA)
    print(f"{b:>3} {2.0 / (2 ** b - 1):>7.5f} {PARAMETRE * b:>17} {e:>10}"
          f" {a5 / 120:>10.4f} {a3 / 120:>9.4f} {a2 / 120:>10.4f}")
```

```
bas    adim  agirlik(basamak)  esz.istek  bes sinif  uc sinif  iki sinif
 16 0.00003       34309406720          5     0.8667    0.8667     0.9417
 12 0.00049       25732055040         11     0.8667    0.8667     0.9417
  8 0.00784       17154703360         24     0.8750    0.8750     0.9417
  6 0.03175       12866027520         37     0.8500    0.8750     0.9417
  5 0.06452       10721689600         47     0.8417    0.8667     0.9333
  4 0.13333        8577351680         62     0.8000    0.9083     0.9333
  3 0.28571        6433013760         88     0.6333    0.7583     0.8583
  2 0.66667        4288675840        138     0.2083    0.3583     0.3583
```

Tablonun üç ana satırı 16, 8 ve 4 basamaktır. Bellek **34,3 milyardan**
17,2 milyara, oradan 8,6 milyar basamağa iniyor; tam olarak dörtte bir. Eşzamanlı istek ise
5'ten 24'e, oradan **62**'ye çıkıyor: on iki katı. Bu orantısızlık YM13'ten gelir. Ağırlık bütçeden
bir kez düşülür ve 16 basamakta bütçenin neredeyse tamamını yer; basamak azaldıkça ağırlığın payı
küçülür ve kalanın **tamamı** isteklere gider.

İsabet sütunları aynı hızda gitmiyor. Beş sınıflı konu ataması 16 basamakta **0,8667**, sekiz
basamakta **0,8750** — yani ilk yarılanma isabette ölçülebilir bir iz bırakmıyor. Altı ve beş
basamakta 0,8500 ve 0,8417 ile hafifçe geriliyor. Dört basamakta **0,8000**, üç basamakta
**0,6333**, iki basamakta **0,2083**. Son satır bir isabet değil bir çöküştür: 0,2083, benzeticinin
alfabetik olarak ilk etikete düşme oranıdır.

#### Farkın Adımın Altında Kalması

Bu düşüşün nedeni tahmin edilecek bir şey değil, hesaplanacak bir şeydir. Bir kararın sağlamlığı
**farktır**: seçilen konunun puanı ile en yakın rakibinin puanı arasındaki uzaklık. Yuvarlama bu
uzaklığı ancak adım kadar oynatabilir; fark adımdan büyükse karar yerinde kalır, küçükse
kaybolabilir. Aşağıdaki iki ölçü de koşumdan bağımsızdır ve isabet ölçülmeden önce bakılabilir.

```python
def farklar(b):
    f = {"bes sinif": [], "uc sinif": [], "iki sinif": []}
    for x in TALEP:
        p = puan(x["metin"], b)
        v = sorted(p.values(), reverse=True)
        s = sec(p)
        f["bes sinif"].append(v[0] - v[1])
        f["uc sinif"].append(p[s] - max(p[k] for k in KONU if GRUP[k] != GRUP[s]))
        f["iki sinif"].append(p[s] - max(p[k] for k in KONU if ACIL[k] != ACIL[s]))
    return f


print("gorev      ortalama fark   farki adimin altinda kalan pay (bas 8 / 4 / 3)")
for ad, f in farklar(16).items():
    o = [sum(1 for x in f if x < 2.0 / (2 ** b - 1)) / 120 for b in (8, 4, 3)]
    print(f"{ad:<10} {sum(f) / 120:>13.4f}   " + "   ".join(f"{x:.4f}" for x in o))
print("\nbas  tablodaki ayri deger  ayrimi silinen satir (121 satirda)")
for b in (16, 8, 4, 3, 2):
    d = {nicem(w, b) for s in AGIRLIK.values() for w in s.values()}
    z = sum(1 for s in AGIRLIK.values() if len({nicem(w, b) for w in s.values()}) == 1)
    print(f"{b:>3} {len(d):>20} {z:>27}")
print("\n'endek' satiri basamak duzeylerinde:")
for b in (16, 8, 4, 3):
    print(f"  {b:>2} " + " ".join(f"{k}={nicem(AGIRLIK['endek'][k], b):.4f}"
                                  for k in KONU))
```

```
gorev      ortalama fark   farki adimin altinda kalan pay (bas 8 / 4 / 3)
bes sinif         0.1597   0.0167   0.4167   0.7250
uc sinif          0.1995   0.0167   0.2750   0.6667
iki sinif         0.2665   0.0083   0.2000   0.4500

bas  tablodaki ayri deger  ayrimi silinen satir (121 satirda)
 16                  133                           0
  8                   55                           0
  4                    4                          24
  3                    2                          53
  2                    1                         121

'endek' satiri basamak duzeylerinde:
  16 fatura=0.5000 ariza=0.5000 sayac=0.7095 tarife=0.5000 kesinti=0.5000
   8 fatura=0.5020 ariza=0.5020 sayac=0.7059 tarife=0.5020 kesinti=0.5020
   4 fatura=0.5333 ariza=0.5333 sayac=0.6667 tarife=0.5333 kesinti=0.5333
   3 fatura=0.5714 ariza=0.5714 sayac=0.5714 tarife=0.5714 kesinti=0.5714
```

İlk tablo, isabet tablosunun sırasını **isabete bakmadan** açıklıyor. Ortalama fark beş sınıflı
görevde **0,1597**, üç sınıflıda 0,1995, iki sınıflıda **0,2665**. Görev kabalaştıkça rakip
uzaklaşır, çünkü fatura ile tarife arasındaki karışıklık ekip yönlendirmesini bozmaz ve arıza ile
kesinti arasındaki karışıklık aciliyeti bozmaz. Aynı yanıt, kaba okunduğunda daha sağlam bir
karardır.

Sağdaki üç sütun bunu düzey düzey sayıyor. Sekiz basamakta adım 0,00784 ve kayıtların yalnız
**0,0167**'sinde fark bu adımın altında; isabetin bu düzeyde oynamaması bu yüzden beklenen bir
sonuçtur. Dört basamakta adım 0,13333'e çıkıyor ve beş sınıflı görevde kayıtların **0,4167**'si
kırılgan hâle geliyor, iki sınıflı görevde ise **0,2000**'i. Üç basamakta oranlar 0,7250 ile
0,4500. Kırılganlık payının sırası isabetin düşme sırasıyla aynıdır ve bu sıra basamak düşürmeden
önce hesaplanabilir.

İkinci tablo mekanizmayı gösteriyor. 121 satırın 605 ağırlığı 16 basamakta **133** ayrı değer
taşıyor; sekiz basamakta 55'e iniyor ama hiçbir satır ayrımını kaybetmiyor. Dört basamakta
temsil edilebilir değer sayısı **4**'e düşüyor ve **24 satırın** beş konu için tuttuğu değerler
birbirine eşitleniyor; o satırlar artık hiçbir şey ayırt etmiyor. Üç basamakta bu sayı 53, iki
basamakta 121, yani tablonun tamamı. Nicemleme ağırlıkları küçültmez, **birbirinden ayırt edilemez
hâle getirir**; silinen şey büyüklük değil ayrımdır.

Son blok tek bir satırda aynı şeyi gösteriyor. Sayaç okumasına işaret eden `endek` parçası 16
basamakta sayaç için 0,7095, öbür dört konu için 0,5000 taşıyor; ayrım 0,2095. Sekiz basamakta
0,7059 ile 0,5020, ayrım 0,2039 — neredeyse aynı. Dört basamakta değerler 0,6667 ile 0,5333'e
oturuyor ve ayrım 0,1334'e iniyor. Üç basamakta beş değer de **0,5714**; satır artık sayacı
işaret etmiyor. Ağırlıkların hiçbiri sıfırlanmadı, hiçbiri anlamlı ölçüde küçülmedi; yalnız
aralarındaki uzaklık temsil edilemez hâle geldi.

#### İsabetin Düştüğü Nokta

Tablonun okunacak yeri dört ile üç basamak arasıdır. Sekizden dörde inerken beş sınıflı isabet
0,0750 geriliyor ve bellek yarıya iniyor; dörtten üçe inerken isabet **0,1667** geriliyor ve bellek
yalnız dörtte bir daha azalıyor. Bedelin eğrisi ile kazancın eğrisi burada kesişiyor: dört basamak
altında kazanılan her basamak, öncekinden daha pahalıya geliyor.

Hangi görevin önce düştüğü sorusunun yanıtı da tablodadır. Dört basamakta beş sınıflı ayrım
0,8667'den **0,8000**'e düşerken üç sınıflı ekip yönlendirmesi 0,8667 ile 0,9083 arasındaki bandın
içinde kalıyor ve iki sınıflı aciliyet ayrımı 0,9417'den yalnız **0,9333**'e iniyor. İki basamak
daha aşağıda, üç basamakta, kaba görevler de düşüyor ama beş sınıflı görevin çok gerisinden:
0,7583 ve 0,8583. Kural şudur: **ince ayrım önce gider.** Aynı nicemlenmiş model, bir talebi hangi
ekibe yollayacağını hâlâ bilirken hangi konuya ait olduğunu bilemez hâle gelmiştir.

Bunun tasarımdaki karşılığı doğrudandır. Bir kurulumda basamak sayısını düşürmenin
kabul edilebilir olup olmadığı modele değil **göreve** bağlıdır. Aynı ağırlıklar üstünde iki iş
yürüyorsa, kaba olanı dört basamakla çalıştırmak ile ince olanı dört basamakla çalıştırmak aynı
karar değildir. Ölçülmesi gereken de tek bir isabet değil, **her görev için ayrı** bir isabettir.

#### Özet

- Nicemleme burada bir aralığın eşit adımlara bölünmesidir; ölçülen tek büyüklük basamak sayısıdır
  ve bellek parametre sayısı çarpı basamak olarak yazılır.
- Ağırlık belleği 16 basamakta 34,3 milyar, 8 basamakta 17,2 milyar, 4 basamakta 8,6 milyar; aynı
  bütçedeki eşzamanlı istek 5'ten 24'e ve 62'ye çıkıyor, çünkü ağırlık bütçeden bir kez düşülür.
- Beş sınıflı isabet 8 basamağa kadar 0,8667 bandında kalıyor, 4 basamakta 0,8000, 3 basamakta
  0,6333, 2 basamakta 0,2083'e düşüyor; son satır isabet değil alfabetik çöküştür.
- Ortalama karar farkı beş sınıfta 0,1597, iki sınıfta 0,2665; farkı adımın altında kalan pay 4
  basamakta 0,4167 ile 0,2000 ve bu sıra isabetin düşme sırasını basamak düşürmeden önce veriyor.
- 605 ağırlık 4 basamakta 4 ayrı değere iniyor ve 24 satır bütün ayrımını kaybediyor; nicemleme
  büyüklüğü değil ayrımı siler.
- İsabetin düştüğü nokta dört ile üç basamak arasıdır ve önce düşen görev beş sınıflı konu
  atamasıdır; kaba görevler iki basamak daha dayanıyor.

#### Sonraki Adım

Bu iki derste ağırlıklar hep **verilmiş** kabul edildi. Ölçek seçildi, basamak sayısı düşürüldü,
bellek ve isabet yan yana yazıldı; ama ağırlıkların kendisine hiç dokunulmadı. Oysa yerel bir
kurulumun uzak bir uç noktada bulunmayan asıl imkânı budur: ağırlıklar elinde olduğu için
**değiştirilebilirler**. Kendi verinle birkaç yüz örnek üstünde eğitim sürdürülürse modelin bu
göreve isabeti yükselebilir. Yükselir mi, ne kadar yükselir ve aynı kazanç isteme birkaç cümle
eklemekle zaten alınabiliyor muydu — bunlar ölçülmedi. Sonraki ders aynı görevde **istem düzeneği**
ile **ince ayarı** yan yana koyar, bedeli örnek sayısı ve koşum sayısıyla yazar ve ince ayarın
**kazanmadığı** bir noktayı gösterir.

### İnce Ayar

Source: https://academia.sh/tr/kurslar/model-apileri/ince-ayar

Aynı etiketli örneklerin isteme konmasıyla ağırlıklara işlenmesinin aynı 60 kurgu sınama kaydında yan yana ölçülmesi: düzeneksiz taban 0,6000, dört örnekle ince ayar hiçbir ağırlığı oynatmıyor ve 0,6000'de kalıyor, sekiz örnekte 0,7333 ile istem düzeneğinin 0,6500'ünü geçiyor, on altı örnekte 0,8833. Otuz iki örnekte iki yol 0,9000 ile 0,9500 bandında örtüşüyor, altmış örnekte istem düzeneği 0,9667 veriyor ve ince ayar 0,9500'de kalıyor: ince ayar kazanmıyor. Bedel iki ayrı birimdedir; istem düzeneği istek başına bağlamı 28,48'den 623,48 belirtece, yani 21,9 katına çıkarıyor, ince ayar bir kerelik 180 güncelleme adımı ve 605 ağırlığın 0,2992 payını oynatıyor.

Önceki iki derste ağırlıklar hep verilmiş kabul edildi: ölçek seçildi, basamak sayısı düşürüldü,
bellek ve isabet yan yana yazıldı. Ağırlıkların kendisine dokunulmadı. Oysa yerel bir kurulumun
uzak bir uç noktada bulunmayan asıl imkânı budur; ağırlıklar elinde olduğu için değiştirilebilirler.

İkinci dersin sonundaki tablo bir seçim dayatmıştı: bütçe küçük ölçeği seçtirdiğinde bu görevdeki
isabet düşük kalıyor. Bunu yükseltmenin iki yolu var ve ikisi de **aynı şeye** ihtiyaç duyuyor,
etiketli örneğe. Birinci yol örnekleri **isteme koymaktır**; her istekle birlikte modele birkaç
çözülmüş talep gösterilir. İkinci yol örnekleri **ağırlığa işlemektir**; model bir kez eğitilir ve
istem kısa kalır. Bu ders ikisini aynı örnek sayısında yan yana ölçer ve ince ayarın **kazanmadığı**
noktayı gösterir. Önceden eğitim ile ince ayarın iki aşamalı yapısı Makine Öğrenmesi kursunun
mimariler konusunda ve Yapay Zekâ Mühendisliğine Giriş kursunun dil modelleri konusunda ele
alındı; o ayrım burada tekrarlanmaz, yalnız iki yolun sayısı karşılaştırılır.

- **YM21.** Kod bir **benzeticidir**; talepler **kurgudur**, tohum **20260218**. Ölçek önceki
  derslerin **küçük** ölçeğidir, çünkü bütçe onu seçtirdi.
- **YM22.** 120 kurgu talebin ilk 60'ı **eğitim havuzu**, son 60'ı **sınama kümesidir**. Sınama
  kümesine hiçbir düzenek dokunmaz.
- **YM23. İstem düzeneği:** seçilen örnekler isteme konur. Bağlamdaki bir örnek, kendi parçalarına
  kendi konusu için **geçici** bir destek verir; destek istekten isteğe taşınmaz.
- **YM24. İnce ayar:** aynı örnekler üzerinde **hata güdümlü** güncelleme. Yalnız yanlış bilinen
  örneklerde ağırlık oynar ve oynayan ağırlık **kalıcıdır**.
- **YM25.** Koşum sayısı, eğitim kümesinin baştan sona kaç kez geçildiğidir; güncelleme adımı
  sayısı örnek sayısı çarpı koşum sayısıdır.
- **YM26.** İki yol **aynı örnekleri** kullanır. Karşılaştırma eşit etiketli örnek sayısındadır;
  değişen tek şey örneğin nereye konduğudur.
- **YM27.** İki koşum, örneklerin **iki ayrı çekilişidir** (tohum 20260218 ve 20260219). Altmış
  örnekte iki çekiliş aynı kümeyi verir, bu yüzden orada fark sıfırdır.
- **YM28. Kazanç kuralı:** bir yolun üstünlüğü iki çekilişin **ikisinde de** aynı yönde değilse
  ölçülmemiş sayılır.
- **YM29.** Bedel iki ayrı birimdedir: istem düzeneği **istek başına belirteç**, ince ayar **bir
  kerelik örnek ve koşum sayısı**.
- **YM30.** Ağırlık tablosu 121 satır çarpı beş konu, yani **605 ağırlıktır**; ince ayarın
  oynattığı kayıt sayısı bunun içinden sayılır.

#### Aynı Örnekler, İki Ayrı Yer

Benzetici önceki derslerinkiyle aynı; değişen tek şey, puanın üstüne bir **düzeltme tablosu**
eklenebilmesi. Düzeltme istemden geliyorsa geçicidir ve o isteğin bağlamıyla birlikte gider;
eğitimden geliyorsa kalıcıdır ve istem kısa kalır. İkisinin de girdisi aynı etiketli örneklerdir.

```python
# YEREL BENZETICI -- KURGUDUR. Onceki derslerin benzeticisi kisaltilarak kurulur.
TOHUM, M32 = 20260218, 0xFFFFFFFF


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
KALIP = {"fatura": ["bu ayki tutar gecen aya gore cok yuksek",
                    "odedim ama sistemde borc gorunuyor",
                    "ayrintili dokumu nereden gorebilirim"],
         "ariza": ["evde su akmiyor bir sorun var",
                   "baglanti bozuk oldu ve hic calismiyor",
                   "ariza kaydi actim ama ekip gelmedi"],
         "sayac": ["okuma yanlis girilmis endeks tutmuyor",
                   "cihaz degisimi icin randevu istiyorum",
                   "endeksi ile fatura ayni degil"],
         "tarife": ["hangi basamaktayim ogrenmek istiyorum",
                    "tarife degisikligi icin ne yapmaliyim",
                    "birim ucret abone tipine gore degisir mi"],
         "kesinti": ["mahallede elektrik yok ne zaman gelecek",
                     "planli duyuru nereden takip edilir",
                     "aksamdan beri kesinti yasiyoruz"]}
EK = ["ayrica gecen hafta da aradim", "kayit numarasi verildi",
      "ekip bilgi verecekti", "degisiklik talebim de var"]
TALEP = []                              # 120 KURGU destek talebi
for i in range(120):
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    m = KALIP[k][int(r() * 3)]
    if r() < 0.34:
        m += " " + EK[int(r() * 4)]
    TALEP.append({"no": 4001 + i, "konu": k, "metin": m})

GECIS = {}
for k, liste in KALIP.items():
    for m in liste:
        for t in set(belirtecle(m)):
            GECIS.setdefault(t, {})[k] = 1
for e in EK:
    for t in set(belirtecle(e)):
        GECIS.setdefault(t, {})

TABAN, AGIRLIK = 0.50, {}
for i, t in enumerate(sorted(GECIS)):
    r = uretec(TOHUM + 7919 * (i + 1))
    satir = {k: TABAN for k in KONU}
    if GECIS[t]:
        for k in GECIS[t]:
            satir[k] = TABAN + 0.05 + 0.40 * r()
    else:
        satir[KONU[int(r() * 5)]] = TABAN + 0.02 + 0.10 * r()
    AGIRLIK[t] = satir

SATIR = 12                              # kucuk olcek: butcenin sectigi olcek
OGRENILMIS = set(sorted(AGIRLIK,
                        key=lambda t: (TABAN - max(AGIRLIK[t].values()), t))[:SATIR])
EGITIM, SINAMA = TALEP[:60], TALEP[60:]
YONERGE = "Talebi su etiketlerden birine ata: fatura ariza sayac tarife kesinti . "


def puan(metin, duzeltme=None):
    """Taban puan ogrenilmis satirlarin en yuksek degeri; duzeltme ustune eklenir."""
    parca = belirtecle(metin)
    p = {k: TABAN for k in KONU}
    for t in parca:
        if t in OGRENILMIS:
            for k in KONU:
                p[k] = max(p[k], AGIRLIK[t][k])
    for t in parca:
        for k in KONU:
            p[k] += (duzeltme or {}).get((t, k), 0.0)
    return max(sorted(p), key=lambda a: p[a])


def olc(duzeltme=None):
    return sum(puan(x["metin"], duzeltme) == x["konu"] for x in SINAMA) / 60


print("egitim havuzu", len(EGITIM), "kayit ; sinama", len(SINAMA), "kayit")
print("taban isabet (duzeneksiz kucuk olcek):", f"{olc():.4f}")
print("yonerge belirteci:", len(belirtecle(YONERGE)),
      "; ortalama talep belirteci:",
      round(sum(len(belirtecle(x["metin"])) for x in SINAMA) / 60, 2))
```

```
egitim havuzu 60 kayit ; sinama 60 kayit
taban isabet (duzeneksiz kucuk olcek): 0.6000
yonerge belirteci: 18 ; ortalama talep belirteci: 10.48
```

Taban **0,6000**. Bu, ikinci dersin sonunda bütçenin dayattığı ölçeğin bu görevdeki hâlidir ve iki
yolun da aşması gereken sayıdır. Ortalama bir talep 10,48 belirteç, yönerge 18 belirteç; yani
düzeneksiz bir istek yaklaşık 28 belirteçtir. Bu sayı istem düzeneğinin bedelini okurken ölçü
olacak.

#### Örnek Sayısı Arttıkça

Aşağıdaki kod aynı örnek kümesini iki yere de koyar ve yalnız sınama kümesinde ölçer. Örnekler
eğitim havuzundan iki ayrı çekilişle seçilir; ikinci çekiliş kazancın ölçülmüş sayılıp
sayılmayacağına karar vermek içindir.

```python
ORNEK, ADIM = 0.30, 0.05                # baglamdan gelen destek ve ince ayar adimi


def sec_ornek(n, tohum):
    r, h = uretec(tohum), list(range(60))
    for i in range(59, 0, -1):
        j = int(r() * (i + 1))
        h[i], h[j] = h[j], h[i]
    return [EGITIM[i] for i in sorted(h[:n])]


def baglamdan(ornekler):                # isteme konan ornekler: gecici destek
    return {(t, o["konu"]): ORNEK for o in ornekler for t in belirtecle(o["metin"])}


def egit(ornekler, gecis):              # hata gudumlu guncelleme; agirliklar kalici
    D = {}
    for _ in range(gecis):
        for o in ornekler:
            s = puan(o["metin"], D)
            if s != o["konu"]:
                for t in belirtecle(o["metin"]):
                    D[(t, o["konu"])] = D.get((t, o["konu"]), 0.0) + ADIM
                    D[(t, s)] = D.get((t, s), 0.0) - ADIM
    return D


print(" n  istem A  istem B  ayar k=1  ayar k=3  ayarB k=3  istem bel  oynayan")
for n in (4, 8, 16, 32, 60):
    a, b = sec_ornek(n, TOHUM), sec_ornek(n, TOHUM + 1)
    ia, ib = olc(baglamdan(a)), olc(baglamdan(b))
    y1, y3, yb = olc(egit(a, 1)), olc(egit(a, 3)), olc(egit(b, 3))
    bel = sum(len(belirtecle(o["metin"])) for o in a)
    print(f"{n:>2}  {ia:.4f}   {ib:.4f}   {y1:.4f}    {y3:.4f}     {yb:.4f}"
          f"     {bel:>6}  {len(egit(a, 3)):>7}")

print("\nn=60 sabit , kosum sayisi degisiyor:")
print("  k   isabet  guncelleme adimi  oynayan kayit")
for k in (1, 2, 3, 6, 10):
    D = egit(sec_ornek(60, TOHUM), k)
    print(f" {k:>2}   {olc(D):.4f}  {60 * k:>16}  {len(D):>13}")

ort = sum(len(belirtecle(x["metin"])) for x in SINAMA) / 60
bel60 = sum(len(belirtecle(o["metin"])) for o in sec_ornek(60, TOHUM))
gi = len(belirtecle(YONERGE)) + bel60 + ort
ga = len(belirtecle(YONERGE)) + ort
D60 = egit(sec_ornek(60, TOHUM), 3)
print(f"\nistek basina baglam: istem duzenegi {gi:.2f} , ince ayar {ga:.2f} belirtec"
      f" ({gi / ga:.1f} kat)")
print(f"ince ayarin bedeli n=60 , k=3: {60 * 3} guncelleme adimi , {len(D60)} kayit ,"
      f" 605 agirligin {len(D60) / 605:.4f} payi")
```

```
 n  istem A  istem B  ayar k=1  ayar k=3  ayarB k=3  istem bel  oynayan
 4  0.5667   0.6500   0.6000    0.6000     0.7333         38        0
 8  0.6500   0.6667   0.7333    0.7333     0.8000         73       35
16  0.8333   0.7500   0.8833    0.8833     0.8667        138       49
32  0.9000   0.9500   0.8500    0.9167     0.9000        292      101
60  0.9667   0.9667   0.9333    0.9500     0.9500        595      181

n=60 sabit , kosum sayisi degisiyor:
  k   isabet  guncelleme adimi  oynayan kayit
  1   0.9333                60            121
  2   0.9333               120            162
  3   0.9500               180            181
  6   0.9500               360            181
 10   0.9500               600            181

istek basina baglam: istem duzenegi 623.48 , ince ayar 28.48 belirtec (21.9 kat)
ince ayarin bedeli n=60 , k=3: 180 guncelleme adimi , 181 kayit , 605 agirligin 0.2992 payi
```

En üstteki satır iki yolun da işe yaramadığı yerdir. Dört örnekle ince ayar **hiçbir ağırlığı
oynatmıyor**: oynayan kayıt sayısı **0**, çünkü model o dört örneği zaten doğru biliyordu ve hata
güdümlü güncellemenin tetiklenmesi için bir hata gerekiyor. İsabet tabanda, 0,6000'de kalıyor. Aynı
dört örnek isteme konduğunda ise isabet **0,5667**'ye **düşüyor**; bağlamdaki dört örnek, sınama
kayıtlarının bir bölümünü kendi konularına doğru çekiyor. İkinci çekilişte aynı iki sayı 0,6500 ve
0,7333, yani yön bile aynı değil. Dört örnekle ölçülmüş hiçbir şey yoktur.

Sekiz ve on altı örnekte ince ayar açık ara önde. Sekizde **0,7333** ve **0,8000**, istem
düzeneğinin iki çekilişteki en iyisi olan 0,6667'nin üstünde; on altıda **0,8833** ve 0,8667,
istem düzeneğinin 0,8333 ve 0,7500'ünün üstünde. Her iki çekilişte de aynı yönde olduğu için bu
üstünlük ölçülmüş sayılır. Nedeni yapısaldır: hata güdümlü güncelleme örneği **birden çok kez**
kullanır ve yalnız yanlış bilinen yerleri düzeltir, bağlama konan örnek ise bir kez okunur ve
doğru bildiği yerleri de oynatır.

#### İnce Ayarın Kazanmadığı Nokta

Otuz iki örnekte tablo dönüyor. İnce ayar üç koşumla **0,9167** ve **0,9000** veriyor, istem
düzeneği **0,9000** ve **0,9500**. Bantlar örtüşüyor ve iki çekilişte üstünlük aynı yöne bakmıyor;
YM28'e göre burada ölçülmüş bir kazanç yoktur. Aynı satırda tek koşumluk ince ayar **0,8500**, yani
istem düzeneğinin iki değerinin de altında. Koşum sayısını üçe çıkarmak 0,0667 kazandırıyor ve bu, örnek
eklemekten değil **aynı örneği yeniden geçmekten** gelen bir kazançtır.

Altmış örnekte belirsizlik kalmıyor. İki çekiliş de bütün havuzu seçtiği için sayılar birbirinin
aynı: istem düzeneği **0,9667**, ince ayar **0,9500**. Fark **0,0167** ve koşum değişkenliği
**sıfır**. Bu, ince ayarın **kazanmadığı** noktadır ve tesadüf değildir. Altmış örneğin tamamı
bağlamda duruyorsa model her isteği çözülmüş bir kümeyle birlikte okuyor; ince ayar ise aynı
örneklerden yalnız **hata verdiklerini** kullanmış, 605 ağırlığın 181'ini oynatmış ve geri kalanına
dokunmamış. Elinde bütün etiketli veri varken onu bir eğitim koşumuna sıkıştırmak, bu görevde
kayıptır.

Koşum sayısı bu farkı kapatamıyor. Altmış örnek sabit tutulup koşum sayısı artırıldığında isabet
tek koşumda **0,9333**, üç koşumda **0,9500** ve orada duruyor; altı ve on koşum aynı 0,9500'ü
veriyor. Üçüncü koşumdan sonra eğitim kümesinde düzeltilecek hata kalmadığı için oynayan kayıt
sayısı da **181**'de sabitleniyor. Güncelleme adımı 180'den 600'e çıkıyor ve karşılığında hiçbir
şey alınmıyor. İnce ayarın bu görevdeki tavanı 0,9500'dür ve o tavan koşum ekleyerek değil ancak
başka bir yolla yükselir.

Kararı veren şey isabet sütunu değil, son iki satırdır. İstem düzeneği altmış örnekle isteğin
bağlamını 28,48 belirteçten **623,48** belirtece, yani **21,9 katına** çıkarıyor ve bu bedel her
istekte yeniden ödeniyor. İlk dersin hesabına göre bağlam uzunluğu istek başına ara durumla doğru
orantılıdır; yirmi bir kat bağlam, aynı bütçede yirmi bir kat az eşzamanlı istek demektir. İnce
ayarın bedeli ise **bir kereliktir**: altmış etiketli örnek, üç koşum, 180 güncelleme adımı ve
0,2992 payında oynayan ağırlık. Sonraki her istek yine 28,48 belirteç.

Karşılaştırma bu yüzden tek sayıyla kapanmaz. Etiketli örnek azken ince ayar üstün ve ucuzdur.
Örnek çoğaldıkça istem düzeneği isabette yakalar ve geçer, ama bunu bağlamı büyüterek yapar; kaç
isteğin aynı anda işleneceği önemliyse, 0,0167'lik bir isabet farkı yirmi bir kat kapasiteye
değmez. Ölçülmesi gereken ikisidir ve bu iki sayı aynı birimde değildir.

#### Özet

- İki yol da aynı girdiyi ister: etiketli örnek. Değişen tek şey örneğin isteme mi ağırlığa mı
  konduğudur; bu yüzden karşılaştırma eşit örnek sayısında yapılır.
- Dört örnekle ince ayar hiçbir ağırlığı oynatmıyor ve taban 0,6000'de kalıyor; aynı dört örnek
  isteme konduğunda isabet 0,5667'ye düşüyor. İki çekilişin yönü bile aynı değil.
- Sekiz ve on altı örnekte ince ayar iki çekilişte de önde: 0,7333 ile 0,8833'e karşı 0,6500 ile
  0,8333. Bu üstünlük ölçülmüş sayılır.
- Otuz iki örnekte bantlar örtüşüyor (0,9000 ile 0,9500'e karşı 0,9000 ile 0,9167); ölçülmüş bir
  kazanç yoktur ve tek koşumluk ince ayar 0,8500 ile geride kalır.
- Altmış örnekte istem düzeneği 0,9667, ince ayar 0,9500; koşum değişkenliği sıfır olduğu için
  ince ayarın kaybı gerçektir.
- Bedeller aynı birimde değildir: istem düzeneği bağlamı istek başına 21,9 katına çıkarır, ince
  ayar bir kerelik 180 güncelleme adımı ve 605 ağırlığın 0,2992 payını oynatır.

#### Sonraki Adım

Son satırdaki 0,2992 payı sorulmadan geçildi. İnce ayar hangi ağırlığın oynayacağına **karar
vermedi**; hata güdümlü güncelleme, yanlış bilinen bir örnekte hangi parça geçtiyse ona dokundu ve
181 kayıt öylece ortaya çıktı. Bu sayı bir tasarım kararı değil, bir yan üründür. Oysa oynayan
ağırlık sayısı doğrudan bir maliyettir: saklanacak, taşınacak, geri alınacak ve her görev için
ayrıca tutulacak olan şey odur. Aynı isabet daha az ağırlık oynatılarak alınabilir miydi, hangi
ağırlıkların dondurulacağına önceden karar verilse ne kaybedilirdi ve güncellemenin kendisi
tabloya bir **ek** olarak yazılsa saklanan sayı adedi ne olurdu — bunların hiçbiri denenmedi.
Sonraki ders tam güncellemeyi, katman dondurmayı ve tabloya eklenen düşük ranklı bir düzeltmeyi
yan yana ölçer ve iki sayıyı basar: güncellenen parametre payı ile isabet.

### Uyarlama Yöntemleri

Source: https://academia.sh/tr/kurslar/model-apileri/uyarlama-yontemleri

Aynı saha uyarlamasında tam güncelleme, katman dondurma ve düşük ranklı ekin güncellediği parametre payı ile isabetinin yan yana ölçülmesi: 2292 sayılık kurgu yerel model saha yazımında 0,2500 ve 0,0833 veriyor, tam güncelleme 1,0000 ve 0,9861, yalnız başı güncelleyen katman dondurma 0,6944 ve 0,7500, parametrelerin 0,2094'ünü güncelleyen düşük ranklı ek 0,9583 ve 0,9306. Rankı 3'ten 4'e çıkarmak uyarlama başına 210 sayı daha saklatır ve ortalama kazancı 0,0070'tir, iki koşum farkının altında. Sekiz alana uyarlamada saklanan sayı 18336'ya karşı 6132'dir ve gizli genişlik büyüdükçe ekin payı 0,2094'ten 0,0284'e iner.

İnce ayar bir modeli yeni bir alana taşır ve bunu **bütün ağırlıkları oynatarak** yapar. Bir
önceki ders bunun bedelini örnek sayısı ve koşum sayısıyla yazdı. Yazılmayan bir bedel daha var:
uyarlanan her alan için modelin **tam bir kopyası** saklanır. Sekiz alan sekiz kopya demektir.

Bu ders daha azını oynatmayı dener. Aynı uyarlama görevinde üç kurulum yan yana konur — **tam
güncelleme**, **katman dondurma** ve **düşük ranklı ek** — ve her birinin **güncellediği
parametre payı** ile **isabeti** birlikte basılır. Yanına saklanan sayı adedi yazılır, çünkü
uyarlamanın asıl bedeli eğitim sırasında değil, sonrasında ödenir.

- **YM31.** Kod bir **benzeticidir**. Yerel model, sözlük, kayıtlar ve etiketler **kurgudur**;
  gerçek bir uç nokta çağrılmaz. Tohum **20260218**.
- **YM32.** Model üç katmandır: bir **giriş arama tablosu**, bir **gövde matrisi** ve bir **baş**.
  Ağırlıkların tamamı elimizdedir; kendi barındırdığın bir modelin ayırt edici yanı budur.
- **YM33.** İki alan ayrıdır: model **genel yazımlı** kurgu taleplerle önceden eğitilir, sonra
  saha ekibinin **kısaltmalı** kurgu kayıtlarına uyarlanır. Kayıtların bir payı başka bir konunun
  kısaltmasını taşıyan yanıltıcı bir ek alır.
- **YM34. Düşük ranklı ek**, ağırlık matrisini yerinde değiştirmez; yanına iki ince matrisin
  çarpımını ekler. İkincisi sıfırdan başladığı için ilk anda taban model bozulmaz. Denetimsiz
  Öğrenme kursundaki tekil değer ayrışımı dersi bir matrisin düşük ranklı bir çarpımla yaklaşık
  yazılabildiğini ölçmüştü; buradaki yapı aynı fikrin **güncelleme** tarafıdır.
- **YM35.** **Baş her kurulumda güncellenir**; kurulumları ayıran şey gövdenin ve arama tablosunun
  ne kadarının oynadığıdır. İki koşum **önceden eğitim tohumuyla** alınır (20260218 ve 20260219),
  kümeler değişmez.

#### Katmanlar ve Ağırlık Bütçesi

Uzak bir uç noktada ölçülebilen tek şey yüzeydi. Kendi barındırdığın bir modelde ölçülebilen şey
**sayıların kendisidir**: kaç tane var, hangisi hangi katmanda, kaçı kaydediliyor.

```python
# BENZETICI -- KURGUDUR. Yerel model, sozluk, kayitlar ve etiketler ders icinde
# yazilir; gercek bir model uc noktasi cagrilmaz. Tohum 20260218.
from math import exp

TOHUM, M32 = 20260218, 0xFFFFFFFF


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
GENEL = [("bu ayki fatura tutari gecen aya gore yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti")]
SAHA = [("fat sapma itiraz dosyasi acildi", "fatura"),
        ("tahak farki cikti fat duzelt", "fatura"),
        ("fat kalem hatasi bildirildi", "fatura"),
        ("fat iade sureci baslatildi", "fatura"),
        ("arz hat kesik ekip yonlendirildi", "ariza"),
        ("pano arz kodu iki bir dort", "ariza"),
        ("arz tekrar etti kalici cozum", "ariza"),
        ("arz gecici onarim yapildi", "ariza"),
        ("syc endeks sapmasi tespit", "sayac"),
        ("syc degisim isi planlandi", "sayac"),
        ("syc muhur kontrolu yapildi", "sayac"),
        ("syc seri numarasi eslesmedi", "sayac"),
        ("trf basamak gecisi talebi", "tarife"),
        ("trf birim degisimi islendi", "tarife"),
        ("trf sozlesme guncellemesi bekliyor", "tarife"),
        ("trf indirim kosulu incelendi", "tarife"),
        ("kes duyurusu bolgeye islendi", "kesinti"),
        ("kes suresi uzadi bilgilendirme", "kesinti"),
        ("kes sonrasi enerji verildi", "kesinti"),
        ("kes plani ertelendi yeni saat", "kesinti")]
YANIL = [" fat kaydi da acildi", " arz notu eklendi",
         " syc formu istendi", " trf grubu kontrol edildi"]


def kume(kalip, n, tohum, yanpay=0.0):
    r, k = uretec(tohum), []
    for i in range(n):
        c = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
        aday = [x for x in kalip if x[1] == c]
        m = aday[int(r() * len(aday))][0]
        if r() < yanpay:                # baska konunun kisaltmasini tasiyan ek
            m += YANIL[int(r() * 4)]
        k.append((m, c))
    return k


ONCEDEN = kume(GENEL, 150, TOHUM)                   # onceden egitim alani
UYARLAMA = kume(SAHA, 48, TOHUM + 7, 0.30)          # saha yazimi, uyarlama ornekleri
SINAMA = kume(SAHA, 72, TOHUM + 11, 0.30)           # saha yazimi, sinama
SOZLUK = {}
for m in [x[0] for x in GENEL + SAHA] + YANIL:
    for t in belirtecle(m):
        SOZLUK.setdefault(t, len(SOZLUK))
V, H, C = len(SOZLUK), 12, len(KONU)


def kodla(k):
    return [(sorted({SOZLUK[t] for t in belirtecle(m)}), KONU.index(c)) for m, c in k]


ON_K, UY_K, SN_K = kodla(ONCEDEN), kodla(UYARLAMA), kodla(SINAMA)


def kur(tohum):
    """Giris arama tablosu, govde matrisi, bas. Govde birim dizey cevresinde baslar."""
    r = uretec(tohum)
    return [[[(r() - 0.5) * 0.4 for _ in range(H)] for _ in range(V)],
            [[1.0 * (k == j) + (r() - 0.5) * 0.2 for j in range(H)] for k in range(H)],
            [[(r() - 0.5) * 0.4 for _ in range(C)] for _ in range(H)]]


def carp(giris, W, n):
    """giris: (satir, deger) ciftleri; seyrek carpim."""
    h = [0.0] * n
    for i, v in giris:
        Wi = W[i]
        for j in range(n):
            h[j] += v * Wi[j]
    return h


def ileri(p, tok, ek=None):
    """ek verilirse her katmana dusuk rankli bir ek eklenir (ikinci bolum)."""
    kat, ara = [(t, 1.0) for t in tok], []
    for n in (0, 1):
        h, z = carp(kat, p[n], H), None
        if ek:
            U, Vt = ek[n]
            z = carp(kat, U, len(Vt))
            for j, x in enumerate(carp(list(enumerate(z)), Vt, H)):
                h[j] += x
        ara.append((kat, h, z))
        kat = [(j, x) for j, x in enumerate(h) if x > 0.0]      # dogrultma, seyrek
    return ara, kat, carp(kat, p[2], C)


def geri(p, tok, y, ek, adim, hangi):
    """hangi: tam | bas | ek. Bas her kurulumda guncellenir, digerleri secime bagli."""
    ara, kat, o = ileri(p, tok, ek)
    mx = max(o)
    e = [exp(x - mx) for x in o]
    s = sum(e)
    d = [x / s for x in e]
    d[y] -= 1.0
    B, da = p[2], [0.0] * H
    for k, v in kat:
        da[k] = sum(d[j] * B[k][j] for j in range(C))
        for j in range(C):
            B[k][j] -= adim * d[j] * v
    for n in (1, 0):
        giris, h, z = ara[n]
        W, U, Vt = p[n], *(ek[n] if ek else (None, None))
        dh = [da[j] if h[j] > 0.0 else 0.0 for j in range(H)]
        if n == 1:
            da = [sum(dh[j] * W[k][j] for j in range(H)) for k in range(H)]
            if ek:
                dz = [sum(dh[j] * Vt[q][j] for j in range(H)) for q in range(len(Vt))]
                for k in range(H):
                    da[k] += sum(U[k][q] * dz[q] for q in range(len(Vt)))
        if hangi == "tam":
            for i, v in giris:
                for j in range(H):
                    W[i][j] -= adim * dh[j] * v
        elif hangi == "ek":
            dz = [sum(dh[j] * Vt[q][j] for j in range(H)) for q in range(len(Vt))]
            for q in range(len(Vt)):
                for j in range(H):
                    Vt[q][j] -= adim * dh[j] * z[q]
            for i, v in giris:
                for q in range(len(Vt)):
                    U[i][q] -= adim * dz[q] * v


def isabet(p, k, ek=None):
    return sum(max(range(C), key=lambda j: ileri(p, tok, ek)[2][j]) == y
               for tok, y in k) / len(k)


def onceden_egit(tohum):
    p = kur(tohum)
    for e in range(30):
        for tok, y in ON_K:
            geri(p, tok, y, None, 0.10, "tam")
    return p


TABAN_A, TABAN_B = onceden_egit(TOHUM), onceden_egit(TOHUM + 1)
print(f"sozluk {V} parca , gizli genislik {H} , sinif {C}")
print(f"giris {V * H} + govde {H * H} + bas {H * C} = {V * H + H * H + H * C} sayi")
print("kosum   onceden egitim alani   saha alani")
for ad, p in (("A", TABAN_A), ("B", TABAN_B)):
    print(f"  {ad}   {isabet(p, ON_K):>18.4f}   {isabet(p, SN_K):>10.4f}")
```

```
sozluk 174 parca , gizli genislik 12 , sinif 5
giris 2088 + govde 144 + bas 60 = 2292 sayi
kosum   onceden egitim alani   saha alani
  A               1.0000       0.2500
  B               1.0000       0.0833
```

Önceden eğitim alanında isabet iki koşumda da **1,0000**; model kendi alanını öğrenmiş durumda.
Saha yazımına geçildiğinde aynı model **0,2500** ve **0,0833** veriyor. Beş sınıflı bir görevde
rastgele seçim 0,2000 civarındadır, yani taban model saha kayıtlarında **hiçbir şey bilmiyor**;
iki koşum arasındaki 0,1667'lik fark bunun kanıtıdır, ölçülen şey bilgi değil gürültüdür. Uyarlama
kaçınılmazdır ve soru **hangi sayıların** oynayacağıdır.

#### Güncellenen Parametre Payı ile İsabet

Kurulumlar aynı kırk sekiz uyarlama kaydı, aynı yirmi beş döngü ve aynı adım boyuyla koşturulur;
tek değişen, geri yayılımın **hangi paya** dokunduğudur.

```python
from copy import deepcopy


def ek_kur(rank, tohum):
    """Her ek bir U (satir x rank) ve bir Vt (rank x H) ciftidir. Vt sifirdan baslar,
    yani uyarlamanin ilk aninda ek hicbir sey eklemez ve taban model bozulmaz."""
    r = uretec(tohum)
    return [([[(r() - 0.5) * 0.3 for _ in range(rank)] for _ in range(n)],
             [[0.0] * H for _ in range(rank)]) for n in (V, H)]


def uyarla(taban, hangi, rank, tohum, dongu=25, adim=0.08):
    p = deepcopy(taban)
    ek = ek_kur(rank, tohum + 3) if rank else None
    for e in range(dongu):
        for tok, y in UY_K:
            geri(p, tok, y, ek, adim, hangi)
    return isabet(p, SN_K, ek), isabet(p, ON_K, ek)


TOPLAM = V * H + H * H + H * C
KURULUM = [("tam guncelleme", "tam", 0), ("katman dondurma", "bas", 0)] + \
          [(f"dusuk rankli ek r={r}", "ek", r) for r in (1, 2, 3, 4)]
print("kurulum              guncellenen     pay  saha A  saha B  genel A  genel B")
print(f"{'uyarlama yok':<20} {0:>11}  {0.0:.4f}  {isabet(TABAN_A, SN_K):>6.4f}"
      f"  {isabet(TABAN_B, SN_K):>6.4f}  {isabet(TABAN_A, ON_K):>7.4f}"
      f"  {isabet(TABAN_B, ON_K):>7.4f}")
for ad, hangi, rank in KURULUM:
    n = TOPLAM if hangi == "tam" else (H * C if hangi == "bas"
                                       else rank * (V + H) + rank * 2 * H + H * C)
    a, b = uyarla(TABAN_A, hangi, rank, TOHUM), uyarla(TABAN_B, hangi, rank, TOHUM + 1)
    print(f"{ad:<20} {n:>11}  {n / TOPLAM:.4f}  {a[0]:>6.4f}  {b[0]:>6.4f}"
          f"  {a[1]:>7.4f}  {b[1]:>7.4f}")

print("\nsekiz ayri sahaya uyarlama, saklanan sayi adedi:")
for ad, n in (("tam guncelleme", TOPLAM), ("katman dondurma", H * C),
              ("dusuk rankli ek r=2", 2 * (V + H) + 2 * 2 * H + H * C)):
    ortak = 0 if n == TOPLAM else TOPLAM
    print(f"  {ad:<20} {ortak} + 8 x {n} = {ortak + 8 * n}")

print("\ngizli genislik buyudukce (kosumdan bagimsiz, yalniz sayim):")
print("  H       tam  dondurma  r=2 ek   ek payi")
for h in (H, 64, 256):
    tam = V * h + h * h + h * C
    ek2 = 2 * (V + h) + 2 * 2 * h + h * C
    print(f"  {h:<5} {tam:>7}  {h * C:>8}  {ek2:>6}   {ek2 / tam:.4f}")
```

```
kurulum              guncellenen     pay  saha A  saha B  genel A  genel B
uyarlama yok                   0  0.0000  0.2500  0.0833   1.0000   1.0000
tam guncelleme              2292  1.0000  1.0000  0.9861   1.0000   1.0000
katman dondurma               60  0.0262  0.6944  0.7500   0.5133   0.1733
dusuk rankli ek r=1          270  0.1178  0.7639  0.7222   0.5133   0.2733
dusuk rankli ek r=2          480  0.2094  0.9583  0.9306   1.0000   0.5533
dusuk rankli ek r=3          690  0.3010  1.0000  0.9722   1.0000   1.0000
dusuk rankli ek r=4          900  0.3927  0.9861  1.0000   1.0000   1.0000

sekiz ayri sahaya uyarlama, saklanan sayi adedi:
  tam guncelleme       0 + 8 x 2292 = 18336
  katman dondurma      2292 + 8 x 60 = 2772
  dusuk rankli ek r=2  2292 + 8 x 480 = 6132

gizli genislik buyudukce (kosumdan bagimsiz, yalniz sayim):
  H       tam  dondurma  r=2 ek   ek payi
  12       2292        60     480   0.2094
  64      15552       320    1052   0.0676
  256    111360      1280    3164   0.0284
```

Tam güncelleme 2292 sayının hepsini oynatıyor ve **1,0000 / 0,9861** veriyor. Katman dondurma
bunun **0,0262**'siyle, yani altmış sayıyla çalışıyor ve **0,6944 / 0,7500**'de kalıyor: kırk
sekiz örnek başa yeni bir eşleme öğretmeye yetiyor, ama gövde saha kısaltmalarını hâlâ
tanımadığı için isabet yarıda kalıyor. Düşük ranklı ek rank ikide **0,2094** payla **0,9583 /
0,9306**'ya çıkıyor; tam güncellemeye uzaklığı 0,0417 ile 0,0555 arası, katman dondurmaya
uzaklığı 0,1806 ile 0,2639 arası. Aradaki farkın büyük kısmı, güncellenen payın **onda ikisiyle**
alınıyor.

Rank merdiveni nerede durulacağını söylüyor. Rank bir yetmiyor (**0,7639 / 0,7222**): tek bir yön
iki yazım arasındaki kaymayı taşıyamıyor. Rank üç **1,0000 / 0,9722**, rank dört **0,9861 /
1,0000** veriyor; ortalamalar 0,9861 ve 0,9931, yani rankı üçten dörde çıkarmanın ortalama kazancı
**0,0070**. Aynı satırların iki koşum farkı 0,0278 ve 0,0139'dur. Kazanç farkın altındadır ve
karşılığında uyarlama başına **210 sayı** daha saklanır: eklenen düzeneğin bedeli kesin, kazancı
ölçülemez durumdadır.

Son iki sütun beklenmedik olanı gösteriyor. Katman dondurma, gövdeyi koruduğu hâlde önceki
alandaki isabeti **0,5133 / 0,1733**'e düşürüyor; korunan gövde işe yaramıyor, çünkü iki alanın
**ortak** kullandığı baş yeniden yazıldı. Tam güncelleme ise önceki alanı **1,0000**'da tutuyor:
arama tablosunda yalnız saha kayıtlarında geçen satırlar oynadı, genel yazımın satırlarına
dokunulmadı. Bir katmanı dondurmak o katmanın yeteneğini koruduğu anlamına gelmez; korunan şey
**ağırlıklar**, kaybedilen şey **davranıştır**.

#### Saklanan Sayı Adedi ve Ölçek

Sekiz sahaya uyarlama satırı kararın nerede ödendiğini gösteriyor. Tam güncellemede taban
paylaşılamaz; sekiz kopya **18336** sayı eder. Katman dondurmada taban bir kez saklanır, her saha
yalnız kendi başını ekler: **2772**. Düşük ranklı ekte taban yine bir kez saklanır, sahalar 480'er
sayı ekler: **6132**, yani tam güncellemenin üçte biri.

Ölçek tablosu bu oranın sabit olmadığını söylüyor. Rank sabit tutulduğunda ekin maliyeti gizli
genişlikle **doğrusal**, tam güncellemenin maliyeti gövdede **karesel** büyür. Genişlik 12'de ek
payı **0,2094**, 64'te **0,0676**, 256'da **0,0284**. Bu sayım koşumdan bağımsızdır ve uyarlama
yöntemi tartışmasının niçin **büyük** modellerde başladığını açıklar.

#### Özet

- Kurgu yerel model 2292 sayıdır (giriş 2088, gövde 144, baş 60) ve uyarlanmamış hâli saha
  yazımında 0,2500 ile 0,0833, yani rastgele seçim düzeyinde kalır.
- Tam güncelleme tamamını oynatır ve 1,0000 / 0,9861 verir; bedeli her alan için bir tam kopyadır.
- Katman dondurma 0,0262 payla 0,6944 / 0,7500'de kalır ve önceki alandaki isabeti 0,5133 /
  0,1733'e düşürür: dondurulan ağırlık korunur, davranış korunmaz.
- Düşük ranklı ek 0,2094 payla 0,9583 / 0,9306 verir; tam güncellemeye uzaklığı 0,0417 ile 0,0555
  arasındadır.
- Rankı üçten dörde çıkarmanın ortalama kazancı 0,0070, aynı satırların iki koşum farkı 0,0278 ve
  0,0139'dur: kazanç ölçülmemiş sayılır, 210 ek sayı kesindir.
- Sekiz sahada saklanan sayı 18336'ya karşı 6132'dir ve gizli genişlik 12'den 256'ya çıktığında
  ekin payı 0,2094'ten 0,0284'e iner.

#### Sonraki Adım

Bu derste büyük modelin ağırlıkları elimizdeydi. Elde her zaman ağırlık olmaz; çoğu zaman olan
tek şey büyük bir modelin **çıktısıdır**. O çıktı bir etiket kümesi gibi kullanılıp **küçük bir
modelin** eğitiminde girdi yapılabilir. Sonraki ders bunu ölçer: büyük modelin ürettiği
etiketlerle eğitilen küçük bir model, aynı büyüklükte ama yalnız insan etiketiyle eğitilen bir
modele göre ne kazanıyor, öğretmenin isabetinin ne kadarını yakalıyor ve **hangi görevde**
aradaki açık kapanmıyor.

### Damıtma

Source: https://academia.sh/tr/kurslar/model-apileri/damitma

Büyük modelin etiketlediği 240 kurgu kayıtla eğitilen küçük bir modelin, yalnız altı insan etiketiyle eğitilen aynı modele göre ne kazandığının iki görevde ölçülmesi: konu görevinde 0,5000'den 0,6333'e çıkıyor ve öğretmenin isabetinin tamamını yakalıyor, ama 240 insan etiketinin verdiği 0,9000'e göre açığın yalnız üçte birini kapatıyor. Ayrı konu sayma görevinde damıtma geri götürüyor, 0,5833'ten 0,3667 ve 0,2417'ye düşüyor, çünkü öğretmen saymıyor. Damıtılmış modelin hatalarının 0,9545'i öğretmenin de yanıldığı kayıtlarda, altı etiketle eğitilende bu pay 0,3000.

Bir önceki derste büyük modelin ağırlıkları elimizdeydi ve onların bir kısmını oynattık. Çoğu
durumda elde ağırlık yoktur; elde olan tek şey, büyük modelin verdiği **yanıtlardır**. Bu yanıtlar
bir etiket kümesi gibi kullanılıp **küçük bir modelin** eğitiminde girdi yapılabilir. Yapılan iş
**damıtmadır**: büyük modelin davranışı, onun binde biri kadar sayı taşıyan bir modele aktarılmaya
çalışılır.

Damıtmanın çekiciliği açıktır. İnsan etiketi pahalıdır, model etiketi ise bir çağrıdır. Ölçülmesi
gereken şey de bu yüzden tek bir sayı değildir: küçük model **öğretmenin isabetinin ne kadarını**
yakalıyor, aynı emeği insan etiketine harcasaydık nereye varırdık ve **hangi görevde** bu aktarım
hiç çalışmıyor.

- **YM36.** Kod bir **benzeticidir**. Büyük model, küçük model ve kayıtların tamamı **kurgudur**;
  gerçek bir uç nokta çağrılmaz. Tohum **20260218**.
- **YM37.** Kayıt bir gövde cümlesi ve en çok iki **kısa ektir**. Etiketlerden biri **konu**
  (gövdenin konusu, beş sınıf), öteki **ayrı konu adedi** (metinde geçen ayrı konu sayısı, dört
  sınıf). Kayıtların bir payında gövde konuyu ele vermez.
- **YM38. Büyük model konuyu bir anahtar tablosundan puanlar, ayrı konu adedini ise saymaz**;
  uzunluk sınıfından tahmin eder. İkinci davranış, dil modellerinin sayma görevlerindeki
  zayıflığının kurgu karşılığıdır ve M28'in ilk kursunda ölçülmüştü.
- **YM39. Küçük model** belirteç torbasından doğrudan sınıfa giden tek bir dizeydir; öğretmenin
  taşıdığı yapının hiçbirini taşımaz. Eğitimi ders içinde yazılır.
- **YM40.** Üç kaynak karşılaştırılır: **altı insan etiketi**, **iki yüz kırk öğretmen etiketi** ve
  **iki yüz kırk insan etiketi**. Sonuncusu bir **üst sınırdır**, gerçek bir seçenek değil.
- **YM41.** İki koşum **öğretmenin etiketleme tohumu** değiştirilerek alınır (20260218 ve
  20260219); kayıtlar ve sınama kümesi iki koşumda da aynıdır.

#### Öğretmen ve İki Görev

Damıtmanın sınırı öğretmenin kendisidir; bu yüzden önce öğretmen ölçülür. İki görev bilerek farklı
seçildi: biri anahtar sözcük eşlemesiyle çözülebilen bir sınıflandırma, öteki metinde geçen ayrı
konuların **sayılması**.

```python
# BENZETICI -- KURGUDUR. Buyuk model, kucuk model ve kayitlarin tamami ders icinde
# yazilir; gercek bir uc nokta cagrilmaz. Tohum 20260218.
from math import exp

TOHUM, M32 = 20260218, 0xFFFFFFFF


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 belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
GOVDE = [("fatura tutari gecen aya gore yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti")]
KISA = {"fatura": "fatura notu", "ariza": "ariza kaydi", "sayac": "sayac formu",
        "tarife": "tarife grubu", "kesinti": "kesinti plani"}
BELIRSIZ = ["gecen hafta bir sorun yasadim yardim gerekiyor",
            "bu durumu kime iletmem gerektigini bilmiyorum"]


def kayitlar(n, tohum):
    """Bir govde cumlesi ve en cok iki kisa ek. Konu govdeninkidir; sayi ayri konu adedidir."""
    r, k = uretec(tohum), []
    for i in range(n):
        c = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
        if r() < 0.10:                          # govde konuyu ele vermiyor
            m, gecen = BELIRSIZ[int(r() * 2)], []
        else:
            aday = [x for x in GOVDE if x[1] == c]
            m, gecen = aday[int(r() * len(aday))][0], [c]
        for esik in (0.62, 0.45):
            if r() < esik:
                b = KONU[int(r() * 5)]
                if b not in gecen:
                    m += " ayrica " + KISA[b]
                    gecen.append(b)
        k.append({"metin": m, "konu": c, "sayi": len(gecen)})
    return k


ETIKETLI = kayitlar(6, TOHUM + 1)           # insan etiketi pahalidir: alti kayit
ETIKETSIZ = kayitlar(240, TOHUM + 2)        # etiketsiz yigin
SINAMA = kayitlar(120, TOHUM + 3)

IZ = {"fatur": "fatura", "tutar": "fatura", "borc": "fatura", "odedi": "fatura",
      "ariza": "ariza", "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza",
      "sayac": "sayac", "endek": "sayac", "okuma": "sayac", "randev": "sayac",
      "tarif": "tarife", "birim": "tarife", "abone": "tarife", "basam": "tarife",
      "kesin": "kesinti", "duyur": "kesinti", "mahal": "kesinti", "planl": "kesinti"}
TUZAK = {"notu": "fatura", "kaydi": "ariza", "formu": "sayac", "grubu": "tarife",
         "plani": "kesinti"}                # kisa ekler tabloda tam agirlikla duruyor
CAGRI = [0, 0]


def buyuk_model(metin, tohum, sicaklik=0.50):
    """KURGU buyuk model. Konuyu anahtar tablosundan puanlar; sayi gorevini SAYMAZ,
    uzunluk sinifindan tahmin eder. Ikinci davranis M28'in sayma zayifligina karsilik gelir."""
    CAGRI[0] += 1
    bel = belirtecle(metin)
    CAGRI[1] += len(bel)
    p = {k: 0.12 for k in KONU}
    for t in bel:
        for tablo, w in ((IZ, 1.0), (TUZAK, 0.70)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    r = uretec(tohum ^ sum((i + 1) * ord(c) for i, c in enumerate(metin)))
    ad = sorted(p)
    e = [exp(p[a] / sicaklik) for a in ad]
    s = sum(e)
    konu = ad[ayrik(r(), [x / s for x in e])]
    uzun = 0 if len(bel) <= 7 else (1 if len(bel) <= 10 else 2)
    sayi = ayrik(r(), ([0.10, 0.56, 0.24, 0.10], [0.06, 0.32, 0.40, 0.22],
                       [0.04, 0.20, 0.36, 0.40])[uzun])
    return konu, sayi


def olc(kume, tohum):
    dk = ds = 0
    for x in kume:
        k, s = buyuk_model(x["metin"], tohum)
        dk += k == x["konu"]
        ds += s == x["sayi"]
    return dk / len(kume), ds / len(kume)


dag = {}
for x in SINAMA:
    dag[x["sayi"]] = dag.get(x["sayi"], 0) + 1
print("sinama kayit", len(SINAMA), ", ayri konu adedi dagilimi", dict(sorted(dag.items())))
print("ornek kayit:", SINAMA[1]["metin"])
print("           konu", SINAMA[1]["konu"], ", ayri konu adedi", SINAMA[1]["sayi"])
print("\nbuyuk model              konu isabeti  sayi isabeti")
for ad, th in (("kosum A (20260218)", TOHUM), ("kosum B (20260219)", TOHUM + 1)):
    a, b = olc(SINAMA, th)
    print(f"{ad:<24} {a:>12.4f}  {b:>12.4f}")
print(f"sinama olcumunun bedeli: cagri {CAGRI[0]} , giris belirteci {CAGRI[1]}")
```

```
sinama kayit 120 , ayri konu adedi dagilimi {0: 4, 1: 38, 2: 63, 3: 15}
ornek kayit: evde su akmiyor bir ariza var galiba
           konu ariza , ayri konu adedi 1

buyuk model              konu isabeti  sayi isabeti
kosum A (20260218)             0.6333        0.3583
kosum B (20260219)             0.7167        0.3000
sinama olcumunun bedeli: cagri 240 , giris belirteci 3214
```

Büyük model konu görevinde **0,6333 / 0,7167**, sayma görevinde **0,3583 / 0,3000** veriyor.
Sayma görevinde dört sınıf var ve en kalabalık sınıf sınamanın 63 kaydını tutuyor; yani her kayda
o sınıfı veren bir yordam 0,5250 alırdı. Öğretmen bunun altındadır. İki koşum arasındaki fark da
konu görevinde 0,0834, sayma görevinde 0,0583: öğretmen belirsiz bir bileşendir ve etiketleri de
belirsizdir.

#### Küçük Modelin Yakaladığı Pay

Küçük model her iki görevde üç ayrı kaynakla eğitilir. Öğretmenin etiketleri, iki yüz kırk
etiketsiz kaydın her biri için bir çağrı yapılarak üretilir.

```python
SOZLUK = {}
for m in [x[0] for x in GOVDE] + BELIRSIZ + ["ayrica " + v for v in KISA.values()]:
    for t in belirtecle(m):
        SOZLUK.setdefault(t, len(SOZLUK))
V = len(SOZLUK)


def parcala(metin):
    return sorted({SOZLUK[t] for t in belirtecle(metin) if t in SOZLUK})


def hedef(konu, sayi, alan):
    return KONU.index(konu) if alan == "konu" else sayi


def egit(ornek, sinif, tohum, dongu=40, adim=0.12):
    """KUCUK model: belirtec torbasindan dogrudan sinifa tek dizey, V x sinif sayi."""
    r = uretec(tohum)
    W = [[(r() - 0.5) * 0.2 for _ in range(sinif)] for _ in range(V)]
    for e in range(dongu):
        for tok, y in ornek:
            o = [sum(W[i][j] for i in tok) for j in range(sinif)]
            mx = max(o)
            d = [exp(x - mx) for x in o]
            s = sum(d)
            d = [x / s for x in d]
            d[y] -= 1.0
            for i in tok:
                for j in range(sinif):
                    W[i][j] -= adim * d[j]
    return W


def kestir(W, tok, sinif):
    o = [sum(W[i][j] for i in tok) for j in range(sinif)]
    return max(range(sinif), key=lambda j: o[j])


def kucuk_isabet(W, sinif, alan):
    return sum(kestir(W, parcala(x["metin"]), sinif) == hedef(x["konu"], x["sayi"], alan)
               for x in SINAMA) / len(SINAMA)


CAGRI[0] = CAGRI[1] = 0
DAMITMA = {t: [(x, *buyuk_model(x["metin"], t)) for x in ETIKETSIZ]
           for t in (TOHUM, TOHUM + 1)}       # etiketsiz yigin ogretmene etiketletiliyor
ETIKETLEME = (CAGRI[0], CAGRI[1])
KAYNAK = [("insan etiketi 6", lambda a, t: [(parcala(x["metin"]),
                                             hedef(x["konu"], x["sayi"], a))
                                            for x in ETIKETLI]),
          ("ogretmen etiketi 240", lambda a, t: [(parcala(x["metin"]), hedef(k, s, a))
                                                 for x, k, s in DAMITMA[t]]),
          ("insan etiketi 240", lambda a, t: [(parcala(x["metin"]),
                                               hedef(x["konu"], x["sayi"], a))
                                              for x in ETIKETSIZ])]
OG = (olc(SINAMA, TOHUM), olc(SINAMA, TOHUM + 1))
AGIRLIK = {}
print("gorev  kucuk modelin kaynagi   isabet A  isabet B  ogretmen A  yakalanan pay")
for alan, sinif in (("konu", 5), ("sayi", 4)):
    og = OG[0][0 if alan == "konu" else 1]
    for ad, veriyi_kur in KAYNAK:
        W = egit(veriyi_kur(alan, TOHUM), sinif, TOHUM)
        a = kucuk_isabet(W, sinif, alan)
        b = kucuk_isabet(egit(veriyi_kur(alan, TOHUM + 1), sinif, TOHUM + 1), sinif, alan)
        AGIRLIK[(alan, ad)] = (W, sinif)
        print(f"{alan:<6} {ad:<22} {a:>8.4f}  {b:>8.4f}  {og:>10.4f}  {a / og:>13.4f}")
    print(f"{alan:<6} {'buyuk model (ogretmen)':<22} {og:>8.4f}"
          f"  {OG[1][0 if alan == 'konu' else 1]:>8.4f}")

print("\nkucuk modelin hatasi ogretmeninkiyle ne kadar ortusuyor (kosum A):")
for alan in ("konu", "sayi"):
    for ad in ("insan etiketi 6", "ogretmen etiketi 240"):
        W, sinif = AGIRLIK[(alan, ad)]
        ortak = hata = 0
        for x in SINAMA:
            dogru = hedef(x["konu"], x["sayi"], alan)
            k, s = buyuk_model(x["metin"], TOHUM)
            kh = kestir(W, parcala(x["metin"]), sinif) != dogru
            hata += kh
            ortak += kh and hedef(k, s, alan) != dogru
        print(f"  {alan:<6} {ad:<22} kucuk hata {hata:>3} , ortak {ortak:>3}"
              f" , pay {ortak / hata:.4f}")
print(f"\nkucuk model {V} x sinif sayi ; insan etiketi 6 ya da 240 ;"
      f" ogretmen cagrisi {ETIKETLEME[0] // 2} , giris belirteci {ETIKETLEME[1] // 2}")
```

```
gorev  kucuk modelin kaynagi   isabet A  isabet B  ogretmen A  yakalanan pay
konu   insan etiketi 6          0.5000    0.5583      0.6333         0.7895
konu   ogretmen etiketi 240     0.6333    0.6917      0.6333         1.0000
konu   insan etiketi 240        0.9000    0.9000      0.6333         1.4211
konu   buyuk model (ogretmen)   0.6333    0.7167
sayi   insan etiketi 6          0.5833    0.5833      0.3583         1.6279
sayi   ogretmen etiketi 240     0.3667    0.2417      0.3583         1.0233
sayi   insan etiketi 240        0.9417    0.9417      0.3583         2.6279
sayi   buyuk model (ogretmen)   0.3583    0.3000

kucuk modelin hatasi ogretmeninkiyle ne kadar ortusuyor (kosum A):
  konu   insan etiketi 6        kucuk hata  60 , ortak  18 , pay 0.3000
  konu   ogretmen etiketi 240   kucuk hata  44 , ortak  42 , pay 0.9545
  sayi   insan etiketi 6        kucuk hata  50 , ortak  32 , pay 0.6400
  sayi   ogretmen etiketi 240   kucuk hata  76 , ortak  58 , pay 0.7632

kucuk model 103 x sinif sayi ; insan etiketi 6 ya da 240 ; ogretmen cagrisi 240 , giris belirteci 3256
```

Konu görevinde damıtma çalışıyor. Altı insan etiketiyle eğitilen küçük model **0,5000 / 0,5583**
veriyor; iki yüz kırk öğretmen etiketiyle eğitilen aynı model **0,6333 / 0,6917**'ye çıkıyor.
Kazanç 0,1333 ve **yakalanan pay 1,0000**: küçük model öğretmenin isabetine tam olarak
yetişiyor. Buraya kadar damıtma vaadini tutuyor.

Üçüncü satır vaadin sınırını gösteriyor. Aynı iki yüz kırk kayıt **insan** etiketiyle verilseydi
küçük model **0,9000** verirdi. Damıtılmış modelin kapattığı açık, 0,5000 ile 0,9000 arasındaki
mesafenin yalnız **üçte biridir**. Küçük modelin taşıyamadığı bir şey yok; taşıyamayan öğretmendir.
Damıtma modeli değil, **öğretmenin gördüğü kadarını** kopyalar.

Sayma görevi bunu tersine çeviriyor ve dersin asıl sayısını veriyor. Altı insan etiketiyle eğitilen
küçük model **0,5833** alıyor. İki yüz kırk öğretmen etiketiyle eğitilen aynı model **0,3667 /
0,2417**'ye **düşüyor**. Kırk kat daha fazla etiket, iki yüz kırk çağrı ve 3256 giriş belirteci
harcandı ve sonuç altı etiketle eğitilen modelden kötü. Öğretmen o görevde saymıyor, uzunluktan
tahmin ediyor; damıtma bu tahmin alışkanlığını sadakatle aktarıyor. Üst sınır ise **0,9417**: görev
küçük model için zor değil, öğretmen için zor.

Hata örtüşmesi sütunu aktarımın ne kadar sadık olduğunu söylüyor. Konu görevinde damıtılmış modelin
44 hatasının **42'si**, öğretmenin de yanıldığı kayıtlarda; pay **0,9545**. Altı insan etiketiyle
eğitilen modelde aynı pay **0,3000**. İkisi de hata yapıyor, ama damıtılmış olan **aynı** hataları
yapıyor. Bir sistemin iki bileşeni aynı yerde yanılıyorsa, ikisini yan yana koymak hiçbir şey
yakalamaz.

Son olarak iki koşum sütunu damıtmanın kendine özgü bir kırılganlığını gösteriyor. Öğretmen
etiketleme tohumu değiştiğinde damıtılmış modelin sayma isabeti **0,3667'den 0,2417'ye** düşüyor;
0,1250'lik bir oynama. İnsan etiketiyle eğitilen satırlar iki koşumda da aynı sayıyı veriyor.
Öğretmenin belirsizliği eğitim kümesine yazıldı ve orada kalıcı hâle geldi.

#### Özet

- Büyük model konu görevinde 0,6333 / 0,7167, ayrı konu sayma görevinde 0,3583 / 0,3000 veriyor;
  sayma görevinde en kalabalık sınıfı seçen bir yordamın 0,5250'sinin altında kalıyor.
- Konu görevinde damıtma altı insan etiketine göre 0,5000'den 0,6333'e çıkarıyor ve öğretmenin
  isabetinin tamamını yakalıyor.
- Aynı iki yüz kırk kaydın insan etiketi 0,9000 verir; damıtma açığın yalnız üçte birini kapatır,
  çünkü tavan küçük model değil öğretmendir.
- Sayma görevinde damıtma geri götürüyor: 0,5833'ten 0,3667 ve 0,2417'ye. Üst sınır 0,9417'dir,
  yani görev küçük model için değil öğretmen için zordur.
- Damıtılmış modelin 44 konu hatasının 42'si öğretmenin de yanıldığı kayıtlarda (pay 0,9545); altı
  insan etiketiyle eğitilen modelde bu pay 0,3000.
- Bedel iki yüz kırk öğretmen çağrısı ve 3256 giriş belirtecidir; karşılığında altı insan etiketi
  yerine iki yüz kırk model etiketi elde edilir ve öğretmenin koşum belirsizliği devralınır.

#### Sonraki Adım

Bu derste küçük model büyük modelin çıktısından doğdu. Ortaya çıkan ağırlıklar hiçbir insanın
yazmadığı, tamamen başka bir modelin yanıtlarından türetilmiş sayılardır. Aynı şey bir önceki
dersin uyarlama farkları için de geçerlidir: elde, bir başkasının modelinden **türetilmiş** bir
nesne vardır. O nesneyi kendi sunucunda çalıştırmak, abonelere bir paket içinde vermek, bir
başkasına satmak ya da yalnız çıktısını sunmak aynı şey değildir. Sonraki ders bu ayrımı sayar:
dört **kullanım koşulu sınıfı** bir kullanım senaryosuna uygulandığında kaç dağıtım seçeneği
kapanıyor, hangi koşul tek başına en çok seçeneği kapatıyor ve geriye kaç seçenek kalıyor.

### Model Depoları ve Kullanım Koşulları

Source: https://academia.sh/tr/kurslar/model-apileri/model-depolari-ve-lisanslar

Bir kullanım senaryosunda dört kullanım koşulu sınıfının kaç dağıtım seçeneğini kapattığının sayılması: dört varlık türü ile dört kanaldan kurulu on altı seçenekten kullanım sınırı tek başına 6, yeniden dağıtım hakkı 3, türev çalışma koşulu 2 ve ticari kullanım kaydı 2 seçenek kapatıyor, toplam 13; birlikte kapattıkları ise 10, çünkü üç seçenek birden fazla koşulla kapanıyor. Açık kalan altı seçeneğin dördü tek kanaldadır. Kullanım sınırının kaldırılması altı değil üç seçenek açar. Aylık istek hacmi üç katına çıktığında açık seçenek altıdan dörde, on katına çıktığında bire iner. Ders M28/K03 kursunun kapanışıdır.

Bir önceki derste küçük model büyük modelin çıktısından doğdu. Ondan önceki derste elde uyarlama
farkları kaldı. İkisi de aynı türden nesnelerdir: bir başkasının modelinden **türetilmiş**, tek
başına bir anlamı olmayan sayı yığınları. Bu nesneleri kendi sunucunda çalıştırmak, kiraladığın
ortak bir ortama koymak, abonelere bir paket içinde vermek ya da herkese açık bırakmak birbirinin
aynı değildir.

Bu dersin ölçtüğü şey bir metnin ne dediği değil, **kaç seçeneğin kapandığıdır**. Dağıtım
seçenekleri sayılabilir bir kümedir; kullanım koşulları bu küme üzerinde birer süzgeçtir. Süzgeçler
uygulandığında geriye kaç seçenek kaldığı, hangi süzgecin **tek başına** ne kadar kapattığı ve
kaldırıldığında ne kadarını **geri açtığı** ayrı ayrı sayılabilir. Sayım tamamen belirlenmiştir;
tohuma bağlı hiçbir çekiliş yoktur, bu yüzden ölçü koşumdan bağımsızdır.

- **YM42.** Varlık türleri, kanallar, hacimler ve koşul sınıfları **kurgudur** ve ders içinde
  tanımlanır. Hiçbir depo, lisans, kurum, ülke ya da düzenleme adı geçmez; koşullar yalnız
  **sınıflarıyla** anılır.
- **YM43.** Dört **varlık türü** dağıtılabilir: yalnız çıktı, uyarlama farkı, tam ağırlık kopyası
  ve damıtılmış küçük model. Uyarlama farkı ile damıtılmış küçük model önceki iki
  dersin ürettiği nesnelerdir.
- **YM44.** Dört **kanal** vardır: kurum içi, kiralanan ortak ortam, ücretli abone paketi ve açık
  yayım. Her kanalın aylık istek hacmi, kurum sınırının dışına çıkıp çıkmadığı, ticari olup
  olmadığı ve alıcısının bilinip bilinmediği yazılıdır.
- **YM45.** **Kullanım sınırı**, taban modelin çalıştığı bir seçenekte aylık istek eşiğinin
  aşılamayacağını söyler. **Yeniden dağıtım hakkı**, taban ağırlığın bir kopyasının kurum sınırının
  dışına çıkamayacağını söyler. **Türev çalışma koşulu**, türetilmiş bir varlığın ancak koşulların
  alıcıyla birlikte taşınabildiği bir kanalda verilebileceğini söyler. **Ticari kullanım kaydı**,
  ticari bir kanalda kullanımın hangi tabana dayandığının kayda geçmesini ister ve bu kayıt taban
  modelin çağrı defterinden üretilir.
- **YM46.** Bu bir hukuk dersi değildir. Sayılan şey metinlerin anlamı değil, **belirli koşul
  yüklemlerinin kapattığı seçenek adedidir**; yüklemler yukarıda yazılıdır ve kodda birebir
  görünür.

#### Dört Koşul Sınıfı ve On Altı Seçenek

Koşulların hepsi aynı anda uygulanır ve bir seçenek en az bir koşula takılıyorsa kapanır. Bu
yüzden tek başına en çok kapatan koşul, kaldırıldığında en çok açan koşul olmak zorunda değildir.

```python
# KURGUDUR. Varlik turleri, kanallar, hacimler ve dort kosul sinifi ders icinde
# tanimlanir; hicbir depo, lisans, kurum ya da duzenleme adi gecmez.
VARLIK = [  # ad, taban model calisir mi, taban agirligin kopyasi mi, turev mi
    ("yalniz cikti", True, False, False),
    ("uyarlama farki", True, False, True),
    ("tam agirlik kopyasi", True, True, False),
    ("damitilmis kucuk model", False, False, True)]
KANAL = [   # ad, aylik istek, kurum disina cikiyor mu, ticari mi, alici biliniyor mu
    ("kurum ici", 40000, False, False, True),
    ("kiralanan ortak ortam", 120000, True, True, True),
    ("ucretli abone paketi", 900000, True, True, True),
    ("acik yayim", 3000000, True, False, False)]
SECENEK = [(v, k) for v in VARLIK for k in KANAL]


def k1(v, k, esik):
    """Kullanim siniri: taban modelin calistigi secenekte aylik istek esigi asilamaz."""
    return v[1] and k[1] > esik


def k2(v, k, esik):
    """Yeniden dagitim hakki: taban agirligin kopyasi kurum sinirinin disina cikamaz."""
    return v[2] and k[2]


def k3(v, k, esik):
    """Turev calisma kosulu: turetilmis varlik ancak kosullarin aliciyla birlikte
    tasinabildigi kanalda verilebilir."""
    return v[3] and not k[4]


def k4(v, k, esik):
    """Ticari kullanim kaydi: ticari kanalda kullanimin hangi tabana dayandigi kayda
    gecer; kayit taban modelin cagri kaydindan uretilir."""
    return k[3] and not v[1]


KOSUL = [("kullanim siniri", k1), ("yeniden dagitim hakki", k2),
         ("turev calisma kosulu", k3), ("ticari kullanim kaydi", k4)]


def kapali(secenek, kosullar, esik):
    return [ad for ad, f in kosullar if f(*secenek, esik)]


def sayim(kosullar, esik, hacim=1):
    kanal = [(a, h * hacim, d, t, b) for a, h, d, t, b in KANAL]
    sec = [(v, k) for v in VARLIK for k in kanal]
    return sum(1 for s in sec if kapali(s, kosullar, esik)), len(sec)


ESIK = 250000
print(f"secenek {len(SECENEK)} = {len(VARLIK)} varlik x {len(KANAL)} kanal ,"
      f" aylik istek esigi {ESIK}")
print("\nkosul                    tek basina  kaldirilinca acilan")
kapanan = 0
for ad, f in KOSUL:
    tek = sum(1 for s in SECENEK if f(*s, ESIK))
    eksik = sayim([x for x in KOSUL if x[0] != ad], ESIK)[0]
    hepsi = sayim(KOSUL, ESIK)[0]
    kapanan += tek
    print(f"{ad:<24} {tek:>10}  {hepsi - eksik:>19}")
hepsi = sayim(KOSUL, ESIK)[0]
print(f"{'toplam':<24} {kapanan:>10}  {'':>19}")
print(f"\ndort kosul birlikte {hepsi} secenegi kapatiyor , acik kalan {len(SECENEK) - hepsi}")
print("\nvarlik                  acik kalan kanallar")
for v in VARLIK:
    acik = [k[0] for k in KANAL if not kapali((v, k), KOSUL, ESIK)]
    print(f"{v[0]:<23} {' , '.join(acik) if acik else 'yok'}")
```

```
secenek 16 = 4 varlik x 4 kanal , aylik istek esigi 250000

kosul                    tek basina  kaldirilinca acilan
kullanim siniri                   6                    3
yeniden dagitim hakki             3                    1
turev calisma kosulu              2                    1
ticari kullanim kaydi             2                    2
toplam                           13                     

dort kosul birlikte 10 secenegi kapatiyor , acik kalan 6

varlik                  acik kalan kanallar
yalniz cikti            kurum ici , kiralanan ortak ortam
uyarlama farki          kurum ici , kiralanan ortak ortam
tam agirlik kopyasi     kurum ici
damitilmis kucuk model  kurum ici
```

Dört koşul **tek başına** 6, 3, 2 ve 2 seçenek kapatıyor; toplam **13**. Birlikte kapattıkları ise
**10**. Aradaki üç seçenek birden fazla koşula takılıyor, yani iki kez sayılmış durumda. Kapatma
sayılarını toplamak, koşulların etkisini yüzde otuz abartır.

Kaldırılınca açılan sütunu bunun karşılığıdır. Kullanım sınırı tek başına altı seçenek kapatıyor
ama kaldırıldığında yalnız **üç** seçenek açılıyor; kalan üçü yeniden dağıtım hakkına ya da türev
çalışma koşuluna zaten takılıyordu. Ticari kullanım kaydı ise tek başına yalnız iki seçenek
kapatıyor ve kaldırıldığında **ikisini de** geri açıyor; hiçbir koşulla örtüşmüyor. Bir koşulun
ağırlığı kapattığı sayıda değil, **tek başına kapattığı** sayıdadır.

Son tablo hangi seçeneklerin ayakta kaldığını gösteriyor. Tam ağırlık kopyası ile damıtılmış küçük
model için geriye tek bir kanal kalıyor: kurum içi. Bu kursun ürettiği iki nesne ise uyarlama farkı
ile damıtılmış küçük modeldir ve ikisi aynı sayıda seçenek kapatmıyor: uyarlama farkı taban modeli
çalıştırdığı için kullanım sınırına takılıyor, damıtılmış model çalıştırmadığı için ticari kullanım
kaydını üretemiyor. İkisi de daralıyor, ama **ayrı koşullardan**.

#### Eşik ve Hacim Değişince

Aynı koşullar sabit bir sayı vermez; sayı senaryonun büyüklüğüne bağlıdır.

```python
cok = sum(1 for s in SECENEK if len(kapali(s, KOSUL, ESIK)) > 1)
print(f"birden fazla kosulla kapanan secenek {cok} ; tek kosulla kapanan"
      f" {hepsi - cok} ; toplam kapanan {hepsi}")
print("\nesik ve hacim duyarliligi (kosumdan bagimsiz sayim):")
print("      esik  hacim  kapanan  acik  kullanim sinirinin tek basina kapattigi")
for esik, h in ((100000, 1), (250000, 1), (1000000, 1), (5000000, 1),
                (250000, 3), (250000, 10)):
    kap, top = sayim(KOSUL, esik, h)
    tek = sum(1 for v in VARLIK for k in KANAL if k1(v, (k[0], k[1] * h), esik))
    print(f"{esik:>10}  {str(h) + 'x':>5}  {kap:>7}  {top - kap:>4}  {tek:>38}")
```

```
birden fazla kosulla kapanan secenek 3 ; tek kosulla kapanan 7 ; toplam kapanan 10

esik ve hacim duyarliligi (kosumdan bagimsiz sayim):
      esik  hacim  kapanan  acik  kullanim sinirinin tek basina kapattigi
    100000     1x       12     4                                       9
    250000     1x       10     6                                       6
   1000000     1x        8     8                                       3
   5000000     1x        7     9                                       0
    250000     3x       12     4                                       9
    250000    10x       15     1                                      12
```

Eşik dört katına çıktığında açık seçenek altıdan sekize çıkıyor, eşik tamamen gevşediğinde dokuza.
Ters yönde ise değişim daha serttir: aylık hacim üç katına çıktığında açık seçenek **dörde**, on
katına çıktığında **bire** iniyor. On kat hacimde kurum içi kanal bile eşiği aşıyor ve geriye
yalnız damıtılmış modelin kurum içinde çalıştırılması kalıyor. Koşullar değişmedi; büyüyen şey iş
yüküydü. Bir dağıtım kararı, koşul metni okunduğu gün değil, **hacim eşiği geçtiği gün** kapanır.

#### Özet

- On altı dağıtım seçeneği dört varlık türü ile dört kanaldan kurulur; koşullar bu küme üzerinde
  birer yüklemdir ve sayım koşumdan bağımsızdır.
- Dört koşulun tek başına kapattığı toplam 13, birlikte kapattıkları 10'dur; üç seçenek birden
  fazla koşula takılır.
- Kullanım sınırı tek başına 6 seçenek kapatır ama kaldırıldığında 3 seçenek açar; ticari kullanım
  kaydı 2 kapatır ve 2 açar, yani hiçbir koşulla örtüşmez.
- Tam ağırlık kopyası ile damıtılmış küçük model için geriye tek kanal kalır, ama biri yeniden
  dağıtım hakkından biri ticari kullanım kaydından daralır.
- Aylık hacim üç katına çıktığında açık seçenek 6'dan 4'e, on katına çıktığında 1'e iner: kararı
  kapatan şey koşul metni değil, eşiğin geçildiği gündür.

#### Kurs Kapanışı

| Ders | Düzeneksiz | Düzenekli | Bedel |
|---|---|---|---|
| `api-kullanimi/01` — konuşma durumu | durum gönderilmiyor 0,2000 | tam döküm 0,8250 (**+0,6250**) | giriş belirteci 8346 → 31160 |
| `api-kullanimi/02` — ilk parça | akışsız, etiket sonda 16,03 adım | akış + etiket başta 4,96 adım (**−11,07**) | belirteç aynı; kurtarılan kesik yanıt 0 → 31 |
| `api-kullanimi/03` — geçerli araç çağrısı oranı | katalog yok 0,0500 | ad + parametre 0,6917 (**+0,6417**) | giriş 3694 → 11614; kalıntı 14 yanlış araç |
| `api-kullanimi/04` — şemaya uyum | isteme yazılan şema 0,7583 | arayüz alanı 0,9000 (**+0,1417**) | giriş belirteci 7654 → 4294; doğru kayıt başına 125,8 → 65,7 |
| `api-kullanimi/05` — kullanılabilir kayıt oranı | ince ızgara 0,8167 (183 belirteç) | kırpık ızgara 0,7000 (**−0,1167**) | kayıt başına 224,1 → 60,0 belirteç |
| `api-kullanimi/06` — üç komşunun aynı konudan olma payı | 144 boyut 0,9259 | 72 boyut 0,9028 (**−0,0231**) | saklanan sayı 10368 → yarısı |
| `api-kullanimi/07` — taşınan alan sayısı | sağlayıcının kendi arayüzü 12 | ortak arayüz 8 (**−4**) | çıkış belirteci 773 → 1638; okunabilen kesilme 0 |
| `api-kullanimi/08` — çağrı sayısı / etkilenen istek | toplu boyut 1: 120 çağrı, 1 istek | toplu boyut 12: 10 çağrı (**−110**), 12 istek | giriş 5854 → 1784; boyut 18'de isabet 0,0667 |
| `yz-uretim-kalitesi/01` — ağır yükte tamamlama payı | düzeneksiz 0,8562 | geri çekilmeli deneme 0,8750 (**+0,0188**) | koşum farkı da 0,0188; komşu akış 0,9500 → 0,8667 |
| `yz-uretim-kalitesi/02` — doğru yanıt payı | önbelleksiz 0,9333 | uzun ömürlü yanıt önbelleği 0,5542 (**−0,3791**) | çağrı 240 → 29; bayat pay 0,0208 → 0,4417 |
| `yz-uretim-kalitesi/03` — bekleme adımı / doğruluk | büyük bağlam 3,0000 adım, 0,9292 | iki aşamalı 1,7500 adım (**−1,2500**), **−0,0125** | giriş belirteci 19716 |
| `yz-uretim-kalitesi/04` — istek başına belirteç | kısaltmasız 81,6 | üç kısaltma politikası 50,5 (**−31,1**) | doğru etiket başına okununca aradaki fark daralıyor |
| `yz-uretim-kalitesi/05` — toplam isabet | yedeksiz 0,8450 | yedekli 0,8850 (**+0,0400**) | kesintisiz tabana göre 0,8975 → 0,8850; yedek katman 0,6667 |
| `yz-uretim-kalitesi/06` — isabet / oynayan yanıt payı | kalemler sabit 0,9125 | biçim sözcüğü serbest 0,5525 (**−0,3600**) | sağlayıcıdaki üç kalem oynadığında pay 0,1150 |
| `yz-destekli-gelistirme/01` — kabul edilen görev (24) | bağlamsız 7 | bütün kod tabanı 18 (**+11**) | 1104 → 4224 belirteç; bin belirteçte kabul 6,34 → 4,26 |
| `yz-destekli-gelistirme/02` — beklenen kabul | bütün dosyalar 0,6921 | seçilmiş dosyalar 0,8233 (**+0,1312**) | 4224 → 2274 belirteç; 120 → 45 dosya |
| `yz-destekli-gelistirme/03` — doğru adım (480) | sekiz adımda bir durma 355 | her adımda durma 478 (**+123**) | durma 60 → 479; kaçan hata 21 → 1 |
| `yz-destekli-gelistirme/04` — yakalanan kusur (28) | denetimsiz 0 | üç denetim 26 (**+26**) | kaçan 2; biri hiç uyarı almadan giriyor |
| `yz-destekli-gelistirme/05` — ayırt edilen bozuk sürüm (6) | üretilen sınama kümesi 3 | tek elle hiza maddesi 4 (**+1**) | 14 sınamanın 2'si temiz kodda düşüyor, 9'u hiçbir şey ayırmıyor |
| `yz-destekli-gelistirme/06` — sır sınıfı kapsaması | süzgeçsiz 0,0000 | alan adı süzgeci 0,9333 (**+0,9333**) | serbest metinde 12 iz kalıyor; kabul edilenlerde yanlış payı 0,5263 |
| `yerel-modeller/01` — etiket isabeti / eşzamanlı istek | küçük ölçek 0,6333, 248 istek | büyük ölçek 0,8667 (**+0,2334**), 5 istek | isabet çarpı eşzamanlı istek 157,1 → 4,3 |
| `yerel-modeller/02` — beş sınıflı konu isabeti | 16 basamak 0,8667 | 4 basamak 0,8000 (**−0,0667**) | bellek 34,3 → 8,6 milyar basamak; eşzamanlı istek 5 → 62 |
| `yerel-modeller/03` — isabet (60 kayıt) | taban 0,6000 | 60 örnekle istem 0,9667, ince ayar 0,9500 (**−0,0167**) | istek başına bağlam 28,48 → 623,48 belirteç; 180 adım, ağırlığın 0,2992'si |
| `yerel-modeller/04` — saha isabeti | uyarlama yok 0,2500 | düşük ranklı ek 0,9583 (**+0,7083**) | güncellenen pay 0,2094; sekiz sahada 18336 → 6132 sayı |
| `yerel-modeller/05` — konu isabeti | altı insan etiketi 0,5000 | 240 öğretmen etiketi 0,6333 (**+0,1333**) | 240 çağrı, 3256 belirteç; sayma görevi 0,5833 → 0,3667 |
| `yerel-modeller/06` — açık dağıtım seçeneği (16) | koşul okunmadan 16 | dört koşul sınıfı 6 (**−10**) | hacim on katına çıkınca 1 |

Kursun kuralı tabloda satır satır yazılıdır: **bir model çağrısı bir işlev çağrısı değil bir ağ
işlemidir; başarısızlığı yazılmayan çağrı ölçülmemiş sayılır.** Düzeneksiz sütunundaki sayıların
hiçbiri kötü bir kod yüzünden düşük değildir. Hepsi, çağrının gecikeceği, sıraya gireceği, yarıda
kesileceği, reddedileceği ya da bir başkasının sınırını tüketeceği hesaba katılmadığı için
düşüktür.

**İkinci iddia da aynı tablodan okunur: eklenen dayanıklılık işi kötüleştirebilir.** Bunu adıyla
yazan satırlar şunlardır. `yz-uretim-kalitesi/01`'de sabit aralıklı yeniden deneme ağır yükte
tamamlamayı düzeneksizin altına indirir ve aynı sınırı paylaşan etkileşimli akışı 0,9500'den
0,8667'ye düşürür. `yz-uretim-kalitesi/02`'de yanıt önbelleği çağrıyı 240'tan 29'a indirirken doğru
yanıt payını 0,9333'ten 0,5542'ye götürür. `yz-uretim-kalitesi/05`'te yedek katman toplam isabeti
yükseltiyor gibi görünür, ama kesintisiz tabana göre okunduğunda düşüş vardır ve yedeğe düşen
isteklerin isabeti 0,6667'dir. `yz-destekli-gelistirme/02`'de bağlamı büyütmek beklenen kabulü
0,8233'ten 0,6921'e indirir. `api-kullanimi/07`'de ortak arayüz çıkış belirtecini iki katına
çıkarır ve 117 kesilmenin hiçbirini okunabilir kılmaz. `api-kullanimi/08`'de toplu boyutu
büyütmek çağrıyı 120'den 10'a indirirken bağlam penceresini aşırma noktasında isabeti 0,0667'ye
düşürür. `yerel-modeller/03`'te altmış örnekle ince ayar istem düzeneğini geçmez.
`yerel-modeller/05`'te damıtma sayma görevinde 0,5833'ten 0,3667'ye götürür. Sekiz ayrı yerde
düzenek, eklendiği için ödedi.

Yirmi altı derste çağrı bir ağ işlemi olarak ele alındı ve her düzeneğin bedeli yazıldı. Bir şey
hiç sorulmadı: modele verilen **bilgi** hep istemin içine **elle** kondu. Belge dağarcığı kurgu
olarak vardı, ama bin belgelik bir dağarcıktan o isteme **hangi üçünün** gireceği, o seçimin
**hangi tabana karşı** ölçüleceği ve yanlış üçlüyü seçmenin bedelinin ne olduğu bir kez bile
sayılmadı. Sonraki kurs bu seçimi bir ölçüm nesnesine dönüştürür.

