İçeriğe Atla
Mustafa Erbay
Rehberler · 9 dk okuma · görüntülenme Read in English

Farklı AI Araçları Arası Geçiş Neden Zor, Çözümü Nasıl?

Birden fazla yapay zeka sağlayıcısı arasında geçiş yapmanın getirdiği teknik zorlukları ve bu sorunlara karşı kendi geliştirdiğim çözüm yaklaşımlarını…

100%

Geçenlerde kendi yan ürünümün AI destekli operasyon katmanını geliştirirken, tek bir LLM sağlayıcısına bağlı kalmanın getirdiği riskleri ve maliyetleri net bir şekilde gördüm. Piyasadaki modellerin yetenekleri hızla değişirken, birine sıkı sıkıya bağlanmak hem fiyat hem de performans açısından esnekliğimi ciddi oranda kısıtlıyordu. Bu durum, beni farklı AI araçları arasında sorunsuz geçiş yapabilecek bir mimari kurmaya itti.

Bu yazıda, birden fazla AI modeli kullanmanın neden zor olduğunu, bu zorlukların üstesinden gelmek için neler yaptığımı ve kendi deneyimlerimden yola çıkarak nasıl bir çözüm mimarisi kurduğumu anlatacağım. Amacım, hem vendor lock-in riskini azaltmak hem de farklı görevler için en uygun ve maliyet etkin modeli dinamik olarak seçebilmekti.

Neden Farklı AI Modellerine İhtiyaç Duyuyoruz?

Tek bir yapay zeka modeline veya sağlayıcısına bağlı kalmak, uzun vadede çeşitli zorluklara yol açabilir. Benim gibi küçük ölçekli projelerden, üretim ERP’si gibi büyük sistemlere kadar her yerde bu riskleri göz önünde bulundurmak gerekiyor. Özellikle maliyet, performans ve özellik setleri açısından tek bir noktaya bağımlılık, esnekliği kısıtlayan en büyük faktörlerden biri haline geliyor.

Farklı sağlayıcıların modelleri belirli görevlerde diğerlerinden daha iyi performans gösterebilir veya daha uygun maliyetli olabilir. Örneğin, bir model metin özetleme konusunda çok başarılıyken, diğeri kod üretme veya karmaşık mantık yürütme için daha optimize edilmiş olabilir. Bu durumda, her göreve özel en iyi aracı seçmek, hem kaliteli çıktı elde etmenizi hem de operasyonel giderlerinizi optimize etmenizi sağlar.

AI Modelleri Arası Geçişteki Temel Zorluklar Nelerdir?

Farklı AI modelleri arasında geçiş yapmaya karar verdiğinizde, teknik olarak aşmanız gereken önemli engeller ortaya çıkıyor. Bu engeller, API uyumsuzluklarından model davranış farklılıklarına, maliyet yönetiminden veri güvenliğine kadar geniş bir yelpazeyi kapsar. Bu zorlukları iyi anlamak, sağlam bir geçiş stratejisi oluşturmanın ilk adımıdır.

API Uyumsuzlukları ve Veri Formatları

Her AI sağlayıcısının kendi REST API endpoint’leri, request payload yapıları ve response formatları var. Bir modelden diğerine geçerken, kodunuzdaki API çağrılarını ve veri işleme mantığını tamamen yeniden yazmak zorunda kalabilirsiniz. Bu, özellikle çok sayıda modelle çalışmayı planlıyorsanız ciddi bir geliştirme yükü ve hata potansiyeli yaratır. Örneğin, bir API messages alanını kullanırken, diğeri prompt ve history gibi ayrı alanlar bekleyebilir.

# Provider A API
client_a.chat.completions.create(
    model="model-a",
    messages=[{"role": "user", "content": "Merhaba!"}]
)

# Provider B API
client_b.completions.generate(
    engine="model-b",
    prompt="Merhaba!",
    user="user-id-123"
)

Bu farklılıklar, benim gibi esnek bir altyapı arayanlar için ilk başta can sıkıcı olabiliyor. Her yeni entegrasyon için benzer bir dönüşüm katmanı yazmak, zamanla sürdürülemez bir hale geliyor.

Model Davranışı ve Çıktı Kalitesi Farklılıkları

Farklı modeller, aynı prompt’a bile farklı yanıtlar üretebilir. Bir model belirli bir tonu veya formatı daha iyi korurken, diğeri daha yaratıcı veya daha az tutarlı olabilir. Bu durum, uygulamanızın kullanıcı deneyimini doğrudan etkileyebilir. Özellikle RAG tabanlı sistemlerde, retriever’dan gelen bağlamı işleme biçimleri ve bu bağlamdan yanıt üretme yetenekleri modeller arasında belirgin farklar gösterir.

Bir üretim ERP’sinde, AI ile üretim planlama yaparken, farklı modellerin aynı planlama senaryosuna verdiği yanıtların tutarlılığı ve doğruluğu kritik öneme sahipti. Bir modelin verdiği çıktı yanlış anlaşılmaya yol açarken, diğerinin çıktısı doğrudan aksiyon alınabilir nitelikte olabiliyordu. Bu farklılıklar, model seçimini ve prompt engineering sürecini oldukça karmaşık hale getiriyor.

Fiyatlandırma ve Kota Yönetimi

Her AI sağlayıcısının farklı fiyatlandırma modelleri ve kullanım kotaları bulunur. Bazıları token bazlı ücret alırken, bazıları işlem sayısına veya kaynak kullanımına göre faturalandırabilir. Bu farklılıkları takip etmek ve maliyetleri optimize etmek zorlayıcı olabilir. Ayrıca, yüksek trafik anlarında bir sağlayıcının kota limitlerine takılmak, uygulamanızın kesintiye uğramasına neden olabilir.

Veri Gizliliği, Güvenlik ve Gecikme

Farklı sağlayıcıların veri işleme politikaları ve güvenlik standartları değişebilir. Hassas verilerle çalışırken, her sağlayıcının uyumluluk ve gizlilik taahhütlerini dikkatlice değerlendirmek gerekir. Ayrıca, coğrafi konumları ve ağ altyapıları nedeniyle farklı sağlayıcılarda gecikmeler (latency) de değişebilir. Kullanıcılarınıza yakın veri merkezleri olan sağlayıcıları tercih etmek, yanıt sürelerini iyileştirebilir.

Bu sorunlar bir araya geldiğinde, birden fazla AI modelini entegre etmek ve yönetmek, başlangıçta göründüğünden çok daha büyük bir proje haline geliyor.

Unified API veya Adaptör Katmanı Yaklaşımı Nasıl Çalışır?

Bu zorlukların üstesinden gelmek için en etkili yaklaşımlardan biri, bir “Unified API” veya “Adaptör Katmanı” oluşturmaktır. Benim deneyimimde, bu tür bir katman, farklı AI sağlayıcıları arasındaki API uyumsuzluklarını soyutlayarak, uygulamanızın tek bir tutarlı arayüz üzerinden tüm modellere erişmesini sağlıyor. Bu sayede, altındaki sağlayıcıyı değiştirseniz bile uygulamanızın kodunda minimum değişikliğe ihtiyaç duyulur.

Bu yaklaşım, daha önce bir üretim ERP’sinde farklı ödeme ağ geçitlerini veya çeşitli CRM API’lerini entegre ederken kullandığım stratejiye çok benziyor. Temel fikir, her dış sistem için bir “adaptör” yazmak ve bu adaptörlerin hepsinin aynı “interface”i uygulamasını sağlamaktır. Böylece, ana uygulamanız sadece bu interface ile etkileşime girer ve hangi adaptörün kullanıldığına bakılmaksızın aynı mantığı çalıştırabilir.

graph TD;
  A["Istemci Uygulama"] --> B["Unified AI API Katmanı"];
  B --> C["Provider A Adaptörü"];
  B --> D["Provider B Adaptörü"];
  B --> E["Provider C Adaptörü"];
  C --> F["Provider A API"];
  D --> G["Provider B API"];
  E --> H["Provider C API"];
  style B fill:#f9f,stroke:#333,stroke-width:2px;
  style C fill:#ccf,stroke:#333,stroke-width:2px;
  style D fill:#ccf,stroke:#333,stroke-width:2px;
  style E fill:#ccf,stroke:#333,stroke-width:2px;

Bu mimari, uygulamanızın iş mantığını AI sağlayıcılarının API detaylarından ayırır. Örneğin, bir generate_text fonksiyonu çağırırsınız ve bu fonksiyon, arka planda hangi AI sağlayıcısının API’sini çağıracağını ve yanıtı nasıl normalize edeceğini kendi içinde yönetir. Bu, özellikle AI pazarının sürekli evrildiği ve yeni modellerin sıkça çıktığı günümüzde, uygulamanızın geleceğe hazır olmasını sağlar.

Örnek Bir Adaptör Katmanı Tasarımı

Bir adaptör katmanı oluştururken, öncelikle ortak AI operasyonlarını kapsayan bir arayüz (interface) tanımlamakla başlarım. Python’da bunu abstract base class (ABC) kullanarak yapabiliriz. Bu interface, tüm farklı AI sağlayıcılarının implemente etmesi gereken temel metodları belirler.

import abc

class BaseAIProvider(abc.ABC):
    @abc.abstractmethod
    def generate_completion(self, messages: list[dict], **kwargs) -> str:
        """
        Verilen mesaj listesine göre metin tamamlama yapar.
        """
        pass

    @abc.abstractmethod
    def generate_embedding(self, text: str) -> list[float]:
        """
        Verilen metin için embedding vektörü oluşturur.
        """
        pass

    @abc.abstractmethod
    def get_model_info(self) -> dict:
        """
        Model hakkında bilgi döndürür (maliyet, limitler vb.).
        """
        pass

class ProviderAAdapter(BaseAIProvider):
    def __init__(self, api_key: str, model_name: str):
        self.client = SomeProviderAClient(api_key)
        self.model_name = model_name

    def generate_completion(self, messages: list[dict], **kwargs) -> str:
        # Provider A API'sine özel çağrı ve yanıtı normalize etme
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=messages,
            **kwargs
        )
        return response.choices[0].message.content

    def generate_embedding(self, text: str) -> list[float]:
        response = self.client.embeddings.create(
            model=self.model_name,
            input=[text]
        )
        return response.data[0].embedding

    def get_model_info(self) -> dict:
        return {"name": self.model_name, "cost_per_token": 0.0001, "max_tokens": 8192}

# Diğer sağlayıcılar için de benzer adaptörler yazılır
class ProviderBAdapter(BaseAIProvider):
    # ... implementasyonlar ...
    pass

Bu yapı sayesinde, ana uygulamanız ProviderAAdapter veya ProviderBAdapter’ın doğrudan detaylarıyla uğraşmak yerine, sadece BaseAIProvider interface’ini kullanan bir nesneyle etkileşime girer. Bu, kod tekrarını azaltır ve yeni bir AI sağlayıcısı eklendiğinde veya mevcut bir sağlayıcı değiştiğinde değişiklikleri tek bir noktada yapmanızı sağlar. Bu esneklik, özellikle hızlı değişen AI dünyasında kritik bir avantaj sunuyor.

Akıllı Yönlendirme ve Fallback Stratejileri

Adaptör katmanını kurduktan sonraki adım, gelen istekleri hangi AI sağlayıcısına veya modeline yönlendireceğimize karar veren akıllı bir yönlendirme mekanizması geliştirmektir. Bu, benim gibi maliyet, performans ve güvenilirlik arasında denge kurmaya çalışanlar için oyunun kurallarını değiştiren bir özellik. Basit bir if-else yapısından, daha karmaşık kural tabanlı veya performans odaklı yönlendirmelere kadar çeşitli stratejiler izlenebilir.

Kural Tabanlı Yönlendirme (Rule-based Routing)

En temel yönlendirme stratejisi, belirli görevleri belirli modellere atamaktır. Örneğin, bir ERP’deki fatura özetleme gibi kritik ve hassas görevleri, daha pahalı ama daha güvenilir olduğu bilinen bir modele yönlendirebilirsiniz. Daha az kritik veya yüksek hacimli görevler, örneğin basit metin tamamlama, daha uygun fiyatlı modellere yönlendirilebilir.

def route_ai_request(task_type: str, prompt: str, providers: dict[str, BaseAIProvider]) -> BaseAIProvider:
    if task_type == "critical_financial_report":
        return providers["premium_provider"]
    elif task_type == "simple_chat":
        return providers["cost_effective_provider"]
    elif "kod üret" in prompt.lower():
        return providers["code_generation_provider"]
    else:
        return providers["default_provider"]

Bu kural tabanlı yapı, benim üretim ERP’sinde farklı AI modellerini entegre ederken kullandığım ilk yaklaşımdı. Hangi modelin hangi iş için daha uygun olduğunu belirledikten sonra, bu kuralları sisteme tanımlayarak otomatik yönlendirme sağlıyorduk.

Performans ve Maliyet Tabanlı Yönlendirme

Daha gelişmiş bir strateji, modellerin güncel performans verilerini (gecikme süresi, hata oranları) ve maliyetlerini dikkate almaktır. Bir izleme sistemi üzerinden sürekli olarak bu metrikleri toplar ve en iyi performansı en uygun maliyetle sunan modeli dinamik olarak seçerim. Örneğin, A sağlayıcısı şu an daha az gecikme sunuyorsa, istekleri oraya yönlendirirken, B sağlayıcısının token maliyeti belirgin bir şekilde düşerse oraya geçebilirim.

Fallback Mekanizmaları

Birincil AI sağlayıcısının erişilemez hale gelmesi veya bir hata döndürmesi durumunda, isteği otomatik olarak ikincil bir sağlayıcıya yönlendiren bir fallback mekanizması kurmak kritik öneme sahiptir. Bu, uygulamanızın kesintisiz çalışmasını sağlar ve kullanıcı deneyimini olumsuz etkileyecek durumlara karşı bir güvence oluşturur.

def reliable_ai_call(task_type: str, prompt: str, providers: dict[str, BaseAIProvider]) -> str:
    primary_provider = route_ai_request(task_type, prompt, providers)
    try:
        return primary_provider.generate_completion(messages=[{"role": "user", "content": prompt}])
    except Exception as e:
        print(f"Primary provider ({primary_provider.get_model_info()['name']}) failed: {e}. Trying fallback.")
        # Fallback'e geçiş mantığı
        fallback_provider_name = "fallback_provider" if primary_provider.get_model_info()['name'] != "fallback_provider" else "another_provider"
        if fallback_provider_name in providers:
            return providers[fallback_provider_name].generate_completion(messages=[{"role": "user", "content": prompt}])
        else:
            raise RuntimeError("No fallback provider available.")

Bu tür bir yapı, sistemin direncini artırır ve beklenmedik sorunlara karşı daha hazırlıklı olmanızı sağlar. Kendi yan ürünlerimde, özellikle anonim Türkiye veri platformunda, dış API bağımlılıklarında bu tür fallback mekanizmalarını sıkça kullanıyorum.

Prompt Engineering ve Model Uyumsuzluklarını Yönetmek

Farklı AI modelleri arasında geçiş yaparken, sadece API uyumsuzluklarını değil, aynı zamanda prompt engineering tarafındaki farklılıkları da yönetmek gerekiyor. Her modelin prompt’lara farklı tepki verdiğini ve en iyi sonuçları almak için prompt’ları modele özel olarak optimize etmenin gerektiğini kendi tecrübelerimden biliyorum. Bu durum, özellikle bir modelden diğerine geçtiğinizde beklenmedik çıktı kalitesi düşüşlerine yol açabilir.

Prompt Templating ile Dinamik Prompt Oluşturma

Bu sorunu çözmek için, prompt’ları hardcode etmek yerine bir templating sistemi kullanmak çok faydalı. Jinja2 gibi bir template motoru ile dinamik olarak prompt’lar oluşturabilir ve her modele özel değişkenleri veya talimatları bu template’lere dahil edebilirim. Bu sayede, aynı temel prompt’u farklı modellerin beklentilerine göre uyarlamak mümkün olur.

from jinja2 import Template

# Genel bir prompt template
general_template = Template("""
Sen bir {{ role }}'sin. Aşağıdaki metni özetle:
Metin: {{ text }}
""")

# Modele özel ek talimatlar içeren bir template
model_a_template = Template("""
Sen bir {{ role }}'sin. Lütfen bu özetleme işlemini akademik bir dille yap ve sadece ana fikirleri belirt.
Metin: {{ text }}
""")

# Kullanım
data = {"role": "uzman analist", "text": "Uzun bir makale metni buraya gelecek..."}
prompt_for_general = general_template.render(data)
prompt_for_model_a = model_a_template.render(data)

print(f"Genel Prompt: {prompt_for_general}")
print(f"Model A Prompt: {prompt_for_model_a}")

Bu yaklaşım, prompt’ların merkezi bir yerde yönetilmesini ve gerektiğinde modele özel ince ayarların yapılmasını kolaylaştırır. Böylece, bir model değişiminde tüm prompt’ları tek tek düzenlemek yerine, sadece ilgili template’leri güncellemek yeterli olur.

Model-Spesifik Ayarlar ve RAG İlişkisi

Bazı modeller, system mesajlarını daha iyi anlarken, diğerleri user ve assistant rolleri arasında net ayrımlar bekleyebilir. Prompt’un formatı, kullanılan özel token’lar veya hatta temperature gibi parametreler bile modelden modele farklılık gösterebilir. Bu ince farklar, özellikle Retrieval-Augmented Generation (RAG) mimarilerinde, retriever’dan gelen bağlamın ne kadar etkili kullanılacağını doğrudan etkiler.

RAG pipeline’larında, retriever’dan gelen bağlamı prompt’a ekleme biçimim de modele göre değişebilir. Bir model, bağlamı doğrudan user mesajının içinde görmeyi tercih ederken, diğeri system mesajıyla birlikte daha iyi çalışabilir. Bu uyumsuzlukları yönetmek için, adaptör katmanımın prompt’ları modele göre dönüştürme yeteneği olması gerekiyor. Bu sayede, RAG ile getirilen bağlamın her model tarafından en verimli şekilde işlenmesini sağlıyorum.

Gözlemlenebilirlik (Observability) ve Maliyet Yönetimi

Çoklu AI sağlayıcısı stratejisi uygularken, sistemin gözlemlenebilirliği ve maliyet yönetimi kritik bir hale gelir. Hangi modelin ne kadar kullanıldığı, hangi isteklerin başarılı olduğu, gecikme süreleri ve en önemlisi her bir sağlayıcı için ne kadar harcandığı gibi metrikleri sürekli takip etmem gerekiyor. Aksi takdirde, maliyetler kontrol dışına çıkabilir veya performans sorunları fark edilmeden kalabilir.

Metrik Toplama ve İzleme

Her AI çağrısı için metrikler toplamak, sistemin sağlığını ve verimliliğini anlamak için vazgeçilmezdir. Benim yaklaşımım, her adaptör katmanı çağrısında şu verileri kaydetmektir:

  • Sağlayıcı Adı ve Model Kimliği: Hangi modelin kullanıldığını belirtir.
  • İstek Tipi: Tamamlama, embedding vb.
  • Gecikme Süresi (Latency): İstek ne kadar sürede tamamlandı.
  • Giriş/Çıkış Token Sayısı: Maliyet hesaplaması için temel veri.
  • Durum Kodu/Hata Mesajı: İstek başarılı mı oldu, yoksa bir hata mı döndü?
  • Maliyet: İstek başına tahmini maliyet.

Bu metrikleri Prometheus veya Grafana gibi araçlarla görselleştirerek, hangi modelin ne kadar yüke maruz kaldığını, performansının nasıl olduğunu ve maliyet trendlerini kolayca izleyebiliyorum. Özellikle üretim ERP’sinde, bu tür detaylı metrikler, operasyonel kararlar alırken bana çok yardımcı oluyordu.

graph TD;
  A["Istemci Uygulama"] --> B["Unified AI API Katmanı"];
  B -- "İstek/Yanıt" --> C["AI Sağlayıcı Adaptörü"];
  C -- "API Çağrısı" --> D["AI Sağlayıcı API"];
  B -- "Metrikler (Gecikme, Token, Hata)" --> E["Metrik Toplayıcı (Prometheus)"];
  E --> F["İzleme Paneli (Grafana)"];
  style B fill:#f9f,stroke:#333,stroke-width:2px;
  style E fill:#fcf,stroke:#333,stroke-width:2px;

Maliyet Optimizasyonu ve Raporlama

Toplanan token sayıları ve maliyet bilgileriyle, her sağlayıcının gerçek maliyetini doğru bir şekilde hesaplayabiliyorum. Bu veriler, hangi modelin belirli bir görev için en uygun maliyetli olduğunu belirlememe ve yönlendirme stratejilerimi buna göre ayarlamama olanak tanır. Örneğin, belirli bir modelin maliyeti beklenmedik şekilde artarsa, otomatik olarak daha ucuz bir alternatife geçiş yapabilirim.

Ayrıca, bu verileri kullanarak düzenli maliyet raporları oluşturmak, bütçe yönetiminde şeffaflık sağlar. Bu raporlar, AI tüketim paternlerini anlamama ve gelecekteki harcamaları tahmin etmeme yardımcı olur. Kendi finansal hesaplayıcılarımda, bu tür maliyet analizlerini sıkça kullanır ve optimize etmeye çalışırım.

Sonuç

Birden fazla AI aracı arasında geçiş yapabilen bir mimari kurmak, ilk başta karmaşık gibi görünse de, uzun vadede projenizin esnekliğini, güvenilirliğini ve maliyet verimliliğini artırmak için kritik öneme sahiptir. API uyumsuzlukları, model davranış farklılıkları ve maliyet yönetimi gibi zorluklar, adaptör katmanları, akıllı yönlendirme ve güçlü gözlemlenebilirlik stratejileriyle aşılabilir.

Kendi deneyimlerimden yola çıkarak, bu yaklaşımın sadece vendor lock-in riskini azaltmakla kalmayıp, aynı zamanda her göreve özel en iyi AI modelini dinamik olarak seçme özgürlüğü sunduğunu gördüm. Bu, hem uygulamanızın performansını ve çıktı kalitesini artırır hem de operasyonel maliyetlerinizi optimize etmenizi sağlar. Gelecekte AI teknolojileri daha da hızla gelişirken, bu tür esnek mimariler, sistemlerimizin ayakta kalmasının anahtarı olacak.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

Birden fazla AI modeli arasında geçiş yaparken en büyük zorluklar nelerdir?
Benim deneyimimde, birden fazla AI modeli arasında geçiş yaparken en büyük zorluk, her bir modelin kendine özgü API'leri ve veri formatlarını anlamak ve entegre etmek oldu. Her bir modelin farklı gereksinimleri ve kısıtlamaları vardı, bu da esnek bir çözüm geliştirmeyi zorlaştırdı.
Farklı AI modellerini entegre ederken maliyet ve performans tradeoff'ları nasıl yönetilir?
Ben, farklı AI modellerini entegre ederken, her bir modelin maliyet ve performansını dikkatlice değerlendirdim. Bazı modeller yüksek performans sunarken, diğerleri daha uygun maliyetliydi. Bu tradeoff'ları yönetmek için, her bir modelin güçlü ve zayıf yanlarını analiz ettim ve görevlere özel olarak en uygun modeli seçtim.
AI modelleri arasında geçiş yaparken hata yönetimi nasıl yapılmalıdır?
Hata yönetimi, AI modelleri arasında geçiş yaparken kritik bir konudur. Ben, her bir modelin hata yönetim mekanizmalarını理解 ettim ve entegre ettiğim sistemde merkezi bir hata yönetim sistemi kurdum. Bu, hataları hızlı bir şekilde tespit edip düzeltmeme ve sistemdeki tutarlılığı sağlamama yardımcı oldu.
Farklı AI modellerini kullanırken vendor lock-in riskini nasıl azaltabiliriz?
Vendor lock-in riskini azaltmak için, ben her bir modelin bağımsız olarak çalışabilmesi için bir mimari kurdum. Bu, herhangi bir modelde meydana gelen değişikliklere veya sorunlara karşı sistemi daha esnek ve dayanıklı hale getirdi. Ayrıca, farklı modellerin entegre edildiği bir framework geliştirdim, bu da yeni modellerin kolayca eklenmesine veya mevcut modellerin değiştirilmesine olanak tanıdı.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar