Ders 09 / 22
Araç Çağrısının Yürütülmesi
Aracın döndürdüğü sonucun modele hangi biçimde geri verildiğinin ölçülmesi: 24 kurgu görevde ham gözlem 770 gözlem belirteci ve 10103 toplam belirteçle 0,9583 başarım verir. Gözlemi yedi sözcüğe kırpmak belirteci 9160'a indirir ama abone tipini düşürdüğü için dört işyeri faturası tam yarısı çıkar ve başarım 0,7917'ye iner. Dört sözcüğe kırpmak zinciri koparır: araç hatası 8'den 116'ya, adım 97'den 156'ya, toplam belirteç 15945'e fırlar ve başarım 0,2917'de kalır — ucuzlatmak pahalılaştırır. Taşınacak alanı bildiren özet, ham gözlemin başarımını iki koşumda da korurken gözlem belirtecini 401'e, doğru yanıt başına belirteci 439'dan 401'e indirir. Aynı özetten abone tipi çıkarıldığında başarım kırpmanınkine, 0,7917'ye düşer: özet, bildirimi kadar iyidir.
İçindekiler
Önceki derste araç tanımı dört düzeye ayrıldı ve en yüksek düzeyde geçerli çağrı oranı 0,8919, görev başarımı 0,9583 oldu. O ölçümde çağrının dönüşü hiç sorgulanmadı: araç ne döndürdüyse bütün alanlarıyla duruma yazıldı ve bir sonraki adıma taşındı.
Bir döngüde bu kararsız bir varsayımdır. Araç sonucu modele geri verilen bir gözlemdir ve o gözlem her adımda istemde yeniden durur. Bir belge aracının döndürdüğü tam metin, bir okuma aracının döndürdüğü dört alan, bir yazma aracının onayı — hepsi döngü uzadıkça birikir. Bu dersin sorusu şudur: gözlem hangi biçimde geri verilirse başarım ne olur ve döngü boyunca kaç belirteç birikir.
- AB9. 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.
- AB10. Araç bir sözlük döndürür; gözlem o sözlüğün metne çevrilmiş halidir. Ajan durumunu sözlükten değil, gözlem metninden geri okuyarak günceller.
- AB11. Üç gözlem biçimi vardır. Ham gözlem bütün alanları taşır. Kırpılmış gözlem metni belirli bir sözcük sayısında keser; kesilen yerde değeri eksik kalan alan geri okunamaz. Özetlenmiş gözlem, araç başına bildirilen alanları taşır.
- AB12. Kırpma iki eşikte ölçülür: yedi sözcük ve dört sözcük.
- AB13. Biriken gözlem her adımda istemde yeniden gönderilir. Ortak döngü bu birikimi adım başına sabit bir katsayıyla sayar; bu ders o katsayının yerine gerçekten taşınan gözlemin belirtecini koyar. Belirteç kurgu belirteçleyiciyle sayılır.
- AB14. Hata döndüren çağrının gözlemi de birikir; hata metni de bir gözlemdir.
- AB15. Taban çizgisi ham gözlemdir; düzeneksiz döngü budur. Kırpma ve özetleme eklenen düzenektir. Adım bütçesi dört biçimde de sekizdir.
- AB16. Görev başarımı, döngünün bıraktığı sonucun doğru yanıta eşit olmasıdır.
Gözlemin Üç Biçimi
Aşağıdaki kod ortak ortamı, araç kümesini ve görev kümesini kurar, sonra gözlem katmanını ekler: sözlüğü metne çeviren bir yazıcı, metinden alanları geri okuyan bir çözücü ve üç biçim.
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) def cagir_arac(ad, durum): """Sema disindaki alanlar suzulur; eksik alan aracin kendi hatasidir.""" CAGRI[0] += 1 if ad not in ARAC: return {"hata": "arac yok"} kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum} return ARAC[ad]["islev"](**kw) # ---- 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 # Aracin dondurdugu sozluk, modele geri verilmeden once bir metne cevrilir. OZET_ALAN = {"sayac_oku": ("onceki", "simdiki", "tip"), "tuketim": ("m3",), "tarife": ("tutar",), "belge_ara": ("kod",), "kayit_yaz": ("yazildi",)} BICIM = {"ham": None, "kirpik 7": 7, "kirpik 4": 4, "ozet": None} def sozlukten(s): return " , ".join(f"{k} = {v}" for k, v in s.items()) def coz(metin): """Gozlem metninden alanlari geri okur; degeri kesilmis alan dusulur.""" d = {} for p in metin.split(" , "): a, _, v = p.partition(" = ") v = v.strip(" ,") if v: d[a.strip(" ,")] = int(v) if v.lstrip("-").isdigit() else v return d def gozlemle(ad, sonuc, bicim): """Ham , kirpilmis ya da ozetlenmis gozlem metni.""" if bicim == "ozet": sonuc = {k: v for k, v in sonuc.items() if k in OZET_ALAN.get(ad, ())} metin = sozlukten(sonuc) if BICIM[bicim]: metin = " ".join(metin.split()[:BICIM[bicim]]) return metin def ajan_gozlem(g, bicim="ham", en_cok_adim=8, tohum=TOHUM): """Ortak ajan dongusu; tek fark gozlemin bir metne cevrilip geri okunmasi ve biriken gozlem belirtecinin her adimda yeniden gonderilmesi.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} iz, adim, bel, hata, birik = [], 0, 0, 0, 0 dizi, k = g["dizi"], 0 while adim < en_cok_adim: adim += 1 bel += 60 + birik # biriken gozlem her adimda yeniden gonderilir 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) else ARAC_ADI[int(r() * len(ARAC_ADI))] if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) iz.append((sec, "hata" in s)) bel += 30 metin = gozlemle(sec, s, bicim) birik += len(belirtecle(metin)) if "hata" in s: hata += 1 continue d = coz(metin) alan.update(d) if sec == "tuketim" and "m3" in d: alan["sonuc"] = d["m3"] if sec == "tarife" and "tutar" in d: alan["sonuc"] = d["tutar"] if sec == "belge_ara" and "kod" in d: alan["sonuc"] = d["kod"] if sec == hedef: k += 1 return {"adim": adim, "belirtec": bel, "hata": hata, "gozlem": birik, "yanit": alan.get("sonuc")} for ad in ("sayac_oku", "belge_ara"): ornek = ARAC[ad]["islev"](**{"abone": "A007", "anahtar": "endeks farki"}) for b in ("ham", "kirpik 7", "ozet"): m = gozlemle(ad, ornek, b) print(f"{ad:<10} {b:<9} {len(belirtecle(m)):>2} belirtec {m}") print(f"{ad:<10} kirpik 7 geri okunan alanlar :", " , ".join(coz(gozlemle(ad, ornek, "kirpik 7"))))
sayac_oku ham 19 belirtec onceki = 78189 , simdiki = 78241 , tip = mesken , bolge = merkez sayac_oku kirpik 7 9 belirtec onceki = 78189 , simdiki = 78241 sayac_oku ozet 14 belirtec onceki = 78189 , simdiki = 78241 , tip = mesken sayac_oku kirpik 7 geri okunan alanlar : onceki , simdiki belge_ara ham 19 belirtec kod = SY01 , metin = endeks farki tuketimi verir sayac donusu 100000 eklenir belge_ara kirpik 7 8 belirtec kod = SY01 , metin = endeks belge_ara ozet 3 belirtec kod = SY01 belge_ara kirpik 7 geri okunan alanlar : kod , metin
İki araç aynı ham boyu taşıyor — on dokuz belirteç — ve iki biçim onları çok farklı yerlerinden
kesiyor. Kırpma konuma bakar: sayac_oku gözleminde son iki alan, abone tipi ve bölge,
yedinci sözcükten sonra kaldıkları için düşüyor. Özet bildirime bakar: aynı araçta tip
bildirilmiş olduğu için kalıyor, bölge bildirilmediği için gidiyor. Belge aracında sıralama tersine
işliyor; orada kod başta durduğu için kırpma onu koruyor, özet ise metnin tamamını atarak on dokuz
belirteci üçe indiriyor.
Dört Biçimin Sayıları
Aynı 24 kurgu görev dört biçimde koşturulur. Gözlem belirteci, döngü boyunca üretilen gözlem metinlerinin toplam uzunluğudur; toplam belirteç ise onların yeniden gönderilmesini de içerir.
def olc(bicim, tohum=TOHUM): CAGRI[0] = 0 ok = adim = bel = hata = goz = 0 for g in GOREV: s = ajan_gozlem(g, bicim, tohum=tohum) ok += s["yanit"] == dogru_yanit(g) adim += s["adim"] bel += s["belirtec"] hata += s["hata"] goz += s["gozlem"] return ok / len(GOREV), CAGRI[0], hata, adim, goz, bel print("gozlem bicimi cagri hata adim gozlem bel toplam bel basarim A" " basarim B yanit basina") for b in BICIM: a, c = olc(b), olc(b, TOHUM + 1) print(f"{b:<13} {a[1]:>6} {a[2]:>5} {a[3]:>5} {a[4]:>11} {a[5]:>11}" f" {a[0]:>9.4f} {c[0]:>9.4f} {a[5] / (a[0] * 24):>12.0f}") OZET_ALAN["sayac_oku"] = ("onceki", "simdiki") # tip bildirimden dusuruldu a = olc("ozet") print(f"dar ozet ( tip bildirilmiyor ) : basarim {a[0]:.4f} , gozlem belirteci" f" {a[4]} , arac hatasi {a[2]}")
gozlem bicimi cagri hata adim gozlem bel toplam bel basarim A basarim B yanit basina ham 74 8 97 770 10103 0.9583 0.9583 439 kirpik 7 74 8 97 428 9160 0.7917 0.7500 482 kirpik 4 149 116 156 616 15945 0.2917 0.2917 2278 ozet 74 8 97 401 9229 0.9583 0.9583 401 dar ozet ( tip bildirilmiyor ) : basarim 0.7917 , gozlem belirteci 311 , arac hatasi 8
Taban çizgisi ilk satırdır: ham gözlem 770 gözlem belirteci üretir, toplam 10103 belirteç harcar ve başarımı 0,9583‘te tutar. İkinci satır kırpmanın kattığını ve düşürdüğünü yan yana koyar. Gözlem belirteci **428’e**, toplam 9160’a iner — ama başarım 0,7917 olur. Çağrı, adım ve araç hatası hiç değişmez; düşen dört görevin hepsi işyeri abonesidir ve dördünde de fatura tam yarısı çıkar. Tip düşünce tarife aracı bildirilmiş varsayılan değeri, yani meskeni kullanır. Kırpma bir hata üretmedi, sessiz bir yanlış üretti.
Üçüncü satır kursun ikinci iddiasının açık bir örneğidir. Kırpmayı dört sözcüğe sıkmak sayac_oku
gözleminde ikinci endeksi de keser; tuketim aracı eksik alanla döner, zincir kopar ve ajan aynı
adımı yeniden dener. Araç hatası 8’den 116’ya, çağrı 74’ten 149’a, adım 97’den 156’ya
çıkar. Sonuç şudur: gözlem belirteci ham biçimden hâlâ düşük (616), fakat toplam belirteç
15945’e fırlar — ham biçimin bir buçuk katı. Gözlemi ucuzlatmak döngüyü pahalılaştırdı.
Bildirim ve Konum
Son satır özetin sayısıdır ve tabloda tek başına durur: başarım iki koşumda da 0,9583, yani ham gözlemle aynı; gözlem belirteci 401, yani hamın yarısından az; doğru yanıt başına belirteç 439’dan 401’e iner. Özet hem en ucuz hem en isabetli biçimdir, çünkü neyi atacağını konumdan değil bildirimden okur.
Bu üstünlük bedava değildir ve son çıktı satırı bedelini yazar. Özetin bildiriminden yalnız tip
alanı düşürüldüğünde başarım 0,7917’ye iner — kırpmanın düştüğü yere. Özet, bildirimi kadar
iyidir; hangi alanın sonraki adımda gerekeceğini bilen kişi onu bildirmek zorundadır ve bunu
bilmiyorsa özet, kırpmadan daha güvenli değildir.
Tabloda bir satır ters görünüyor: özetin gözlem belirteci kırpık yedininkinden düşük (401’e karşı
428) ama toplam belirteci yüksek (9229’a karşı 9160). Nedeni birikimin aritmetiğidir. Bir gözlem,
kendisinden sonra gelen her adımda yeniden gönderilir; bu yüzden erken gözlem geç gözlemden
pahalıdır. Özet, sayac_oku gözlemini 14 belirteçte tutar (kırpma 9’da), ve o gözlem çoğu görevin
ilk adımındadır. Buna karşılık özetin büyük kazancı belge_aradadır (19’dan 3’e), ve o gözlem
tek adımlık görevlerin son adımıdır, yani hiç yeniden gönderilmez.
Özet
- Araç sonucu duruma doğrudan yazılmaz: bir gözlem metnine çevrilir, geri okunur ve her adımda istemde yeniden gönderilir.
- Ham gözlem 770 gözlem belirteci, 10103 toplam belirteç ve 0,9583 başarım verir; taban çizgisi budur.
- Yedi sözcüğe kırpmak belirteci 9160’a indirir ama abone tipini düşürdüğü için dört işyeri faturasını yarıya indirir ve başarımı 0,7917’ye çeker; araç hatası hiç artmaz, yanlış sessizdir.
- Dört sözcüğe kırpmak zinciri koparır: araç hatası 116’ya, adım 156’ya, toplam belirteç 15945’e çıkar ve başarım 0,2917’ye iner; gözlemi ucuzlatmak döngüyü pahalılaştırır.
- Bildirimli özet ham gözlemin başarımını korurken gözlem belirtecini 401’e ve doğru yanıt başına belirteci 401’e indirir; aynı özetten tip çıkarıldığında başarım 0,7917’ye düşer.
- Birikimde erken gözlem geç gözlemden pahalıdır: bir gözlem kendisinden sonraki her adımda yeniden gönderilir.
Sonraki Adım
Bu iki derste araçlar tanımlandı, çağrıldı ve dönüşleri biçimlendirildi. Hepsinin ortak bir yanı vardı: her araç sabit bir işi yapıp döndü. Bir okuma sabit sayıda alan, bir hesap sabit sayıda işlem, bir arama sabit bir metin. Bu yüzden bir çağrının ne kadar tutacağı hiç sorulmadı. Ajanın kendi yazdığı bir programı çalıştıran bir araçta bu varsayım kalkar: kaç adım süreceği, kaç hücre tutacağı ve kaç çıktı üreteceği tanımda yazmaz, ancak çalışırken görülür. Sonraki ders böyle bir aracı sanal alan içinde kaynak sınırlarıyla kurar, bildirilen sınırı aşan çağrıları sayar ve durdurmanın kaç görevi düşürdüğünü ayrıca yazar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.