İçeriğe geç
academia.sh

Ders 13 / 26

Hata ve Kesinti Yönetimi

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.

İçindekiler

Ö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 ikisi 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

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

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östergedir; 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.

İ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