---
title: 'Web Arama ve Gezinme'
source: 'https://academia.sh/tr/kurslar/yapay-zeka-ajanlari/web-arama-ve-gezinme'
course: 'Yapay Zekâ Ajanları'
language: tr
updated: '2026-08-17T18:06:32+00:00'
license: 'CC BY-SA 4.0'
---

# Web Arama ve Gezinme

Dış bilgiye erişimin bir kaynak sınıflandırması olarak sayılması: on sekiz kurgu kaynak birincil, ikincil ve denetimsiz diye sınıflanır ve yirmi dört dış bilgi görevi beş kurulumda koşturulur. Dış bilgisiz döngü 0,2083 doğru yanıt verir; yalnız birincil kaynak 0,7500'e çıkarır; ikincil sınıfı da karışıma katmak 0,3750'ye düşürür ve on görevi kirletir; üç sınıf birlikte kirli görevi on beşe çıkarır. Aynı havuzda seçimi sınıfa göre sıralamak doğru yanıtı 0,7500'e geri getirir, kirli görevi beşe indirir ve çağrı sayısını değiştirmez. Yanlış kod duruma girdikten sonra ortalama 3,40 ile 4,00 adım taşınır ve kirli görevlerin tamamında kayıt yazma adımına ulaşır. Ölçüm bandı 0,0833'tür, bu yüzden 0,3750'lik düşüş de 0,3750'lik toparlanma da ölçülmüştür.

Bir önceki ders ajanın dokunduğu yüzeyi bir yetki kapısına bağladı: hangi yolun okunacağı, hangi
komutun çalışacağı bizim bildirdiğimiz bir kümeydi. Dış bilgi bu zemini kaldırır. Ajan bir arama
aracıyla kayıt bulup bir gezinme aracıyla içeriğini okuduğunda gelen metin **bizim değildir**; ne
bir izin listesine sığar ne bir şemaya.

Dışarıdan gelen bilgiye tek bir soru sorulabilir: **bu kaydı kim tuttu.** Ders o soruyu bir
**kaynak sınıflandırmasına** çevirir ve iki şey sayar: karışım doğru yanıt payını nasıl oynatıyor,
ve yanlış bir kayıt duruma girdikten sonra kaç adım taşınıyor.

- **AB37.** Kod bir **benzeticidir**; gerçek bir arama ya da gezinme aracı çağrılmaz. Kaynaklar,
  iddialar ve sorular **kurgudur**, tohum **20260218**.
- **AB38. Kaynaklar yalnız sınıfıyla anılır.** Hiçbir site, alan adı, kurum ya da ülke adı
  yazılmaz; bir kaynak kurgu kayıt numarası ve sınıfından ibarettir.
- **AB39. Üç sınıf vardır:** **birincil** (işletmenin kendi kaydı), **ikincil** (türetilmiş
  derleme), **denetimsiz** (açık katkı). Bildirilen güvenilirlik payları 0,95, 0,70 ve 0,30'dur ve
  kurgudur; ölçülen şey payın değeri değil karışımın sonucudur.
- **AB40.** On sekiz kurgu kaynağın her biri tek bir konuyu kapsar ve o konuda ya doğru kaydı taşır
  ya taşımaz; taşımayan kaynak **başka bir konunun kodunu** verir.
- **AB41.** Yirmi dört görev altı konuya dağılır; iki konu iç belge dağarcığında vardır, dördü
  **yalnız dışarıdadır**.
- **AB42. Görev dizisi üç adımdır:** ara, getir, kayda yaz. Yanlış kod yanıtta kalmaz, **yan etkili
  adıma da ulaşabilir**.
- **AB43. Taban çizgisi dış bilgisiz döngüdür** — ajan yalnız iç belge dağarcığına bakar. Bedel
  **araç çağrısı, adım, kirli görev** ve yanlış kodun **taşındığı adım** olarak yazılır.

## Ortak Döngü

Ortam, beş temel araç ve ajan döngüsü kurs boyunca aynıdır.

```python
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


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)}


print("ortak ortam:", len(ABONE), "abone ,", len(BELGE), "belge ,",
      len(ARAC), "arac ,", len(GOREV), "gorev")
```

```
ortak ortam: 60 abone , 5 belge , 5 arac , 24 gorev
```

## Kaynak Sınıfı, Karışım ve Seçim

Yüzeye iki araç eklenir: `web_ara` konuya uyan kayıtları getirir, `sayfa_getir` seçilen kaydın
taşıdığı kodu okur. Arama aracının verdiği tek tasarım kararı şudur: **karışımda hangi sınıflar var
ve aday listesinden hangisi seçilir.** Seçim bir kaydı doğrulamaz, yalnız sınıfına bakar.

```python
# ---- KURGU dis bilgi yuzeyi: kaynaklar sinifiyla anilir, hicbir yer adi yoktur
KOD = ("SY01", "TR01", "BR01", "BR02", "BR03", "BR04")
SORU = {"SY01": "sayac donusunde endeks farki nasil hesaplanir",
        "TR01": "tarife basamaklari hangi metrekup degerlerinde degisir",
        "BR01": "bolge dagitim katsayisi kac",
        "BR02": "sayac degisim araligi kac yil",
        "BR03": "itiraz suresi kac gun",
        "BR04": "gecikme orani nasil hesaplanir"}
KONU_IZ = {"endek": "SY01", "basam": "TR01", "katsa": "BR01",
           "degis": "BR02", "itira": "BR03", "gecik": "BR04"}
SINIF = ("birincil", "ikincil", "denetimsiz")
GUVEN = {"birincil": 0.95, "ikincil": 0.70, "denetimsiz": 0.30}
KAYNAK, GETIR = {}, []
for i in range(18):
    r = uretec(TOHUM + 2593 * i)
    s = SINIF[ayrik(r(), [0.28, 0.34, 0.38])]
    KAYNAK[f"K{i + 1:02d}"] = {"sinif": s, "kapsam": KOD[int(r() * 6)],
                               "dogru": r() < GUVEN[s]}
KARISIM, SIRALI = [set(SINIF)], [False]


def konu_coz(a):
    return next((KONU_IZ[t] for t in belirtecle(a) if t in KONU_IZ), None)


def t_web_ara(anahtar="", **_):
    kod = konu_coz(anahtar)
    aday = [k for k, v in KAYNAK.items()
            if v["kapsam"] == kod and v["sinif"] in KARISIM[0]]
    if not aday:
        return {"hata": "kaynak yok"}
    if SIRALI[0]:                       # sinif sirali secim: once birincil
        aday.sort(key=lambda k: (SINIF.index(KAYNAK[k]["sinif"]), k))
    return {"kaynak": aday[0], "bulunan": len(aday)}


def t_sayfa_getir(kaynak=None, **_):
    v = KAYNAK.get(kaynak)
    GETIR.append(None if v is None else v["dogru"])    # iz ile hizali kalir
    if v is None:
        return {"hata": "kaynak yok"}
    return {"sonuc": v["kapsam"] if v["dogru"]
            else KOD[(KOD.index(v["kapsam"]) + 3) % 6], "sinif": v["sinif"]}


ARAC.update({"web_ara": {"islev": t_web_ara, "alan": ("anahtar",), "yan_etki": False},
             "sayfa_getir": {"islev": t_sayfa_getir, "alan": ("kaynak",), "yan_etki": False}})
ARAC_ADI = list(ARAC)

DIS = []
for i in range(24):
    r = uretec(TOHUM + 4643 * i)
    kod = KOD[ayrik(r(), [0.16, 0.16, 0.18, 0.16, 0.16, 0.18])]
    DIS.append({"ad": f"W{i + 1:02d}", "kod": kod, "abone": f"A{1 + int(r() * 60):03d}",
                "istek": SORU[kod], "dizi": ("web_ara", "sayfa_getir", "kayit_yaz")})


def kosum(siniflar, sirali=False, ic=False, tohum=TOHUM):
    """ic=True: dis bilgi yok, ajan yalniz ic belge dagarcigina bakar."""
    KARISIM[0], SIRALI[0] = set(siniflar), sirali
    CAGRI[0] = 0
    dogru = adim = kirli = tasinan = kayit = 0
    for g in DIS:
        GETIR.clear()
        s = ajan(dict(g, dizi=("belge_ara", "kayit_yaz")) if ic else g, tohum=tohum)
        d = s["yanit"] == g["kod"]
        dogru, adim = dogru + d, adim + s["adim"]
        yer = [i for i, (a, _) in enumerate(s["iz"]) if a == "sayfa_getir"]
        yanlis = [yer[m] for m, ok in enumerate(GETIR) if ok is False]
        if yanlis and not d:
            kirli, tasinan = kirli + 1, tasinan + s["adim"] - yanlis[-1]
            kayit += any(a == "kayit_yaz" and not h for a, h in s["iz"])
    return dogru, kirli, tasinan / kirli if kirli else 0.0, kayit, CAGRI[0], adim


print("kaynak sinifi dagilimi:",
      {s: sum(v["sinif"] == s for v in KAYNAK.values()) for s in SINIF})
print("sinifin dogru bilgi tasiyan kaynagi:",
      {s: sum(v["sinif"] == s and v["dogru"] for v in KAYNAK.values()) for s in SINIF})
print("gorev konusu:", {k: sum(g["kod"] == k for g in DIS) for k in KOD})
print("\nkurulum                dogru A  dogru B  kirli gorev  tasinan adim"
      "  kirli kayit  arac cagrisi  adim")
for ad, sf, sr, ic in (("dis bilgi yok", (), False, True),
                       ("yalniz birincil", ("birincil",), False, False),
                       ("birincil + ikincil", SINIF[:2], False, False),
                       ("uc sinif", SINIF, False, False),
                       ("uc sinif , sinif sirali", SINIF, True, False)):
    a = kosum(sf, sr, ic)
    b = kosum(sf, sr, ic, TOHUM + 1)
    print(f"{ad:<22} {a[0] / 24:>8.4f} {b[0] / 24:>8.4f}  {a[1]:>11}"
          f"  {a[2]:>12.2f}  {a[3]:>11}  {a[4]:>12}  {a[5]:>4}")
```

```
kaynak sinifi dagilimi: {'birincil': 6, 'ikincil': 5, 'denetimsiz': 7}
sinifin dogru bilgi tasiyan kaynagi: {'birincil': 6, 'ikincil': 3, 'denetimsiz': 1}
gorev konusu: {'SY01': 3, 'TR01': 2, 'BR01': 5, 'BR02': 5, 'BR03': 4, 'BR04': 5}

kurulum                dogru A  dogru B  kirli gorev  tasinan adim  kirli kayit  arac cagrisi  adim
dis bilgi yok            0.2083   0.2083            0          0.00            0            91   110
yalniz birincil          0.7500   0.8333            0          0.00            0           121   139
birincil + ikincil       0.3750   0.4167           10          3.40           10           121   139
uc sinif                 0.3750   0.3750           15          3.60           15           103   126
uc sinif , sinif sirali   0.7500   0.7917            5          4.00            5           103   126
```

## Karışımın Değiştirdiği Sayı

Taban satırı dış bilgisiz döngüdür: iç belge dağarcığı altı konunun ikisini kapsadığı için doğru
yanıt **0,2083**'te kalıyor. Birincil kaynakları açmak bunu **0,7500**'e çıkarıyor ve kirli görev
sıfır: birincil kaynakların altısı da doğru kaydı taşıyor. Bedel 91'den **121** çağrıya, 110'dan
**139** adıma çıkmaktır; birincil sınıf altı konunun dördünü kapsadığı için kalan ikisinde arama
`kaynak yok` döndürüyor ve ajan adımı yeniden deniyor.

Üçüncü satır kursun ikinci iddiasının örneğidir. Karışıma ikincil sınıfı katmak doğru yanıtı
**0,7500'den 0,3750'ye düşürüyor**. Mekanizma ikinci çıktı satırındadır: ikincil kaynakların beşinin
yalnız üçü doğru kaydı taşıyor ve seçim sınıfa bakmadığı için ikincil bir kayıt birincil olanın
önüne geçebiliyor. Kaynak eklemek burada **bilgi değil gürültü ekledi**.
Denetimsiz sınıfı da katmak doğru yanıtı 0,3750'de bırakıyor ama kirli görevi **10'dan 15'e**
çıkarıyor; buna karşılık çağrı 121'den **103**'e düşüyor, çünkü kapsama tamamlanınca `kaynak yok`
hatası kalmıyor. Daha ucuz ve daha kirli.

Son satır düzeltmenin nerede olduğunu gösteriyor. Havuz aynı, karışım aynı, çağrı **103** ve adım
**126** ile değişmedi; değişen tek şey aday listesinin **sınıfa göre sıralanmasıdır**. Doğru yanıt
**0,7500**'e dönüyor, kirli görev 15'ten **5**'e iniyor. Aynı isabeti yalnız birincil kaynakla da
almıştık, ama orada 121 çağrı ve 139 adım gerekiyordu. **Güvenilmez sınıfı atmak değil, sınıfları
sıralamak** hem daha doğru hem daha ucuz. Kalan beş kirli görev de sıralamanın sınırını yazıyor:
birincil kaynağı hiç olmayan iki konu, görev dağılımında tam **beş** göreve karşılık geliyor.

İki koşum sütunu hangi farkın gerçek olduğunu söyler: en büyük koşum farkı yalnız birincil
satırındaki 0,8333 ile 0,7500 arasındadır, band **0,0833**. Hem 0,3750'lik düşüş hem 0,3750'lik
toparlanma bandın çok üstündedir ve **ölçülmüştür**. Kirlenmenin ömrü kirli görev ve taşınan adım sütunlarındadır: yanlış kod
duruma girdikten sonra ortalama **3,40**, **3,60** ve **4,00** adım taşınıyor ve kirli görevlerin
**tamamı** kirli kayıt sütununda da görünüyor. Yanlış kaynak yanıtta durmuyor, `kayit_yaz` ile
kalıcı hâle geliyor.

## Özet

- Dış bilgide denetlenebilen şey içeriğin doğruluğu değil kaydın sınıfıdır; kaynaklar birincil,
  ikincil ve denetimsiz diye sayılır ve hiçbiri adıyla anılmaz.
- Dış bilgisiz döngü 0,2083 doğru yanıt verir; yalnız birincil kaynak 0,7500'e çıkarır, bedeli
  91'den 121'e çıkan çağrıdır.
- Karışıma ikincil sınıfı katmak doğru yanıtı 0,3750'ye düşürür; kaynak eklemek bilgi değil gürültü
  ekleyebilir ve bu kursun ikinci iddiasının bir örneğidir.
- Üç sınıf birlikte kirli görevi 15'e çıkarır ama çağrıyı 103'e indirir; aynı havuzda seçimi sınıfa
  göre sıralamak doğru yanıtı 0,7500'e getirir, kirli görevi 5'e indirir, çağrıyı artırmaz.
- Yanlış kod ortalama 3,40 ile 4,00 adım taşınır ve kirli görevlerin tamamında kayıt yazma adımına
  ulaşır; ölçüm bandı 0,0833 olduğu için her iki 0,3750'lik oynama da ölçülmüştür.

## Sonraki Adım

Bu derste yanlış bir kodun **taşındığı** adım sayıldı, ama taşıyan şeyin kendisi ölçülmedi. Ajanın
durumu her adımda büyüyor: gözlemler birikiyor, iz uzuyor ve bir sonraki çağrıya gönderilen her
turda artıyor. Bağlam penceresi Yapay Zekâ Mühendisliğine Giriş kursunda tanımlandı, konuşma
durumunun her istekte yeniden gönderilmesi Model API'leri ile Uygulama Geliştirme kursunda ölçüldü;
ikisi de tekrarlanmaz. Sonraki ders döngüye özgü olanı sorar: adım başına kaç belirteç taşınıyor,
pencereye kaç adım sığıyor, ve pencere dolduğunda **hangi alan** düşüyor.
