Ders 17 / 26
Ajanlı Kodlama
Çok adımlı bir işin devredilmesinde denetim noktası aralığının ölçülmesi: altmış kurgu işin 480 adımı altı ayrı aralıkta koşturulunca her adımda durmak 478/480 doğru adım veriyor ama 479 durma istiyor, sekiz adımda bir durmak 60 durmaya iniyor ve 355/480'e düşüyor. Yakalanan hata başına boşa giden adım 1,00'den 5,64'e çıkıyor; kaçan hata 1'den 21'e. Çağrı sayısı altı aralıkta neredeyse sabit (549 ile 598 arası), yani durmanın bedeli çağrı değil insan bakışıdır. Doğru adım başına belirteç iki koşumda da üç adımlık aralıkta en düşüktür (146,8 ve 144,9), yani en doğru aralık ile en ucuz aralık aynı değildir.
İçindekiler
Önceki iki derste her görev tek bir çağrıydı: bağlam gitti, öneri geldi, geliştirici kabul etti ya da etmedi. Karar noktası tekti ve öneriyle aynı yerdeydi. Bir dosyayı okumak, bir işlevi değiştirmek, çağıranları güncellemek ve raporu yeniden biçimlemek tek bir istekle devredildiğinde bu düzen bozulur: araç arka arkaya adım atar, her adım bir öncekinin üstüne kurulur ve geliştirici artık her adımda değil, durduğu yerde bakar.
Bu ders o durma yerini ölçer ve başka bir şey ölçmez. Aracın nasıl planladığı, neyi hatırladığı ve döngüsünü nasıl kapattığı burada ele alınmaz; bunlar bu müfredatın Yapay Zekâ Ajanları kursunun konusudur. Buradaki tek soru şudur: kaç adımda bir durulduğunda hata yayılmadan yakalanıyor ve bunun bedeli ne.
- YG17. Kurulum önceki iki dersle aynıdır: kurgu kod tabanı (beş modül, 53 satır), yirmi dört kurgu görev ve yardımcı benzeticisi. Gerçek bir ajanlı kodlama aracı çalıştırılmaz.
- YG18. Çok adımlı iş: 60 kurgu iş, her biri 8 adım, toplam 480 adım. Her adımın bağlamı seçilidir, yani yalnız o adımın gerektirdiği dosyalar gönderilir.
- YG19. Yayılma kuralı: reddedilen bir adım fark edilmezse sonraki adımlar onun üstüne kurulur ve bulaşık sayılır. Bu dersin ölçtüğü tek yapısal olgu budur.
- YG20. Denetim noktası her
dadımda bir ve işin sonunda konur; durakta o pencere insana bakılır. - YG21. Görme payı pencere büyüdükçe düşer:
0,95 - 0,07 x (d - 1), alt sınır0,40. Sekiz adımlık bir değişikliği tek seferde okumak, tek adımı okumaktan zordur. - YG22. Yakalanan hata yeniden koşulur: hatalı adımdan durağa kadarki adımlar yeniden çağrılır ve düzeldiği varsayılır. Bunlar boşa giden adımdır.
- YG23. Yakalanmayan hata tabana girer: işin kalan adımları bulaşıktır ve sonraki duraklar onu göremez, çünkü bakılan şey kabul edilmiş taban değil yeni iştir.
- YG24. Bedel üç ayrı kalemdir: durma sayısı (insanın baktığı kez), çağrı ve belirteç; her durak ayrıca 50 belirteç durum özeti ekler.
- YG25. Teslim ölçüsü doğru adımdır: kaçan hatası olan bir işte doğru adım sayısı hatanın bulunduğu yere kadardır.
- YG26. Adım sonuçları aralıktan bağımsız olarak aynı tohumla üretilir; aralıklar arasında değişen tek şey nerede durulduğudur. İkinci koşum tohum 20260219.
Bir İşin İzi
Önce tek bir iş iki ayrı aralıkla koşturulur. Aynı sekiz adım, aynı sonuçlar; değişen yalnız durakların yeri.
# AYNI KURGU KURULUM -- bes modullu kod tabani (53 satir), 24 kurgu gorev, # yardimci benzeticisi. Gercek bir ajanli kodlama araci calistirilmaz. 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 izno(m): h = 2166136261 for c in m: h = ((h ^ ord(c)) * 16777619) & M32 return h SINIF = ("tamamlama", "aciklama", "donusturme") DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py") GEREKEN = { 0: ("okuma.py",), 1: ("tarife.py",), 2: ("denetim.py", "okuma.py"), 3: ("ozet.py", "denetim.py"), 4: ("bicim.py", "ozet.py"), 5: ("tarife.py", "okuma.py"), 6: ("ozet.py", "okuma.py", "tarife.py"), 7: ("denetim.py", "bicim.py"), } GOREV = [ {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)} for s in SINIF for i in range(8) ] TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18} def yardimci(gorev, baglam, tohum=TOHUM): # BENZETICI -- KURGUDUR r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam)))) ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"]) ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA) puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"] puan = min(max(puan, 0.0), 1.0) kabul = r() < puan belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0) return {"kabul": kabul, "puan": puan, "belirtec": belirtec} IS_SAYI, ADIM, DURUM_BEL = 60, 8, 50 def gorme(d): """Denetim penceresi buyudukce insanin hatayi gorme payi duser.""" return max(0.95 - 0.07 * (d - 1), 0.40) def devir(j, d, tohum=TOHUM, ayrinti=False): """Tek bir cok adimli isin d adimda bir durdurularak kosturulmasi.""" say = {"cagri": 0, "belirtec": 0, "durma": 0, "yakalanan": 0, "kacan": 0, "bosa": 0, "dogru": 0} hatali, kacti = None, False for k in range(ADIM): g = GOREV[(j * ADIM + k) % len(GOREV)] s = yardimci(g, g["gereken"], tohum ^ izno("adim|" + str(j) + "|" + str(k))) say["cagri"] += 1 say["belirtec"] += s["belirtec"] if kacti: if ayrinti: print(f" adim {k} {g['ad']:<14} bulasik (kacan hatanin ustune)") continue if hatali is None and not s["kabul"]: hatali = k if ayrinti: d_ad = "kabul" if s["kabul"] else "RET" if hatali is not None and hatali < k: d_ad = "bulasik" print(f" adim {k} {g['ad']:<14} {d_ad}") if (k + 1) % d == 0 or k == ADIM - 1: say["durma"] += 1 say["belirtec"] += DURUM_BEL if hatali is None: if ayrinti: print(f" DURMA adim {k}: temiz") continue r = uretec(tohum ^ izno("denetim|" + str(j) + "|" + str(k))) if r() < gorme(d): yeniden = k - hatali + 1 say["yakalanan"] += 1 say["bosa"] += yeniden say["cagri"] += yeniden say["belirtec"] += yeniden * s["belirtec"] if ayrinti: print(f" DURMA adim {k}: hata adim {hatali} noktasinda" f" gorundu, {yeniden} adim yeniden") hatali = None else: say["kacan"] += 1 kacti = True if ayrinti: print(f" DURMA adim {k}: gorulmedi, hata tabana girdi") say["dogru"] = hatali if kacti else ADIM return say print("is 0, adim araligi 4:") a = devir(0, 4, ayrinti=True) print(" ->", {x: a[x] for x in ("dogru", "bosa", "durma", "cagri", "belirtec")}) print("\nis 0, adim araligi 8:") b = devir(0, 8, ayrinti=True) print(" ->", {x: b[x] for x in ("dogru", "bosa", "durma", "cagri", "belirtec")})
is 0, adim araligi 4:
adim 0 tamamlama-1 kabul
adim 1 tamamlama-2 kabul
adim 2 tamamlama-3 RET
adim 3 tamamlama-4 bulasik
DURMA adim 3: hata adim 2 noktasinda gorundu, 2 adim yeniden
adim 4 tamamlama-5 kabul
adim 5 tamamlama-6 kabul
adim 6 tamamlama-7 RET
adim 7 tamamlama-8 bulasik
DURMA adim 7: hata adim 6 noktasinda gorundu, 2 adim yeniden
-> {'dogru': 8, 'bosa': 4, 'durma': 2, 'cagri': 12, 'belirtec': 1178}
is 0, adim araligi 8:
adim 0 tamamlama-1 kabul
adim 1 tamamlama-2 kabul
adim 2 tamamlama-3 RET
adim 3 tamamlama-4 bulasik
adim 4 tamamlama-5 bulasik
adim 5 tamamlama-6 bulasik
adim 6 tamamlama-7 bulasik
adim 7 tamamlama-8 bulasik
DURMA adim 7: hata adim 2 noktasinda gorundu, 6 adim yeniden
-> {'dogru': 8, 'bosa': 6, 'durma': 1, 'cagri': 14, 'belirtec': 1312}
İki iz aynı sekiz adımı taşıyor ve altta yatan sonuçlar da aynı: 2 ve 6 numaralı adımlar
reddediliyor. Değişen tek şey durakların yeridir, ama iz aynı değildir. Dört adımlık aralıkta
ilk hata iki adım yayıldıktan sonra yakalanıyor, ikinci hata da öyle; toplam dört adım yeniden
koşuluyor. Sekiz adımlık aralıkta ilk hata altı adım yayıyor ve ikinci hata hiç
görünmüyor — 6 numaralı adım o noktada zaten bulaşık olduğu için ayrı bir hata olarak
sayılmıyor. İkisi de sonunda sekiz doğru adım teslim ediyor, ama biri 12 çağrı ve 1178 belirteç,
öbürü 14 çağrı ve 1312 belirteç harcıyor.
Bu tek iş iyi bir örnek ama bir sayı değildir: burada denetim ikisinde de gördü. Görmediğinde ne olacağı ancak yeterince iş üzerinde okunur.
Aralığın Süpürülmesi
Altmış iş, dört yüz seksen adım, altı ayrı denetim aralığı. Adım sonuçları aralıktan bağımsızdır; değişen tek şey durakların yeridir.
def kosum(d, tohum=TOHUM): top = {"cagri": 0, "belirtec": 0, "durma": 0, "yakalanan": 0, "kacan": 0, "bosa": 0, "dogru": 0} for j in range(IS_SAYI): for a, v in devir(j, d, tohum).items(): top[a] += v return top ADIMLAR = IS_SAYI * ADIM BASLIK = ("aralik gorme durma yakalanan kacan bosa dogru adim" " cagri belirtec bel/dogru") def yaz(d, tohum): a = kosum(d, tohum) print(f"{d:>6}{gorme(d):>7.2f}{a['durma']:>7}{a['yakalanan']:>11}{a['kacan']:>7}" f"{a['bosa']:>6}{a['dogru']:>8}/{ADIMLAR}{a['cagri']:>7}{a['belirtec']:>10}" f"{a['belirtec'] / a['dogru']:>11.1f}") print("kosum A (tohum 20260218)") print(BASLIK) for d in (1, 2, 3, 4, 6, 8): yaz(d, TOHUM) print("\nkosum B (tohum 20260219)") print(BASLIK) for d in (1, 2, 3, 4, 6, 8): yaz(d, TOHUM + 1)
kosum A (tohum 20260218)
aralik gorme durma yakalanan kacan bosa dogru adim cagri belirtec bel/dogru
1 0.95 479 90 1 90 478/480 570 78648 164.5
2 0.88 233 69 8 109 455/480 589 67790 149.0
3 0.81 172 52 11 104 441/480 584 64746 146.8
4 0.74 117 45 11 118 430/480 598 63320 147.3
6 0.60 104 23 23 69 367/480 549 57784 157.4
8 0.46 60 14 21 79 355/480 559 56414 158.9
kosum B (tohum 20260219)
aralik gorme durma yakalanan kacan bosa dogru adim cagri belirtec bel/dogru
1 0.95 467 71 4 71 463/480 551 76070 164.3
2 0.88 224 52 11 79 430/480 559 64318 149.6
3 0.81 168 44 12 78 428/480 558 62010 144.9
4 0.74 107 29 14 85 392/480 565 59550 151.9
6 0.60 105 24 17 79 393/480 559 58790 149.6
8 0.46 60 18 16 101 393/480 581 59032 150.2
Yayılmanın Ölçüsü
Sorunun ilk yarısı — hata yayılmadan yakalanıyor mu — tabloda iki sütunun bölümüdür. Boşa giden adım, yakalanan hata sayısına bölündüğünde yakalandığı ana kadar kaç adım yayıldığını verir. Birinci koşumda bu sayı sırayla 1,00 / 1,58 / 2,00 / 2,62 / 3,00 / 5,64; ikinci koşumda 1,00 / 1,52 / 1,77 / 2,93 / 3,29 / 5,61. İki koşum ayrı ayrı aynı şeyi söylüyor: her adımda durulduğunda hata yayılmıyor, sekiz adımda bir durulduğunda ortalama beş buçuk adım yayıldıktan sonra yakalanıyor.
Kaçan hata sütunu ikinci yarıyı veriyor. Her adımda durmak birinci koşumda 1, ikinci koşumda 4 hatayı kaçırıyor; sekiz adımda bir durmak 21 ve 16. Bunun nedeni tabloda yazılı: görme payı 0,95’ten 0,46’ya iniyor, çünkü sekiz adımlık bir değişikliği tek seferde okumak zordur.
Bir sütun burada yanıltıcıdır ve okunmamalıdır: yakalanan hata sayısı. Aralık büyüdükçe 90’dan 14’e iniyor, sanki hata azalmış gibi. Azalan şey hata değil, hata sayabildiğimiz iştir; kaçan bir hata işin kalanını bulaştırdığı için o işte başka hata sayılmaz. Devredilen işin kalitesi “kaç hata bulundu” ile ölçülemez. Ölçülebilen tek şey teslim edilen doğru adımdır: 478/480’den 355/480’e, ikinci koşumda 463/480’den 393/480’e.
Aynı bağlılık durma sütununda da görünüyor. Her adımda durulan koşumda durak sayısı 480 değil 479; ikinci koşumda 467. Eksik duraklar, hatası kaçmış işlerin kalanıdır: taban artık bulaşık olduğu için o duraklarda bakılacak temiz bir iş kalmamıştır ve sayılmazlar. Tablodaki sütunlar birbirinden bağımsız değildir, çünkü devredilen iş de bağımsız adımlardan oluşmuyor.
Durmanın Bedeli
Bedel üç kalemdir ve üçü aynı yöne gitmiyor. Çağrı sayısı altı aralıkta 549 ile 598 arasında, ikinci koşumda 551 ile 581 arasında kalıyor — yani neredeyse sabit. Sık durmak yeniden koşum doğurur, seyrek durmak daha uzun yeniden koşum doğurur; ikisi birbirini götürür. Durmak bir çağrı meselesi değildir.
Belirteç düzenli düşüyor: 78648’den 56414’e, yani seyrek durmak toplam belirtecin yaklaşık yüzde yirmi sekizini kurtarıyor. Bunun büyük kısmı durak başına eklenen 50 belirteçlik durum özetinden gelir; 479 durak ile 60 durak arasındaki fark tek başına 20950 belirteçtir.
Asıl bedel üçüncü kalemdedir ve belirteçle ödenmez: durma sayısı. Her adımda durmak insanı 479 kez masaya çağırıyor, sekiz adımda bir durmak 60 kez. Aradaki fark sekiz kattır ve karşılığında kazanılan 123 doğru adımdır. Kurtarılan her doğru adım için insan yaklaşık 3,4 kez fazladan bakmıştır. Bu takas bir mühendislik kararıdır ve tabloda yazılıdır; hangi tarafın seçileceği adımın ne kadar geri alınabilir olduğuna bağlıdır.
Son sütun üçüncü bir eniyileme noktası gösteriyor. Doğru adım başına belirteç iki koşumda da üç adımlık aralıkta en düşüktür: 146,8 ve 144,9. Bu, en çok doğru adım veren aralık (bir) değildir; en az durma isteyen aralık (sekiz) de değildir. Üç ayrı ölçüt, üç ayrı kazanan. Bir denetim aralığı seçmek bu yüzden bir eniyileme değil bir beyandır: hangi maliyeti düşürdüğünü söylemeden seçilmiş bir aralık, ölçülmüş sayılmaz.
Özet
- Çok adımlı bir devirde yakalanmayan bir hata sonraki adımlara bulaşır; denetim noktası bu bulaşmayı kestiği yerdir ve tek ölçtüğü şey nerede durulduğudur.
- Yakalanana kadar yayılan adım sayısı her adımda durulduğunda 1,00, sekiz adımda bir durulduğunda 5,64’tür; ikinci koşumda 1,00 ve 5,61.
- Kaçan hata 1’den 21’e çıkar (ikinci koşumda 4’ten 16’ya), çünkü pencere büyüdükçe görme payı 0,95’ten 0,46’ya iner.
- Yakalanan hata sayısı bir kalite ölçüsü değildir: aralık büyüdükçe düşer, çünkü kaçan hata işin kalanını sayılamaz kılar. Ölçülebilen tek şey teslim edilen doğru adımdır (478/480’e karşı 355/480).
- Bedelin üç kalemi ayrışır: çağrı sayısı neredeyse sabittir (549 ile 598 arası), belirteç yüzde yirmi sekiz düşer, durma sayısı sekiz kat düşer. Sık durmanın asıl fiyatı insan bakışıdır.
- Doğru adım başına belirteç iki koşumda da üç adımlık aralıkta en düşüktür (146,8 ve 144,9); en doğru aralık, en ucuz aralık ve en az durduran aralık üç ayrı satırdır.
Sonraki Adım
Bu derste denetim noktası bir yer olarak ele alındı ve görme payı tek bir sayıya sıkıştırıldı: duran insan hatayı bir olasılıkla görüyor, görmüyorsa hata tabana giriyor. O sayının içinde ne olduğu hiç açılmadı. Durakta tam olarak neye bakılıyor — kod koşuyor mu, doğru sonucu mu veriyor, var olmayan bir bağımlılığı mı çağırıyor, bağlama giren metinde ne taşındı. Denetim noktası koyuldu, ama neyin denetleneceği söylenmedi. Sonraki ders bu boşluğu doldurur ve görme payını bir varsayım olmaktan çıkarıp ölçülen bir sayıya çevirir: birbirinden bağımsız denetimler aynı üretilmiş kod üzerinde koşturulur, her birinin yakaladığı kusur ayrı sayılır ve hiçbirinin yakalamadığı kalıntı adıyla yazılır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.