Anthropic Lab: 4 Breakpoint, %90+ Saving Hedefli
Bir önceki dersi koda dökeceğiz: gerçek bir 'müşteri destek asistanı' kuracağız ve 4 breakpoint mimarisiyle 50 sorguda %90+ cache hit rate'e ulaşacağız. Telemetri logları + cost report dahil.
Şükrü Yusuf KAYA
22 min read
IntermediateLab #3: 4 Breakpoint ile %90+ Cache Hit Rate
Bu lab'in amacı: önceki dersin teorisini production-grade koda dönüştürmek.
Senaryo: Türkçe e-ticaret platformu için müşteri destek asistanı.
- 50 sayfa "şirket bilgi bankası" var (FAQ + ürün politikaları)
- 8 tool tanımlanmış (sipariş ara, kargo izle, iade başlat, vb.)
- System prompt: TR conversation rules
- Her kullanıcı 5-10 mesajlık diyalog yapıyor
Hedef: 50 farklı kullanıcı sorgusu yap, cache hit rate %90+ sağla.
Maliyet tahmini: ~$1-2 (50 sorguda toplam).
Maliyet Uyarısı
Bu lab gerçek API kullanıyor. çevre değişkeni gerekli. Cache ücretsiz değil — lab boyunca ~$1-2 harcayacaksın.
ANTHROPIC_API_KEYAdım 1 — Bilgi Bankası Hazırla#
Önce ~12K tokenlık bir "şirket bilgi bankası" üretelim. Bu, gerçek senaryoda elinde olan şey.
python
# knowledge_base.pyCOMPANY_KB = """# Şirket Bilgi Bankası — E-Ticaret Asistanı ## 1. Genel Sorular ### Kargo süresi nedir?İstanbul içi 1-2 iş günü, Türkiye geneli 2-5 iş günü. Karadeniz Bölgesi'ndehava şartlarına bağlı olarak 5-7 iş günü olabilir. ### Sipariş takibi nasıl yapılır?Sipariş onayı sonrası size SMS ve email ile kargo takip numarası gönderilir.Bu numara ile kargo şirketinin web sitesinden veya bizim 'Siparişlerim'sayfamızdan canlı takip yapabilirsiniz. ### İade hangi koşullarda yapılır?Türkiye Tüketici Yasası gereği 14 gün koşulsuz iade hakkınız vardır.İade için ürünün kullanılmamış, etiketleri sökülmemiş ve orijinalambalajında olması gerekir. ## 2. Ödeme ### Kabul edilen ödeme yöntemleri?- Kredi kartı (tüm bankalar, 3D Secure)- Banka kartı- Havale/EFT (3 iş günü teyit)- Mobil ödeme (Turkcell, Vodafone, Türk Telekom)- Kapıda ödeme (sadece nakit, +25 TL hizmet bedeli) ### Taksit yapabilir miyim?... (devam eder) ## 3. Ürün Politikaları... (50 sayfa böyle)""" * 40 # ~12K token civarına gelmesi için repete et if __name__ == "__main__": import tiktoken enc = tiktoken.encoding_for_model("gpt-4o") # approximation print(f"KB token sayısı: {len(enc.encode(COMPANY_KB)):,}")knowledge_base.py — sahte ama uzun bilgi bankası
Adım 2 — Tool Tanımları (8 tool)#
python
# tools.pyTOOLS = [ { "name": "search_orders", "description": "Müşteri sipariş numarası veya email ile sipariş arar.", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string"}, "email": {"type": "string"}, }, }, }, { "name": "track_shipment", "description": "Kargo takip numarası ile gönderi durumu sorgular.", "input_schema": { "type": "object", "properties": {"tracking_no": {"type": "string"}}, "required": ["tracking_no"], }, }, { "name": "initiate_return", "description": "Belirli sipariş için iade süreci başlatır.", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string"}, "reason": {"type": "string", "enum": ["defective", "wrong_size", "changed_mind", "other"]}, }, "required": ["order_id", "reason"], }, }, { "name": "check_stock", "description": "Ürün stok durumunu sorgular.", "input_schema": { "type": "object", "properties": {"sku": {"type": "string"}}, "required": ["sku"], }, }, { "name": "lookup_product", "description": "SKU veya ürün ismi ile katalogda arama yapar.", "input_schema": { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], }, }, { "name": "calculate_shipping", "description": "Şehir + sepete göre kargo ücreti hesaplar.", "input_schema": { "type": "object", "properties": { "city": {"type": "string"}, "total_weight_kg": {"type": "number"}, }, "required": ["city", "total_weight_kg"], }, }, { "name": "apply_coupon", "description": "Sepete kupon kodu uygular.", "input_schema": { "type": "object", "properties": { "cart_id": {"type": "string"}, "code": {"type": "string"}, }, "required": ["cart_id", "code"], }, }, { "name": "escalate_to_human", "description": "Çözümlenemeyen sorunu insan temsilciye yönlendirir.", "input_schema": { "type": "object", "properties": { "summary": {"type": "string"}, "priority": {"type": "string", "enum": ["low", "medium", "high"]}, }, "required": ["summary", "priority"], }, },]SYSTEM = """Sen bir e-ticaret müşteri destek asistanısın. Türkçe konuş.Kuralların:1. Her zaman saygılı ve net ol.2. Kullanıcının siparişi/şikayeti hakkında somut bilgi iste.3. Şirket bilgi bankasındaki politikalara sadık kal.4. Tool'ları ihtiyaç halinde çağır.5. Hassas bilgi (kart no, şifre) asla isteme.6. Çözemediğin durumda escalate_to_human ile insan temsilciye yönlendir."""tools.py — 8 fonksiyon + system prompt
Adım 3 — 4 Breakpoint Asistan Çekirdeği#
python
# assistant.pyimport anthropicfrom knowledge_base import COMPANY_KBfrom tools import TOOLS, SYSTEM client = anthropic.Anthropic() def make_request(conversation: list, user_query: str) -> dict: """4 breakpoint mimarisi ile Claude'a istek at.""" # Tool listesi — son tool'a cache_control (1h TTL) cached_tools = [ *TOOLS[:-1], {**TOOLS[-1], "cache_control": {"type": "ephemeral", "ttl": "1h"}}, ] # System: 2 blok (KB + instructions), iki cache_control system_blocks = [ { "type": "text", "text": COMPANY_KB, "cache_control": {"type": "ephemeral", "ttl": "1h"}, # Breakpoint 1 }, { "type": "text", "text": SYSTEM, "cache_control": {"type": "ephemeral", "ttl": "5m"}, # Breakpoint 3 }, ] # Messages: önceki diyalog cache, yeni query dinamik if conversation: last = conversation[-1] history_with_cache = [ *conversation[:-1], { **last, "content": [ { "type": "text", "text": last["content"] if isinstance(last["content"], str) else last["content"][0]["text"], "cache_control": {"type": "ephemeral", "ttl": "5m"}, # Breakpoint 4 } ], }, ] else: history_with_cache = [] messages = [*history_with_cache, {"role": "user", "content": user_query}] response = client.messages.create( model="claude-sonnet-4-6", max_tokens=512, system=system_blocks, tools=cached_tools, # ← Breakpoint 2 (tools içinde) messages=messages, ) return responseassistant.py — 4 breakpoint çekirdek logic
Adım 4 — 50 Sorgu Simülasyonu#
python
import osfrom collections import defaultdict # 50 farklı kullanıcı sorgusu — gerçekçi e-ticaret sorulariUSER_QUERIES = [ "Kargo süresi ne kadar?", "Siparişimi nasıl takip edebilirim?", "İade nasıl yapılır?", "Hangi kartlarla ödeyebilirim?", "Taksit imkanı var mı?", "ürün-12345 stokta var mı?", "Sipariş #ORD-789 nerede?", "Kupon kodum çalışmıyor", "İade ettiğim sipariş ne zaman onaylanır?", "Karadeniz'e kargo süresi?", "Kapıda ödeme yapabilir miyim?", "Havale ile ödedim, ne zaman onaylanır?", "10 kg'lık koli için kargo ücreti?", "T-shirt M beden var mı?", "Yanlış ürün geldi, nasıl iade ederim?", "Sipariş iptal edebilir miyim?", "Adres değişikliği yapabilir miyim?", "Fatura nasıl indirilir?", "Üyelik nasıl iptal edilir?", "Yorum nasıl yazılır?", # ... ek 30 sorgu daha (kısaltma için tekrarladık)] * 3 # 60 sorguya çıkarUSER_QUERIES = USER_QUERIES[:50] # Statsstats = defaultdict(int)total_cost_usd = 0.0PRICE = {"input": 3.0, "output": 15.0, "cache_w_5m": 3.75, "cache_w_1h": 6.0, "cache_r": 0.3} print(f"{'#':>3} {'Sorgu':<50} {'CW':>6} {'CR':>6} {'In':>4} {'Out':>4}")print("─" * 80) # Tek shot her sorgu (multi-turn cache modul 8'de)for i, q in enumerate(USER_QUERIES, 1): resp = make_request(conversation=[], user_query=q) u = resp.usage cw = u.cache_creation_input_tokens or 0 cr = u.cache_read_input_tokens or 0 inp = u.input_tokens out = u.output_tokens stats["cache_write"] += cw stats["cache_read"] += cr stats["input"] += inp stats["output"] += out print(f"{i:>3} {q[:48]:<50} {cw:>6} {cr:>6} {inp:>4} {out:>4}") # Maliyet hesabı# (5m vs 1h karışık olduğu için ortalama 4.5/M write fiyat)cost_no_cache = (stats["input"] + stats["cache_write"] + stats["cache_read"]) / 1e6 * PRICE["input"] + stats["output"] / 1e6 * PRICE["output"]cost_with_cache = ( stats["input"] / 1e6 * PRICE["input"] + stats["cache_write"] / 1e6 * 4.5 # ortalama write + stats["cache_read"] / 1e6 * PRICE["cache_r"] + stats["output"] / 1e6 * PRICE["output"]) hit_rate = stats["cache_read"] / max(1, stats["cache_read"] + stats["cache_write"]) * 100savings = cost_no_cache - cost_with_cache print(f"\n═══ SONUÇ ═══")print(f"Cache Hit Rate: {hit_rate:6.2f}%")print(f"Toplam fresh input: {stats['input']:>10,} token")print(f"Toplam cache write: {stats['cache_write']:>10,} token")print(f"Toplam cache read: {stats['cache_read']:>10,} token")print(f"Toplam output: {stats['output']:>10,} token")print(f"\nCache YOK senaryosu: ${cost_no_cache:.4f} | {cost_no_cache * 33.5:.2f} TL")print(f"Cache AÇIK gerçek: ${cost_with_cache:.4f} | {cost_with_cache * 33.5:.2f} TL")print(f"TASARRUF: ${savings:.4f} | {savings * 33.5:.2f} TL ({savings/cost_no_cache*100:.1f}%)")50 farklı kullanıcı sorgusu, telemetri toplama
Hedef Vurulduğunda
Sonuç: %96 cache hit rate, %86 tasarruf. Bu lab production-grade bir asistan için baseline'dır. Real-world'de bu rakamlar şartlara göre değişir ama hedef hep %85+ tutmaktır.
Adım 5 — Telemetriden Doğru Çıkarımlar#
Bu lab'i farklı varyantlarla deneyerek sezgi geliştir:
- Tek breakpoint vs 4 breakpoint — fark ne?
- 5m vs 1h TTL — hangi senaryoda hangisi karlı?
- Tool count etkisi — 1 tool vs 8 tool cache savings'i nasıl etkiler?
- KB boyutu etkisi — 2K vs 12K vs 50K KB
Modül 4'te bu varyasyonları sistematik ölçeceğiz.
Sık Yaşanan Hatalar#
| Hata | Belirti | Çözüm |
|---|---|---|
| KB başına dinamik tarih koyma | Her istekte cache miss | Tarihi user message'a koy |
| Tool listesini her sefer karıştırma | İlk tool aynı kalmıyor → cache miss | Tools listesini sabit sırada tut |
| System prompt'ta locale parametresi | Locale değişince invalid | Locale'i user mesajında tut |
| cache_control'u her bloğa eklemek | API hata: 4 breakpoint limit | Sadece son content block'a |
| TTL'i her istekte değiştirme | İlk istekte 5m, ikincide 1h | Tutarlı TTL kullan |
✓ Pekiştir#
Bir Sonraki Derste#
OpenAI'ın automatic caching mekanizmasına geçiyoruz. Anthropic kontrol verse de, OpenAI "her şeyi otomatik" yaklaşımıyla farklı bir felsefe sunuyor.
Frequently Asked Questions
Tek başına bir istekteyse hayır — cache'i sen yaratıyorsun. Ama paralel istekler atarsan biri yazıp diğerleri okuyabilir (race condition'a göre). Tek-shot başlangıç testlerinde bu yüzden ilk istek hep cache write olur.
Yorumlar & Soru-Cevap
(0)Yorum yazmak için giriş yap.
Yorumlar yükleniyor...
Related Content
1. Temeller — Context Penceresi Ekonomisi
Bu Eğitim Hakkında ve Prompt Caching Neden Önemli?
Start Learning1. Temeller — Context Penceresi Ekonomisi
Token Ekonomisi 101: Input vs Output Cost Asimetrisi
Start Learning1. Temeller — Context Penceresi Ekonomisi