Son günlerde sıfırdan, tamamen kendi bilgisayarımda çalışan bir kişisel asistan kurdum. Hiçbir ücretli API çağrısı yok, hiçbir veri dizüstü bilgisayarımın dışına çıkmıyor. İnternette arama yapıyor, kod yazıp kaydediyor, sesimi anlıyor, sesli yanıt veriyor, uzun süreli hafızaya sahip ve Ollama aracılığıyla yerel bir dil modeli (LLM) çalıştırıyor. Sonuç oldukça iyi çalışıyor, ancak bu yolda edindiğim deneyimler, yerel LLM'ler ve ajanlarla çalışan herkesin karşılaştığı birçok kavramı gün yüzüne çıkardı. Özellikle 'buluttaki 70B+ bir LLM' ile 'dizüstü bilgisayar GPU'sunda çalışan 8-14B bir LLM' arasındaki devasa farkı anlamak kritik. Bu makale tam da bu kavramlar üzerine.
Mimari genel hatlarıyla şöyle: Kullanıcı sesi → VAD (konuşma algılama) → Whisper (konuşmadan metne) → LangChain/LangGraph Ajanı → Ollama (yerel LLM) → Araçlar: web arama, hava durumu, hafıza... → Piper (metinden konuşmaya) → Ses yanıtı. Her şey yerel çalışıyor: LLM Ollama ile, transkripsiyon faster-whisper ile, ses sentezi Piper ile ve hafıza SQLite ile. Web aramaları dışında hiçbir veri makinenin dışına çıkmıyor.
Kavram 1: Ajanlar sadece 'LLM + döngü + araçlar'dan ibaret. Bir yapay zeka 'ajanı' sihir değildir; her adımda metinle yanıt verme veya bir fonksiyon çağırma (tool) kararı alabilen, sonucu gözlemleyip tekrar karar veren bir döngü içinde çalışan LLM'dir. LangChain 1.0, bunu create_agent ile resmileştirir ve LangGraph üzerine inşa eder. Her 'araç' sadece dekoratör eklenmiş bir Python fonksiyonudur; docstring, modelin ne zaman kullanacağını belirleyen açıklama haline gelir. Model fonksiyonu doğrudan çalıştırmaz; 'get_weather fonksiyonunu city='İstanbul' ile çağırmak istiyorum' diyen bir yapı üretir, framework gerçekten çalıştırır ve sonucu modele geri verir.
Gelecekte Ne Bekleniyor?
Kavram 2: Küçük modellerde tool calling kırılgandır. Projenin en büyük baş ağrısı buydu. Tool calling, modelin runtime'ın (benim durumumda Ollama) yorumlayabileceği belirli bir yapıyı (genellikle JSON) üretmek üzere eğitilmiş olmasını gerektirir. Ancak her model/quantizasyon doğru tool calling şablonuna sahip değildir; bir testte model,
Kavram 3: Modelin kararına güvenmeyin, onun yerine siz karar verin. 'X hakkında araştır yap ve özet kaydet' gibi bir istekte model, gerçekten araştırma yapmak yerine, daha sonra Google'ı açacak bir script yazabiliyor. Çözüm, prompt'u iyileştirmek değil, kararı modelin elinden almaktı: Bu kalıbı anahtar kelimelerle tespit edip LLM'i çağırmadan önce aramayı yapmak ve gerçek sonuçları doğrudan bağlama enjekte etmek. Model artık araştırma yapıp yapmamaya karar vermiyor, sadece elindeki bilgiyi sentezliyor. Bu genel bir ders: Karar ne kadar deterministik alınabiliyorsa, sistem o kadar güvenilir olur. Her şeyi modelin 'muhakemesine' bırakmak cazip, ancak küçük modeller apaçık kararlarda bile hata yapabiliyor.
Kavram 4: Ajan hafızası tek bir şey değildir. Bir ajanda 'hafıza' aslında en az üç farklı şeydir: Mevcut konuşma bağlamı (LangGraph'da checkpointer ile yönetilir), kalıcı konuşma hafızası (program çalıştırmaları arasında hayatta kalan checkpoint - InMemorySaver'dan SqliteSaver'a geçtim) ve uzun süreli hafıza (konuşmadan bağımsız hatırlanması gereken bilgiler - ayrı bir SQLite tablosu ve remember_fact/recall_facts araçları ile). Önemli bir detay: Kalıcı konuşma hafızası sınırsız büyür. Birçok etkileşimden sonra tüm geçmiş her turda yeniden gönderilmeye başlar ve bağlam penceresini doldurup uzun yanıtları keser. Çözüm, eski geçmişi otomatik olarak özetlemektir; LangChain 1.0'da Summarizer ile hazır olarak gelir.
Kaynak: dev.to