Kendi yan ürünlerimden birinde, kullanıcıların metin özetleme ve analiz ihtiyaçlarını karşılamak için AI API’lerini yoğun bir şekilde kullanıyordum. İlk başta her şey yolundaydı, ancak kullanıcı sayısı arttıkça ve özellikler genişledikçe, API maliyetleri beklediğimden çok daha hızlı yükselmeye başladı. Aylık faturayı görünce anladım ki, sadece kod yazmak yetmiyor, API kullanımını da aktif olarak optimize etmek gerekiyormuş.
AI API’lerinin maliyetleri, özellikle token kullanımı ve model seçimi üzerinden hızlıca artabiliyor. Bu yazıda, bu harcamaları kontrol altına almak ve hatta belirgin oranda düşürmek için kendi projelerimde uyguladığım ve işe yaradığını gördüğüm 5 pratik yolu anlatacağım. Amacım, size de benzer sorunlar yaşadığınızda uygulayabileceğiniz somut adımlar sunmak.
1. Prompt Engineering ile Token Optimizasyonu Nasıl Yapılır?
AI API’lerinin maliyetleri genellikle işlenen token sayısına göre belirlenir ve uzun prompt’lar, gereksiz token tüketimine yol açar. Bu, hem girdi (input) hem de çıktı (output) prompt’ları için geçerlidir; ne kadar kısa ve net olursanız, o kadar az ödersiniz. Benim deneyimimde, çoğu geliştirici prompt’ları yazarken maliyetten çok, modelin istenen çıktıyı vermesine odaklanır ki bu başlangıç için doğal bir yaklaşımdır.
Ancak, üretim ortamında maliyetleri düşürmek için prompt’ları daha verimli hale getirmek şarttır. Örneğin, bir üretim ERP’sinde operatörlere yardımcı olmak için kullandığımız bir AI asistanında, ilk başta çok uzun ve detaylı talimatlar veriyorduk. Sonra fark ettim ki, bu talimatların çoğunu modelin zaten bildiği genel bilgiler oluşturuyor ve sadece anahtar kelimelerle daha kısa prompt’lar da aynı verimliliği sağlıyordu.
Prompt’ları Kısaltma ve Netleştirme Teknikleri
Prompt’ları optimize etmek için birkaç temel teknik var. İlk olarak, gereksiz kelimelerden ve dolambaçlı ifadelerden kaçınarak doğrudan konuya girmek büyük fark yaratır. Örneğin, “Lütfen aşağıdaki metni özetler misiniz?” yerine sadece “Metni özetle:” demek bile token kazandırır. Bu, modelin istenen göreve odaklanmasını kolaylaştırırken, aynı zamanda API’ye gönderilen veri miktarını da azaltır.
İkinci olarak, few-shot örnekler yerine zero-shot veya daha az örnek kullanmak da maliyetleri düşürebilir. Eğer model belirli bir görevi zaten iyi yapabiliyorsa, uzun örnekler vermek yerine sadece görevi tanımlamak yeterli olabilir. Öte yandan, karmaşık veya niş görevlerde few-shot örnekler çıktının kalitesini artırsa da, maliyetin de artacağını unutmamak gerekir. Bu bir kalite-maliyet trade-off meselesidir ve her zaman en iyi kaliteyi hedeflemek yerine, yeterli kaliteyi en düşük maliyetle elde etmeye çalışmak daha pragmatiktir.
Üçüncüsü, talimatların yerleşimi önemlidir. Modelin en çok dikkat etmesini istediğiniz bilgileri prompt’un başına veya sonuna yerleştirmek, aradaki gereksiz token’ların etkisini azaltabilir. Ayrıca, JSON çıktı formatı gibi spesifik formatlar istiyorsanız, bunu net bir şekilde belirtmek ve hatta örnek bir JSON şeması sunmak, modelin daha az “deneme-yanılma” token’ı harcamasını sağlar. Bu, özellikle otomatize edilmiş iş akışlarında çıktının tutarlı olmasını sağladığı için kritik bir adımdır.
# Örnek: Kötü prompt
prompt_kötü = """
Merhaba yapay zeka asistanı, umarım iyisindir. Bana aşağıdaki uzun metni çok detaylı olmayacak şekilde özetlemeni rica ediyorum.
Lütfen sadece ana fikirleri ve en önemli noktaları vurgula. Özette gereksiz bilgilerden kaçın ve mümkün olduğunca kısa ol.
İşte metin:
[Uzun metin buraya gelecek]
"""
# Örnek: Optimize edilmiş prompt
prompt_iyi = """
Metni özetle, ana fikirleri ve en önemli noktaları vurgula:
[Metin buraya gelecek]
"""
# Token sayısını kontrol etmek için (örneğin OpenAI'ın tiktoken kütüphanesi ile)
# import tiktoken
# enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
# print(f"Kötü prompt token sayısı: {len(enc.encode(prompt_kötü))}")
# print(f"İyi prompt token sayısı: {len(enc.encode(prompt_iyi))}")
2. Model Seçimini Akıllıca Yapmak: Her İşe Aynı Model Uymaz
Birçok kişi AI API’lerini kullanmaya başladığında, genellikle en popüler veya en yetenekli modele yönelir. Örneğin, GPT-4’ün sunduğu üstün yetenekler cazip gelebilir. Ancak bu modellerin maliyetleri, daha küçük ve daha hızlı modellere göre belirgin oranda daha yüksektir. Benim kendi yan ürünlerimde, en başta her iş için en iyi modeli kullanmaya çalıştım, ancak kısa sürede bunun sürdürülebilir olmadığını fark ettim.
Farklı görevler, farklı model yetenekleri gerektirir. Basit metin özetleme, sınıflandırma veya hızlı yanıt gerektiren görevler için genellikle daha küçük ve uygun fiyatlı modeller yeterli olabilir. Örneğin, bir chat uygulamasında kullanıcı sorularına hızlıca yanıt vermek için Gemini Flash veya GPT-3.5 Turbo gibi modeller, GPT-4 veya Gemini Ultra’dan çok daha maliyet-etkindir. Daha düşük maliyetli modellerle başlarken, modelin karmaşık görevlerdeki performansını dikkatlice test etmek önemlidir.
Göreve Özel Model Seçimi ve Fallback Stratejileri
Önemli olan, her bir AI görevini analiz edip ona en uygun ve en ucuz modeli seçmektir. Eğer bir görev kritik doğruluk veya karmaşık muhakeme gerektiriyorsa (örneğin hukuki metin analizi veya derinlemesine kod üretimi), daha yetenekli ve pahalı bir model seçmek mantıklı olabilir. Bu tür senaryolarda, yüksek maliyet, elde edilen değerle dengelenebilir.
Ancak, basit bir müşteri destek botu yanıtı veya kısa bir metin çevirisi için aynı yetenekli modeli kullanmak, gereksiz harcama demektir. Bu tür görevler için daha hafif modeller seçerek, genel AI faturanızda ciddi düşüşler sağlayabilirsiniz. Benim bir projemde, çoğu rutin görev için GPT-3.5’a geçiş yaparak, maliyetleri kabaca yarıya indirmeyi başarmıştım.
Bir başka strateji de fallback mekanizmaları oluşturmaktır. İlk olarak daha ucuz bir modelle deneme yapar, eğer çıktı kalitesi yeterli değilse veya model belirli bir güven eşiğinin altında kalırsa, otomatik olarak daha yetenekli ve pahalı bir modele geçiş yapabilirsiniz. Bu yaklaşım, maliyetleri optimize ederken kritik görevlerde kaliteyi garanti altına almanızı sağlar. Bu hibrid yaklaşım, özellikle farklı karmaşıklıkta istekler alan sistemler için idealdir.
# Örnek: Dinamik model seçimi
def get_ai_response(task_type, prompt):
if task_type == "simple_summary" or task_type == "quick_faq":
# Basit özetleme veya SSS için daha uygun fiyatlı model
model = "gemini-flash-1.5" # veya "gpt-3.5-turbo"
print(f"'{model}' modeli ile basit işlem yapıldı.")
# Burada gerçek API çağrısı ve yanıtın işlenmesi olmalı
# response = call_api(model, prompt)
# if not is_quality_sufficient(response): # Kalite kontrolü
# model = "gemini-pro-1.5" # Fallback
# print(f"Fallback olarak '{model}' modeli kullanıldı.")
# response = call_api(model, prompt)
elif task_type == "complex_analysis" or task_type == "code_generation":
# Karmaşık analiz veya kod üretimi için daha yetenekli model
model = "gemini-ultra-1.5" # veya "gpt-4-turbo"
print(f"'{model}' modeli ile karmaşık işlem yapıldı.")
# response = call_api(model, prompt)
else:
# Varsayılan veya genel amaçlı model
model = "gpt-3.5-turbo"
print(f"'{model}' modeli ile varsayılan işlem yapıldı.")
# response = call_api(model, prompt)
# return response
# Kullanım
get_ai_response("simple_summary", "Bugün hava güzel.")
get_ai_response("complex_analysis", "Finansal raporu analiz et.")
Özellikle OpenRouter gibi çoklu sağlayıcı platformlarını kullanarak, farklı modeller arasında geçiş yapmak hem esnekliği artırır hem de maliyet optimizasyonu için yeni kapılar açar. Hatta bazı sağlayıcılar (Groq, Cerebras) belirli modeller için çok daha hızlı ve maliyet-etkin çözümler sunabiliyor, bu da performans ve maliyet arasında doğru dengeyi bulmak için harika bir fırsat. Bu sağlayıcıları bir Proxy arkasına koyup, dinamik routing ile request’leri en uygun modele yönlendirebiliriz.
3. Retrieval-Augmented Generation (RAG) ile Harici Bilgi Yönetimi
AI modellerinin en büyük maliyet kalemlerinden biri, bağlam penceresini (context window) dolduran uzun metinlerdir. Bir ERP sisteminde kullanıcılar “X ürününün son beş yıllık satış trendi nedir?” gibi sorular sorduğunda, bu bilginin tamamını her seferinde prompt’a dahil etmek çok pahalıya patlar. İşte burada RAG (Retrieval-Augmented Generation) devreye giriyor. RAG, modelin ihtiyaç duyduğu bilgiyi harici bir veritabanından alıp, sadece ilgili parçaları prompt’a ekleyerek token tüketimini önemli ölçüde azaltır.
Ben kendi projelerimde, özellikle üretim ERP’sinde, büyük miktarda şirket içi doküman, ürün bilgisi ve geçmiş satış verisiyle çalıştım. Bu verileri doğrudan bir LLM’e göndermek hem maliyetli hem de güvenlik açısından riskliydi. RAG mimarisi sayesinde, bu verileri bir vektör veritabanında depolayıp, kullanıcının sorusuna en uygun parçaları alıp modele sadece bu parçalarla birlikte soru metnini gönderdim. Bu yaklaşım, sadece token maliyetini düşürmekle kalmadı, aynı zamanda modelin “halüsinasyon” yapma olasılığını da azalttı.
RAG Mimarisi Nasıl Çalışır ve Token Tasarrufu Sağlar?
RAG mimarisi temel olarak iki adımdan oluşur: Bilgi Alma (Retrieval) ve Cevap Üretme (Generation). İlk adımda, kullanıcı sorusu bir embedding modelinden geçirilerek bir vektöre dönüştürülür. Bu vektör, daha önce indekslenmiş ve vektörleştirilmiş olan harici bilgi parçaları (dokümanlar, veritabanı kayıtları vb.) arasında en alakalı olanları bulmak için kullanılır. İkinci adımda ise, bulunan alakalı bilgi parçaları, orijinal soru ile birlikte bir LLM’e prompt olarak gönderilir.
Bu süreç, LLM’in tüm bilgi setini baştan sona okumasına gerek kalmadan, yalnızca ilgili ve küçük bir bağlam üzerinde çalışmasını sağlar. Böylece, hem prompt’un uzunluğu kısalır hem de daha doğru ve bağlama uygun yanıtlar alınır. Örneğin, bir üretim ERP’sinde bir ürünün teknik özelliklerini sorgularken, tüm ürün kataloğunu göndermek yerine, sadece o ürüne ait teknik doküman parçalarını göndermek çok daha verimli olacaktır.
graph TD; A["Kullanıcı Sorgusu"] --> B["Embedding Oluştur"]; B --> C["Vektör Veritabanında Arama"]; C --> D["En Alakalı Parçaları Seç"]; D --> E["Prompt Oluştur (Sorgu + Alakalı Parçalar)"]; E --> F["LLM API Çağrısı"]; F --> G["Cevap"];
4. Caching ve Tekrar Kullanım Stratejileri ile Geri Dönüşümlü Harcama
AI API çağrıları her zaman aynı yanıtı üretir mi? Eğer prompt aynıysa ve model deterministikse, evet. Bu durumda, her seferinde aynı çağrıyı tekrar yapmak yerine, yanıtı önbelleğe almak (caching) büyük bir maliyet tasarrufu sağlayabilir. Benim bir yan ürünümde, finansal hesaplayıcılar için belirli senaryoların analizini yapıyordum. Bu senaryolar sıkça tekrarlandığı için, her seferinde AI’ya gitmek yerine, yanıtları önbelleğe alarak API çağrılarını belirgin oranda azalttım.
Caching stratejileri, özellikle sıkça sorgulanan ama seyrek değişen veriler veya analizler için çok etkilidir. Örneğin, bir ürünün genel bir açıklamasını veya bir SSS (Sıkça Sorulan Sorular) yanıtını bir AI modelinden ürettirdiğinizde, bu yanıt muhtemelen uzun süre geçerliliğini koruyacaktır. Bu tür durumlarda, ilk çağrının yanıtını kaydedip, sonraki aynı istekler için doğrudan önbellekten servis etmek, hem maliyeti sıfırlar hem de yanıt süresini (latency) düşürür.
Ne Zaman ve Nasıl Cache Yapmalı?
Caching yaparken dikkat edilmesi gereken birkaç nokta var. İlk olarak, önbelleğe alacağınız yanıtların deterministik ve statik olduğundan emin olmalısınız. Eğer modelin yanıtı her zaman değişiyorsa (örneğin yaratıcı yazım görevleri), caching’in faydası olmayacaktır. İkinci olarak, önbelleğin ne kadar süreyle geçerli olacağını (TTL - Time-To-Live) belirlemek önemlidir. Çok kısa bir TTL, caching’in faydasını azaltırken, çok uzun bir TTL eski verilerin sunulmasına neden olabilir.
Uygulama katmanında Redis gibi hızlı bir key-value store kullanarak, gelen AI API isteklerinin hash’lenmiş prompt’larını anahtar olarak kullanıp, model yanıtlarını değer olarak saklayabiliriz. Bir istek geldiğinde, önce önbellekte bu prompt’un yanıtı olup olmadığına bakılır. Eğer varsa, yanıt doğrudan önbellekten döner; yoksa API çağrısı yapılır ve yanıt önbelleğe alınır.
import hashlib
import json
import redis
# Redis bağlantısı (örnek)
# r = redis.Redis(host='localhost', port=6379, db=0)
def get_ai_response_with_cache(prompt, model_name, ttl=3600): # TTL 1 saat
prompt_hash = hashlib.sha256((prompt + model_name).encode('utf-8')).hexdigest()
# Önbellekte kontrol et
# cached_response = r.get(prompt_hash)
# if cached_response:
# print("Yanıt önbellekten alındı.")
# return json.loads(cached_response)
# Önbellekte yoksa, API çağrısı yap
print("API'ye çağrı yapıldı.")
# Gerçek AI API çağrısı burada olmalı
# response = call_ai_api(prompt, model_name)
response = {"generated_text": f"Bu '{prompt}' için yapay zeka tarafından üretilen bir yanıttır. (Model: {model_name})"}
# Yanıtı önbelleğe al
# r.setex(prompt_hash, ttl, json.dumps(response))
return response
# Kullanım
get_ai_response_with_cache("Metni özetle: AI maliyetleri.", "gpt-3.5-turbo")
get_ai_response_with_cache("Metni özetle: AI maliyetleri.", "gpt-3.5-turbo") # İkinci çağrı önbellekten gelmeli
Caching, özellikle okuma yoğunluğu yüksek uygulamalarda AI API maliyetlerini düşürmek için vazgeçilmez bir araçtır. Ancak karmaşık cache invalidation stratejileri bazen kendi başına bir sorun haline gelebilir. Bu yüzden, caching’i nerede ve nasıl uygulayacağınıza karar verirken uygulamanızın ihtiyaçlarını ve veri değişim sıklığını göz önünde bulundurmak önemlidir.
5. Batch İşleme ve Asenkron API Çağrıları ile Verimlilik Artışı
Tek tek yapılan AI API çağrıları, özellikle büyük veri setleriyle çalışırken hem maliyetli hem de zaman alıcı olabilir. Çoğu AI sağlayıcısı, birden fazla isteği tek bir API çağrısında toplamanıza olanak tanıyan batch işleme yetenekleri sunar. Bu, genellikle daha düşük token maliyeti veya daha verimli kaynak kullanımı anlamına gelir. Benim bir veri analiz projemde, yüzlerce kısa metni özetlemem gerektiğinde, bunları tek tek göndermek yerine batch olarak göndererek hem maliyetten tasarruf ettim hem de işlem süresini belirgin oranda kısalttım.
Batch işleme, özellikle offline veya near real-time (yakın gerçek zamanlı) işleme gerektiren senaryolar için idealdir. Örneğin, gece yapılan bir raporlama işi veya kullanıcıların anlık yanıt beklemediği bir veri sınıflandırma görevi için batch API’ler harikadır. Bu yaklaşımla, API’ye olan bağlantı maliyeti ve overhead her bir istek için ayrı ayrı ödenmek yerine, tek bir toplu istek için ödenir.
Asenkron İşleme ile Süreçleri Optimize Etme
Batch işleme ile birlikte asenkron API çağrıları da maliyet ve performans optimizasyonunda önemli bir rol oynar. Birçok AI API’si, uzun süreli işlemler için asenkron (non-blocking) çağrı modelleri sunar. Bu, isteği gönderip yanıtı hemen beklemek yerine, isteğin arka planda işlenmesini sağlayıp, yanıt hazır olduğunda geri bildirim almanızı (callback veya polling ile) sağlar.
Asenkron çağrılar, uygulamanızın ana iş parçacığının engellenmesini önleyerek genel sistem performansını artırır. Ayrıca, genellikle batch işleme ile birlikte kullanıldığında daha da verimli hale gelirler. Örneğin, bir message queue (Kafka, RabbitMQ) kullanarak işlenecek metinleri sıraya koyabilir, ayrı bir worker servisi bu kuyruktan batch’ler halinde metinleri alıp AI API’sine asenkron olarak gönderebilir. Yanıtlar geldiğinde ise yine bir kuyruk veya veritabanı aracılığıyla ilgili yerlere iletilir.
Bu yaklaşım, özellikle büyük ölçekli veri işleme ve arka plan görevleri için çok önemlidir. Bir üretim ERP’sinde, yeni eklenen ürünlerin otomatik etiketlenmesi veya stok hareketlerinin özetlenmesi gibi görevler için bu tür bir asenkron batch sistemi kurmuştum. Bu sayede, kullanıcı deneyimi etkilenmeden, maliyet etkin bir şekilde büyük hacimli AI işleme gerçekleştirebiliyorduk.
graph TD;
A["Uygulama"] --> B["Mesaj Kuyruğu (İşlenecek Veriler)"];
B --> C["Batch İşleyici (Worker)"];
C --> D{"Veri Toplama & Batch Oluşturma"};
D --> E["AI API (Batch Çağrı)"];
E -- Asenkron Yanıt --> F["Yanıt Kuyruğu"];
F --> G["Sonuç İşleyici"];
G --> H["Veritabanı/Kullanıcı"];
Sonuç
AI API harcamalarını optimize etmek, sadece cüzdanınızı değil, aynı zamanda sistemlerinizin genel verimliliğini de etkileyen sürekli bir süreçtir. Kendi yirmi yıllık teknik deneyimimde gördüğüm en önemli şeylerden biri, maliyet optimizasyonunun sadece “para kısmak” değil, aynı zamanda kaynakları daha akıllıca kullanmakla ilgili olduğudur. Prompt’ları kısaltmaktan, doğru modeli seçmeye, RAG ile harici bilgiyi yönetmekten, caching ve batch işlemlere kadar bu beş pratik yöntem, AI API maliyetlerinizi belirgin oranda düşürmenize yardımcı olabilir.
Unutmayın, her uygulamanın kendine özgü gereksinimleri ve kısıtlamaları vardır. Bu stratejileri kendi projenize uyarlarken, her zaman kalite ve maliyet arasındaki dengeyi göz önünde bulundurun. Hata yapmaktan çekinmeyin; ben de ilk başlarda bir üretim ERP’sinde AI entegrasyonu yaparken, gereksiz yere yüksek maliyetlerle karşılaştım ve bu sayede bu dersleri öğrendim. Önemli olan, sürekli ölçmek, test etmek ve öğrenmek. Bu sayede, hem bütçenizi koruyabilir hem de yapay zekanın sunduğu potansiyelden tam olarak faydalanabilirsiniz.