İçeriğe geç
academia.sh

Ders 08 / 22

Araç Tanımı

Aracın adının, açıklamasının ve şemasının döngüye ne kattığının ölçülmesi: 24 kurgu görevde tanım dört düzeyde verilir ve yalnız ad verildiğinde 157 çağrının 113'ü araç hatasıyla döner, geçerli çağrı oranı 0,2803'te kalır, görev başarımı 0,3333 olur. Açıklama eklendiğinde hata 56'ya iner ve başarım 0,6667'ye çıkar. Şema eklendiğinde çağrı sayısı 74'e, hata 8'e düşer ve geçerli oran 0,8919 olur, ama başarım 0,7917'de durur: şema alan adlarını verir, hangi alanın hangi değeri taşıdığını vermez ve yer değiştiren iki endeks şemadan geçen bir çağrıyla 52 yerine 99948 döndürür. Örnek çağrı bu payı sıfırlar, başarımı 0,9583'e çıkarır ve adım, çağrı ile araç hatasını hiç değiştirmez; bedeli katalogun 97'den 164 belirtece büyümesidir ve doğru yanıt başına belirteç 1126'dan 1212'ye çıkar.

İçindekiler

Önceki yedi derste ajan döngüsü kuruldu: algı, akıl yürütme, eylem ve gözlem sırası, planlayıcı ile yürütücünün ayrılması, adım bütçesi, durdurma ölçütü, öz eleştiri turu, çoklu ajan düzeni ve yan etkili araçta onay noktası. Hepsinde bir şey sessizce varsayıldı: araç hazır ve doğruydu.

Bu ders o varsayımı kaldırır: aracın tanımı döngüye ne katıyor? Model API’leri ile Uygulama Geliştirme kursu tek bir çağrının biçimini ölçmüştü — katalog verilmediğinde geçerli çağrı oranı 0,0500, adlar ve parametreler birlikte verildiğinde 0,6917. O ölçüm bir metnin ayrıştırılması üzerineydi ve tekrarlanmaz; sayılar girdi alınır. Buradaki çağrı bir işlev sınırından geçer ve ölçülen şey tanımın döngü boyunca kattığıdır.

  • AB1. Ortam, araç kümesi, görev kümesi ve ajan döngüsü kurgudur; gerçek bir model uç noktası, araç sunucusu ya da çalışma zamanı çağrılmaz. 60 kurgu abone, 5 kurgu belge, 5 araç ve bilinen bir araç dizisiyle çözülen 24 görev. Tohum 20260218, ikinci koşum 20260219.
  • AB2. Araç tanımı dört düzeyde verilir: yalnız ad; ad ve açıklama; ad, açıklama ve şema; şema ve örnek çağrı. Her düzey bir öncekini kapsar.
  • AB3. Tanım iki şeyi belirler: doğru aracı seçme payının çarpanını ve bildirilen her alanın doldurulma payını. Ad zayıf bir imdir; açıklama aracın ne yaptığını, şema hangi alanları istediğini söyler.
  • AB4. Şema alan adlarını verir, alanların hangi değeri taşıdığını vermez. Aynı türden iki alan (onceki ve simdiki) 0,30 payla yer değiştirir; örnek çağrı bu payı sıfırlar.
  • AB5. Araç hatası aracın kendi döndürdüğü hatadır: eksik alan ya da olmayan araç. Şema dışındaki alanlar çağrı sınırında süzülür; geçerli çağrı, hata döndürmeyendir.
  • AB6. Katalog her adımda istemde durur; bedeli düzeyin belirteç sayısıdır.
  • AB7. Taban çizgisi yalnız ad düzeyidir; düzeneksiz döngü budur. Adım bütçesi dört düzeyde de sekizdir.
  • AB8. Görev başarımı, döngünün bıraktığı sonucun doğru yanıta eşit olmasıdır; ajanın kendi kendine durup durmadığından bağımsızdır.

Tanımın Dört Düzeyi

Aşağıdaki kod ortamı, araç kümesini, görev kümesini ve ajan döngüsünü kurar, sonra döngünün üzerine tanım katmanını ekler. Çağrı sınırı şema dışı alanları yine süzer, fakat bildirilen bir alanın doldurulup doldurulmadığı artık tanımın düzeyine bağlıdır.

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):
    b = []
    for s in str(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 str(m):
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


# ---- KURGU ortam: olcum aginin kayitlari
BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
ABONE = {}
for i in range(60):
    r = uretec(TOHUM + 31 * i)
    onceki = 10000 + int(r() * 80000)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "onceki": onceki, "simdiki": onceki + int(r() * 70)}
BASAMAK, USTU = ((10, 4), (25, 7), (40, 11)), 16
ISYERI_KAT = 2
BELGE = {"TR01": "tarife basamaklari 10 25 40 metrekup ve ustu",
         "TR02": "isyeri abonesinde birim ucret iki katidir",
         "SY01": "endeks farki tuketimi verir sayac donusu 100000 eklenir",
         "AR01": "ariza kaydi acildiginda saha ekibi iki gun icinde gider",
         "KS01": "planli kesinti duyurusu bir hafta once yayimlanir"}

CAGRI = [0]                              # arac cagri sayaci


def _bedel(m3, tip):
    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
    top += kalan * USTU
    return top * (ISYERI_KAT if tip == "isyeri" else 1)


def t_sayac_oku(abone=None, **_):
    a = ABONE.get(abone)
    if a is None:
        return {"hata": "abone yok"}
    return {"onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"], "bolge": a["bolge"]}


def t_tuketim(onceki=None, simdiki=None, **_):
    if onceki is None or simdiki is None:
        return {"hata": "eksik alan"}
    f = simdiki - onceki
    return {"m3": f + 100000 if f < 0 else f}


def t_tarife(m3=None, tip="mesken", **_):
    if m3 is None:
        return {"hata": "eksik alan"}
    return {"tutar": _bedel(m3, tip)}


def t_belge(anahtar=None, **_):
    if not anahtar:
        return {"hata": "eksik alan"}
    ab = set(belirtecle(anahtar))
    en, kod = -1, None
    for k, m in BELGE.items():
        o = len(ab & set(belirtecle(m)))
        if o > en:
            en, kod = o, k
    return {"kod": kod, "metin": BELGE[kod]} if en > 0 else {"hata": "bulunamadi"}


def t_kayit(abone=None, sutun=None, deger=None, **_):
    if not (abone and sutun and deger is not None):
        return {"hata": "eksik alan"}
    return {"yazildi": True, "abone": abone, "sutun": sutun, "deger": deger}


ARAC = {
    "sayac_oku":  {"islev": t_sayac_oku, "alan": ("abone",), "yan_etki": False},
    "tuketim":    {"islev": t_tuketim, "alan": ("onceki", "simdiki"), "yan_etki": False},
    "tarife":     {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False},
    "belge_ara":  {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False},
    "kayit_yaz":  {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True},
}
ARAC_ADI = list(ARAC)

# ---- KURGU gorevler: her biri bilinen bir arac dizisiyle cozulur
GOREV = []
for i in range(24):
    r = uretec(TOHUM + 9973 * i)
    ab = f"A{1 + int(r() * 60):03d}"
    t = ayrik(r(), [0.30, 0.22, 0.20, 0.28])
    if t == 0:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "bedel", "abone": ab,
                      "istek": f"{ab} abonesinin bu donem bedeli nedir",
                      "dizi": ("sayac_oku", "tuketim", "tarife")})
    elif t == 1:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "tuketim", "abone": ab,
                      "istek": f"{ab} abonesinin bu donem tuketimi kac metrekup",
                      "dizi": ("sayac_oku", "tuketim")})
    elif t == 2:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "belge", "abone": ab,
                      "istek": "sayac donusunde endeks farki nasil hesaplanir",
                      "dizi": ("belge_ara",)})
    else:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "kayit", "abone": ab,
                      "istek": f"{ab} abonesinin bedelini hesapla ve kayda yaz",
                      "dizi": ("sayac_oku", "tuketim", "tarife", "kayit_yaz")})


def dogru_yanit(g):
    a = ABONE[g["abone"]]
    f = a["simdiki"] - a["onceki"]
    m3 = f + 100000 if f < 0 else f
    if g["tur"] == "tuketim":
        return m3
    if g["tur"] == "belge":
        return "SY01"
    return _bedel(m3, a["tip"])


# ---- KURGU ajan: her adimda bir arac secer ya da biter
def gorme(d):
    return max(0.34, 0.80 - 0.09 * (d - 1))       # dogru araci secme payi, derinlikle duser


ACIKLAMA = {
    "sayac_oku": "abonenin onceki ve simdiki sayac endeksini dondurur",
    "tuketim":   "iki endeks arasindaki farki metrekup olarak verir",
    "tarife":    "metrekup ve abone tipinden donem bedelini hesaplar",
    "belge_ara": "anahtar metne en yakin kurgu belgeyi getirir",
    "kayit_yaz": "bir abonenin bir sutununa deger yazar ; yan etkilidir"}
ORNEK = {"sayac_oku": "sayac_oku ( abone = A007 )",
         "tuketim":   "tuketim ( onceki = 41200 , simdiki = 41255 )",
         "tarife":    "tarife ( m3 = 55 , tip = mesken )",
         "belge_ara": "belge_ara ( anahtar = endeks farki )",
         "kayit_yaz": "kayit_yaz ( abone = A007 , sutun = bedel , deger = 470 )"}
# duzey : ad , secim carpani , alan doldurma payi , yer degistirme payi
TANIM = {1: ("yalniz ad", 0.62, 0.45, 0.30),
         2: ("ad + aciklama", 0.86, 0.72, 0.30),
         3: ("ad + aciklama + sema", 1.00, 1.00, 0.30),
         4: ("sema + ornek cagri", 1.00, 1.00, 0.00)}


def katalog(duzey, ad):
    s = ad
    if duzey >= 2:
        s += " : " + ACIKLAMA[ad]
    if duzey >= 3:
        s += " ( " + " , ".join(ARAC[ad]["alan"]) + " )"
    if duzey >= 4:
        s += " ornek : " + ORNEK[ad]
    return s


TANIM_BEL = {d: sum(len(belirtecle(katalog(d, a))) for a in ARAC) for d in TANIM}


def cagir_tanimli(ad, durum, duzey, rt):
    """Ortak cagri sinirinin tanim katmanli hali: bildirilen alanin
    doldurulup doldurulmadigi tanimin duzeyine baglidir."""
    CAGRI[0] += 1
    if ad not in ARAC:
        return {"hata": "arac yok"}
    _, _, pay, karis = TANIM[duzey]
    kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum and rt() < pay}
    if {"onceki", "simdiki"} <= set(kw) and rt() < karis:
        kw["onceki"], kw["simdiki"] = kw["simdiki"], kw["onceki"]
    return ARAC[ad]["islev"](**kw)


def ajan_tanim(g, duzey=4, en_cok_adim=8, tohum=TOHUM):
    """Ortak ajan dongusu; tek fark cagrinin tanim katmanindan gecmesi
    ve katalogun her adimda istemde durmasi."""
    r = uretec(tohum ^ izno(g["ad"]))
    rt = uretec(tohum ^ izno(g["ad"] + "tanim"))
    carpan = TANIM[duzey][1]
    alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"}
    iz, adim, bel, hata, yabanci = [], 0, 0, 0, 0
    dizi, k = g["dizi"], 0
    while adim < en_cok_adim:
        adim += 1
        bel += 60 + 22 * len(iz) + TANIM_BEL[duzey]
        hedef = dizi[k] if k < len(dizi) else None
        if hedef is None:
            if r() < 0.88:
                break
            sec = ARAC_ADI[int(r() * len(ARAC_ADI))]
        else:
            sec = hedef if r() < gorme(k + 1) * carpan else ARAC_ADI[int(r() * len(ARAC_ADI))]
        if sec == "kayit_yaz":
            alan["deger"] = alan.get("sonuc")
        s = cagir_tanimli(sec, alan, duzey, rt)
        iz.append((sec, "hata" in s))
        bel += 30
        if "hata" in s:
            hata += 1
            continue
        yabanci += sec not in dizi
        alan.update({kk: vv for kk, vv in s.items() if kk != "hata"})
        if sec == "tuketim":
            alan["sonuc"] = s["m3"]
        if sec == "tarife":
            alan["sonuc"] = s["tutar"]
        if sec == "belge_ara":
            alan["sonuc"] = s["kod"]
        if sec == hedef:
            k += 1
    return {"adim": adim, "belirtec": bel, "hata": hata, "yabanci": yabanci,
            "yanit": alan.get("sonuc")}


for d in TANIM:
    print(f"duzey {d}  {TANIM[d][0]:<20} katalog {TANIM_BEL[d]:>3} belirtec")
print("  duzey 3 satiri :", katalog(3, "tuketim"))
print("  duzey 4 eki    : ornek :", ORNEK["tuketim"])
g = GOREV[2]
for d in (3, 4):
    s = ajan_tanim(g, d)
    print(f"  {g['ad']} {g['tur']:<8} duzey {d}  yanit {s['yanit']:>6}  dogru"
          f" {dogru_yanit(g)}  arac hatasi {s['hata']}")
duzey 1  yalniz ad            katalog  10 belirtec
duzey 2  ad + aciklama        katalog  71 belirtec
duzey 3  ad + aciklama + sema katalog  97 belirtec
duzey 4  sema + ornek cagri   katalog 164 belirtec
  duzey 3 satiri : tuketim : iki endeks arasindaki farki metrekup olarak verir ( onceki , simdiki )
  duzey 4 eki    : ornek : tuketim ( onceki = 41200 , simdiki = 41255 )
  G03 tuketim  duzey 3  yanit  99948  dogru 52  arac hatasi 1
  G03 tuketim  duzey 4  yanit     52  dogru 52  arac hatasi 1

Son iki satır bu dersin çekirdeğidir. Aynı görev, aynı tohum, aynı araç dizisi ve aynı sayıda araç hatası. Üçüncü düzeyde ajan tuketim aracını şemanın bildirdiği iki alanla çağırdı, çağrı şemadan geçti, araç hata döndürmedi — ve sonuç 52 yerine 99948 çıktı. Şema onceki ile simdiki adlarını bildiriyor, hangisinin küçük olduğunu bildirmiyor. Alanlar yer değiştirdiğinde fark eksiye düşüyor, sayaç dönüşü kuralı devreye giriyor ve araç yüz bine yakın bir tüketim döndürüyor. Bu çağrı geçerlidir ve yanlıştır.

Dört Düzeyin Sayıları

Aynı 24 kurgu görev dört tanım düzeyinde koşturulur; başarım iki tohumla ayrı ayrı basılır.

def olc(duzey, tohum=TOHUM):
    CAGRI[0] = 0
    ok = adim = bel = hata = yab = 0
    for g in GOREV:
        s = ajan_tanim(g, duzey, tohum=tohum)
        ok += s["yanit"] == dogru_yanit(g)
        adim += s["adim"]
        bel += s["belirtec"]
        hata += s["hata"]
        yab += s["yabanci"]
    return ok / len(GOREV), CAGRI[0], hata, yab, adim, bel


print("tanim duzeyi          cagri  hata  gecerli  basarim A  basarim B  adim"
      "  belirtec  yanit basina")
for d in TANIM:
    a, b = olc(d), olc(d, TOHUM + 1)
    print(f"{TANIM[d][0]:<20} {a[1]:>6} {a[2]:>5}  {(a[1] - a[2]) / a[1]:>7.4f}"
          f"  {a[0]:>9.4f}  {b[0]:>9.4f}  {a[4]:>4}  {a[5]:>8}  {a[5] / (a[0] * 24):>12.0f}")
a = olc(4)
print(f"en yuksek duzey : gecerli {a[1] - a[2]} cagrinin {a[3]} tanesi gorevin"
      f" dizisinde olmayan bir araci cagiriyor")
tanim duzeyi          cagri  hata  gecerli  basarim A  basarim B  adim  belirtec  yanit basina
yalniz ad               157   113   0.2803     0.3333     0.4167   167     27950          3494
ad + aciklama           111    56   0.4955     0.6667     0.5833   129     27489          1718
ad + aciklama + sema     74     8   0.8919     0.7917     0.7917    97     21387          1126
sema + ornek cagri       74     8   0.8919     0.9583     0.9583    97     27886          1212
en yuksek duzey : gecerli 66 cagrinin 8 tanesi gorevin dizisinde olmayan bir araci cagiriyor

Taban çizgisi ilk satırdır: yalnız ad bilindiğinde 157 çağrının 113’ü araç hatasıyla dönüyor, geçerli çağrı oranı 0,2803, başarım 0,3333. Hataların çoğu eksik alandır. Ad, aracın ne istediğini söylemez; ajan elindeki durumdan hangi anahtarı geçireceğini bilemez. Bedeli adım sütununda görünür: bütçe sekiz olduğu halde toplam adım 167, görev başına yedinin üstünde. Hatalı çağrı adımı harcar ve diziyi ilerletmez.

Açıklama eklendiğinde hata 56’ya, çağrı 111’e iniyor, başarım 0,6667 oluyor. Açıklama iki iş yapar: doğru aracı seçme payını yükseltir ve alanların hangi bilgiyi istediğini ima eder. Şema eklendiğinde çağrı 74’e, hata 8’e düşüyor, geçerli oran 0,8919 oluyor ve adım 97’ye iniyor. Kalan sekiz hata şemayla ilgili değildir: yanlış seçilen bir aracın kendi ön koşulu tutmaz.

Şemanın Söylemediği

Üçüncü ve dördüncü satır aynı çağrıyı, aynı hatayı ve aynı adımı taşıyor; başarımları 0,7917 ile 0,9583 olarak ayrışıyor. Aradaki 0,1666, örnek çağrının kattığıdır ve döngüye tek bir adım eklemeden gelir. İki koşum farkı ilk iki düzeyde 0,0834, son iki düzeyde sıfırdır; 0,1666 bu bandın iki katının üstündedir ve ölçülmüş sayılır. Örnek çağrı, şemanın veremediği tek bilgiyi verir: alanın hangi değeri taşıdığını.

Bedel belirteç sütunundadır. Katalog 97 belirteçten 164 belirtece büyür ve her adımda istemde durduğu için toplam belirteç 21387’den 27886’ya çıkar. Doğru yanıt başına belirteç ise 1126’dan 1212’ye yükselir: örnek çağrı başarımı yükseltirken bu ölçekte birim maliyeti de yükseltiyor. Bedeli yazılmayan düzenek ölçülmemiş sayılır; buradaki bedel altmış yedi belirteçtir.

Son satır şemanın en dıştaki sınırıdır. En yüksek düzeyde bile geçerli 66 çağrının sekizi görevin dizisinde olmayan bir aracı çağırıyor. Model API’leri kursunda aynı kalıntı ondört yanlış araç adıydı; orada çağrı bir metindi, burada bir işlev sınırından geçti ve araç düzgün çalıştı. Bir tanım neyin çağrılabileceğini söyler, neyin çağrılması gerektiğini söylemez.

Özet

  • Araç tanımı dört düzeye ayrılır: yalnız ad, ad ve açıklama, şema, şema ve örnek çağrı.
  • Yalnız ad verildiğinde 157 çağrının 113’ü araç hatasıyla döner, geçerli oran 0,2803, başarım 0,3333’tür; hatalı çağrı adım harcar ve toplam adımı 167’ye çıkarır.
  • Açıklama hatayı 56’ya, şema 8’e indirir; şemayla çağrı 74’e, adım 97’ye iner, geçerli oran 0,8919 olur.
  • Şema alan adlarını verir, alanın hangi değeri taşıdığını vermez: yer değiştiren iki endeks şemadan geçen bir çağrıyla 52 yerine 99948 döndürür.
  • Örnek çağrı başarımı 0,7917’den 0,9583’e çıkarır ve adımı, çağrıyı, hatayı hiç değiştirmez; bedeli katalogun 164 belirtece büyümesi ve yanıt başına belirtecin 1126’dan 1212’ye çıkmasıdır.
  • En yüksek düzeyde bile geçerli 66 çağrının sekizi görevin dizisinde olmayan aracı çağırır; geçerlilik doğruluk değildir.

Sonraki Adım

Bu derste araç çağrıldı ve döndürdüğü sözlük olduğu gibi duruma yazıldı; her alan bir sonraki adıma taşındı ve her adımda istemde yeniden durdu. Belirteç sütununun görev başına bin belirtecin üstüne çıkmasının bir nedeni budur. Sonucu olduğu gibi taşımak tek seçenek değildir: kırpılabilir, özetlenebilir, yalnız gereken alan bırakılabilir. Her biri belirteci düşürür ve bir şeyi düşürme riski taşır. Sonraki ders sonucun modele hangi biçimde geri verildiğini ölçer ve başarımı döngü boyunca biriken belirteçle yan yana basar.

İ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