İçeriğe geç
academia.sh

Ders 01 / 26

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.

İçindekiler

İ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.

# 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 nn turluk bir görüşmenin toplam gönderimi n(n+1)/2n(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.

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.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat