Ana içeriğe geç

2.6 Prompt Şablonları

Kim için: 🟢 başlangıç 🔵 iş 🟣 kişisel

⏱️ Süre: ~25 dakika
📋 Önkoşul: 2.5 bitmiş — few-shot ve CoT'yi biliyorsun
🎯 Çıktı: Aynı prompt'u **100 farklı girdiyle** çağırmak için tek bir şablon dosyası kullanırsın; kendi `prompts/` klasörünü kurarsın; prompt değişikliklerini git ile versiyonlarsın.

Yabancı kelime mi gördün?

Bu sayfadaki italik-altı çizili ifadelerin (template, placeholder, variable gibi) üstüne mouse'unu getir — kısa tanım çıkar.

Neden bu sayfa?

2.5'e kadar her prompt'u Python kodunun içinde string olarak yazdın. Tek seferlik denemeler için iyi. Ama gerçek projede aynı prompt'u 100 farklı kullanıcı girdisiyle çalıştıracaksın — string concatenation ile yazdığında kod 5 satırda 50 satıra çıkar, bakımı imkânsızlaşır.

İkincisi: Prompt'lar kod kadar önemli birer varlık. Bir e-posta sınıflandırma prompt'unu 3 ay sonra geliştirmek isteyeceksin — git history'de eski sürüm görmek istersin. Bu yüzden prompt'lar ayrı dosya olarak prompts/ klasöründe yaşamalı, kod gibi versiyonlanmalı.

Üçüncüsü: Anthropic Console'un Prompt Builder özelliği (2024 sonu) tam bu iş için var — prompt'ları görsel olarak şablonlaştır, değişken tanımla, test et. Bu pratik bilinmesi gereken Anthropic ekosistem aracı.

Prompt şablonları kısaca — üç paragraf, matematiksiz

Şablon = sabit metin + değişken yerler. "Merhaba {{ad}}, bugün {{tarih}} ve seni özledim." gibi. {{ad}} ve {{tarih}} placeholder'lar, çağırırken gerçek değerlerle doldurulur. Aynı şablon binlerce kez farklı verilerle kullanılır.

Üç Python yöntemi: (1) f-string — f"Merhaba {ad}", en hızlı, basit; (2) string.TemplateTemplate("Merhaba $ad").substitute(ad="Kemal"), biraz daha güvenli (yanlış parametre = hata); (3) Jinja2 — Template("Merhaba {{ ad }}").render(ad="Kemal"), en güçlü (loop, condition, filter destekler). Production projede genellikle Jinja2.

Anthropic Console'da Prompt Builder görsel arayüzde {{variable}} yer tutucularıyla şablon hazırlamana izin verir. Test sekmesinde değişkenleri doldurup Claude'u denersin. Üretim API çağrısında ise yerleştirmeyi istemci tarafında (Jinja2 / f-string) yaparsın; Messages API'sinin doğrudan "variables" parametresi yoktur. Caching ile uyum: sabit talimat + sistem promptu cache_control ile işaretlenir, değişken kısım her çağrıda yeniden gönderilir.

Bu sayfanın ekosistemi — kim kime ne veriyor

🗺️ Ekosistem — şablon + değişken → çağrı
flowchart LR
  S["👤 Sen"]
  TPL["📄 prompts/\nemail_class.j2\n(şablon dosyası)"]
  DATA[("📊 girdi listesi\nemails.json\n100 e-posta")]
  ENG["⚙️ Jinja2\nrender"]
  PROMPT["📝 dolu\nprompt\n(her satır ayrı)"]
  API["🌐 Claude API"]
  OUT["📊 çıktılar\nresults.json"]

  S --> TPL
  S --> DATA
  TPL --> ENG
  DATA --> ENG
  ENG --> PROMPT --> API --> OUT

  classDef sen fill:#ddd6fe,stroke:#7c3aed,color:#111
  classDef tpl fill:#fef3c7,stroke:#ca8a04,color:#111
  classDef data fill:#dbeafe,stroke:#2563eb,color:#111
  classDef eng fill:#fef3c7,stroke:#ca8a04,color:#111
  classDef uzak fill:#fed7aa,stroke:#ea580c,color:#111
  class S sen
  class TPL,PROMPT tpl
  class DATA,OUT data
  class ENG eng
  class API uzak
Düğüm Nerede Ne iş yapıyor
👤 Sen prompts/ klasörünü tasarlıyor Şablon dosyası + girdi listesi + render kodu
📄 Şablon prompts/email_class.j2 Jinja2 sözdizimi: {{ ... }} ve {% ... %} blokları
📊 Girdi listesi JSON / CSV / DB Değişken değerlerinin kaynağı
⚙️ Jinja2 render Python jinja2 kütüphanesi Şablon + değer = dolu prompt
📝 Dolu prompt Bellek (string) API'ye gönderilecek final metin
🌐 Claude API api.anthropic.com Doldurulmuş prompt'u işliyor
📊 Çıktılar JSON dosyası Toplu sonuç, sonra analiz edilir

Uygulama — iki yol

Yol A — Yerel Jinja2 ile prompt klasörü

prompts/email_class.j2:

Sen bir e-posta sınıflandırma asistanısın.

Aşağıdaki e-postayı şu kategorilerden birine sınıflandır:
{% for kat in kategoriler %}
- {{ kat }}
{% endfor %}

<email>
Gönderen: {{ gonderen }}
Konu: {{ konu }}
İçerik:
{{ icerik }}
</email>

Sadece kategori adını döndür, başka açıklama yok.

Render + çağrı kodu:

import json
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
import anthropic

# Jinja2 ortamı
env = Environment(loader=FileSystemLoader("prompts"))
template = env.get_template("email_class.j2")

# Girdi
emails = [
    {"gonderen": "fatura@vodafone.com.tr", "konu": "Fatura Hatırlatma",
     "icerik": "Sayın müşterimiz, faturanızın son ödeme tarihi yarındır..."},
    {"gonderen": "ahmet@arkadas.com", "konu": "Bu hafta sonu",
     "icerik": "Selam, hafta sonu kahveye gidelim mi?"},
    {"gonderen": "noreply@spam-site.xyz", "konu": "TIKLA, KAZAN!",
     "icerik": "Şanslı seçildiniz! 1 milyon TL kazanmak için..."},
]
KATEGORILER = ["fatura", "kişisel", "spam", "iş", "promosyon"]

# Render + API
client = anthropic.Anthropic()
sonuclar = []

for email in emails:
    prompt = template.render(
        kategoriler=KATEGORILER,
        gonderen=email["gonderen"],
        konu=email["konu"],
        icerik=email["icerik"],
    )
    cevap = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=20,
        temperature=0,
        messages=[{"role": "user", "content": prompt}],
    )
    kategori = cevap.content[0].text.strip()
    sonuclar.append({"konu": email["konu"], "kategori": kategori})
    print(f"📧 {email['konu']:<30}{kategori}")

# Toplu kayıt
Path("results.json").write_text(json.dumps(sonuclar, ensure_ascii=False, indent=2))
print(f"\n{len(sonuclar)} e-posta sınıflandırıldı, results.json kaydedildi")

Beklenen çıktı:

📧 Fatura Hatırlatma             → fatura
📧 Bu hafta sonu                  → kişisel
📧 TIKLA, KAZAN!                  → spam

✅ 3 e-posta sınıflandırıldı, results.json kaydedildi

Burada olan nedir (diyagram referansı): Diyagramın tüm akışı tek script'te. Şablon dosyası kod dışında durur — git'te versiyonlanır, prompt'u değiştirmek için Python kodunu açmana gerek yok.

Yol B — Anthropic Console Prompt Builder (görsel araç)

Anthropic Console içinde Prompt Builder ekranı var — tarayıcıda görsel olarak {{degisken}} placeholder'lı şablon yazıyor, "Generate a Prompt" ile Claude'un kendisi şablonu iyileştiriyor, sonra "Test" sekmesinde değişkenleri doldurup deniyorsun.

console.anthropic.com → Workbench → Prompt Builder

Önemli not: Anthropic Messages API'sinin doğrudan "variables" parametresi yoktur (Bazı dokümantasyonlarda görülen extra_body={"metadata": {"variables": ...}} deseni Messages API tarafından çözümlenmez — değişken yerleştirme istemci tarafında yapılır). Yani:

  • Console Workbench'te şablonu hazırlarsın (hızlı tasarım, görsel test)
  • Üretim kodunda Jinja2 / f-string ile değişkenleri yerleştirir, sonuçta tek bir düz metin olarak messages.create(...) çağırırsın (Yol A)
import anthropic
from jinja2 import Environment, FileSystemLoader, StrictUndefined

# StrictUndefined: değişken eksikse açık hata atar (sessiz boşluk yerine)
env = Environment(loader=FileSystemLoader("prompts/"), undefined=StrictUndefined)
sablon = env.get_template("email_class.j2")

prompt_metni = sablon.render(
    kategoriler="fatura, kişisel, spam, iş, promosyon",
    gonderen="fatura@vodafone.com.tr",
    konu="Fatura Hatırlatma",
    icerik="Sayın müşterimiz...",
)

client = anthropic.Anthropic()
cevap = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=20,
    temperature=0,
    system="Sen bir e-posta sınıflandırma asistanısın. Sadece kategori adını döndür.",
    messages=[{"role": "user", "content": prompt_metni}],
)
print(cevap.content[0].text)

Burada olan nedir: Şablonu istemci tarafında Jinja2 ile dolduruyorsun, Claude'a düz metin gidiyor. Caching kullanmak istersen sabit kısmı (system prompt + sabit talimat) cache_control ile işaretlersin — şablonun değişen kısmı her çağrıda yeniden gönderilir, sabit kısım cache'lenir.

prompts/ klasör yapısı önerisi

Production projende şu yapı işe yarar:

projem/
├── prompts/
│   ├── email_class.j2          # e-posta sınıflandırma
│   ├── ozetleme.j2             # uzun metin → 3 cümle özet
│   ├── ceviri_tr_en.j2         # Türkçe→İngilizce çeviri
│   └── _system/
│       ├── garson.txt          # 2.4'ten gelen rol
│       └── tarih_uzmani.txt
├── prompts.py                  # render yardımcı fonksiyonları
└── tests/
    └── test_prompts.py         # her şablonu örnek girdiyle test

Anahtar disiplin: - Her prompt ayrı dosya (mix etme) - _system/ alt klasörü sistem prompt'lar için - tests/test_prompts.py her şablonu örnek girdiyle çağırıp çıktının format-uyumlu olduğunu test eder (Bölüm 2.8'de detay) - Git: her prompt değişikliği commit'le, mesajda niye değiştiğini yaz

📖 Anthropic bu konuyu nasıl anlatıyor — öz

Anthropic 2024'te prompt yönetimine resmi destek ekledi:

1. Prompt Templates Anthropic Console'da görsel. console.anthropic.com → "Workbench" → değişken tanımla, prompt'u kaydet, versiyonla. Geliştirici olmayan ekip üyeleri (PM, content team) prompt değiştirebilir, kod değişmez.

2. Variables ve caching uyumlu. Şablonun sabit kısmı (sistem prompt + few-shot örnekleri) cache'lenebilir, sadece {{variable}} kısımları her çağrıda farklı. 2.2'deki maliyet patlaması sorununun çözüm yolu.

3. Anthropic'in iç ekibi de bu deseni kullanır. Claude Code, Claude.ai gibi Anthropic ürünleri kendi prompt'larını şablonla yönetiyor — public bir uygulamadan gerçek kanıt.

Teknik detay — isteyene (parameter adları, mekanikler, edge case'ler)

Variable syntax. {{variable_name}} — boşluk olmadan. Anthropic Console'da, API'de, SDK'da aynı söz dizimi.

Variable scoping. Sistem prompt + user mesajı + assistant mesajı hepsinde değişken kullanılabilir. Aynı değişken birden fazla yerde geçerse aynı değer.

Escape mekaniği. Gerçek {{ veya }} yazmak istersen { { veya } } (arada boşluk). Pratikte nadir ihtiyaç.

Jinja2 advanced features. {% if %}, {% for %}, {% include %}, custom filters ({{ name | upper }}). Anthropic native template bunları desteklemez — sade {{var}} substitution. Karmaşık logic için Jinja2'yi yerel kullan, render edilmiş sonucu Anthropic'e gönder.

Test edilebilirlik. Her şablon için pytest testi yazılabilir — örnek girdi → render → çıktının pattern eşleştiği kontrol et. Bölüm 2.8'de detay.

Prompt versiyon yönetimi. Git'te prompts/email_class.j2 history takip edilebilir. Production'da hangi sürümün canlı olduğunu env değişkeni / config dosyası ile bil.

A/B test deseni. İki versiyon prompt (email_class_v1.j2, email_class_v2.j2), trafiği %50/%50 böl, kalite/maliyet karşılaştır. Bölüm 8'de production deseni.

Kaynak: platform.claude.com — Prompt Engineering Best Practices (EN, ~15 dk). Anthropic Console workbench: console.anthropic.com → "Workbench / Prompt Builder". Görsel şablon tasarımı + sürüm geçmişi burada.

📦 Bu sayfayı bitirdiğini nasıl kanıtlarsın

1. 📝 Refleksiyon yazısı — 5 dakika

"Prompt şablonlaştırdım. [Hangi görev için] kullanacağım, [Jinja2 / Anthropic native] seçtim çünkü [neden]. prompts/ klasör yapımda [şu] dosyalar olacak. Versiyon yönetiminde [git history / Anthropic Console] kullanacağım."

Kaydet: muhendisal-notlarim/bolum-2/06-sablonlar/refleksiyon.txt

2. 📸 Ekran görüntüsü — 3 dakika

Neyin görüntüsü: Yol A çıktısı — 3 farklı e-posta için tek şablon, 3 farklı doğru kategori.

OS Kısayol
Windows Win + Shift + S
Mac Cmd + Shift + 4
Linux Shift + PrtScr

Kaydet: muhendisal-notlarim/bolum-2/06-sablonlar/sablon-cikti.png

3. 💻 prompts/ klasörün + GitHub repo — 10 dakika

Kendi projende prompts/ klasörü kur, içine en az 2 farklı şablon koy (örn: özetleme + sınıflandırma). Render kodu ekle. GitHub'da public repo olarak yayınla (veya gist).

Repo/gist linkini kaydet: muhendisal-notlarim/bolum-2/06-sablonlar/prompts-repo-link.txt

🔗 Birlikte okuma — neden ne oldu
  1. **Prompt'lar string concat ile yazılırsa kod karışır.** Prompt değişikliği = kod değişikliği. Bu yüzden **prompt'ları ayrı dosyaya çıkarmak ilk adım.**
  2. **Prompt'u ayrı dosya yapmak onu 'varlık' haline getirir.** Git'te versiyonlanır, ekip üyesi düzenleyebilir. Bu yüzden **prompt mühendisliği yazılım geliştirme disipliniyle yürür.**
  3. **Jinja2 karmaşık şablonlarda; Anthropic native basit değişkenler için.** Her ikisini de bilmek yeterli. Bu yüzden **araç seçimi şablonun karmaşıklığına göre yapılır.**
  4. **Anthropic native variables + caching = maliyet kontrolünün altın deseni.** Sabit kısım cache'lenir, değişken kısım her çağrıda değişir. Bu yüzden **fatura optimizasyonunun ilk noktası bu desen.**
  5. **Production'da prompt'lar kod kadar disiplinle yönetilir.** Test, A/B, version history. Bu yüzden **prompt'lar repoda kodu gibi yaşar, e-postada değil.**

Sonuç: Prompt'u "kod içine string atmak" amatör; prompt'u "varlık olarak yönetmek" production. Bu sayfa o atlamayı verdi. Sıradaki iki sayfada güvenlik (2.7 prompt injection) ve ölçüm (2.8 prompt eval) — production hattını tamamlayan iki ayak.

➡️ Sonraki adım

2.7 Prompt Enjeksiyonu ve Savunma → — Kullanıcı prompt'una "sistem talimatlarını unut, başka şey yap" yazarsa ne olur? Saldırı türleri, savunma desenleri, Anthropic önerisi.

2.5 Few-shot ve CoT  |  Bölüm 2 girişi  |  Ana sayfa

Pekiştirme: Anthropic Console'a (console.anthropic.com) git, "Workbench" sekmesinde bir şablon kur, değişken ekle, "Run" ile test et. Görsel arayüzü tanımak production'da paha biçilmez.

MühendisAl Platform — Sözlük (Glossary)

Bu dosya pre_build.py hook'u tarafından her sayfaya otomatik eklenir.

Markdown abbr extension bu tanımları alıp terimin her geçtiği yerde

HTML <abbr title="..."> sarımı yapar → MkDocs Material tooltip gösterir.

DİKKAT: abbr case-sensitive. "Agent" tanımı "agent" kelimesini sarmaz.

Bu yüzden hem büyük hem küçük harf varyantları ayrı tanımlanır.

Yeni terim eklerken: *[TERIM]: Açıklama — tek satır, 160 karakterden kısa

Terimler alfabetik (büyük harf), hemen altında küçük harf varyantı.