#!/usr/bin/env python3
"""Generate all SVG illustrations for Chapter 3 (Knowledge Base & RAG).
Figures (14 total):
fig3-1: Chapter roadmap
fig3-2: RAG end-to-end pipeline (concrete example)
fig3-3: Dense embedding evolution (with dimensions & training)
fig3-4: HNSW index structure (enlarged)
fig3-5: BM25 scoring mechanism (enlarged)
fig3-6: Hybrid retrieval + reranking (with scores)
fig3-7: RAPTOR tree structure (enlarged)
fig3-8: GraphRAG relation network (enlarged)
fig3-9: Agentic vs Non-Agentic RAG (concrete queries)
fig3-10: Agentic RAG system architecture (Exp 3.6)
fig3-11: Contextual retrieval (concrete prefix example)
fig3-12: Structured knowledge extraction pipeline (Exp 3.10)
fig3-13: Externalized learning loop (concrete)
fig3-14: GAIA experience learning (Exp 3.11)
"""
import math
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
from svg_lib import (
SVG, COLORS, FONT, MONO, STROKE_W, CORNER_R, _escape, _marker_def,
FS_TITLE, FS_BODY, FS_SMALL, FS_TINY, FS_LABEL,
)
OUT = os.path.join(os.path.dirname(__file__), 'images')
# ──────────────────────── Helpers ────────────────────────
def _pill(svg, x, y, w, h, label, fill='light', font_size=FS_SMALL, bold=False):
"""Rounded pill / tag shape."""
svg.rect(x, y, w, h, fill=fill, rx=h // 2)
c = 'white' if fill in ('dark', 'darker') else 'text'
svg.text(x + w / 2, y + h / 2, label, size=font_size, fill=c, bold=bold)
# ──────────────────────── fig3-1 ────────────────────────
def fig3_1():
"""Knowledge map of this chapter"""
w, h = 860, 580
svg = SVG(w, h)
svg.text(w / 2, 32, "Bölüm 3: Bilgi Tabanı ve RAG — Bilgi Haritası", size=FS_TITLE, bold=True)
# --- Row 1: RAG foundations ---
r1_y = 70
svg.rect(30, r1_y, 800, 130, fill='white', stroke='border', dash=True)
svg.text(80, r1_y + 20, "RAG Temelleri", size=FS_BODY, bold=True, anchor='start')
boxes_r1 = [
("Yoğun Gömme", 50, "Word2Vec → BGE-M3"),
("Seyrek Gömme", 230, "TF-IDF / BM25"),
("Hibrit Erişim + Yeniden Sıralama", 410, "İki Kuleli Erişim + Cross-Encoder"),
("Çok Modlu Çıkarım", 650, "Yerel / Metin / Araç"),
]
for label, bx, sub in boxes_r1:
svg.box(bx, r1_y + 38, 160, 50, label, fill='light', bold=True, font_size=FS_SMALL)
svg.text(bx + 80, r1_y + 38 + 50 + 18, sub, size=FS_TINY, fill='text_light')
# --- Arrow down ---
svg.arrow(w / 2, r1_y + 130, w / 2, r1_y + 160)
# --- Row 2: Advanced knowledge structuring ---
r2_y = 230
svg.rect(30, r2_y, 800, 100, fill='white', stroke='border', dash=True)
svg.text(80, r2_y + 20, "Mevcut Bilgiden Öğrenme", size=FS_BODY, bold=True, anchor='start')
boxes_r2 = [
("RAPTOR\n Ağaç Hiyerarşik İndeks", 50),
("GraphRAG\n Varlık İlişki Grafiği", 230),
("Agentic RAG\n Araç Olarak Erişim", 410),
("Bağlam Duyarlı Erişim\n Önek Özet Zenginleştirme", 590),
]
for label, bx in boxes_r2:
svg.box(bx, r2_y + 35, 160, 55, label, fill='medium', font_size=FS_SMALL)
# --- Arrow down ---
svg.arrow(w / 2, r2_y + 100, w / 2, r2_y + 130)
# --- Row 3: Learning from experience ---
r3_y = 360
svg.rect(30, r3_y, 800, 100, fill='white', stroke='border', dash=True)
svg.text(80, r3_y + 20, "Özerk Keşiften Öğrenme", size=FS_BODY, bold=True, anchor='start')
boxes_r3 = [
("Eğitim sonrası\n RL → Kas Hafızası", 100),
("Bağlam İçi Öğrenme\n Çıkarım Anı Yumuşak Erişim", 330),
("Dışsallaştırılmış Öğrenme\n Bilgi Tabanı + Araç Üretimi", 560),
]
for label, bx in boxes_r3:
svg.box(bx, r3_y + 35, 200, 55, label, fill='light', font_size=FS_SMALL)
# --- Bottom: core insight ---
svg.rect(180, 490, 500, 44, fill='dark')
svg.text(w / 2, 512, "Acı Ders: Arama + Öğrenme = Genel Yöntem", size=FS_BODY, fill='white', bold=True)
svg.arrow(w / 2, r3_y + 100, w / 2, 488)
svg.save(os.path.join(OUT, 'fig3-1.svg'))
# ──────────────────────── fig3-2 ────────────────────────
def fig3_2():
"""RAG End-to-End Pipeline (Concrete Example)"""
w, h = 880, 440
svg = SVG(w, h)
svg.text(w / 2, 30, "RAG Uçtan Uca Boru Hattı", size=FS_TITLE, bold=True)
# Step 1: User query
svg.box(20, 65, 180, 55, "① Kullanıcı Sorgusu", fill='medium', bold=True, font_size=FS_BODY)
q_lines = ['"Kasten adam öldürmenin cezası kaç yıl?"']
svg.text(110, 145, q_lines[0], size=FS_SMALL, fill='text_light')
svg.arrow(200, 92, 238, 92)
# Step 2: Retrieval
svg.box(240, 65, 180, 55, "② Erişim", fill='light', bold=True, font_size=FS_BODY)
svg.text(330, 140, "Yoğun Erişim + BM25", size=FS_SMALL, fill='text_light')
svg.text(330, 160, "→ En İyi K Metin Parçası", size=FS_SMALL, fill='text_light')
svg.arrow(420, 92, 458, 92)
# Step 3: Augmentation
svg.box(460, 65, 180, 55, "③ Zenginleştirme", fill='light', bold=True, font_size=FS_BODY)
svg.text(550, 140, "Sorgu + Erişilen Sonuçlar", size=FS_SMALL, fill='text_light')
svg.text(550, 160, "→ Tam İstemi Oluştur", size=FS_SMALL, fill='text_light')
svg.arrow(640, 92, 678, 92)
# Step 4: Generation
svg.box(680, 65, 180, 55, "④ Üretim", fill='medium', bold=True, font_size=FS_BODY)
svg.text(770, 140, "LLM bağlamı sentezler", size=FS_SMALL, fill='text_light')
svg.text(770, 160, "→ Yanıt üret", size=FS_SMALL, fill='text_light')
# Concrete data flow example
svg.line(20, 195, 860, 195, color='dark', dash=True)
svg.text(w / 2, 215, "Örnek veri akışı", size=FS_BODY, bold=True)
# Retrieved chunks
svg.rect(20, 235, 400, 90, fill='code_bg', stroke='dark', rx=4)
svg.text(220, 253, "Erişilen metin parçaları", size=FS_SMALL, bold=True)
svg.mono(30, 278, "Ceza Kanunu Madde 232: Kasten başkasını öldüren kişi ölüm cezası,", size=FS_TINY)
svg.mono(30, 298, "ömür boyu hapis veya on yıldan az olmamak üzere hapis cezasına çarptırılır...", size=FS_TINY)
# Augmented prompt
svg.rect(440, 235, 420, 90, fill='code_bg', stroke='dark', rx=4)
svg.text(650, 253, "Zenginleştirilmiş İstem", size=FS_SMALL, bold=True)
svg.mono(450, 278, "Aşağıdaki yasal hükümlere göre soruyu yanıtla:", size=FS_TINY)
svg.mono(450, 298, "[Ceza Kanunu Madde 232...] S: Kasten adam öldürmenin cezası nedir?", size=FS_TINY)
# Generated answer
svg.rect(20, 345, 840, 80, fill='light', stroke='border')
svg.text(w / 2, 363, "Üretilen yanıt", size=FS_SMALL, bold=True)
svg.mono(30, 390, "Ceza Kanunu Madde 232'ye göre kasten adam öldürme suçu ölüm, ömür boyu hapis veya on yıldan az olmamak üzere hapis cezasıyla cezalandırılır;", size=FS_TINY)
svg.mono(30, 412, "hafifletici durumlarda ceza üç yıldan az on yıldan fazla olmamak üzere hapis cezasıdır.", size=FS_TINY)
svg.save(os.path.join(OUT, 'fig3-2.svg'))
# ──────────────────────── fig3-3 ────────────────────────
def fig3_3():
"""Evolution of dense embedding techniques"""
w, h = 860, 340
svg = SVG(w, h)
svg.text(w / 2, 30, "Yoğun gömme tekniklerinin evrimi", size=FS_TITLE, bold=True)
items = [
("Word2Vec", "2013", "300D\nStatik kelime vektörleri", "Birlikte geçme\nTahminsel eğitim"),
("GloVe", "2014", "300D\nKüresel istatistikler", "Matris ayrıştırma\n+ Birlikte geçme"),
("BERT", "2018", "768D\nBağlam duyarlı", "Transformer\nMLM ön eğitimi"),
("Sentence-BERT", "2019", "768D\nCümle düzeyi gömme", "Siyam ağı\nZıtsal öğrenme"),
("BGE-M3", "2024", "1024D\nÇok dilli uzun metinler", "Çok aşamalı\nHibrit eğitim"),
]
n = len(items)
pad_l, pad_r = 80, 80
usable = w - pad_l - pad_r
gap = usable / (n - 1)
line_y = 90
svg.line(pad_l - 30, line_y, w - pad_r + 30, line_y, color='dark')
svg.elems.append(
f''
)
for i, (name, year, dims, training) in enumerate(items):
x = pad_l + i * gap
svg.circle(x, line_y, 8, fill='dark')
svg.text(x, line_y - 30, name, size=FS_BODY, bold=True)
svg.text(x, line_y + 28, year, size=FS_SMALL, fill='text_light')
svg.rect(x - 65, line_y + 50, 130, 55, fill='light')
for j, dl in enumerate(dims.split('\n')):
svg.text(x, line_y + 68 + j * 22, dl, size=FS_SMALL)
svg.rect(x - 65, line_y + 115, 130, 55, fill='code_bg', stroke='dark', rx=4)
for j, tl in enumerate(training.split('\n')):
svg.text(x, line_y + 133 + j * 22, tl, size=FS_SMALL, fill='text_light')
# Bottom labels
svg.text(pad_l + gap * 0.5, h - 18,
"Statik kelime vektörleri (kelime başına bir vektör)", size=FS_SMALL, fill='text_light')
svg.text(pad_l + gap * 3.5, h - 18,
"Bağlam duyarlı gömmeler (kelime başına çoklu vektör)", size=FS_SMALL, fill='text_light')
svg.line(pad_l + gap * 1.5, 75, pad_l + gap * 1.5, h - 35, color='dark', dash=True)
svg.save(os.path.join(OUT, 'fig3-3.svg'))
# ──────────────────────── fig3-4 ────────────────────────
def fig3_4():
"""HNSW index structure"""
w, h = 750, 440
svg = SVG(w, h)
svg.text(w / 2, 30, "HNSW indeks yapısı", size=FS_TITLE, bold=True)
layers = [
("Katman 2 (seyrek · uzun mesafe bağlantılar)", 70, 3),
("Katman 1 (orta yoğunluk)", 185, 6),
("Katman 0 (yoğun · tüm düğümler)", 300, 10),
]
for label, base_y, count in layers:
svg.rect(30, base_y - 30, w - 60, 90, fill='white', stroke='dark', dash=True)
svg.text(100, base_y - 14, label, size=FS_SMALL, fill='text_light', anchor='start')
spacing = (w - 140) / (count + 1)
positions = []
for j in range(count):
cx = 70 + spacing * (j + 1)
cy = base_y + 25
svg.circle(cx, cy, 14, fill='light')
positions.append((cx, cy))
for j in range(count - 1):
skip = 1 if count <= 6 else (2 if j % 2 == 0 else 1)
if j + skip < count:
x1, y1 = positions[j]
x2, y2 = positions[j + skip]
svg.line(x1 + 14, y1, x2 - 14, y2, color='dark')
# Search path arrows
svg.arrow(w / 2, 130, w / 2 - 50, 165, color='border')
svg.text(w / 2 + 80, 148, "Arama üst katmandan başlar", size=FS_SMALL, fill='text_light')
svg.arrow(w / 2 - 50, 245, w / 2 - 80, 280, color='border')
svg.text(w / 2 + 60, 263, "Katman katman aşağı doğru inceltilir", size=FS_SMALL, fill='text_light')
# Key properties
svg.rect(50, h - 45, 300, 32, fill='light')
svg.text(200, h - 29, "Artımlı güncellemeleri destekler · Yüksek geri çağırma", size=FS_SMALL, bold=True)
svg.rect(400, h - 45, 300, 32, fill='code_bg', stroke='dark', rx=4)
svg.text(550, h - 29, "O(log N) sorgu karmaşıklığı", size=FS_SMALL)
svg.save(os.path.join(OUT, 'fig3-4.svg'))
# ──────────────────────── fig3-5 ────────────────────────
def fig3_5():
"""BM25 scoring mechanism"""
w, h = 800, 380
svg = SVG(w, h)
svg.text(w / 2, 30, "BM25 puanlama mekanizması", size=FS_TITLE, bold=True)
# Formula
svg.rect(40, 50, w - 80, 50, fill='code_bg', stroke='dark', rx=4)
svg.mono(60, 75,
"Score(Q,D) = Σ IDF(qi) × TF(qi,D)×(k1+1) / (TF + k1×(1-b+b×|D|/avgdl))",
size=FS_SMALL)
# Three components
boxes = [
("Terim frekansı doygunluğu (TF)", 40, 'light', [
"k₁ doygunluk hızını kontrol eder",
"TF ↑ ama katkı azalır",
"Örnek: 5→10 tekrar",
"Skor sadece ~%20 artar",
]),
("Ters belge frekansı (IDF)", 290, 'light', [
"Kelime nadirliğini ölçer",
"\"the\" → IDF ≈ 0",
"\"cezalandırma\" → IDF ≈ 5.2",
"Nadir kelime ağırlığı >> yaygın kelime",
]),
("Uzunluk normalizasyonu (b)", 540, 'light', [
"b ∈ [0,1] normalizasyon gücü",
"b=0: uzunluğu yok say",
"b=1: tam normalizasyon",
"Uzun belgelere yanlılığı önle",
]),
]
for title, bx, fill, details in boxes:
svg.rect(bx, 120, 220, 170, fill=fill)
svg.text(bx + 110, 148, title, size=FS_BODY, bold=True)
svg.line(bx + 20, 163, bx + 200, 163, color='dark')
for k, line in enumerate(details):
svg.text(bx + 110, 190 + k * 28, line, size=FS_SMALL, fill='text_light')
# Result bar
for bx in [150, 400, 650]:
svg.line(bx, 290, bx, 315, color='dark')
svg.rect(40, 315, w - 80, 48, fill='medium')
svg.text(w / 2, 339, "Nihai skor = Σ (TF doygunluğu × IDF ağırlığı × uzunluk normalizasyonu)", size=FS_BODY, bold=True)
svg.save(os.path.join(OUT, 'fig3-5.svg'))
# ──────────────────────── fig3-6 ────────────────────────
def fig3_6():
"""Hybrid retrieval and re-ranking pipeline (with score examples)"""
w, h = 880, 480
svg = SVG(w, h)
svg.text(w / 2, 30, "Hibrit erişim ve yeniden sıralama boru hattı", size=FS_TITLE, bold=True)
# Query
svg.rect(30, 55, 160, 50, fill='medium')
svg.text(110, 73, "Kullanıcı sorgusu", size=FS_BODY, bold=True)
svg.mono(110, 93, '"kedicik davranışı"', size=FS_TINY, anchor='middle')
# Dense retrieval
svg.arrow(190, 68, 238, 68)
svg.box(240, 50, 180, 50, "Yoğun erişim", fill='light', bold=True, font_size=FS_BODY)
svg.text(330, 118, "Anlamsal eşleşme: kedicik ≈ kedi", size=FS_SMALL, fill='text_light')
dense_results = [
("doc3: \"kedigil alışkanlıklar ve kedi oyunu...\"", "cos=0.87"),
("doc7: \"kedi tımarlama örüntüleri...\"", "cos=0.82"),
("doc1: \"evcil hayvan bakım temelleri...\"", "cos=0.71"),
]
for i, (doc, score) in enumerate(dense_results):
y = 140 + i * 32
svg.mono(250, y, doc, size=FS_TINY)
svg.text(700, y, score, size=FS_TINY, fill='text_light', anchor='start')
# Sparse retrieval
svg.arrow(190, 90, 238, 270)
svg.box(240, 250, 180, 50, "Seyrek erişim (BM25)", fill='light', bold=True, font_size=FS_BODY)
svg.text(330, 318, "Tam eşleşme: \"kedicik\" anahtar kelimesi", size=FS_SMALL, fill='text_light')
sparse_results = [
("doc5: \"kedicik kum eğitimi...\"", "BM25=8.4"),
("doc9: \"kedicik sahiplenme rehberi...\"", "BM25=6.1"),
("doc2: \"yavru kedi sağlık ipuçları...\"", "BM25=3.2"),
]
for i, (doc, score) in enumerate(sparse_results):
y = 340 + i * 32
svg.mono(250, y, doc, size=FS_TINY)
svg.text(700, y, score, size=FS_TINY, fill='text_light', anchor='start')
# Merge + rerank
svg.arrow(770, 180, 808, 220)
svg.arrow(770, 370, 808, 330)
svg.rect(790, 215, 70, 120, fill='medium')
svg.text(825, 250, "Birleştir", size=FS_BODY, bold=True)
svg.text(825, 275, "Tekilleştir", size=FS_BODY, bold=True)
svg.text(825, 300, "6→5", size=FS_SMALL, fill='text_light')
svg.save(os.path.join(OUT, 'fig3-6.svg'))
# ──────────────────────── fig3-7 ────────────────────────
def fig3_7():
"""RAPTOR tree structure"""
w, h = 800, 440
svg = SVG(w, h)
svg.text(w / 2, 30, "RAPTOR ağaç hiyerarşik indeksi", size=FS_TITLE, bold=True)
# Root
svg.box(300, 55, 200, 50, "Genel özet", fill='dark', bold=True, font_size=FS_BODY)
svg.text(300 + 200 + 15, 80, "← Kök düğüm", size=FS_SMALL, fill='text_light', anchor='start')
# Mid-level
mid_nodes = [("Küme özeti A", 80), ("Küme özeti B", 320), ("Küme özeti C", 560)]
for label, x in mid_nodes:
svg.box(x, 150, 160, 48, label, fill='medium', font_size=FS_BODY)
svg.line(400, 105, 160, 150, color='border')
svg.line(400, 105, 400, 150, color='border')
svg.line(400, 105, 640, 150, color='border')
svg.text(35, 230, "Orta katman ↑", size=FS_SMALL, fill='text_light', anchor='start')
# Leaf nodes — 7 boxes evenly distributed, narrower to avoid overlap
chunks = [
[(40, "Metin parçası 1"), (140, "Metin parçası 2"), (240, "Metin parçası 3")], # Cluster A → cluster center ~160
[(360, "Metin parçası 4"), (460, "Metin parçası 5")], # Cluster B → cluster center ~410
[(560, "Metin parçası 6"), (660, "Metin parçası 7")], # Cluster C → cluster center ~640
]
leaf_w = 88
mid_cxs = [160, 400, 640]
for gi, group in enumerate(chunks):
for cx, label in group:
svg.box(cx, 250, leaf_w, 40, label, fill='light', font_size=FS_SMALL)
svg.line(cx + leaf_w / 2, 250, mid_cxs[gi], 198, color='dark')
svg.text(35, 295, "Yaprak katmanı ↑", size=FS_SMALL, fill='text_light', anchor='start')
# Original document
svg.rect(40, 320, 720, 55, fill='white', stroke='dark', dash=True)
svg.text(400, 340, "Orijinal belge", size=FS_BODY, fill='text_light')
for bx in range(60, 720, 110):
svg.rect(bx, 350, 90, 16, fill='light')
# Bottom label
svg.text(w / 2, h - 20, "Aşağıdan yukarı özyinelemeli soyutlama: ayrıntılar → konular → genel bakış", size=FS_BODY, fill='text_light')
svg.save(os.path.join(OUT, 'fig3-7.svg'))
# ──────────────────────── fig3-8 ────────────────────────
def fig3_8():
"""GraphRAG relational network"""
w, h = 750, 430
svg = SVG(w, h)
svg.text(w / 2, 28, "GraphRAG varlık-ilişki bilgi grafiği", size=FS_TITLE, bold=True)
nodes = [
("Intel", 375, 100, 'medium'),
("SSE", 150, 190, 'light'),
("AVX", 550, 190, 'light'),
("XMM kaydı", 100, 320, 'light'),
("ADDPS", 280, 340, 'light'),
("YMM kaydı", 520, 320, 'light'),
("FP işlemleri", 375, 250, 'light'),
]
node_r = 42
# Community box (drawn first, as background layer, to avoid covering subsequent nodes and edges)
svg.rect(50, 275, 300, 110, fill='none', stroke='border', dash=True)
svg.text(200, 395, "Topluluk: SSE komut kümesi", size=FS_SMALL, fill='text_light')
for label, x, y, fill in nodes:
svg.circle(x, y, node_r, fill=fill, label=label, font_size=FS_SMALL)
edges = [
(0, 1, "Geliştirme"), (0, 2, "Geliştirme"),
(1, 3, "Kullanım"), (1, 6, ""), (1, 4, "İçerir"),
(2, 5, "Kullanım"), (2, 6, "Yürütme"),
(6, 3, ""), (6, 5, "İşlem"),
]
for i, j, elabel in edges:
x1, y1 = nodes[i][1], nodes[i][2]
x2, y2 = nodes[j][1], nodes[j][2]
dx, dy = x2 - x1, y2 - y1
dist = math.sqrt(dx * dx + dy * dy)
ux, uy = dx / dist, dy / dist
ax1 = x1 + ux * (node_r + 3)
ay1 = y1 + uy * (node_r + 3)
ax2 = x2 - ux * (node_r + 14)
ay2 = y2 - uy * (node_r + 14)
svg.arrow(ax1, ay1, ax2, ay2, label=elabel, color='dark')
svg.save(os.path.join(OUT, 'fig3-8.svg'))
# ──────────────────────── fig3-9 ────────────────────────
def fig3_9():
"""Agentic RAG vs Non-Agentic RAG (Specific Example)"""
w, h = 880, 560
svg = SVG(w, h)
col_w = 400
lx, rx = 20, 460
# --- Left: Non-Agentic ---
svg.rect(lx, 50, col_w, 45, fill='medium')
svg.text(lx + col_w / 2, 73, "Ajan Olmayan RAG", size=FS_BODY, bold=True)
steps_l = [
("Sorgu: \"Alkollüyken ihmalle ağır yaralamanın cezası, \nsanığın daha önce hırsızlık sabıkası varsa?\"", 'light'),
("Tek erişim:\n\"İhmalle ağır yaralamanın cezalandırılması\"", 'light'),
("Erişim sonucu: Sadece ihmalle yaralama için\ntemel hükümler bulundu (eksik bağlam)", 'code_bg'),
("Doğrudan üretim: \"Alkollü\" ve\n\"önceki sabıka\" etkileyen faktörler eksik", 'light'),
]
prev_y = 95
for i, (s, fill) in enumerate(steps_l):
y = 110 + i * 108
svg.box(lx + 30, y, 340, 80, s, fill=fill, font_size=FS_SMALL)
if i > 0:
svg.arrow(lx + 200, prev_y + 80 + 2, lx + 200, y - 2)
prev_y = y
svg.text(lx + col_w / 2, h - 15, "Tek geçiş · Eksik bilgi", size=FS_BODY, fill='text_light')
# --- Separator ---
svg.line(440, 50, 440, h - 5, color='dark', dash=True)
# --- Right: Agentic ---
svg.rect(rx, 50, col_w, 45, fill='medium')
svg.text(rx + col_w / 2, 73, "Agentic RAG (ReAct)", size=FS_BODY, bold=True)
steps_r = [
("Düşünce: 3 alt soruya ayrıştırmak gerekiyor", 'light'),
("Arama ①: \"İhmalle ağır yaralamanın cezalandırılması\"\nArama ②: \"Alkollülük halinde cezai sorumluluk\"\nArama ③: \"Önceki hırsızlık sabıkasının etkisi\"", 'code_bg'),
("Gözlem: Temel hükümler bulundu ancak\n\"önceki sabıka\" ile \"ihmalle yaralama\" arası bağlantı eksik", 'light'),
("Arama ④: \"Farklı suç türlerinde tekerrür\nyargısal yorum\"", 'code_bg'),
("Sentez: Tüm yasal hükümleri ve ceza\nanalizini içeren tam yanıt", 'medium'),
]
ys = []
for i, (s, fill) in enumerate(steps_r):
y = 105 + i * 86
hh = 68
svg.box(rx + 30, y, 340, hh, s, fill=fill, font_size=FS_SMALL)
ys.append(y)
if i > 0:
svg.arrow(rx + 200, ys[i - 1] + hh + 2, rx + 200, y - 2)
# Iteration loop arrow
loop_x = rx + 370 + 10
svg.elems.append(
f''
)
svg.text(loop_x + 4, (ys[1] + ys[2]) / 2 + 34, "Yineleme", size=FS_SMALL, fill='text_light',
anchor='start')
svg.text(rx + col_w / 2, h - 15, "Çok turlu yineleme · Eksiksiz bilgi", size=FS_BODY, fill='text_light')
svg.save(os.path.join(OUT, 'fig3-9.svg'))
# ──────────────────────── fig3-10 ────────────────────────
def fig3_10():
"""Agentic RAG System Architecture (Experiment 3.6)"""
w, h = 880, 500
svg = SVG(w, h)
svg.text(w / 2, 30, "Deney 3.6: Agentic RAG Sistem Mimarisi", size=FS_TITLE, bold=True)
# Agent core
svg.rect(220, 55, 440, 200, fill='white', stroke='border')
svg.text(440, 78, "Ajan (ReAct Döngüsü)", size=FS_BODY, bold=True)
# ReAct steps inside agent
react_items = [
("① Düşünce", 240, 100, 180, 45, 'light'),
("② Eylem", 460, 100, 180, 45, 'medium'),
("③ Gözlem", 350, 180, 180, 45, 'light'),
]
for label, bx, by, bw, bh, fill in react_items:
svg.box(bx, by, bw, bh, label, fill=fill, font_size=FS_SMALL, bold=True)
svg.arrow(420, 122, 458, 122)
svg.arrow(640, 130, 530, 178, color='border')
svg.arrow(350, 202, 280, 145, color='border')
# Loop label
svg.text(360, 165, "Bilgi yeterli olana kadar döngü", size=FS_TINY, fill='text_light')
# User
svg.box(20, 95, 160, 55, "Kullanıcı sorgusu", fill='medium', bold=True, font_size=FS_BODY)
svg.arrow(180, 122, 218, 122)
# Final answer
svg.box(700, 95, 160, 55, "Nihai yanıt", fill='medium', bold=True, font_size=FS_BODY)
svg.arrow(660, 122, 698, 122)
# Tool layer
svg.rect(100, 290, 680, 85, fill='white', stroke='border', dash=True)
svg.text(440, 312, "Araç katmanı", size=FS_BODY, bold=True)
tools = [
("knowledge_base_search", 120, 330, 220),
("web_search", 370, 330, 140),
("code_interpreter", 540, 330, 160),
]
for label, tx, ty, tw in tools:
svg.rect(tx, ty, tw, 35, fill='light')
svg.mono(tx + tw / 2, ty + 17, label, size=FS_TINY, anchor='middle')
svg.arrow(440, 255, 440, 288)
svg.arrow(440, 288, 440, 255)
# Knowledge base backends
svg.rect(100, 400, 680, 85, fill='white', stroke='dark', dash=True)
svg.text(440, 420, "Bilgi tabanı arka ucu (değiştirilebilir)", size=FS_BODY, bold=True)
backends = [
("retrieval-pipeline\nHibrit erişim", 120),
("structured-index\nRAPTOR/GraphRAG", 340),
("contextual-retrieval\nBağlam duyarlı", 560),
]
for label, bx in backends:
svg.box(bx, 435, 180, 45, label, fill='light', font_size=FS_SMALL)
svg.arrow(230, 365, 230, 398)
svg.arrow(440, 375, 440, 398)
svg.save(os.path.join(OUT, 'fig3-10.svg'))
# ──────────────────────── fig3-11 ────────────────────────
def fig3_11():
"""Context-aware retrieval (specific prefix example)"""
w, h = 880, 430
svg = SVG(w, h)
svg.text(w / 2, 30, "Bağlam duyarlı erişim", size=FS_TITLE, bold=True)
# Left: Traditional chunking
svg.rect(20, 55, 400, 170, fill='white', stroke='border')
svg.text(220, 78, "Geleneksel parçalama (bağlamsız)", size=FS_BODY, bold=True)
svg.rect(40, 95, 360, 50, fill='code_bg', stroke='dark', rx=4)
svg.mono(50, 112, "Şirketin ikinci çeyrek geliri %3 arttı,", size=FS_TINY)
svg.mono(50, 132, "esas olarak yeni ürün hatlarının katkısıyla.", size=FS_TINY)
svg.text(220, 170, "Soru: \"Şirket\" kim? Hangi yıl?", size=FS_SMALL, fill='text_light')
svg.text(220, 195, "→ Erişim, ilgisiz birçok şirketin gelir verisiyle eşleşir", size=FS_SMALL, fill='text_light')
# Right: Contextual
svg.rect(460, 55, 400, 170, fill='white', stroke='border')
svg.text(660, 78, "Bağlam duyarlı parçalama", size=FS_BODY, bold=True)
svg.rect(480, 95, 360, 35, fill='medium')
svg.mono(490, 113, "[ACME Şirketi 2025 Ç2 Kazanç Raporu · Temel Performans Göstergeleri]", size=FS_TINY)
svg.rect(480, 130, 360, 50, fill='code_bg', stroke='dark', rx=4)
svg.mono(490, 148, "Şirketin ikinci çeyrek geliri %3 arttı,", size=FS_TINY)
svg.mono(490, 168, "esas olarak yeni ürün hatlarının katkısıyla.", size=FS_TINY)
svg.text(660, 200, "→ Tam eşleşme ACME + Ç2 + gelir artışı", size=FS_SMALL, fill='text_light')
# Arrow between
svg.text(440, 140, "→", size=FS_TITLE, bold=True)
# Process flow
svg.line(20, 250, 860, 250, color='dark', dash=True)
svg.text(w / 2, 275, "İndeksleme aşaması: LLM bağlam öneki üretir", size=FS_BODY, bold=True)
flow_y = 300
svg.box(30, flow_y, 180, 55, "Orijinal belge", fill='light', bold=True, font_size=FS_BODY)
svg.arrow(210, flow_y + 27, 248, flow_y + 27)
svg.box(250, flow_y, 180, 55, "Parçalama", fill='light', bold=True, font_size=FS_BODY)
svg.arrow(430, flow_y + 27, 468, flow_y + 27)
svg.box(470, flow_y, 180, 55, "LLM önek üretir\n(istem önbellekleme)", fill='medium',
font_size=FS_SMALL, bold=True)
svg.arrow(650, flow_y + 27, 688, flow_y + 27)
svg.box(690, flow_y, 170, 55, "Önek + orijinal metin\n→ İndeks", fill='light', font_size=FS_SMALL, bold=True)
# Stats
svg.text(w / 2, h - 20,
"Etki: Erişim başarısızlık oranı ↓%49 (+BM25), ↓%67 (+yeniden sıralama) — Anthropic verisi",
size=FS_SMALL, fill='text_light')
svg.save(os.path.join(OUT, 'fig3-11.svg'))
# ──────────────────────── fig3-12 ────────────────────────
def fig3_12():
"""Structured knowledge extraction pipeline (Experiment 3.10)"""
w, h = 880, 510
svg = SVG(w, h)
svg.text(w / 2, 30, "Deney 3.10: Yapılandırılmış bilgi çıkarımı (yargısal emsaller)", size=FS_TITLE, bold=True)
# Phase 1 header
svg.rect(20, 55, 840, 200, fill='white', stroke='border')
svg.text(440, 78, "Aşama 1: Bilgi çıkarımı ve yapılandırma", size=FS_BODY, bold=True)
# Raw cases
svg.rect(40, 95, 180, 65, fill='code_bg', stroke='dark', rx=4)
svg.text(130, 113, "Orijinal karar belgeleri", size=FS_SMALL, bold=True)
svg.mono(50, 138, "CAIL2018 veri kümesi", size=FS_TINY)
svg.arrow(220, 127, 258, 127)
# LLM extraction
svg.rect(260, 95, 180, 65, fill='medium')
svg.text(350, 113, "LLM faktör keşfi", size=FS_SMALL, bold=True)
svg.text(350, 138, "Aşağıdan yukarı Şema", size=FS_SMALL, fill='text_light')
svg.arrow(440, 127, 478, 127)
# Structured JSON
svg.rect(480, 95, 200, 65, fill='code_bg', stroke='dark', rx=4)
svg.text(580, 113, "Yapılandırılmış JSON", size=FS_SMALL, bold=True)
svg.mono(490, 138, "{voluntary_surrender:true, compensation:500000,", size=FS_TINY)
svg.mono(490, 155, " injury_level:severe_second_degree}", size=FS_TINY)
# Schema detail
svg.rect(40, 170, 400, 70, fill='light')
svg.text(240, 188, "Modüler veri şeması", size=FS_SMALL, bold=True)
svg.text(240, 212, "Temel şema (gönüllü teslim/tazminat/sabıka) + suç türü genişleme şeması", size=FS_SMALL, fill='text_light')
svg.text(240, 232, "(hırsızlık→ilgili tutar, yaralama→yaralanma derecesi)", size=FS_SMALL, fill='text_light')
# Phase 2 header
svg.rect(20, 270, 840, 200, fill='white', stroke='border')
svg.text(440, 293, "Aşama 2: Faktör analizi ve bilgi modelleme", size=FS_BODY, bold=True)
# Vectorization
svg.rect(40, 310, 200, 65, fill='light')
svg.text(140, 328, "Özellik vektörleştirme", size=FS_SMALL, bold=True)
svg.text(140, 350, "One-hot kodlama + multi-hot kodlama", size=FS_SMALL, fill='text_light')
svg.text(140, 370, "+ log dönüşümü + standartlaştırma", size=FS_SMALL, fill='text_light')
svg.arrow(240, 342, 278, 342)
# Clustering
svg.rect(280, 310, 200, 65, fill='medium')
svg.text(380, 328, "KMeans kümeleme", size=FS_SMALL, bold=True)
svg.text(380, 350, "\"dava prototipi\" keşfi", size=FS_SMALL, fill='text_light')
svg.text(380, 370, "örn., \"silahsız kavga, hafif yaralanma\"", size=FS_SMALL, fill='text_light')
svg.arrow(480, 342, 518, 342)
# Factor importance
svg.rect(520, 310, 200, 65, fill='light')
svg.text(620, 328, "faktör önem modeli", size=FS_SMALL, bold=True)
svg.text(620, 350, "her faktörün ağırlığını nicelleştir", size=FS_SMALL, fill='text_light')
svg.text(620, 370, "ceza karar mantığını oluştur", size=FS_SMALL, fill='text_light')
# Application
svg.arrow(620, 375, 620, 400)
svg.rect(40, 400, 720, 60, fill='light')
svg.text(400, 420, "Uygulama: konuşma tabanlı hukuki danışma Ajanı", size=FS_BODY, bold=True)
svg.text(400, 445, "faktör önemine göre sorular yönlendir → benzer dava prototiplerini getir → veri odaklı ceza analizi",
size=FS_SMALL, fill='text_light')
svg.save(os.path.join(OUT, 'fig3-12.svg'))
# ──────────────────────── fig3-13 ────────────────────────
def fig3_13():
"""Externalized learning loop (concrete example)"""
w, h = 880, 490
svg = SVG(w, h)
svg.text(w / 2, 30, "Dışsallaştırılmış öğrenme: deneyimden yeteneğe kapalı döngü", size=FS_TITLE, bold=True)
# Central Agent
cx, cy = 440, 210
svg.circle(cx, cy, 55, fill='medium', label="Ajan", font_size=FS_BODY)
# 5 steps around the loop
steps = [
("① Görevi yürüt", 120, 100, "iade talebini işle\nmüşteri hizmetleri API'sini çağır"),
("② Geri bildirim al", 680, 100, "45$ başarıyla iade edildi\nson dört haneyi doğrulamak gerekiyor"),
("③ Yansıt ve özümse", 680, 310, "LLM deneyimi özetler:\n\"A Şirketi iadesi doğrulama gerektirir\""),
("④ Bilgi tabanına kaydet", 340, 380, "deneyim → vektörleştirilmiş indeks\nsüreç → araç koduna dönüştür"),
("⑤ Gelecekte erişim ve yeniden kullanım", 120, 310, "benzer görev → deneyimi getir\nbaşarılı stratejiyi doğrudan kullan"),
]
positions = []
for label, x, y, detail in steps:
svg.box(x, y, 200, 80, label + "\n" + detail,
fill='light', font_size=FS_SMALL)
positions.append((x + 100, y + 40))
# Arrows connecting steps
arrow_pairs = [
(0, 1), (1, 2), (2, 3), (3, 4), (4, 0),
]
for si, ei in arrow_pairs:
sx, sy = positions[si]
ex, ey = positions[ei]
dx, dy = ex - sx, ey - sy
dist = math.sqrt(dx * dx + dy * dy)
ux, uy = dx / dist, dy / dist
svg.arrow(sx + ux * 105, sy + uy * 45,
ex - ux * 105, ey - uy * 45, color='dark')
# Two output types
svg.rect(30, 395, 180, 28, fill='dark')
svg.text(120, 409, "Bilgi: özet/ağaç özeti", size=FS_SMALL, fill='white')
svg.rect(670, 395, 180, 28, fill='dark')
svg.text(760, 409, "Araç: süreç → kod", size=FS_SMALL, fill='white')
svg.save(os.path.join(OUT, 'fig3-13.svg'))
# ──────────────────────── fig3-14 ────────────────────────
def fig3_14():
"""GAIA experience learning system (Experiment 3.11)"""
w, h = 880, 510
svg = SVG(w, h)
svg.text(w / 2, 30, "Deney 3.11: GAIA deneyim öğrenme sistemi", size=FS_TITLE, bold=True)
box_h = 60
step_gap = 75
base_y = 100
# --- Left: Learning Mode ---
lx = 20
svg.rect(lx, 55, 400, 420, fill='white', stroke='border')
svg.text(lx + 200, 80, "Öğrenme Modu", size=FS_BODY, bold=True)
learn_steps = [
("GAIA görevi", 'medium', "karmaşık çok adımlı problem"),
("Ajan yürütmesi", 'light', "tarayıcı + dosya + kod yorumlayıcı"),
("Görev başarılı mı?", 'light', "Otomatik Değerlendirme (AWorld)"),
("LLM Yansıtma ve Özetleme", 'medium', "Strateji Özeti Çıkar"),
("Deneyim → Vektörleştirme", 'light', "Deneyim Bilgi Tabanına Kaydet"),
]
for i, (label, fill, sub) in enumerate(learn_steps):
y = base_y + i * step_gap
svg.box(lx + 50, y, 300, box_h, label, sublabel=sub, fill=fill, bold=True, font_size=FS_BODY)
if i > 0:
svg.arrow(lx + 200, base_y + (i - 1) * step_gap + box_h + 2, lx + 200, y - 2)
# --- Right: Apply Mode ---
rx = 460
svg.rect(rx, 55, 400, 420, fill='white', stroke='border')
svg.text(rx + 200, 80, "Uygulama Modu", size=FS_BODY, bold=True)
apply_steps = [
("Yeni GAIA Görevi", 'medium', "Yeni Soru Al"),
("Deneyimin Anlamsal Erişimi", 'light', "Deneyim Tabanında Benzer Görev Ara"),
("Sistem İstemine Enjekte Et", 'medium', "Geçmiş Başarılı Stratejiler Örnek Olarak"),
("Ajan yürütmesi", 'light', "Deneyimden Yararlanarak Daha Verimli Problem Çözme"),
("Başarı Oranı ↑ Verimlilik ↑", 'dark', "Kendi Kendine Evrim: Zamanla Güçlenme"),
]
for i, (label, fill, sub) in enumerate(apply_steps):
y = base_y + i * step_gap
svg.box(rx + 50, y, 300, box_h, label, sublabel=sub, fill=fill, bold=True, font_size=FS_BODY)
if i > 0:
svg.arrow(rx + 200, base_y + (i - 1) * step_gap + box_h + 2, rx + 200, y - 2)
# Arrow from learning to apply: the experience KB (centered vertically)
kb_cy = base_y + 2 * step_gap + box_h / 2 #Align with Step 3 Center
kb_x1, kb_x2 = 375, 505
svg.rect(kb_x1, kb_cy - 25, kb_x2 - kb_x1, 50, fill='dark')
svg.text((kb_x1 + kb_x2) / 2, kb_cy - 8, "Deneyim Bilgi Tabanı", size=FS_SMALL, fill='white', bold=True)
svg.text((kb_x1 + kb_x2) / 2, kb_cy + 12, "(Vektör İndeksi)", size=FS_TINY, fill='white')
# Last learn step right-middle → KB left
last_y = base_y + 4 * step_gap + box_h / 2
svg.arrow(lx + 350, last_y, kb_x1 - 2, kb_cy + 10)
# KB right → second apply step left-middle
apply2_y = base_y + 1 * step_gap + box_h / 2
svg.arrow(kb_x2 + 2, kb_cy - 10, rx + 50, apply2_y)
svg.save(os.path.join(OUT, 'fig3-14.svg'))
# ──────────────────────── Main ────────────────────────
ALL_FIGS = [
fig3_1, fig3_2, fig3_3, fig3_4, fig3_5, fig3_6, fig3_7,
fig3_8, fig3_9, fig3_10, fig3_11, fig3_12, fig3_13, fig3_14,
]
if __name__ == '__main__':
os.makedirs(OUT, exist_ok=True)
for fn in ALL_FIGS:
fn()
print(f" ✓ {fn.__name__}: {fn.__doc__}")
print(f"\nDone — {len(ALL_FIGS)} SVGs saved to {OUT}/")