İçeriğe geç
academia.sh

Ders 03 / 26

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

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.

İçindekiler

Ö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; ikisinin 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.

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

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.

İ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