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
1053 lines
50 KiB
Python
1053 lines
50 KiB
Python
"""[DEPRECATED] Old Chapter 9 (multi-Agent) figure generator.
|
||
|
||
⚠️ DO NOT RUN: After the 2026-03-12 refactoring, chapter numbers changed (original Ch 9 → Ch 10).
|
||
The figures generated by this file actually correspond to the current [Chapter 10] content (multi-Agent collaboration), but are still saved as fig9-*.svg.
|
||
Running it would overwrite the current correct [Chapter 9] (multimodal & real-time interaction) figures, causing content misalignment.
|
||
|
||
The current correct Chapter 9 SVGs (multimodal/voice/Computer Use/VLA/Sim2Real) were
|
||
renamed from original fig8-*.svg in commit a33c88f on 2026-03-12; the current correct Chapter 10 SVGs
|
||
(multi-Agent collaboration) were **manually migrated** from the content originally generated by this file to fig10-*.svg.
|
||
|
||
To regenerate figures from this file, you should instead generate fig10-*.svg and reference them according to chapter10.md.
|
||
|
||
Original (now Ch 10) figure list:
|
||
fig10-1: Shared context vs independent context (concrete context windows)
|
||
fig10-2: Phase-based role switching (prompt/tool-set changes per phase)
|
||
fig10-3: Proposer-Reviewer loop (Slidev PPT iterative feedback)
|
||
fig10-4: Manager sequential coordination (sequential sub-agent delegation)
|
||
fig10-5: Book translation Agent architecture (NEW — Exp 10.4)
|
||
fig10-6: Manager parallel coordination (concurrent agents + message bus)
|
||
fig10-7: Phone + Computer dual Agent (NEW — Exp 10.5/10.6)
|
||
fig10-8: Parallel web scraping (NEW — Exp 10.7)
|
||
fig10-9: Handoff chain pattern (peer control passing)
|
||
fig10-10: MetaGPT SOP pipeline (PM→Arch→Eng→QA with artifacts)
|
||
fig10-11: AI town architecture (memory stream + reflection + planning)
|
||
fig10-12: Voice Werewolf Agent system (NEW — Exp 10.9)
|
||
"""
|
||
|
||
import sys
|
||
print(
|
||
"ERROR: gen_ch9_figs.py is DEPRECATED. Running it would overwrite the\n"
|
||
"correct Chapter 9 (multimodal) figures with old Chapter 10 (multi-agent) content.\n"
|
||
"See module docstring at the top of this file for the rename history.",
|
||
file=sys.stderr,
|
||
)
|
||
sys.exit(2)
|
||
import sys, os
|
||
|
||
sys.path.insert(0, os.path.dirname(__file__))
|
||
from svg_lib import (
|
||
SVG, COLORS, FONT, MONO,
|
||
FS_TITLE, FS_BODY, FS_SMALL, FS_TINY, FS_LABEL, STROKE_W, CORNER_R,
|
||
_escape,
|
||
)
|
||
|
||
OUT = os.path.join(os.path.dirname(__file__), 'images')
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-1: Shared context vs independent context
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_1():
|
||
W, H = 780, 560
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 30, 'Paylaşılan bağlam ile bağımsız bağlam karşılaştırması', size=FS_TITLE, bold=True)
|
||
|
||
col_w = 350
|
||
lx, rx = 20, W - col_w - 20
|
||
|
||
# ── Left: shared context ──
|
||
s.group_box(lx, 55, col_w, 480, 'Paylaşılan bağlam (tek Ajan, birden çok aşama)')
|
||
|
||
ctx_x, ctx_w = lx + 15, col_w - 30
|
||
phases = [
|
||
('Aşama 1: Gereksinim Analisti', 'medium', [
|
||
'sys: "Sorumluluğun gereksinimleri tam anlamak..."',
|
||
'tools: [ask_question, save_req]',
|
||
'user: "CSV analiz betiği yaz"',
|
||
'agent: "Hangi dosya türleri işlenmeli?"',
|
||
]),
|
||
('Aşama 2: Yazılım Mühendisi', 'light', [
|
||
'sys: "Onaylanan gereksinimlere göre kod yaz..."',
|
||
'tools: [write_file, execute_code]',
|
||
'agent: write_file("analyze.py", ...)',
|
||
'agent: execute_code("python test.py")',
|
||
]),
|
||
('Aşama 3: Kod İnceleyici', 'light', [
|
||
'sys: "Kod kalitesini ve güvenliğini incele..."',
|
||
'tools: [run_linter, run_tests]',
|
||
'agent: run_linter → 2 uyarı',
|
||
'agent: approve_code()',
|
||
]),
|
||
]
|
||
|
||
cy = 82
|
||
for title, fill, lines in phases:
|
||
ph = 18 + len(lines) * 18 + 10
|
||
s.rect(ctx_x, cy, ctx_w, ph, fill=fill, rx=4)
|
||
s.text(ctx_x + 8, cy + 14, title, size=FS_SMALL, bold=True, anchor='start')
|
||
for i, ln in enumerate(lines):
|
||
s.mono(ctx_x + 12, cy + 32 + i * 18, ln, size=12)
|
||
cy += ph + 2
|
||
|
||
s.rect(ctx_x, cy, ctx_w, 28, fill='code_bg', rx=3)
|
||
s.text(ctx_x + ctx_w // 2, cy + 14, '↑ Tüm aşamalar aynı konuşma geçmişini paylaşır', size=FS_TINY, bold=True)
|
||
cy += 36
|
||
|
||
s.text(lx + col_w // 2, cy + 10, '✓ Tam yürütme izi', size=FS_SMALL, fill='text_light')
|
||
s.text(lx + col_w // 2, cy + 32, '✗ Bağlam hızla genişler', size=FS_SMALL, fill='text_light')
|
||
|
||
# ── Right: independent context ──
|
||
s.group_box(rx, 55, col_w, 480, 'Bağımsız bağlam (gerçek çoklu Ajan)')
|
||
|
||
agents_data = [
|
||
('Sözlük Ajanı', [
|
||
'sys: "Terimleri belirle ve çevir..."',
|
||
'tools: [search_dict, write_file]',
|
||
'→ glossary.json',
|
||
]),
|
||
('Çeviri Ajanı', [
|
||
'sys: "Bu bölümü çevir..."',
|
||
'tools: [read_file, write_file]',
|
||
'→ chapter3_zh.md',
|
||
]),
|
||
('Redaksiyon Ajanı', [
|
||
'sys: "Terim tutarlılığını kontrol et..."',
|
||
'tools: [read_file, write_file]',
|
||
'→ review_report.md',
|
||
]),
|
||
]
|
||
|
||
ay = 82
|
||
for name, lines in agents_data:
|
||
ah = 18 + len(lines) * 18 + 8
|
||
s.rect(rx + 15, ay, ctx_w, ah, fill='light', rx=4)
|
||
s.text(rx + 23, ay + 14, name, size=FS_SMALL, bold=True, anchor='start')
|
||
for i, ln in enumerate(lines):
|
||
s.mono(rx + 27, ay + 32 + i * 18, ln, size=12)
|
||
ay += ah + 8
|
||
|
||
fs_y = ay + 5
|
||
s.rect(rx + 15, fs_y, ctx_w, 65, fill='medium', rx=4)
|
||
s.text(rx + 15 + ctx_w // 2, fs_y + 16, 'Paylaşılan dosya sistemi', size=FS_SMALL, bold=True)
|
||
files = ['glossary.json', 'chapter3_zh.md', 'review_report.md']
|
||
s.mono(rx + 27, fs_y + 38, ' '.join(files), size=11)
|
||
s.text(rx + 15 + ctx_w // 2, fs_y + 55, '+ Araç çağrısı parametreleri yapılandırılmış veri taşır', size=FS_TINY, fill='text_light')
|
||
|
||
s.text(rx + col_w // 2, fs_y + 82, '✓ Modüler · Genişletilebilir · Paralel', size=FS_SMALL, fill='text_light')
|
||
s.text(rx + col_w // 2, fs_y + 104, '✗ Bilgi senkronizasyonu karmaşık', size=FS_SMALL, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-1.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-2: Phase-based role switching
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_2():
|
||
W, H = 780, 520
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Aşama bazlı rol değişimi: Coding Agent üç aşama', size=FS_TITLE, bold=True)
|
||
|
||
phases = [
|
||
('Gereksinim Analisti', 'medium',
|
||
'"Sorumluluğun gereksinimleri tam anlamak.\nHemen uygulamaya geçme; bu aşamada\ngörevin soru sormak ve onaylamak."',
|
||
['ask_clarifying_question(q)', 'save_requirement(k, v)', 'complete_requirements_analysis()'],
|
||
'complete_requirements_analysis()'),
|
||
('Yazılım Mühendisi', 'light',
|
||
'"Onaylanan gereksinimlere göre yüksek kaliteli Python kodu yaz.\nModüler tasarım ve hata işleme en iyi uygulamalarını izle."',
|
||
['write_file(path, content)', 'read_file(path)', 'execute_code(code)'],
|
||
'submit_for_review()'),
|
||
('Kod İnceleyici', '#e8e8e8',
|
||
'"Kod kalitesini birden çok boyutta değerlendir: \nişlevsel doğruluk, kodlama standartları, \nve güvenlik. Eleştirel düşün."',
|
||
['run_linter(file)', 'run_tests(file)', 'analyze_complexity(file)'],
|
||
None),
|
||
]
|
||
|
||
s.rect(30, 55, W - 60, 28, fill='code_bg', rx=3)
|
||
s.text(W // 2, 69, '▼ Aynı bağlam içinde sürekli akış — konuşma geçmişi aşamalar boyunca tam korunur ▼', size=FS_SMALL, bold=True)
|
||
|
||
pw = 225
|
||
gap = 18
|
||
px_start = (W - 3 * pw - 2 * gap) // 2
|
||
py = 100
|
||
|
||
for i, (role, fill, prompt, tools, trigger) in enumerate(phases):
|
||
x = px_start + i * (pw + gap)
|
||
|
||
s.rect(x, py, pw, 380, fill=fill, rx=6)
|
||
s.text(x + pw // 2, py + 22, f'Aşama {i + 1}', size=FS_TINY, fill='text_light')
|
||
s.text(x + pw // 2, py + 42, role, size=FS_BODY, bold=True)
|
||
|
||
s.rect(x + 8, py + 60, pw - 16, 88, fill='code_bg', rx=3)
|
||
s.text(x + 14, py + 75, 'Sistem İstemi', size=FS_TINY, fill='text_light', anchor='start')
|
||
for j, ln in enumerate(prompt.split('\n')):
|
||
s.text(x + 14, py + 92 + j * 16, ln, size=12, anchor='start', fill='text_light')
|
||
|
||
s.rect(x + 8, py + 158, pw - 16, 18 + len(tools) * 20, fill='white', rx=3)
|
||
s.text(x + 14, py + 172, 'Araç Kümesi', size=FS_TINY, fill='text_light', anchor='start')
|
||
for j, tool in enumerate(tools):
|
||
s.mono(x + 14, py + 190 + j * 20, tool, size=11)
|
||
|
||
if trigger:
|
||
ty = py + 290
|
||
s.rect(x + 8, ty, pw - 16, 48, fill='dark', rx=12)
|
||
s.text(x + pw // 2, ty + 16, 'Geçişi Tetikle', size=FS_TINY, fill='white')
|
||
s.mono(x + pw // 2, ty + 34, trigger, size=10, anchor='middle', fill='white')
|
||
|
||
if i < 2:
|
||
ax1 = x + pw + 2
|
||
ax2 = x + pw + gap - 2
|
||
ay = py + 310
|
||
s.arrow(ax1, ay, ax2, ay)
|
||
|
||
s.text(W // 2, H - 10, 'Rol Geçişi: Sistem istemini + araç kümesini güncelle, konuşma geçmişi ve durum kesintisiz korunur',
|
||
size=FS_SMALL, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-2.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-3: Proposer-Reviewer Loop (Slidev PPT Generation)
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_3():
|
||
W, H = 780, 520
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Proposer-Reviewer Döngüsü: Slidev PPT Üretimi', size=FS_TITLE, bold=True)
|
||
|
||
# Editor (Proposer)
|
||
ex, ey, ew, eh = 30, 65, 300, 200
|
||
s.rect(ex, ey, ew, eh, fill='light')
|
||
s.text(ex + ew // 2, ey + 22, 'Proposer Agent', size=FS_BODY, bold=True)
|
||
s.text(ex + 12, ey + 48, 'Girdi: Genişletilmiş makale özeti (2000 karakter)', size=FS_TINY, anchor='start', fill='text_light')
|
||
editor_lines = [
|
||
'---',
|
||
'theme: academic',
|
||
'---',
|
||
'# Transformer Dikkat Mekanizması',
|
||
'',
|
||
'## Temel Fikir',
|
||
'- Self-attention Q·K^T/√d hesaplar',
|
||
'- Çok başlı dikkat paralel işler',
|
||
]
|
||
ch = s.code_block(ex + 10, ey + 62, ew - 20, editor_lines, font_size=11, line_h=14)
|
||
s.text(ex + ew // 2, ey + eh - 10, 'İçerik yapısını anla → Slaytlara ayrıştır', size=FS_TINY, fill='text_light')
|
||
|
||
# Critic (Reviewer)
|
||
cx, cy, cw, ch_h = 450, 65, 300, 200
|
||
s.rect(cx, cy, cw, ch_h, fill='medium')
|
||
s.text(cx + cw // 2, cy + 22, 'Reviewer Agent', size=FS_BODY, bold=True)
|
||
|
||
s.rect(cx + 10, cy + 42, cw - 20, 38, fill='code_bg', rx=3)
|
||
s.text(cx + 18, cy + 55, '① Slidev render → PDF/PNG', size=FS_TINY, anchor='start')
|
||
s.text(cx + 18, cy + 70, '② Görsel LLM çok boyutlu değerlendirme', size=FS_TINY, anchor='start')
|
||
|
||
feedback_items = [
|
||
'Sayfa Sorun Türü Önem',
|
||
'P3 İçerik çok yoğun Yüksek',
|
||
'P7 Yazı çok küçük Orta',
|
||
'P11 Renk uyumsuzluğu Düşük',
|
||
]
|
||
s.rect(cx + 10, cy + 86, cw - 20, 75, fill='code_bg', rx=3)
|
||
s.text(cx + 18, cy + 100, 'Yapılandırılmış Geri Bildirim:', size=FS_TINY, anchor='start', bold=True)
|
||
for i, fb in enumerate(feedback_items):
|
||
s.mono(cx + 18, cy + 118 + i * 15, fb, size=11)
|
||
s.text(cx + cw // 2, cy + ch_h - 10, 'Render + görsel analiz → uygulanabilir iyileştirme önerileri', size=FS_TINY, fill='text_light')
|
||
|
||
# Arrows between Editor and Critic
|
||
mid_y1 = ey + 70
|
||
mid_y2 = ey + eh - 50
|
||
s.arrow(ex + ew + 2, mid_y1, cx - 2, mid_y1)
|
||
s.text((ex + ew + cx) / 2, mid_y1 - 12, 'Slidev Kodu', size=FS_SMALL, bold=True)
|
||
|
||
s.arrow(cx - 2, mid_y2, ex + ew + 2, mid_y2)
|
||
s.text((ex + ew + cx) / 2, mid_y2 + 16, 'Yapılandırılmış Geri Bildirim', size=FS_SMALL, bold=True)
|
||
|
||
# Iteration timeline
|
||
iy = 290
|
||
s.rect(30, iy, W - 60, 100, fill='code_bg', rx=4)
|
||
s.text(W // 2, iy + 18, 'Yinelemeli İyileştirme Süreci', size=FS_BODY, bold=True)
|
||
|
||
rounds = [
|
||
('Tur 1', '12 sayfalık taslak\n5 sorun', 'light'),
|
||
('Tur 2', '14 sayfa (yoğun sayfalar bölündü)\n2 sorun', 'light'),
|
||
('Tur 3', '14 sayfa (yazı boyutu düzeltildi)\n0 sorun ✓', 'medium'),
|
||
]
|
||
rw = 190
|
||
rx_start = (W - 3 * rw - 2 * 30) // 2
|
||
for i, (name, desc, fill) in enumerate(rounds):
|
||
rx = rx_start + i * (rw + 30)
|
||
ry = iy + 35
|
||
s.rect(rx, ry, rw, 52, fill=fill, rx=3)
|
||
s.text(rx + 10, ry + 16, name, size=FS_SMALL, bold=True, anchor='start')
|
||
for j, ln in enumerate(desc.split('\n')):
|
||
s.text(rx + 10, ry + 34 + j * 16, ln, size=FS_TINY, anchor='start', fill='text_light')
|
||
if i < 2:
|
||
s.arrow(rx + rw + 4, ry + 26, rx + rw + 26, ry + 26, color='dark')
|
||
|
||
# Why not single agent
|
||
wy = 405
|
||
s.rect(30, wy, W - 60, 90, fill='light', rx=4)
|
||
s.text(W // 2, wy + 20, 'Neden tekli ajan kullanılmıyor?', size=FS_BODY, bold=True)
|
||
|
||
single_x = 60
|
||
dual_x = W // 2 + 20
|
||
s.text(single_x, wy + 45, 'Tekli Ajan: Render çıktıları × N tur → bağlam patlaması', size=FS_TINY, anchor='start', fill='text_light')
|
||
s.text(single_x, wy + 63, '(1080p ekran görüntüsü = binlerce token × 14 sayfa × 5 tur)', size=FS_TINY, anchor='start', fill='text_light')
|
||
s.text(dual_x, wy + 45, 'İkili Ajan: Critic yalnızca mevcut sürümü görür', size=FS_TINY, anchor='start')
|
||
s.text(dual_x, wy + 63, 'Editor yalnızca metin geri bildirimini biriktirir → temiz bağlam', size=FS_TINY, anchor='start')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-3.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-4: Manager sequential coordination
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_4():
|
||
W, H = 780, 480
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Manager sıralı koordinasyon: Alt Ajan araç olarak', size=FS_TITLE, bold=True)
|
||
|
||
# Manager
|
||
mx, my, mw, mh = 240, 60, 300, 100
|
||
s.rect(mx, my, mw, mh, fill='medium')
|
||
s.text(mx + mw // 2, my + 22, 'Manager Agent', size=FS_BODY, bold=True)
|
||
s.text(mx + mw // 2, my + 46, 'Görev anlama → ayrıştırma → zamanlama → sentezleme', size=FS_TINY, fill='text_light')
|
||
s.text(mx + mw // 2, my + 66, 'Araç kümesi: [call_agent_A, call_agent_B,', size=FS_TINY, fill='text_light')
|
||
s.text(mx + mw // 2, my + 82, 'call_agent_C, search, write_file]', size=FS_TINY, fill='text_light')
|
||
|
||
# Sub-agents in sequence
|
||
agents = [
|
||
('Alt Ajan A', 'Veri toplama', 'Teknik dokümantasyonu ara\nAnahtar bilgiyi çıkar', 'light'),
|
||
('Alt Ajan B', 'Analiz ve işleme', 'Veriyi karşılaştır ve analiz et\nİstatistik raporu üret', 'light'),
|
||
('Alt Ajan C', 'Rapor üretimi', 'Nihai raporu yaz\nÇıktıyı biçimlendir', 'light'),
|
||
]
|
||
aw = 210
|
||
ax_start = (W - 3 * aw - 2 * 25) // 2
|
||
ay = 240
|
||
|
||
for i, (name, role, desc, fill) in enumerate(agents):
|
||
x = ax_start + i * (aw + 25)
|
||
s.rect(x, ay, aw, 120, fill=fill, rx=6)
|
||
s.text(x + aw // 2, ay + 20, name, size=FS_SMALL, bold=True)
|
||
s.text(x + aw // 2, ay + 40, f'Rol: {role}', size=FS_TINY, fill='text_light')
|
||
for j, ln in enumerate(desc.split('\n')):
|
||
s.text(x + aw // 2, ay + 62 + j * 18, ln, size=FS_TINY, fill='text_light')
|
||
|
||
badge_labels = [f'Adım {i + 1}']
|
||
s.badge(x + aw - 55, ay + 95, 50, 20, badge_labels[0], fill='dark', font_size=FS_TINY)
|
||
|
||
# Arrow from Manager to sub-agent
|
||
s.arrow(mx + mw // 2 - 100 + i * 100, my + mh + 2,
|
||
x + aw // 2, ay - 2, color='dark')
|
||
|
||
# Sequential arrow between sub-agents
|
||
if i < 2:
|
||
s.arrow(x + aw + 2, ay + 60, x + aw + 23, ay + 60)
|
||
|
||
# Data flow
|
||
dy = 380
|
||
s.rect(30, dy, W - 60, 80, fill='code_bg', rx=4)
|
||
s.text(W // 2, dy + 18, 'Sıralı yürütme akışı', size=FS_BODY, bold=True)
|
||
|
||
flow_items = [
|
||
'Manager Ajan A\'yı çağırır',
|
||
'→ A veri döndürür',
|
||
'→ Manager B\'ye aktarır',
|
||
'→ B analiz döndürür',
|
||
'→ Manager C\'ye aktarır',
|
||
'→ C rapor döndürür',
|
||
]
|
||
fx_start = 55
|
||
for i, item in enumerate(flow_items):
|
||
s.text(fx_start + i * 118, dy + 42, item, size=FS_TINY, anchor='start',
|
||
fill='text' if 'Call' in item or 'Return' in item else 'text_light')
|
||
|
||
s.text(W // 2, dy + 65, 'Manager perspektifi: Ajan çağırmak = araç çağırmak (istek gönder → yanıt al)',
|
||
size=FS_SMALL, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-4.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-5: Book translation Agent architecture (Exp 9.4)
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_5():
|
||
W, H = 780, 540
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Deney 9.4: Kitap çeviri Ajanı — Manager modu', size=FS_TITLE, bold=True)
|
||
|
||
# Manager at top
|
||
mx, my, mw, mh = 240, 55, 300, 70
|
||
s.rect(mx, my, mw, mh, fill='medium')
|
||
s.text(mx + mw // 2, my + 22, 'Manager Agent', size=FS_BODY, bold=True)
|
||
s.text(mx + mw // 2, my + 48, 'Görev planlama · İlerleme izleme · İstisna yönetimi · Sonuç sentezi', size=FS_TINY, fill='text_light')
|
||
|
||
# Three sub-agents
|
||
sub_agents = [
|
||
(30, 'Sözlük Ajanı', 'Terim sözlüğü',
|
||
['Tüm kitabı al → Uzmanlık terimlerini belirle', 'Uzman sözlükleri + çeviri geleneklerini ara', 'Çıktı: glossary.json'],
|
||
['{"attention": "dikkat",', ' "transformer": "Transformer",', ' "backprop": "geri yayılım"}']),
|
||
(270, 'Çeviri Ajanı ×N', 'Bölüm çevirisi',
|
||
['Girdi: bölüm + sözlük + rehber', 'Terimleri sözlüğe göre sıkı çevir', 'Çıktı: chapter{n}_zh.md'],
|
||
['"...dikkat mekanizması Query·Key^T\'nin', ' benzerliğini hesaplar..."']),
|
||
(520, 'Redaksiyon Ajanı', 'Tam metin incelemesi',
|
||
['Terim tutarlılığını tara ve doğrula', 'Akıcılık ve okunabilirliği kontrol et', 'Çıktı: review_report.md'],
|
||
['P3: "attention"→"odak" tutarsızlığı', 'P8: Uzun cümle bölünmesi önerildi']),
|
||
]
|
||
|
||
aw = 230
|
||
ay = 170
|
||
|
||
for x, name, role, desc, output in sub_agents:
|
||
s.rect(x, ay, aw, 185, fill='light', rx=6)
|
||
s.text(x + aw // 2, ay + 20, name, size=FS_SMALL, bold=True)
|
||
s.text(x + aw // 2, ay + 38, role, size=FS_TINY, fill='text_light')
|
||
|
||
for i, ln in enumerate(desc):
|
||
s.text(x + 12, ay + 60 + i * 18, ln, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
s.rect(x + 8, ay + 115, aw - 16, 10 + len(output) * 15, fill='code_bg', rx=3)
|
||
for i, ln in enumerate(output):
|
||
s.mono(x + 14, ay + 128 + i * 15, ln, size=10)
|
||
|
||
# Arrow from Manager
|
||
s.arrow(mx + mw // 2, my + mh + 2, x + aw // 2, ay - 2, color='dark')
|
||
|
||
# Sequential arrows between sub-agents
|
||
s.arrow(30 + aw + 4, ay + 90, 270 - 4, ay + 90, label='Sözlük')
|
||
s.arrow(270 + aw + 4, ay + 90, 520 - 4, ay + 90, label='Çeviri')
|
||
|
||
# Shared file system
|
||
fy = 375
|
||
s.rect(30, fy, W - 60, 70, fill='medium', rx=6)
|
||
s.text(W // 2, fy + 18, 'Paylaşılan dosya sistemi', size=FS_BODY, bold=True)
|
||
files = [
|
||
('glossary.json', 'Terim sözlüğü'),
|
||
('chapter{1..10}_zh.md', 'Bölüm çevirisi'),
|
||
('review_report.md', 'İnceleme raporu'),
|
||
('translation_guide.md', 'Çeviri rehberi'),
|
||
]
|
||
fw = (W - 80) // len(files)
|
||
for i, (fname, desc) in enumerate(files):
|
||
cx = 50 + i * fw + fw // 2
|
||
s.mono(cx, fy + 40, fname, size=11, anchor='middle')
|
||
s.text(cx, fy + 58, desc, size=FS_TINY, fill='text_light')
|
||
|
||
# Key insight
|
||
ky = 460
|
||
s.rect(30, ky, W - 60, 60, fill='code_bg', rx=4)
|
||
s.text(W // 2, ky + 18, 'Bağlam izolasyonu avantajları', size=FS_BODY, bold=True)
|
||
s.text(W // 2, ky + 42,
|
||
'Sözlük: yalnızca terimleri görür | Çeviri: yalnızca mevcut bölüm + sözlüğü görür | Manager: yalnızca dosya indeksini tutar',
|
||
size=FS_TINY, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-5.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-6: Manager parallel coordination
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_6():
|
||
W, H = 780, 500
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Manager paralel koordinasyon: mesaj veri yolu mimarisi', size=FS_TITLE, bold=True)
|
||
|
||
# Orchestration Agent
|
||
ox, oy, ow, oh = 240, 55, 300, 70
|
||
s.rect(ox, oy, ow, oh, fill='medium')
|
||
s.text(ox + ow // 2, oy + 22, 'Orkestrasyon Ajanı', size=FS_BODY, bold=True)
|
||
s.text(ox + ow // 2, oy + 48, 'Paralel zamanlama · Gerçek zamanlı izleme · Sonuç toplama', size=FS_TINY, fill='text_light')
|
||
|
||
# Message bus
|
||
bus_y = 155
|
||
s.rect(50, bus_y, W - 100, 36, fill='dark', rx=4)
|
||
s.text(W // 2, bus_y + 18, 'Mesaj Veri Yolu', size=FS_SMALL, fill='white', bold=True)
|
||
|
||
s.arrow(ox + ow // 2, oy + oh + 2, ox + ow // 2, bus_y - 2)
|
||
|
||
# Parallel agents
|
||
agents = [
|
||
('Ajan 1', 'Veri toplama', 'Çalışıyor ◎', 'light'),
|
||
('Ajan 2', 'İçerik analizi', 'Çalışıyor ◎', 'light'),
|
||
('Ajan 3', 'Grafik Üretimi', 'Tamamlandı ✓', 'medium'),
|
||
('Ajan 4', 'Biçim Doğrulama', 'Bekliyor ○', 'code_bg'),
|
||
]
|
||
aw = 160
|
||
gap = 14
|
||
total = len(agents) * aw + (len(agents) - 1) * gap
|
||
ax_start = (W - total) // 2
|
||
ay = 225
|
||
|
||
for i, (name, role, status, fill) in enumerate(agents):
|
||
x = ax_start + i * (aw + gap)
|
||
s.rect(x, ay, aw, 100, fill=fill, rx=6)
|
||
s.text(x + aw // 2, ay + 20, name, size=FS_SMALL, bold=True)
|
||
s.text(x + aw // 2, ay + 40, role, size=FS_TINY, fill='text_light')
|
||
s.text(x + aw // 2, ay + 65, status, size=FS_TINY,
|
||
fill='text_light' if 'Bekliyor' in status else 'text')
|
||
s.text(x + aw // 2, ay + 82, 'Bağımsız Bağlam', size=FS_TINY, fill='text_light')
|
||
|
||
s.arrow(x + aw // 2, bus_y + 38, x + aw // 2, ay - 2, color='dark')
|
||
|
||
# Message examples
|
||
my = 350
|
||
s.rect(30, my, W - 60, 125, fill='code_bg', rx=4)
|
||
s.text(W // 2, my + 18, 'Mesaj Veri Yolu İletişim Örneği', size=FS_BODY, bold=True)
|
||
|
||
messages = [
|
||
('Orch → Ajan 1', '{"type":"start","task":"arxiv makalelerini topla","params":{"query":"LLM agent"}}'),
|
||
('Ajan 3 → Orch', '{"type":"completed","agent_id":"3","result":"charts/fig1.svg üretildi"}'),
|
||
('Ajan 1 → Ajan 2', '{"type":"data_ready","source":"agent_1","file":"raw_data.json"}'),
|
||
('Orch → Ajan 4', '{"type":"start","depends_on":["agent_2","agent_3"]}'),
|
||
]
|
||
for i, (sender, msg) in enumerate(messages):
|
||
y = my + 40 + i * 22
|
||
s.text(40, y, sender, size=FS_TINY, bold=True, anchor='start')
|
||
s.mono(200, y, msg, size=10, anchor='start')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-6.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-7: Phone + Computer Dual Agent (Exp 9.5/9.6)
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_7():
|
||
W, H = 780, 560
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Deney 9.5/9.6: Telefon + Bilgisayar İkili Ajan', size=FS_TITLE, bold=True)
|
||
|
||
# Phone Agent (left)
|
||
px, py, pw, ph = 30, 65, 310, 240
|
||
s.rect(px, py, pw, ph, fill='light', rx=6)
|
||
s.text(px + pw // 2, py + 22, 'Telefon Ajanı', size=FS_BODY, bold=True)
|
||
s.text(px + pw // 2, py + 42, 'Node.js · Gerçek Zamanlı Sesli Arama', size=FS_TINY, fill='text_light')
|
||
|
||
phone_pipeline = [
|
||
('Kullanıcı Sesi', 'Mikrofon Girdisi', 'medium'),
|
||
('VAD + ASR', 'Silero VAD → STT Metne Dökme', 'light'),
|
||
('LLM Çıkarımı', 'Niyeti Anla + Bilgi Çıkar', 'light'),
|
||
('TTS Sentezi', 'Ses Yanıtı Üret → Çal', 'medium'),
|
||
]
|
||
for i, (label, desc, fill) in enumerate(phone_pipeline):
|
||
y = py + 60 + i * 42
|
||
s.rect(px + 10, y, pw - 20, 36, fill=fill, rx=3)
|
||
s.text(px + 20, y + 14, label, size=FS_TINY, bold=True, anchor='start')
|
||
s.text(px + 20, y + 28, desc, size=11, anchor='start', fill='text_light')
|
||
if i < len(phone_pipeline) - 1:
|
||
s.arrow(px + pw // 2, y + 38, px + pw // 2, y + 42, color='dark')
|
||
|
||
# Computer Agent (right)
|
||
cx, cy, cw, ch_h = 440, 65, 310, 240
|
||
s.rect(cx, cy, cw, ch_h, fill='light', rx=6)
|
||
s.text(cx + cw // 2, cy + 22, 'Bilgisayar Ajanı', size=FS_BODY, bold=True)
|
||
s.text(cx + cw // 2, cy + 42, 'Python · Tarayıcı Otomasyonu', size=FS_TINY, fill='text_light')
|
||
|
||
comp_pipeline = [
|
||
('Ekran Görüntüsü', 'Mevcut Tarayıcı Sayfası', 'medium'),
|
||
('Görsel LLM', 'Sayfa Yapısını + Form Alanlarını Anla', 'light'),
|
||
('Eylem Planlama', 'Alanları Bul → Girdi Sırasını Planla', 'light'),
|
||
('Eylemleri Yürüt', 'Tıkla / Girdi / Gönder', 'medium'),
|
||
]
|
||
for i, (label, desc, fill) in enumerate(comp_pipeline):
|
||
y = cy + 60 + i * 42
|
||
s.rect(cx + 10, y, cw - 20, 36, fill=fill, rx=3)
|
||
s.text(cx + 20, y + 14, label, size=FS_TINY, bold=True, anchor='start')
|
||
s.text(cx + 20, y + 28, desc, size=11, anchor='start', fill='text_light')
|
||
if i < len(comp_pipeline) - 1:
|
||
s.arrow(cx + cw // 2, y + 38, cx + cw // 2, y + 42, color='dark')
|
||
|
||
# WebSocket connection between agents
|
||
ws_y = py + ph + 15
|
||
s.rect(30, ws_y, W - 60, 36, fill='dark', rx=4)
|
||
s.text(W // 2, ws_y + 18, 'WebSocket Çift Yönlü İletişim (ws://localhost:8849)', size=FS_SMALL, fill='white', bold=True)
|
||
|
||
s.arrow(px + pw // 2, py + ph + 2, px + pw // 2, ws_y - 2, color='dark')
|
||
s.arrow(cx + cw // 2, cy + ch_h + 2, cx + cw // 2, ws_y - 2, color='dark')
|
||
|
||
# Message examples
|
||
my = ws_y + 50
|
||
s.rect(30, my, W - 60, 150, fill='code_bg', rx=4)
|
||
s.text(W // 2, my + 18, 'Gerçek zamanlı çift yönlü mesaj akışı (telefon ve bilgisayar eşzamanlı kullanılır)', size=FS_BODY, bold=True)
|
||
|
||
msgs = [
|
||
('Telefon → Bilgisayar', '[FROM_PHONE_AGENT] Kullanıcı adının Zhang San olduğunu söylüyor', '→'),
|
||
('Bilgisayar → Telefon', '[FROM_COMPUTER_AGENT] Ad dolduruldu, kimlik numarası gerekiyor', '←'),
|
||
('Telefon → Bilgisayar', '[FROM_PHONE_AGENT] Kimlik numarası 310101199001011234', '→'),
|
||
('Bilgisayar → Telefon', '[FROM_COMPUTER_AGENT] Form gönderildi, kayıt başarılı', '←'),
|
||
]
|
||
for i, (sender, content, direction) in enumerate(msgs):
|
||
y = my + 42 + i * 26
|
||
s.text(42, y, sender, size=FS_TINY, bold=True, anchor='start',
|
||
fill='text' if '→' == direction else 'text_light')
|
||
s.mono(210, y, content, size=10, anchor='start')
|
||
|
||
# Key point
|
||
s.text(W // 2, my + 140,
|
||
'Anahtar: İki ajan birbirini bloklamadan bağımsız ReAct döngülerini paralel çalıştırır',
|
||
size=FS_SMALL, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-7.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-8: Parallel Web Scraping Agent (Exp 9.7)
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_8():
|
||
W, H = 780, 530
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Deney 9.7: Paralel Web Kazıma — Basamaklı Sonlandırma', size=FS_TITLE, bold=True)
|
||
|
||
# Orchestration Agent
|
||
ox, oy, ow, oh = 230, 55, 320, 65
|
||
s.rect(ox, oy, ow, oh, fill='medium')
|
||
s.text(ox + ow // 2, oy + 20, 'Orkestrasyon Ajanı', size=FS_BODY, bold=True)
|
||
s.text(ox + ow // 2, oy + 44, 'Dinamik oluşturma · Gerçek zamanlı izleme · Basamaklı sonlandırma', size=FS_TINY, fill='text_light')
|
||
|
||
# Parallel Computer Use Agents
|
||
agents = [
|
||
('Ajan 1', 'cs.edu.cn', 'Aranıyor... ◎', 'light'),
|
||
('Ajan 2', 'math.edu.cn', 'Bulunamadı ✗', '#e8e8e8'),
|
||
('Ajan 3', 'phys.edu.cn', 'Bulundu! ✓', 'medium'),
|
||
('Ajan 4', 'chem.edu.cn', 'Sonlandırıldı ⊘', 'code_bg'),
|
||
('Ajan 5', 'bio.edu.cn', 'Sonlandırıldı ⊘', 'code_bg'),
|
||
]
|
||
aw = 130
|
||
gap = 12
|
||
total_w = len(agents) * aw + (len(agents) - 1) * gap
|
||
ax_start = (W - total_w) // 2
|
||
ay = 160
|
||
|
||
for i, (name, url, status, fill) in enumerate(agents):
|
||
x = ax_start + i * (aw + gap)
|
||
s.rect(x, ay, aw, 95, fill=fill, rx=4)
|
||
s.text(x + aw // 2, ay + 16, name, size=FS_SMALL, bold=True)
|
||
s.mono(x + aw // 2, ay + 35, url, size=10, anchor='middle')
|
||
s.text(x + aw // 2, ay + 55, 'Akademik Kadro Araması', size=FS_TINY, fill='text_light')
|
||
s.text(x + aw // 2, ay + 75, status, size=FS_TINY,
|
||
bold=('Bulundu' in status), fill='text' if 'Bulundu' in status else 'text_light')
|
||
|
||
s.arrow(ox + ow // 2, oy + oh + 2, x + aw // 2, ay - 2, color='dark')
|
||
|
||
# Cascade termination flow
|
||
ty = 280
|
||
s.rect(30, ty, W - 60, 120, fill='code_bg', rx=4)
|
||
s.text(W // 2, ty + 18, 'Basamaklı Sonlandırma Zaman Çizelgesi', size=FS_BODY, bold=True)
|
||
|
||
timeline = [
|
||
('t=0sn', '5 ajan başlat\n"Zhang Wei" öğretmeni paralel ara'),
|
||
('t=12sn', 'Ajan 2 tamamlandı\nBulunamadı → Normal çıkış'),
|
||
('t=18sn', 'Ajan 3 hedefi buldu!\ntarget_found gönder'),
|
||
('t=18.1sn', 'Orch, 1,4,5 nolu Ajanlara\nterminate yayınlıyor'),
|
||
('t=19sn', 'Tümü sonlandırmayı onayladı\nSonuçları topla ve döndür'),
|
||
]
|
||
tw = 130
|
||
tx_start = (W - len(timeline) * tw) // 2
|
||
for i, (time, desc) in enumerate(timeline):
|
||
x = tx_start + i * tw
|
||
s.text(x + tw // 2, ty + 42, time, size=FS_SMALL, bold=True)
|
||
for j, ln in enumerate(desc.split('\n')):
|
||
s.text(x + tw // 2, ty + 60 + j * 16, ln, size=FS_TINY, fill='text_light')
|
||
if i < len(timeline) - 1:
|
||
s.arrow(x + tw - 2, ty + 55, x + tw + 4, ty + 55, color='dark')
|
||
|
||
# Result and comparison
|
||
ry = 420
|
||
s.rect(30, ry, 340, 85, fill='light', rx=4)
|
||
s.text(200, ry + 18, 'Bulunan sonuç', size=FS_BODY, bold=True)
|
||
result_lines = [
|
||
'Ad: Zhang Wei Fakülte: Fizik Fakültesi',
|
||
'Unvan: Profesör Alan: Kuantum Hesaplama',
|
||
'E-posta: zhangwei@phys.edu.cn',
|
||
]
|
||
for i, ln in enumerate(result_lines):
|
||
s.mono(50, ry + 40 + i * 16, ln, size=11)
|
||
|
||
s.rect(400, ry, 350, 85, fill='medium', rx=4)
|
||
s.text(575, ry + 18, 'Performans Karşılaştırması', size=FS_BODY, bold=True)
|
||
s.text(420, ry + 42, 'Seri: 10 site × 30sn = ~5 dakika', size=FS_TINY, anchor='start', fill='text_light')
|
||
s.text(420, ry + 60, 'Paralel: bulmak için 18sn + sonlandırmak için 1sn = 19sn', size=FS_TINY, anchor='start', bold=True)
|
||
s.text(420, ry + 78, 'Hızlanma: ~15× (basamaklı sonlandırma optimizasyonuyla)', size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-8.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-9: Handoff Chain Pattern
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_9():
|
||
W, H = 780, 440
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Handoff Zincir Deseni: Eşler arası devir + Sözleşme tabanlı işbirliği', size=FS_TITLE, bold=True)
|
||
|
||
nodes = [
|
||
('Ajan A', 'Gereksinim Analizi', 'Çıktı: yapılandırılmış gereksinim belgesi \nspec.json', 'medium'),
|
||
('Ajan B', 'Mimari Tasarım', 'Çıktı: teknik tasarım belgesi \ndesign.md', 'light'),
|
||
('Ajan C', 'Kod Uygulaması', 'Çıktı: kaynak kod \nsrc/*.py', 'light'),
|
||
('Ajan D', 'Test Doğrulaması', 'Çıktı: test raporu \ntest_report.md', 'medium'),
|
||
]
|
||
|
||
nw, nh = 160, 130
|
||
gap = 22
|
||
total_w = len(nodes) * nw + (len(nodes) - 1) * gap
|
||
nx_start = (W - total_w) // 2
|
||
ny = 60
|
||
|
||
for i, (name, role, output, fill) in enumerate(nodes):
|
||
x = nx_start + i * (nw + gap)
|
||
s.rect(x, ny, nw, nh, fill=fill, rx=6)
|
||
s.text(x + nw // 2, ny + 20, name, size=FS_SMALL, bold=True)
|
||
s.text(x + nw // 2, ny + 40, role, size=FS_TINY, fill='text_light')
|
||
|
||
s.rect(x + 8, ny + 55, nw - 16, 50, fill='code_bg', rx=3)
|
||
for j, ln in enumerate(output.split('\n')):
|
||
s.text(x + nw // 2, ny + 72 + j * 16, ln, size=FS_TINY, fill='text_light')
|
||
|
||
s.text(x + nw // 2, ny + nh - 8, 'Tamamlanınca devret →', size=FS_TINY, fill='text_light')
|
||
|
||
if i < len(nodes) - 1:
|
||
s.arrow(x + nw + 4, ny + nh // 2, x + nw + gap - 4, ny + nh // 2)
|
||
|
||
# Handoff data detail
|
||
hy = 215
|
||
s.rect(30, hy, W - 60, 90, fill='code_bg', rx=4)
|
||
s.text(W // 2, hy + 18, 'Devir İçeriği (Ajan A → Ajan B Örneği)', size=FS_BODY, bold=True)
|
||
|
||
handoff_fields = [
|
||
('Tetikleme Koşulu', 'A gereksinim belgesini tamamlar → is_complete=True'),
|
||
('Hedef Ajan', 'target="architect" (Ajan B)'),
|
||
('Devir İçeriği', 'files=["spec.json"] + summary="E-ticaret sistemi: 3 mikroservis, REST API"'),
|
||
('Devir Sonrası Durum', 'status="exit" (kaynakları serbest bırak, bekleme durumunda kalma)'),
|
||
]
|
||
for i, (field, value) in enumerate(handoff_fields):
|
||
y = hy + 38 + i * 16
|
||
s.text(42, y, field + ':', size=FS_TINY, bold=True, anchor='start')
|
||
s.text(150, y, value, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
# Comparison with Manager mode
|
||
cy = 320
|
||
s.rect(30, cy, 340, 100, fill='light', rx=4)
|
||
s.text(200, cy + 18, 'Merkezsizleşmenin Avantajları', size=FS_SMALL, bold=True)
|
||
advantages = [
|
||
'✓ Tüm rolleri anlayan merkezi Manager gerekmez',
|
||
'✓ Net sorumluluk sınırları, arayüz ayrıştırması',
|
||
'✓ Engineer birden çok paralel örneğe sahip olabilir',
|
||
]
|
||
for i, adv in enumerate(advantages):
|
||
s.text(48, cy + 42 + i * 20, adv, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
s.rect(400, cy, 350, 100, fill='light', rx=4)
|
||
s.text(575, cy + 18, 'Merkezsizleşmenin Sınırlamaları', size=FS_SMALL, bold=True)
|
||
limits = [
|
||
'✗ Küresel optimizasyon perspektifi eksik',
|
||
'✗ İstisna yönetimi zor (merkezi koordinasyon yok)',
|
||
'✗ Süreç sabit, dinamik ayarlamak zor',
|
||
]
|
||
for i, lim in enumerate(limits):
|
||
s.text(418, cy + 42 + i * 20, lim, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-9.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# fig9-10: MetaGPT SOP Pipeline
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_10():
|
||
W, H = 780, 530
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'MetaGPT SOP Boru Hattı: Standartlaştırılmış Belge Odaklı', size=FS_TITLE, bold=True)
|
||
|
||
roles = [
|
||
('Ürün Yöneticisi', 'medium',
|
||
'Girdi: Kullanıcı Gereksinim Açıklaması',
|
||
['Özellik Listesi + Öncelik', 'Kullanıcı Hikayeleri (5 adet)', 'Kabul Kriterleri'],
|
||
'docs/PRD.md'),
|
||
('Mimar', 'light',
|
||
'Girdi: PRD.md',
|
||
['Teknoloji Yığını: FastAPI+React', 'API Spesifikasyonu (OpenAPI)', 'Veritabanı Şeması'],
|
||
'docs/design.md'),
|
||
('Mühendis ×3', 'light',
|
||
'Girdi: design.md + modül spesifikasyonu',
|
||
['Modül A: Kullanıcı Servisi', 'Modül B: Sipariş Servisi', 'Modül C: Ödeme Servisi'],
|
||
'src/*.py'),
|
||
('QA Mühendisi', 'medium',
|
||
'Girdi: src/ + PRD.md',
|
||
['Birim Testleri (pytest)', 'Entegrasyon Testleri (API)', 'Hata Raporu → Mühendis'],
|
||
'docs/test_report.md'),
|
||
]
|
||
|
||
rw = 170
|
||
gap = 16
|
||
total_w = len(roles) * rw + (len(roles) - 1) * gap
|
||
rx_start = (W - total_w) // 2
|
||
ry = 55
|
||
|
||
for i, (name, fill, input_desc, outputs, artifact) in enumerate(roles):
|
||
x = rx_start + i * (rw + gap)
|
||
|
||
s.rect(x, ry, rw, 230, fill=fill, rx=6)
|
||
s.text(x + rw // 2, ry + 20, name, size=FS_SMALL, bold=True)
|
||
|
||
s.text(x + 8, ry + 42, input_desc, size=11, anchor='start', fill='text_light')
|
||
|
||
s.rect(x + 8, ry + 58, rw - 16, 20 + len(outputs) * 16, fill='code_bg', rx=3)
|
||
s.text(x + 14, ry + 72, 'Çıktı:', size=FS_TINY, bold=True, anchor='start')
|
||
for j, out in enumerate(outputs):
|
||
s.text(x + 14, ry + 88 + j * 16, out, size=11, anchor='start', fill='text_light')
|
||
|
||
s.rect(x + 8, ry + 168, rw - 16, 30, fill='dark', rx=12)
|
||
s.mono(x + rw // 2, ry + 183, artifact, size=11, anchor='middle', fill='white')
|
||
|
||
if i < len(roles) - 1:
|
||
ax1 = x + rw + 2
|
||
ax2 = x + rw + gap - 2
|
||
s.arrow(ax1, ry + 115, ax2, ry + 115)
|
||
|
||
# QA → Engineer feedback loop
|
||
qa_x = rx_start + 3 * (rw + gap) + rw // 2
|
||
eng_x = rx_start + 2 * (rw + gap) + rw // 2
|
||
s.arrow_curved(qa_x, ry + 230 + 5, eng_x, ry + 230 + 5, curve=-30, label='Hata Düzeltme', dash=True)
|
||
|
||
# Shared file system
|
||
fy = 310
|
||
s.rect(30, fy, W - 60, 50, fill='medium', rx=4)
|
||
s.text(W // 2, fy + 16, 'Paylaşılan Proje Dizini', size=FS_SMALL, bold=True)
|
||
s.mono(W // 2, fy + 36, 'docs/PRD.md docs/design.md src/*.py docs/test_report.md',
|
||
size=11, anchor='middle')
|
||
|
||
# Key insight
|
||
ky = 375
|
||
s.rect(30, ky, W - 60, 130, fill='code_bg', rx=4)
|
||
s.text(W // 2, ky + 18, 'MetaGPT Temel Tasarımı', size=FS_BODY, bold=True)
|
||
|
||
insights = [
|
||
('Standartlaştırılmış Belgeler', 'Her rol net biçimde çıktı üretir — alt akış yalnızca biçimi anlamalı, üst akışın düşünce sürecini değil'),
|
||
('Arayüz Ayrıştırması', 'PM\'i iyileştir (daha güçlü modele geç) — çıktı PRD biçimine uyduğu sürece alt akış sıfır değişiklik gerektirir'),
|
||
('Manager Yok', 'Kontrol DAG boyunca doğal akar: PM→Arch→Eng→QA, merkezi zamanlama ek yükü yok'),
|
||
('İstisna Kanalı', 'QA test başarısız → Hata raporu modüle göre Mühendis\'e yönlendirilir → yinelemeli düzeltme'),
|
||
]
|
||
for i, (title, desc) in enumerate(insights):
|
||
y = ky + 42 + i * 24
|
||
s.text(42, y, '▸ ' + title, size=FS_SMALL, bold=True, anchor='start')
|
||
s.text(180, y, desc, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-10.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# Fig9-11: VLA Architecture (Vision-Language-Action) — Comparison of Three Technical Paths
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_11():
|
||
W, H = 900, 620
|
||
s = SVG(W, H)
|
||
|
||
# Common Input
|
||
in_x, in_y, in_w, in_h = 230, 55, 440, 64
|
||
s.rect(in_x, in_y, in_w, in_h, fill='medium', rx=6)
|
||
s.text(in_x + in_w / 2, in_y + 22, 'Ortak Girdi: kamera görüntüsü + dil talimatı', size=FS_SMALL, bold=True)
|
||
s.text(in_x + in_w / 2, in_y + 44, '"Kırmızı bloğu mavi kutuya koy"', size=FS_TINY, fill='text_light')
|
||
|
||
# Arrows leading to three branches
|
||
s.arrow(in_x + 70, in_y + in_h + 2, 145, 165) # → OpenVLA
|
||
s.arrow(W / 2, in_y + in_h + 2, W / 2, 165) # → π₀
|
||
s.arrow(in_x + in_w - 70, in_y + in_h + 2, 755, 165) # → RT-2
|
||
|
||
# Three-Column Architecture
|
||
col_w, col_gap = 270, 30
|
||
cols_total = 3 * col_w + 2 * col_gap
|
||
sx0 = (W - cols_total) / 2 # = 30
|
||
|
||
columns = [
|
||
('OpenVLA', 'Açık kaynak · ayrık eylem tokenleri', 'light', [
|
||
('Görsel kodlayıcı', 'DINOv2 + SigLIP', 'Piksel özelliklerini çıkar'),
|
||
('LLM omurgası', 'Llama 2 (7B)', 'Talimatları ve sahneleri anla'),
|
||
('Kod çözme yöntemi', 'Otoregresif · metin tokenleri', 'Eylemleri seçeneklere ayrıklaştır'),
|
||
('Eylem çıktısı', '"a=[3,−2,5,...]" tokenleri', 'Adım adım 7-DOF kontrol değeri üret'),
|
||
]),
|
||
('π₀(Pi-Zero)', 'Difüzyon politikası · yumuşak yörünge', 'medium', [
|
||
('Görsel kodlayıcı', 'ViT çoklu görünüm füzyonu', 'Piksel özelliklerini çıkar'),
|
||
('Mixture-of-Transformers', 'Hızlı-yavaş ayrık omurga', 'Dil yavaş düşünme + kontrol hızlı düşünme'),
|
||
('Kod çözme yöntemi', 'Difüzyon gürültü giderme yinelemesi', 'Tüm yörüngeyi kabadan inceye iyileştirme'),
|
||
('Eylem çıktısı', 'Sürekli eylem dizisi (50 adım/parti)', 'Yüksek frekanslı yumuşak kontrol sinyali'),
|
||
]),
|
||
('RT-2', 'Eylem modeli olarak dil modeli', 'light', [
|
||
('Görsel-dil omurgası', 'PaLI-X / PaLM-E', 'VLM uçtan uca anlama'),
|
||
('Eylem gösterimi', 'Eylem → doğal dil tokenleri', '"kolu 5cm sağa hareket ettir"'),
|
||
('Kod çözme yöntemi', 'VLM otoregresyonunu yeniden kullan', 'Metin üretimiyle paylaşılan ağırlıklar'),
|
||
('Eylem çıktısı', 'Metin açıklaması → denetleyici ayrıştırması', 'VLM\'in anlamsal genelleme yeteneğini miras al'),
|
||
]),
|
||
]
|
||
|
||
top_y = 165
|
||
title_h = 50
|
||
row_h = 80
|
||
for i, (name, tag, fill, rows) in enumerate(columns):
|
||
cx = sx0 + i * (col_w + col_gap)
|
||
#Column container
|
||
col_total_h = title_h + len(rows) * row_h + 14
|
||
s.rect(cx, top_y, col_w, col_total_h, fill='white', stroke='border')
|
||
#Title bar
|
||
s.rect(cx, top_y, col_w, title_h, fill=fill)
|
||
s.text(cx + col_w / 2, top_y + 18, name, size=FS_BODY, bold=True)
|
||
s.text(cx + col_w / 2, top_y + 38, tag, size=FS_TINY, fill='text_light')
|
||
|
||
#Rows
|
||
for j, (label, value, hint) in enumerate(rows):
|
||
ry = top_y + title_h + 8 + j * row_h
|
||
s.rect(cx + 10, ry, col_w - 20, row_h - 8, fill='code_bg', rx=4)
|
||
s.text(cx + col_w / 2, ry + 18, label, size=FS_TINY, bold=True)
|
||
s.text(cx + col_w / 2, ry + 38, value, size=FS_TINY)
|
||
s.text(cx + col_w / 2, ry + 56, hint, size=FS_TINY, fill='text_light')
|
||
|
||
# Bottom: unified output layer
|
||
out_y = top_y + title_h + 4 * row_h + 14 + 24
|
||
s.rect(30, out_y, W - 60, 50, fill='darker', rx=6)
|
||
s.text(W / 2, out_y + 18,
|
||
'Robot kontrol sinyalleri: 7-DOF eklem açıları / uç efektör pozu',
|
||
size=FS_SMALL, bold=True, fill='white')
|
||
s.text(W / 2, out_y + 36,
|
||
'Fark, "robota bir sonraki adımı nasıl söyleyeceğinde" yatar, ancak sonuçta ikisi de birleşik bir kontrol arayüzüne iner',
|
||
size=FS_TINY, fill='white')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-11.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# Fig 9-12: Voice Werewolf Agent System (Exp 9.9)
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def fig9_12():
|
||
W, H = 780, 550
|
||
s = SVG(W, H)
|
||
|
||
s.text(W // 2, 28, 'Deney 9.9: Sesli Kurt Adam — Bilgi İzin Kontrolü', size=FS_TITLE, bold=True)
|
||
|
||
# Judge (code-driven)
|
||
jx, jy, jw, jh = 260, 55, 260, 75
|
||
s.rect(jx, jy, jw, jh, fill='dark', rx=6)
|
||
s.text(jx + jw // 2, jy + 20, 'Hakem (kod güdümlü)', size=FS_BODY, bold=True, fill='white')
|
||
s.text(jx + jw // 2, jy + 42, 'Oyun durumu · Aşama kontrolü · Bilgi dağıtımı', size=FS_TINY, fill='white')
|
||
s.text(jx + jw // 2, jy + 58, 'Gece → Gündüz → Oylama → Sonuçlandır', size=FS_TINY, fill='white')
|
||
|
||
# Role agents
|
||
roles = [
|
||
(40, 'Kurt Adam 1', '🐺', 'medium',
|
||
['Görünür: Takım arkadaşı kimlikleri', 'Strateji: Köylü gibi davran', 'Gece: Hedef seç']),
|
||
(185, 'Kurt Adam 2', '🐺', 'medium',
|
||
['Görünür: Takım arkadaşı kimlikleri', 'Strateji: Oylamayı takip ederek koru', 'Gece: Hedefte anlaş']),
|
||
(330, 'Görücü', '🔮', 'light',
|
||
['Görünür: Araştırma sonuçları', 'Strateji: Açıklama zamanını seç', 'Gece: 1 kişiyi kontrol et']),
|
||
(475, 'Cadı', '🧪', 'light',
|
||
['Görünür: Ölüm/iyileştirme', 'Strateji: İksir/panzehiri sakla', 'Gece: 1 kişiyi kurtar/zehirle']),
|
||
(620, 'Köylü ×2', '👤', '#e8e8e8',
|
||
['Görünür: Yalnızca kamuya açık bilgi', 'Strateji: Mantıksal muhakeme', 'Gündüz: Konuşmayı analiz et']),
|
||
]
|
||
|
||
aw, ay = 135, 180
|
||
for x, name, icon, fill, info in roles:
|
||
s.rect(x, ay, aw, 140, fill=fill, rx=6)
|
||
s.text(x + aw // 2, ay + 18, f'{icon} {name}', size=FS_SMALL, bold=True)
|
||
for i, ln in enumerate(info):
|
||
s.text(x + aw // 2, ay + 42 + i * 20, ln, size=11, fill='text_light')
|
||
|
||
# Arrow from Judge
|
||
s.arrow(jx + jw // 2, jy + jh + 2, x + aw // 2, ay - 2, color='dark')
|
||
|
||
# Permission badge
|
||
if 'Kurt Adam' in name:
|
||
s.badge(x + aw - 45, ay + aw - 15, 40, 18, 'Karşılıklı bilgi', fill='darker', font_size=11)
|
||
elif 'Görücü' in name:
|
||
s.badge(x + aw - 55, ay + aw - 15, 50, 18, 'Araştırma sonuçları', fill='darker', font_size=10)
|
||
|
||
# Info permission control
|
||
iy = 340
|
||
s.rect(30, iy, W - 60, 90, fill='code_bg', rx=4)
|
||
s.text(W // 2, iy + 18, 'Bilgi izin kontrolü: hakem role göre bağlamı filtreler', size=FS_BODY, bold=True)
|
||
|
||
perms = [
|
||
('Kurt Adam', 'Tüm kurt adam kimlikleri + gece tartışması + herkese açık konuşma'),
|
||
('Görücü', 'Araştırma sonuçları (yalnızca kendi araştırdığı) + herkese açık konuşma'),
|
||
('Cadı', 'Gecenin ölümleri + panzehir/zehir durumu + herkese açık konuşma'),
|
||
('Köylü', 'Yalnızca herkese açık konuşma + oylama kayıtları (sıfır özel bilgi)'),
|
||
]
|
||
pw = (W - 80) // 2
|
||
for i, (role, perm) in enumerate(perms):
|
||
row, col = i // 2, i % 2
|
||
x = 50 + col * pw
|
||
y = iy + 40 + row * 22
|
||
s.text(x, y, role + ':', size=FS_TINY, bold=True, anchor='start')
|
||
s.text(x + 55, y, perm, size=FS_TINY, anchor='start', fill='text_light')
|
||
|
||
# Voice interaction
|
||
vy = 445
|
||
s.rect(30, vy, W - 60, 85, fill='light', rx=4)
|
||
s.text(W // 2, vy + 18, 'Gerçek zamanlı sesli etkileşim (ASR + LLM + TTS)', size=FS_BODY, bold=True)
|
||
|
||
voice_flow = [
|
||
('Gündüz tartışması', 'Hakem konuşma sırasını yönetir\nkoltuk sırasına göre konuşma'),
|
||
('Oylama aşaması', 'Tüm oyuncuların oyunu topla\noyları say ve sonucu duyur'),
|
||
('Gece aşaması', 'Hakem rolleri sırayla uyandırır\nözel ses kanalı'),
|
||
('İnsan oyuncu', 'Rastgele rol ataması\nses tabanlı oylama/konuşma'),
|
||
]
|
||
vw = (W - 80) // len(voice_flow)
|
||
for i, (title, desc) in enumerate(voice_flow):
|
||
cx = 50 + i * vw + vw // 2
|
||
s.text(cx, vy + 42, title, size=FS_SMALL, bold=True)
|
||
for j, ln in enumerate(desc.split('\n')):
|
||
s.text(cx, vy + 60 + j * 16, ln, size=FS_TINY, fill='text_light')
|
||
|
||
s.save(os.path.join(OUT, 'fig9-12.svg'))
|
||
|
||
|
||
# ════════════════════════════════════════════════════════════════════
|
||
# Main
|
||
# ════════════════════════════════════════════════════════════════════
|
||
|
||
def main():
|
||
os.makedirs(OUT, exist_ok=True)
|
||
|
||
figs = [
|
||
('fig9-1', fig9_1),
|
||
('fig9-2', fig9_2),
|
||
('fig9-3', fig9_3),
|
||
('fig9-4', fig9_4),
|
||
('fig9-5', fig9_5),
|
||
('fig9-6', fig9_6),
|
||
('fig9-7', fig9_7),
|
||
('fig9-8', fig9_8),
|
||
('fig9-9', fig9_9),
|
||
('fig9-10', fig9_10),
|
||
('fig9-11', fig9_11),
|
||
('fig9-12', fig9_12),
|
||
]
|
||
|
||
for name, func in figs:
|
||
func()
|
||
print(f' ✓ {name}')
|
||
|
||
print(f'\nGenerated {len(figs)} figures in {OUT}/')
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|