Ders 14 / 22
Uzun Süreli Bellek
Üç yazma politikasının aynı 48 görevlik ikinci kümede ölçülmesi: her adımın gözlemini ayrı kayıt yapmak 74 kayıt biriktiriyor ve 44 adım kazandırıyor, görev başına tek yanıt kaydı yazmak 24 kayıtla 199 adım kazandırıyor ama başarımı 0,9167'den 0,5833'e düşürüyor, plana giren gözlemleri tek kayıtta birleştiren seçici politika ise yine 24 kayıtla 118 adım kazandırıyor. Kazandıran şey kayıt sayısı değil kaydın birimidir.
İçindekiler
Kısa süreli bellek pencereyle sınırlıdır, ama asıl kayıp sınırda değil: döngü bittiği anda o bağlamın tamamı silinir. Ajan sayacı okur, endeks farkını hesaplar, tarifeyi uygular ve yanıtı verir. Aynı abone başka bir soruyla döndüğünde sayaç yeniden okunur.
Uzun süreli bellek (long-term memory) bu boşluğu doldurur: döngüden bağımsız yaşayan, sonraki görevlerin okuyabildiği bir kayıt kümesi. Buradaki soru neyin geri getirileceği değildir — parçalama, sıralama ve erişim isabeti Gömme Vektörleri ve Erişim Artırılmış Üretim kursunda ölçüldü, tekrarlanmaz. Buradaki soru neyin yazılacağıdır: aynı geri çağırma düzeneğiyle üç yazma politikası koşturulur, her birinde saklanan kayıt sayısı ile sonraki görevlerde kazanılan adım yan yana basılır.
- AB61. Kod bir benzeticidir; gerçek bir model uç noktası, araç sunucusu ya da bellek servisi çağrılmaz. Ortam, araçlar ve görevler kurgudur, tohum 20260218.
- AB62. Bellek bir kayıt listesidir; her kayıt aranabilir bir metin ve alanlarıdır. Gözlem ve yanıt kayıtları abone koduyla, belge kayıtları soru metniyle anahtarlanır.
- AB63. Geri çağırma tek okumadır: istekle ortak belirteci en çok olan kayıt döner, eşitlikte en son yazılan.
- AB64. Üç yazma politikası: her adım (her adımın gözlemi ayrı kayıt), yalnız sonuç (görev başına tek yanıt kaydı), seçici (planın adımlarına giren gözlemler tek kayıtta birleşir).
- AB65. Geri çağrılan alanlar başlangıç durumuna yazılır, çıktısı bilinen adım atlanır; plan tümüyle bellekten karşılanırsa döngü hiç başlamaz.
- AB66. Kayıtlar 24 görevlik ilk kümeden yazılır; ölçüm aynı abonelere sorulan 48 yeni soruda yapılır. Adım bütçesi 8, taban çizgisi belleksiz döngüdür.
Döngü Bittiğinde Geriye Kalan
Aşağıdaki blok ortak tanımı kurar ve tek bir aboneye iki ayrı soru sorar.
# KURGU ortam ve KURGU ajan. Gercek bir model ucu, arac sunucusu ya da bellek # servisi cagrilmaz. Abone kayitlari, belgeler ve gorevler kurgudur, tohum 20260218. 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 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) 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"]) def gorme(d): return max(0.34, 0.80 - 0.09 * (d - 1)) # dogru araci secme payi, derinlikle duser def ajan(g, en_cok_adim=8, tohum=TOHUM, oz_elestiri=False, onay=False): """KURGU ajan dongusu. Gercek bir model cagrilmaz; arac secimi gorevin dizisine ve derinlige bagli tek bir cekilisten gelir.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} iz, adim, bel, hata = [], 0, 0, 0 dizi, k = g["dizi"], 0 while adim < en_cok_adim: adim += 1 bel += 60 + 22 * len(iz) hedef = dizi[k] if k < len(dizi) else None if hedef is None: # is bitti , ajan durmali if r() < 0.88: return {"bitti": True, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} 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 ARAC[sec]["yan_etki"] and onay: alan["onay"] = alan.get("onay", 0) + 1 if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) iz.append((sec, "hata" in s)) bel += 30 if "hata" in s: hata += 1 if oz_elestiri: bel += 40 continue 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 {"bitti": False, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} CAGRI[0] = 0 g1 = GOREV[4] g2 = dict(g1, ad="G05b", tur="tuketim", dizi=("sayac_oku", "tuketim"), istek=f"{g1['abone']} abonesinin bu donem tuketimi kac metrekup") print("gorev kumesi:", {t: sum(g["tur"] == t for g in GOREV) for t in ("bedel", "tuketim", "belge", "kayit")}) print(g1["abone"], "iki ayri soru:", [x[0] for x in ajan(g1)["iz"]], [x[0] for x in ajan(g2)["iz"]], "; arac cagrisi", CAGRI[0])
gorev kumesi: {'bedel': 6, 'tuketim': 8, 'belge': 7, 'kayit': 3}
A026 iki ayri soru: ['sayac_oku', 'tuketim', 'tarife'] ['sayac_oku', 'tuketim'] ; arac cagrisi 5
Aynı abonenin sayacı iki kez okundu. İkinci sorunun ilk iki adımı birincinin birebir tekrarıdır; beş araç çağrısının ikisi yeni bilgi getirmiyor. Kayıp döngünün kusuru değil, kalıcı bir yazma yerinin olmamasıdır.
Üç Yazma Politikası
Ajan döngüsünün tek farkı, başlangıç durumunun bellekten gelmesi ve çıktısı bilinen adımın atlanmasıdır.
PLAN = {"bedel": (("sayac_oku", "tuketim", "tarife"), "{a} abonesinin bu donem bedeli nedir"), "tuketim": (("sayac_oku", "tuketim"), "{a} abonesinin bu donem tuketimi kac metrekup"), "belge": (("belge_ara",), "sayac donusunde endeks farki nasil hesaplanir"), "kayit": (("sayac_oku", "tuketim", "tarife", "kayit_yaz"), "{a} abonesinin bedelini hesapla ve kayda yaz")} TUR = ("bedel", "tuketim", "belge", "kayit") CIKTI = {"sayac_oku": ("onceki", "simdiki", "tip", "bolge"), "tuketim": ("m3",), "tarife": ("tutar",), "belge_ara": ("kod",)} SONUC = {"tuketim": "m3", "tarife": "tutar", "belge_ara": "kod"} def sonraki_kume(n=48): """Ayni abonelere sorulan YENI sorular; recete GOREV ile birebir ayni.""" k = [] for i in range(n): r = uretec(TOHUM + 7919 * (i + 101)) ab = GOREV[int(r() * 24)]["abone"] t = TUR[ayrik(r(), [0.30, 0.22, 0.20, 0.28])] k.append({"ad": f"H{i + 1:02d}", "tur": t, "abone": ab, "dizi": PLAN[t][0], "istek": PLAN[t][1].format(a=ab)}) return k def geri_cagir(bellek, istek): """Tek okuma: ortak belirteci en cok olan, esitlikte en son yazilan kayit.""" b, en, kayit = set(belirtecle(istek)), 0, None for metin, alanlar in bellek: o = len(b & set(belirtecle(metin))) if o >= en and o > 0: en, kayit = o, alanlar return kayit def ajan_b(g, bellek, tohum=TOHUM, en_cok_adim=8): """Ortak dongunun tek farki: baslangic durumu bellekten gelir ve ciktisi zaten bilinen adim atlanir.""" r = uretec(tohum ^ izno(g["ad"])) kayit = geri_cagir(bellek, g["istek"]) c = {"adim": 0, "okundu": kayit is not None, "alan": len(kayit or {}), "kayit": [], "yolda": {}} alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} alan.update(kayit or {}) if "sonuc" in alan: return dict(c, yanit=alan["sonuc"]) adim, k, dizi = 0, 0, g["dizi"] while k < len(dizi) and dizi[k] in CIKTI and all(x in alan for x in CIKTI[dizi[k]]): alan["sonuc"] = alan.get(SONUC.get(dizi[k]), alan.get("sonuc")) k += 1 if k == len(dizi): return dict(c, yanit=alan.get("sonuc")) while adim < en_cok_adim: adim += 1 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) gozlem = {x: s[x] for x in CIKTI.get(sec, ()) if x in s} c["kayit"].append(gozlem) if "hata" in s: continue alan.update({kk: vv for kk, vv in s.items() if kk != "hata"}) if sec in SONUC: alan["sonuc"] = s[SONUC[sec]] if sec == hedef: c["yolda"].update(gozlem) k += 1 return dict(c, adim=adim, yanit=alan.get("sonuc")) def kosum(politika, tohum=TOHUM, n=48): """Once ilk kume kosulur ve politikaya gore yazilir, sonra yeni kume.""" bellek = [] for g in GOREV: s = ajan_b(g, [], tohum) ah = g["istek"] if g["tur"] == "belge" else g["abone"] yaz = (s["kayit"] if politika == "her adim" else [s["yolda"]] if politika == "secici" else [{"sonuc": s["yanit"]}] if politika == "yalniz sonuc" else []) bellek += [(ah + " " + " ".join(f"{x} {v}" for x, v in a.items()), a) for a in yaz if None not in a.values()] CAGRI[0] = 0 adim = dogru = okuma = isabet = alan = 0 for g in sonraki_kume(n): s = ajan_b(g, bellek, tohum) d = s["yanit"] == dogru_yanit(g) adim, dogru, okuma = adim + s["adim"], dogru + d, okuma + s["okundu"] alan, isabet = alan + s["alan"], isabet + (d and s["okundu"]) return (len(bellek), okuma, alan, isabet / max(okuma, 1), adim, CAGRI[0], dogru / n) POL = ("belleksiz", "her adim", "yalniz sonuc", "secici") print("politika kayit okuma alan isabet adim cagri basarim | 2. kosum") for p in POL: a, b = kosum(p), kosum(p, TOHUM + 1) print(f"{p:<14} {a[0]:>5} {a[1]:>5} {a[2]:>4} {a[3]:>7.4f} {a[4]:>5} {a[5]:>5}" f" {a[6]:>6.4f} | {b[4]:>4} adim {b[6]:.4f}")
politika kayit okuma alan isabet adim cagri basarim | 2. kosum belleksiz 0 0 0 0.0000 212 166 0.9167 | 222 adim 0.8958 her adim 74 47 99 0.8936 168 132 0.8958 | 176 adim 0.8542 yalniz sonuc 24 45 45 0.5556 13 10 0.5833 | 14 adim 0.6250 secici 24 47 166 0.8511 94 74 0.8542 | 96 adim 0.8958
Taban çizgisi 48 görevi 212 adım ve 166 araç çağrısıyla bitiriyor, başarım 0,9167. Üç politika bu satırın üstüne kurulur.
Yalnız sonuç en çarpıcı satırdır. 24 kayıtla 212 adımı 13’e indiriyor, yani 199 adım kazandırıyor; araç çağrısı 166’dan 10’a düşüyor. Ama başarım 0,5833’e iniyor. Nedeni şudur: kayıt, abone koduyla anahtarlanmış bir yanıttır, oysa yanıt bir soruya aittir. Abonenin tüketim yanıtı saklanır, sonraki görev aynı abonenin bedelini sorar; değer doğru, soru başkadır.
Her adım politikası 74 kayıt biriktiriyor, üç katı, ve yalnızca 44 adım kazandırıyor (212’den 168’e). Sebep okuma sütununda görünür: 47 okumanın getirdiği toplam alan 99, okuma başına iki alan. Her adımın gözlemi ayrı bir kayıt olduğu için tek okuma tek adımın çıktısını getiriyor. Seçici politika aynı 24 kayıtla 118 adım kazandırıyor (212’den 94’e) ve 47 okumada 166 alan getiriyor; plana giren gözlemler tek kayıtta birleştiği için bir okuma bütün ön koşulları taşıyor.
Kayıt Sayısı Değil Kaydın Birimi
Tablonun iki sıralaması çakışmıyor. Kayıt sayısına göre en cömert politika her adımdır, kazanılan adıma göre yalnız sonuçtur; seçici ise her adımın üçte biri kadar kayıtla onun 2,68 katı adım kazandırıyor. Belirleyici olan kaç kayıt yazıldığı değil, bir kaydın hangi birimi kapsadığıdır: bir adım mı, bir görev mi, bir varlığın bütün alanları mı.
Hangi farkın bulgu sayılacağını ikinci koşum söylüyor. Taban çizgisi 0,9167 ve 0,8958 veriyor, iki koşum farkı 0,0417. Yalnız sonucun kaybı iki koşumda 0,3334 ve 0,2708, ikisi de bandın çok üstünde ve ölçülmüştür. Seçicinin kaybı ise bir koşumda 0,0625, ötekinde 0,0000; bandın etrafında salınıyor ve ölçülmemiş sayılır — 118 adımlık kazancın bir başarım bedeli olduğu bu kurulumda gösterilemedi.
Kural sadedir: belleğe soruya bağlı bir yanıt yazmak, o yanıtı soru değiştiğinde yanlış hâle getirir. Yazılması gereken şey sorudan bağımsız gözlemdir — sayaç okuması, abone tipi, belge kodu. Yanıtın her görevde yeniden üretilmesi, yanlış yanıttan ucuzdur.
Özet
- Döngü bittiğinde kısa süreli bellek silinir; aynı abonenin sayacı sonraki soruda yeniden okunur.
- Ölçülen şey erişim değil yazma kararıdır: aynı geri çağırma düzeneğiyle üç politika üç ayrı sonuç veriyor.
- Yalnız sonuç 24 kayıtla 199 adım kazandırıyor ama başarımı 0,9167’den 0,5833’e düşürüyor; kayıp iki koşum farkının sekiz katıdır ve ölçülmüştür.
- Her adım 74 kayıtla 44, seçici 24 kayıtla 118 adım kazandırıyor; okuma başına gelen alan 99’a karşı 166’dır.
- Kayıt sayısı değil kaydın birimi belirleyicidir; soruya bağlı yanıt yerine gözlem yazmak yanlış yanıtı ortadan kaldırır.
Sonraki Adım
Bu ders belleği görevler arasında ele aldı. Görev içinde sorun tersine döner: bağlam silinmiyor, büyüyor, ve pencere dolduğunda bir şeyin atılması gerekiyor. Atma kararı yazma kararının aynasıdır. Sonraki ders sıkıştırmanın iki yolunu ölçer: gözlemleri özetlemek ve yalnız ilgili olanı tutmak. Sıkıştırma oranı arttıkça taşınan belirteç düşer, ama düşen her alan bir sonraki adımın girdisi olabilir. Ölçülecek olan bu ikisidir: kazanılan belirteç ve atılan alanın gerektiği görev sayısı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.