Ders 20 / 22
İzleme ve Günlükleme
Üretimde koşan bir ajan döngüsünün adım izinin neyi geri okuttuğunun ölçülmesi: yirmi dört görevin on koşumundan oluşan iki yüz kırk koşumluk akışta on beş görev yanlış bitiyor ve nedenleri on iki yanlış seçim ile üç dolaşmadan oluşuyor. Yalnız sonucu saklayan iz bu nedenlerin 0,0000'ini, araç adlarını sayan iz 0,4000'ini, tam gözlemi saklayan iz 1,0000'ini veriyor; saklanan belirteç 2738'den 5954'e ve 13623'e çıkıyor, bulunan neden başına belirteç ise 992,3'ten 908,2'ye iniyor. Altmış bir araç hatasının 0,8689'u doğru biten koşumlarda oluşuyor, yani araç hatası sayacı bir neden değil bir belirtidir.
İçindekiler
Bir önceki iki ders ajanı sınadı. Araç düzeyi sınama beş araca konan kusurları tek tek yokladı, uçtan uca akış sınaması onun kaçırdıklarını yakaladı ve ikisinin de göremediği bir kalıntı kaldı. Her ikisinin de ortak bir kısıtı var: sınanan koşumu biz kurduk. Hangi görevin çalıştığını, hangi aracın bozulduğunu ve doğru yanıtın ne olduğunu önceden biliyorduk.
Üretimde koşan bir döngüde bunların hiçbiri elimizde değildir. Görev bir aboneden gelir, ajan kendi adımlarını seçer, sonuç bir kayda yazılır ve geriye yalnız sakladığımız kadarı kalır. Bu dersin ölçtüğü şey ajanın kendisi değil, izin geri okuttuğudur: bir görev yanlış bittiğinde, sakladığımız kayıt onun neden yanlış bittiğini söyleyebiliyor mu. Gözlemlenebilirliğin genel yordamı Gözlemlenebilirlik ve Güvenilirlik kursunda ve Gözlemlenebilirlik ve İşletim kursunda kuruldu; burada tekrarlanmaz. Ölçülen tek şey adım izinin taşıdığı bilgi ile bedeli arasındaki alışveriştir.
- KL31. Ortam, araçlar, görev kümesi ve ajan döngüsü kurgudur ve aşağıda ders içinde tanımlanır; gerçek bir model uç noktası, araç sunucusu ya da çalışma zamanı çağrılmaz. Tohum 20260218, ikinci koşum 20260219.
- KL32. Üretim akışı, aynı yirmi dört görevin on kez koşmasıdır. Model belirsiz bir
bileşen olduğu için her koşumda ajanın çekilişi ayrıdır; toplam 240 koşum olur. Adım bütçesi
6, yani
ajan-mimarisi/04’ün süpürmesinde en iyi çıkan değerdir. - KL33. Üç iz düzeyi şunları saklar. Yalnız sonuç: görev adı, son yanıt ve döngünün durup durmadığı. Araç adları: bunlara ek olarak hangi aracın kaç kez çağrıldığı — sıra saklanmaz, çünkü bu düzey bir sayaçtır. Tam gözlem: bunlara ek olarak çağrıların sırası ve her çağrının döndürdüğü gözlemin tamamı.
- KL34. Neden, izdeki ilk sapmadır ve tam gözlemden okunur: plan bitmeden plan dışı bir araç çağrıldıysa yanlış seçim, plan bittikten sonra çağrı sürdüyse dolaşma, plandaki araç sırasında hata döndürdüyse araç hatası, hiç sapma yokken plan bitmediyse bütçe.
- KL35. Bir iz düzeyi bir nedeni ancak sakladığı alanlar onu belirliyorsa verir; belirsiz kaldığı yerde neden bulunamadı sayılır ve yanlış tahmin doğru sayılmaz.
- KL36. Saklanan belirteç, kaydın ortak belirteçleyiciden geçirilmesiyle sayılır. Bu kursta iz için kullanılan terim adım izidir.
Üretim Akışı ve Ortak Tanım
Aşağıdaki blok kursun ortak tanımını kurar: ölçüm ağının kurgu abone kayıtları, kurgu belge dağarcığı, beş araç, yirmi dört görev ve ajan döngüsü. Araç seçimi derinlikle bozulur, iş bitince ajan 0,88 payla durur, şema dışı alanlar süzülür ve eksik alan aracın kendi hatasıdır.
# KURGUDUR. Olcum aginin abone kayitlari, belge dagarcigi, bes arac ve yirmi dort # gorev ders icinde tanimlanir; gercek bir uc nokta ya da arac sunucusu cagrilmaz. 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)}
İzin Geri Okuttuğu
Üç düzeyin her biri için aynı akış koşar, kayıtlar kurulur ve başarısız görevlerin nedeni o düzeyin sakladığı alanlardan çıkarılmaya çalışılır. Tam gözlem düzeyini kurmak için araç çağrısı sarmalanır: dönen sözlüğün tamamı günlüğe düşer.
# Uretim akisi: ayni gorev kumesi on kez kosar, ajanin cekilisi her kosumda ayridir. BUTCE, KOSUM = 6, 10 GUNLUK = [] _ham_cagir = cagir_arac def cagir_arac(ad, durum): # tam gozlem duzeyi: donen alanlar da saklanir s = _ham_cagir(ad, durum) GUNLUK.append((ad, dict(s))) return s def neden(g, iz): """Tam gozlemden okunan neden: izdeki ilk sapma.""" k = 0 for ad, gz in iz: if k >= len(g["dizi"]): return "dolasma" if ad != g["dizi"][k]: return "yanlis secim" if "hata" in gz: return "arac hatasi" k += 1 return "butce" if k < len(g["dizi"]) else "bilinmiyor" def tani_ad(g, say): """Ad duzeyi yalniz sayac tutar: sira da gozlem de yok.""" if not [a for a in say if a not in g["dizi"]]: return None if [a for a in g["dizi"] if say.get(a, 0) == 0]: return "yanlis secim" if all(say[a] == g["dizi"].count(a) for a in set(g["dizi"])): return "dolasma" return None ozet = {} for taban in (20260218, 20260219): bulunan, saklanan, basarisiz, dagilim, hata, hata_dogru = [0, 0, 0], [0, 0, 0], 0, {}, 0, 0 for d in range(KOSUM): for g in GOREV: GUNLUK.clear() s = ajan(g, en_cok_adim=BUTCE, tohum=taban + 7 * d) iz = list(GUNLUK) say = {} for a, _ in iz: say[a] = say.get(a, 0) + 1 k1 = {"ad": g["ad"], "yanit": s["yanit"], "bitti": s["bitti"]} kayit = (k1, dict(k1, sayac=say), dict(k1, iz=iz)) for i in range(3): saklanan[i] += len(belirtecle(kayit[i])) hata += s["hata"] if s["yanit"] == dogru_yanit(g): hata_dogru += s["hata"] continue basarisiz += 1 gercek = neden(g, iz) dagilim[gercek] = dagilim.get(gercek, 0) + 1 bulunan[1] += tani_ad(g, say) == gercek bulunan[2] += neden(g, iz) == gercek ozet[taban] = (bulunan, saklanan, basarisiz) n = " , ".join(f"{k} {v}" for k, v in sorted(dagilim.items())) print(f"tohum {taban} , {KOSUM * len(GOREV)} kosum , basarisiz {basarisiz} , neden: {n}") print(f" arac hatasi {hata} , bunun dogru biten kosumdaki payi {hata_dogru / hata:.4f}") print("\niz duzeyi neden bulunan pay saklanan belirtec bulunan neden basina") for i, ad in enumerate(("yalniz sonuc", "arac adlari", "tam gozlem")): a, b = ozet[20260218], ozet[20260219] ba = f"{a[0][i] / a[2]:.4f} {b[0][i] / b[2]:.4f}" bel = f"{a[1][i]:>6} {b[1][i]:>6}" bas = " ".join(f"{x[1][i] / x[0][i]:>7.1f}" if x[0][i] else " -" for x in (a, b)) print(f"{ad:<14} {ba} {bel} {bas}")
tohum 20260218 , 240 kosum , basarisiz 15 , neden: dolasma 3 , yanlis secim 12 arac hatasi 61 , bunun dogru biten kosumdaki payi 0.8689 tohum 20260219 , 240 kosum , basarisiz 11 , neden: dolasma 3 , yanlis secim 8 arac hatasi 66 , bunun dogru biten kosumdaki payi 0.9242 iz duzeyi neden bulunan pay saklanan belirtec bulunan neden basina yalniz sonuc 0.0000 0.0000 2738 2739 - - arac adlari 0.4000 0.2727 5954 6043 992.3 2014.3 tam gozlem 1.0000 1.0000 13623 14486 908.2 1316.9
Yalnız sonucu saklayan iz hiçbir nedeni vermiyor. Bu düzey başarısızlığı sayabilir: on beş görevin yanlış bittiğini bilir. Neden sorulduğunda elinde yalnız yanıt ile durma bayrağı vardır ve bu iki alan, aynı yanlış yanıtı üreten iki ayrı yolu birbirinden ayırmaz. Bir gösterge tablosu bu düzeyle kurulabilir; bir arıza bu düzeyle kapatılamaz.
Araç adlarını sayan iz nedenlerin 0,4000’ini veriyor. Bu düzeyin bildiği şey hangi aracın kaç kez çağrıldığıdır; sıra yoktur. Sayaçta plan dışı bir araç görünüyorsa ve plandaki araçlardan biri hiç çağrılmamışsa plan tamamlanmamıştır, yani sapma yanlış seçimdir. Plan dışı araç var ama plandaki araçların hepsi tam birer kez çağrılmışsa plan bitmiş ve fazladan çağrı sonradan gelmiştir, yani dolaşmadır. Bu iki durumun dışında sayaç iki senaryoyu ayırt edemez: aynı sayaç hem plan ortasında yapılmış bir yanlış seçimden hem de plan bittikten sonraki bir dolaşmadan çıkabilir. O koşumlarda neden bulunamadı sayılır.
Tam gözlem düzeyi nedenlerin hepsini veriyor, çünkü sıra ile birlikte her çağrının döndürdüğü gözlem de saklanmıştır ve plan işaretçisi birebir yeniden yürütülebilir. Bedeli, saklanan belirtecin 2738’den 13623’e çıkmasıdır — beş katı.
Son sütun sıralamayı değiştiriyor. Bulunan neden başına belirteç okunduğunda araç adları düzeyi 992,3, tam gözlem düzeyi 908,2‘dir. Toplamda beş kat pahalı olan düzey, işe yarayan çıktı birimi başına daha ucuzdur, çünkü ucuz düzeyin sakladığı belirtecin çoğu hiçbir soruyu kapatmıyor. İkinci koşumda aynı okuma daha da keskindir: 2014,3’e karşı 1316,9.
Araç Hatası Bir Neden Değil, Belirtidir
Akışta 61 araç hatası var ve bunların 0,8689’u doğru biten koşumlarda oluşuyor. Araç hatası sayacına konan bir uyarı altmış bir kez çalar, elli üçü sorunsuz biten bir görev içindir. Ters yönde de eksiktir: nedenler tablosunda araç hatası sınıfı hiç görünmez. Mekanizma bunu açıklıyor. Plandaki araç sırası geldiğinde girdisi zaten durumda hazırdır ve hata döndürmez; hata ancak yanlış seçilmiş bir araç şemasının istediği alanı bulamadığında çıkar. Yani araç hatası her zaman bir yanlış seçimin ardından gelir ve o seçim düzeltilmeden hata sayısına bakmak insanı aracı düzeltmeye götürür.
İki koşum bandı bu okumanın sınırını da çiziyor. Araç adları düzeyi bir koşumda 0,4000, öbüründe 0,2727 veriyor; aradaki 0,1273 ölçüm bandıdır. Bu düzeyin tam gözlemden 0,6000 geride olması banda göre büyüktür ve bir bulgudur. Ama iki koşum arasında bu düzeyin kendi değerinin ne kadar oynadığı, “araç adları nedenlerin şu kadarını verir” biçimindeki bir iddianın tek başına ölçülmemiş olduğunu söyler; ölçülen şey düzeyler arasındaki sıradır.
Özet
- Üretim akışı yirmi dört görevin on koşumudur; 240 koşumun 15’i yanlış biter ve nedenleri 12 yanlış seçim ile 3 dolaşmadır.
- Yalnız sonuç düzeyi nedenlerin 0,0000’ini, araç adları düzeyi 0,4000’ini, tam gözlem düzeyi 1,0000’ini verir.
- Bedel 2738, 5954 ve 13623 belirteçtir; bulunan neden başına okunduğunda sıralama tersine döner ve tam gözlem 908,2 ile araç adlarının 992,3’ünün altına iner.
- 61 araç hatasının 0,8689’u doğru biten koşumlardadır ve nedenler tablosunda araç hatası sınıfı hiç görünmez: hata sayacı bir belirtidir, neden değildir.
- Araç adları düzeyinin iki koşum arasındaki farkı 0,1273’tür; bu düzeyin tek başına değeri ölçülmemiş, düzeyler arasındaki sıra ölçülmüş sayılır.
Sonraki Adım
İz, bir görevin neden yanlış bittiğini geri okutuyor ve bunun bir belirteç bedeli var. Ama bu bedel, döngünün ödettiği bedelin yalnız bir kalemidir. Ajan her adımda bir çağrı yapar, her çağrı belirteç harcar ve adım sayısı görevden göreve değişir. Sonraki ders bu harcamayı iki ayrı paydayla okur: adım başına ve doğru yanıt başına. İki sıralamanın aynı olmadığı bir nokta vardır ve o noktada hangi düzeneğin ucuz sayılacağı paydanın seçimine bağlıdır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.