Files
ai-agent-book/book-tr/gen_ch1_figs.py
T
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

538 lines
22 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Generate all Chapter 1 figures."""
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
from svg_lib import *
OUT = os.path.join(os.path.dirname(__file__), 'images')
def fig1_4():
"""Kimi K3 / GPT-5.6 native agent architecture — caption Figure 1-4"""
s = SVG(820, 520)
# Title
s.text(410, 30, '"Ajan Olarak Model" mimarisi: yerel araç çağırma', size=FS_TITLE, bold=True)
# Central model box
s.rect(260, 70, 300, 100, fill='medium')
s.text(410, 100, 'LLMKimi K3 / GPT-5.6', size=FS_BODY, bold=True)
s.text(410, 130, 'RL eğitimi sonrası yerel ajan yetenekleri', size=FS_SMALL, fill='text_light')
# Built-in tools on the right
s.group_box(620, 70, 180, 210, 'Yerel araçlar')
s.box(635, 105, 150, 50, '$web_search', fill='light', font_size=FS_SMALL)
s.box(635, 170, 150, 50, 'code_interpreter', fill='light', font_size=FS_SMALL)
s.box(635, 235, 150, 50, 'Daha fazla araç...', fill='white', font_size=FS_SMALL)
s.arrow(560, 120, 633, 130)
s.arrow(633, 195, 560, 145)
# ReAct loop below
s.group_box(100, 210, 460, 280, 'ReAct döngüsü (model içinde özerk yürütme)')
# Step 1: User input
s.box(120, 250, 200, 55, 'Kullanıcı: Son bir aydaki Bitcoin trendini ara\n', fill='light', font_size=FS_SMALL)
# Step 2: Think
s.box(120, 325, 200, 55, 'Düşünce: Gerçek zamanlı veri\naranmalı, sonra kodla analiz edilmeli', fill='#e8e8e8', font_size=FS_SMALL)
s.arrow(220, 307, 220, 323)
# Step 3: Tool call
s.box(340, 250, 200, 55, '$web_search çağrılıyor\n"Son ay BTC fiyatı"', fill='light', font_size=FS_SMALL)
s.arrow(322, 277, 338, 277)
# Step 4: Tool result
s.box(340, 325, 200, 55, 'Sonuç: [fiyat verisi]\n$67,230 → $71,450', fill='#e8e8e8', font_size=FS_SMALL)
s.arrow(440, 307, 440, 323)
# Step 5: Code
s.box(120, 400, 200, 55, 'code_interpreter çağrılıyor\nRSI, MACD hesaplama kodu', fill='light', font_size=FS_SMALL)
s.arrow(340, 377, 220, 398, color='dark')
# Step 6: Final
s.box(340, 400, 200, 55, 'Nihai çıktı: Teknik analiz\nraporu + görselleştirme grafiği', fill='medium', font_size=FS_SMALL)
s.arrow(322, 427, 338, 427)
# RL training signal — go through the gap between ReAct/tools on the right, avoid blocking internal content
s.arrow_curved(565, 480, 410, 172, curve=40, dash=True, color='dark')
s.text(605, 330, 'RL eğitim sinyali', size=FS_TINY, fill='text_light', bold=True, anchor='start')
# Left side: what's different from traditional
s.group_box(15, 70, 230, 120, 'Geleneksel çerçevelerden farklar')
s.text(130, 110, '✗ Harici orkestrasyon koduna gerek yok', size=FS_SMALL, anchor='middle')
s.text(130, 135, '✗ Elle ReAct döngüsü yazmaya gerek yok', size=FS_SMALL, anchor='middle')
s.text(130, 160, '✓ Model tüm süreci özerk şekilde belirler', size=FS_SMALL, anchor='middle')
s.save(f'{OUT}/fig1-3.svg') # ReAct execution process → Figure 1-3
def fig1_1():
"""Three learning paradigms — caption Figure 1-1."""
s = SVG(820, 480)
s.text(410, 30, 'Ajanlar için üç öğrenme paradigması', size=FS_TITLE, bold=True)
col_w = 240
gap = 20
x_start = (820 - 3 * col_w - 2 * gap) / 2
for i, (title, time_label, items, example) in enumerate([
('Eğitim sonrası', 'Eğitim zamanı', [
'Model ağırlıklarını değiştirir',
'Kalıcı · genel',
'Yüksek maliyet · yavaş güncellenir',
], 'ör. bir aracı ne zaman çağıracağını öğrenir'),
('Bağlam içi öğrenme', 'Çıkarım zamanı', [
'Dikkat mekanizmasıyla yumuşak güncelleme',
'Geçici · anında uyum sağlar',
'Bağlam penceresiyle sınırlı',
], 'ör. 3 örnekten bir biçim öğrenir'),
('Dışsallaştırılmış öğrenme', 'Çalışma zamanı', [
'Bilgi tabanı + üretilen araçlar',
'Kalıcı · güncellenebilir',
'Güvenilir · doğrulanabilir',
], 'ör. bir iş akışını araca dönüştürür'),
]):
x = x_start + i * (col_w + gap)
# Header
s.box(x, 65, col_w, 65, title, fill='medium', bold=True, font_size=FS_BODY)
# Time badge
s.badge(x + col_w / 2 - 40, 140, 80, 28, time_label, fill='darker')
# Items
for j, item in enumerate(items):
y = 185 + j * 45
s.box(x, y, col_w, 38, item, fill='light', font_size=FS_SMALL)
# Example
s.rect(x, 330, col_w, 45, fill='code_bg', stroke='dark', rx=4)
s.text(x + col_w / 2, 352, example, size=FS_SMALL, fill='text_light')
# Timeline arrow at bottom
s.arrow(60, 430, 760, 430, color='dark')
s.text(60, 455, 'Yavaş (Haftalar)', size=FS_SMALL, fill='text_light', anchor='start')
s.text(410, 455, 'Öğrenme Hızı', size=FS_SMALL, fill='text_light')
s.text(760, 455, 'Hızlı (Milisaniyeler)', size=FS_SMALL, fill='text_light', anchor='end')
s.save(f'{OUT}/fig1-4.svg') #Three Learning Paradigms → Figure 1-4
def fig1_2():
"""Context ablation experiment design — caption Figure 1-2."""
W = 1000
s = SVG(W, 470)
s.text(W / 2, 30, 'Bağlam Ablasyon Deneyi Tasarımı', size=FS_TITLE, bold=True)
# Two-line column headers so each fits its column without overlap.
components = [
('Sistem', 'istemi'),
('Araç', 'tanımları'),
('Araç çal.', 'sonuçları'),
('Düşünce', 'süreci'),
('Geçmiş', 'mesajlar'),
]
comp_w = 108
comp_gap = 10
label_x = 168 # row labels right-anchored here
comp_x = 182 # check grid starts here
for i, (l1, l2) in enumerate(components):
x = comp_x + i * (comp_w + comp_gap)
s.text(x + comp_w / 2, 56, l1, size=FS_SMALL, bold=True)
s.text(x + comp_w / 2, 76, l2, size=FS_SMALL, bold=True)
# Result column header
result_x = comp_x + len(components) * (comp_w + comp_gap) + 12
s.text(result_x + 90, 66, 'Sonuç', size=FS_SMALL, bold=True)
# Experiment rows (labels shortened to sit within the left margin)
conditions = [
('Tam referans', [True, True, True, True, True], '✓ Normal çalışır'),
('Araç tanımı yok', [True, False, True, True, True], '✗ Araç çağıramaz'),
('Araç sonucu yok', [True, True, False, True, True], '✗ Kör döngü'),
('Muhakeme yok', [True, True, True, False, True], '△ Tutarsız kararlar'),
('Geçmiş yok', [True, True, True, True, False], '△ Tekrarlanan işlemler'),
]
for j, (label, flags, result) in enumerate(conditions):
y = 100 + j * 68
# Row label
s.text(label_x, y + 28, label, size=FS_SMALL, bold=True, anchor='end')
for i, present in enumerate(flags):
x = comp_x + i * (comp_w + comp_gap)
fill = 'light' if present else 'white'
stroke = 'border' if present else 'dark'
s.rect(x, y, comp_w, 55, fill=fill, stroke=stroke, dash=not present)
if present:
s.text(x + comp_w / 2, y + 28, '✓', size=FS_BODY)
else:
s.text(x + comp_w / 2, y + 28, '✗', size=FS_BODY, fill='dark')
# Result (in its own column to the right of the check grid)
s.text(result_x + 90, y + 28, result, size=FS_SMALL, anchor='middle',
fill='text' if '✓' in result else ('text_light' if '△' in result else 'dark'))
s.save(f'{OUT}/fig1-1.svg') # Context ablation experiment → Figure 1-1
def fig1_3():
"""Agent trajectory — caption Figure 1-3."""
s = SVG(820, 680)
s.text(410, 30, 'Ajan izlencesi: Çoklu para birimi toplama görevi için ReAct döngüsü', size=FS_TITLE, bold=True)
lx = 40 # left margin
rw = 480 # box width
code_w = 460
y = 60
# Round 1
s.badge(lx, y, 80, 26, 'Tur 1', fill='darker')
y += 36
# User message
s.rect(lx, y, rw, 50, fill='light')
s.text(lx + 10, y + 16, 'user', size=FS_SMALL, bold=True, anchor='start')
s.text(lx + 10, y + 38, '"Toplam yıllık geliri hesapla: Ç1 $2,5M, Ç2 €2,1M, Ç3 £1,8M"', size=FS_TINY, anchor='start')
y += 60
# Assistant reasoning
s.rect(lx, y, rw, 45, fill='#e8e8e8')
s.text(lx + 10, y + 14, 'assistant.reasoning', size=FS_SMALL, bold=True, anchor='start', fill='darker')
s.text(lx + 10, y + 34, '"EUR ve GBP\'yi USD\'ye çevirip toplamak gerekiyor"', size=FS_TINY, anchor='start')
y += 55
# Tool calls
s.rect(lx, y, rw, 70, fill='code_bg', stroke='dark', rx=4)
s.text(lx + 10, y + 14, 'assistant.tool_calls', size=FS_SMALL, bold=True, anchor='start', fill='darker')
s.mono(lx + 10, y + 36, 'convert_currency(2100000, "EUR", "USD")', size=FS_TINY)
s.mono(lx + 10, y + 54, 'convert_currency(1800000, "GBP", "USD")', size=FS_TINY)
y += 80
# Tool results
s.rect(lx, y, rw, 55, fill='light')
s.text(lx + 10, y + 14, 'tool (result)', size=FS_SMALL, bold=True, anchor='start', fill='darker')
s.mono(lx + 10, y + 36, 'EUR→USD: 2,282,608.70', size=FS_TINY)
s.mono(lx + 250, y + 36, 'GBP→USD: 2,278,481.01', size=FS_TINY)
y += 65
# Round 2
s.badge(lx, y, 80, 26, 'Tur 2', fill='darker')
y += 36
# Assistant reasoning 2
s.rect(lx, y, rw, 45, fill='#e8e8e8')
s.text(lx + 10, y + 14, 'assistant.reasoning', size=FS_SMALL, bold=True, anchor='start', fill='darker')
s.text(lx + 10, y + 34, '"Döviz kurları alındı, toplamak için code interpreter çağrılıyor"', size=FS_TINY, anchor='start')
y += 55
# Code interpreter call
s.rect(lx, y, rw, 50, fill='code_bg', stroke='dark', rx=4)
s.text(lx + 10, y + 14, 'assistant.tool_calls', size=FS_SMALL, bold=True, anchor='start', fill='darker')
s.mono(lx + 10, y + 36, 'code_interpreter("total = 2.5M + 2.28M + 2.28M")', size=FS_TINY)
y += 60
# Round 3
s.badge(lx, y, 80, 26, 'Tur 3', fill='darker')
y += 36
# Final answer
s.rect(lx, y, rw, 45, fill='medium')
s.text(lx + 10, y + 14, 'assistant.content (final answer)', size=FS_SMALL, bold=True, anchor='start')
s.text(lx + 10, y + 36, '"Toplam yıllık gelir $7.061.089,71, çeyreklik ortalama $2.353.696,57"', size=FS_TINY, anchor='start')
y += 55
# Right side: brace + annotation
bx = 540
s.brace_right(bx, 60, y - 10, '')
s.text(600, 250, 'İzlence', size=FS_BODY, bold=True, anchor='start')
s.text(600, 280, '=', size=FS_BODY, anchor='start')
s.text(600, 310, 'LLM\'in her çağrıda', size=FS_BODY, anchor='start')
s.text(600, 340, 'gördüğü tam', size=FS_BODY, anchor='start')
s.text(600, 370, 'girdi', size=FS_BODY, anchor='start')
# Key insight box on right
s.group_box(570, 410, 230, 140, 'Temel özellikler')
s.text(685, 445, 'Bağlam birikimi', size=FS_SMALL, bold=True)
s.text(685, 470, 'Her turda tüm geçmiş görülür', size=FS_TINY, fill='text_light')
s.text(685, 500, 'Yapılandırılmış izlence', size=FS_SMALL, bold=True)
s.text(685, 525, 'user / assistant / tool', size=FS_TINY, fill='text_light')
s.save(f'{OUT}/fig1-2.svg') # Agent trajectory → Figure 1-2
def fig1_wf_chaining():
"""Prompt chaining — workflow pattern (ch1 Orchestration Patterns section)."""
s = SVG(820, 300)
s.text(410, 28, 'İstem zincirleme deseni: çok adımlı içerik üretimi', size=FS_TITLE, bold=True)
# Nodes with concrete descriptions
nodes = [
('Gereksinim belgesi', 'light', FS_SMALL),
('LLM: Taslak oluştur', '#e8e8e8', FS_SMALL),
('LLM: Metni yaz', '#e8e8e8', FS_SMALL),
('LLM: Çeviri', '#e8e8e8', FS_SMALL),
('Çok Dilli Dokümantasyon', 'medium', FS_SMALL),
]
node_w = 130
node_h = 55
gap = 15
total = len(nodes) * node_w + (len(nodes) - 1) * gap
x_start = (820 - total) / 2
y = 65
for i, (label, fill, fs) in enumerate(nodes):
x = x_start + i * (node_w + gap)
s.box(x, y, node_w, node_h, label, fill=fill, font_size=fs)
if i > 0:
px = x_start + (i - 1) * (node_w + gap) + node_w
s.arrow(px + 2, y + node_h / 2, x - 2, y + node_h / 2)
# Gate symbols between steps
gate_y = y + node_h + 15
for i in [1, 2]:
gx = x_start + i * (node_w + gap) + node_w / 2
s.diamond(gx, gate_y + 22, 60, 40, fill='white', label='Kontrol', font_size=FS_TINY)
s.line(gx, y + node_h, gx, gate_y + 2, dash=True, color='dark')
# Example content snippets below
snippet_y = gate_y + 60
snippets = [
(x_start + 15, '"Ürün Sürüm Notları"'),
(x_start + node_w + gap + 15, '→ 5 Bölümlük Taslak'),
(x_start + 2 * (node_w + gap) + 15, '→ 3000 Kelimelik Belge'),
(x_start + 3 * (node_w + gap) + 15, '→ EN / JP / KR'),
]
for sx, txt in snippets:
s.text(sx, snippet_y, txt, size=FS_TINY, fill='text_light', anchor='start')
s.save(f'{OUT}/fig1-5.svg')
def fig1_wf_routing():
"""Routing — workflow pattern (ch1 Orchestration Patterns section)."""
s = SVG(820, 440)
s.text(410, 28, 'Yönlendirme Deseni: Müşteri Hizmetleri Sınıflandırması', size=FS_TITLE, bold=True)
# Input
s.box(30, 130, 150, 55, 'Kullanıcı Sorgusu', fill='medium', font_size=FS_BODY)
# Router
s.diamond(300, 157, 140, 80, fill='#e8e8e8', label='Sınıflandırıcı', font_size=FS_SMALL)
s.arrow(182, 157, 230, 157)
# Branches
branches = [
(55, 'İade Talebi', 'İade Politikası İstemi\n+ Sipariş API', 'light'),
(155, 'Teknik Destek', 'Tanı İstemi\n+ Log Araçları', 'light'),
(255, 'SSS', 'SSS İstemi\n+ Bilgi Tabanı', 'light'),
(355, 'Diğer', 'Haiku (Düşük Maliyet)\n+ Genel İstem', 'white'),
]
bx = 490
bw = 160
for i, (by_offset, label, desc, fill) in enumerate(branches):
by = by_offset
s.box(bx, by, bw, 50, label, fill=fill, bold=True, font_size=FS_SMALL)
s.box(bx + bw + 10, by, 140, 50, desc, fill='code_bg', font_size=FS_TINY)
s.arrow(370, 157, bx - 2, by + 25)
# Annotation
s.text(410, 425, 'Not: Sınıflandırma LLM veya geleneksel sınıflandırıcıyla yapılabilir; basit/yaygın sorgular küçük modellere yönlendirilir', size=FS_SMALL, fill='text_light')
s.save(f'{OUT}/fig1-6.svg')
def fig1_wf_parallel():
"""Parallelization — workflow pattern (ch1 Orchestration Patterns section)."""
s = SVG(820, 360)
s.text(410, 28, 'Paralelleştirme Deseni: Çok Yönlü Kod İncelemesi', size=FS_TITLE, bold=True)
# Input
s.box(30, 130, 150, 55, 'Kod Commit\'i\nPull Request', fill='medium', font_size=FS_SMALL)
# Split
s.text(220, 157, 'Bölümleme', size=FS_SMALL, bold=True)
# Parallel workers
workers = [
(70, 'Güvenlik İnceleme LLM₁', 'SQL Enjeksiyonu\nXSS\nYetki Sızıntısı'),
(155, 'Stil İnceleme LLM₂', 'İsimlendirme Kuralları\nKod Tekrarı\nKarmaşıklık'),
(240, 'Mantık İnceleme LLM₃', 'Sınır Koşulları\nNull Göstericiler\nEşzamanlılık Sorunları'),
]
wx = 290
ww = 155
for i, (wy, title, items) in enumerate(workers):
s.box(wx, wy, ww, 55, title, fill='light', bold=True, font_size=FS_SMALL)
s.box(wx + ww + 5, wy, 130, 55, items, fill='code_bg', font_size=FS_TINY)
s.arrow(180, 157, wx - 2, wy + 28)
# Aggregate
s.box(640, 130, 150, 55, 'Sonuçları Birleştir\nKapsamlı İnceleme Raporu', fill='medium', font_size=FS_SMALL)
for i, (wy, _, _) in enumerate(workers):
s.arrow(wx + ww + 135 + 2, wy + 28, 638, 157)
s.save(f'{OUT}/fig1-7.svg')
def fig1_wf_orchestrator():
"""Orchestrator-workers — workflow pattern (ch1 Orchestration Pattern section)."""
s = SVG(820, 440)
s.text(410, 28, 'Orkestratör-işçi deseni: çok dosyalı kod değişikliği', size=FS_TITLE, bold=True)
# Orchestrator at top: title + internal sub-description arranged vertically
s.rect(260, 60, 300, 95, fill='medium')
s.text(410, 82, 'Orkestratör LLM', size=FS_BODY, bold=True)
s.rect(270, 105, 280, 38, fill='#e8e8e8', rx=4)
s.text(410, 124, '"Sorunu Analiz Et → Dosyaları Bul → Alt Görevleri Ata"', size=FS_TINY)
# Workers
workers = [
(40, 'İşçi 1', 'auth.py dosyasını değiştir\nOAuth2 desteği ekle', 'Read/Edit\nDosya aracı'),
(290, 'İşçi 2', 'api.py dosyasını değiştir\nYeni endpoint ekle', 'Read/Edit\nDosya aracı'),
(540, 'İşçi 3', 'test_auth.py yaz\nTest senaryoları', 'Testleri çalıştır\nAracı'),
]
wy = 220
ww = 230
wh = 55
for wx, title, task, tools in workers:
s.box(wx, wy, ww, wh, f'{title}{task}', fill='light', font_size=FS_SMALL)
s.box(wx + 20, wy + wh + 10, ww - 40, 40, tools, fill='code_bg', font_size=FS_TINY)
s.arrow(410, 157, wx + ww / 2, wy - 2)
# Synthesize
s.box(260, 370, 300, 55, 'Orkestratör: sonuçları birleştir → tutarlılığı doğrula', fill='medium', font_size=FS_SMALL)
for wx, _, _, _ in workers:
s.arrow(wx + ww / 2, wy + wh + 52, 410, 368)
s.save(f'{OUT}/fig1-8.svg')
def fig1_wf_evaluator():
"""Evaluator-optimizer — workflow pattern (ch1 Orchestration Pattern section)."""
s = SVG(820, 380)
s.text(410, 28, 'Değerlendirici-optimize edici deseni: edebi çeviri yinelemesi', size=FS_TITLE, bold=True)
# Generator
s.box(50, 100, 200, 65, 'Üretici LLM\nİlk çeviriyi oluştur', fill='light', font_size=FS_SMALL)
# Output
s.rect(50, 185, 200, 45, fill='code_bg', stroke='dark', rx=4)
s.text(150, 208, '"Bahar uykusu şafaktan habersiz" → v1 çeviri', size=FS_TINY)
s.arrow(150, 167, 150, 183)
# Evaluator
s.box(330, 100, 200, 65, 'Değerlendirici LLM\nÇok boyutlu puanlama', fill='#e8e8e8', font_size=FS_SMALL)
s.arrow(252, 207, 330, 160)
# Evaluation criteria
s.rect(330, 185, 200, 80, fill='code_bg', stroke='dark', rx=4)
s.text(340, 205, 'Doğruluk: 4/5', size=FS_TINY, anchor='start')
s.text(340, 225, 'Akıcılık: 3/5 ← geliştirilmeli', size=FS_TINY, anchor='start')
s.text(340, 245, 'Kültürel uyum: 4/5', size=FS_TINY, anchor='start')
s.arrow(430, 167, 430, 183)
# Feedback loop — label placed above arc to avoid blocking evaluator content
s.arrow_curved(430, 267, 150, 98, curve=80, dash=True, color='dark')
s.text(290, 90, 'Geri bildirim + iyileştirme önerileri', size=FS_TINY, fill='text_light', bold=True)
# Iteration indicator
s.box(610, 100, 170, 55, 'Yineleme sayısı: n', fill='white', font_size=FS_SMALL)
s.text(695, 170, 'Çıkış koşulları:', size=FS_SMALL, bold=True, anchor='start')
s.text(695, 195, '① Tüm boyutlar ≥ 4/5', size=FS_TINY, anchor='start', fill='text_light')
s.text(695, 218, '② Maksimum tur sayısına ulaşıldı', size=FS_TINY, anchor='start', fill='text_light')
# Final output
s.box(220, 310, 380, 55, 'Nihai çıktı: 3 yinelemeden sonra yüksek kaliteli çeviri', fill='medium', font_size=FS_SMALL)
s.save(f'{OUT}/fig1-9.svg')
def fig1_5():
"""Autonomous Agent loop — caption Figure 1-5."""
s = SVG(820, 500)
s.text(410, 28, 'Özerk Ajan yürütme döngüsü', size=FS_TITLE, bold=True)
# While loop structure
s.rect(80, 60, 500, 380, fill='white', stroke='border', rx=8, dash=True)
s.text(330, 82, 'while not done:', size=FS_BODY, bold=True)
# Step 1: Think — title above box, code inside box
s.rect(120, 100, 420, 60, fill='#e8e8e8')
s.text(130, 115, '① Düşün (Muhakeme)', size=FS_SMALL, bold=True, anchor='start')
s.rect(130, 125, 400, 28, fill='code_bg', rx=4)
s.mono(140, 140, '"Arama sonuçları analiz ediliyor...bilgi yetersiz, daha fazla arama gerekli"', size=FS_TINY)
# Step 2: Act
s.rect(120, 175, 420, 60, fill='light')
s.text(130, 190, '② Eylem', size=FS_SMALL, bold=True, anchor='start')
s.rect(130, 200, 400, 28, fill='code_bg', rx=4)
s.mono(140, 215, 'web_search("2025 Ajan RL eğitim teknikleri")', size=FS_TINY)
s.arrow(330, 162, 330, 173)
# Step 3: Observe
s.rect(120, 250, 420, 60, fill='light')
s.text(130, 265, '③ Gözlem', size=FS_SMALL, bold=True, anchor='start')
s.rect(130, 275, 400, 28, fill='code_bg', rx=4)
s.mono(140, 290, 'tool_result: "3 ilgili makale bulundu..."', size=FS_TINY)
s.arrow(330, 237, 330, 248)
# Loop back arrow
s.arrow_curved(540, 280, 540, 120, curve=-40, label='Döngüye devam', color='dark')
# Exit conditions on the right
s.group_box(610, 60, 190, 190, 'Çıkış koşulları')
exits = [
'① Görev tamamlandı',
'② final_answer çağrıldı',
'③ Araç çağrısı dönmedi',
'④ Maksimum tur sayısına ulaşıldı',
'⑤ Hata sayısı aşıldı',
]
for i, ex in enumerate(exits):
s.text(620, 100 + i * 32, ex, size=FS_SMALL, anchor='start')
# Bottom: concrete iteration example
s.rect(80, 360, 500, 70, fill='medium', rx=6)
s.text(330, 380, 'Pratik yürütme örneği: SWE-bench kod düzeltmesi', size=FS_SMALL, bold=True)
s.text(330, 405, 'Kodu ara → Hatayı bul → Dosyayı düzenle → Testleri çalıştır → Başarısız → Tekrar düzenle → Testler geçti → Tamam', size=FS_TINY)
s.text(330, 425, '(5 tur yineleme, 12 araç çağrısı)', size=FS_TINY, fill='text_light')
# Done arrow
s.arrow(330, 312, 330, 358, label='done = True')
s.save(f'{OUT}/fig1-10.svg')
if __name__ == '__main__':
os.makedirs(OUT, exist_ok=True)
# In-chapter figures (referenced as 图 1-1 ~ 图 1-5)
fig1_1()
fig1_2()
fig1_3()
fig1_4()
fig1_5()
# Workflow pattern figures (currently unused in chapter1.md;
# kept for potential future use)
fig1_wf_chaining()
fig1_wf_routing()
fig1_wf_parallel()
fig1_wf_orchestrator()
fig1_wf_evaluator()
print("Chapter 1: 5 in-chapter + 5 workflow figures generated.")