---
title: 'Mesaj Tabanlı Arayüzler'
source: 'https://academia.sh/tr/kurslar/model-apileri/mesaj-tabanli-apiler'
course: "Model API'leri ile Uygulama Geliştirme"
language: tr
updated: '2026-08-17T18:06:37+00:00'
license: 'CC BY-SA 4.0'
---

# Mesaj Tabanlı Arayüzler

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 dördü 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 API Tasarımı ve Belgelendirme 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.
