LLM'ler Notebook'tan Çıktı: Production'da AI Agent'ları Nasıl Yönetirsin?

LLM'ler Notebook'tan Çıktı: Production'da AI Agent'ları Nasıl Yönetirsin?
Photo by Catherine Breslin / Unsplash

ChatGPT'yi Açtın, Sorunu Çözdü. Peki Ya Gerçek Dünyada?

LLM'lerle oynamak kolay. ChatGPT'ye prompt yazarsın, cevap alırsın. Ama iş gerçek bir uygulamaya entegre etmeye geldiğinde, o "chat" arayüzü birden yetersiz kalır. Müşteri destek botu yapacaksan, sadece cevap vermek yetmez. Ticket açması, veritabanına bağlanması, API çağırması gerekir. İşte bu noktada AI agent'lar devreye giriyor.

AI agent dediğim şey, LLM'yi bir "beyin" olarak kullanıp, ona araçlar (tools) verdiğin sistem. LLM düşünür, karar verir, hangi aracı kullanacağına karar verir ve sonucu sana iletir. Bu yazıda, bu agent'ları production ortamında nasıl yöneteceğini anlatacağım.

Agent Nedir, Basit Bot'tan Ne Farkı Var?

Geleneksel chatbot'lar genellikle kural tabanlıdır veya basit intent classification yapar. "Bana hesap bakiyemi göster" dersen, önceden tanımlanmış bir flow'u çalıştırır. AI agent ise daha dinamik. LLM'ye "şu araçlarım var, sen bunları kullanarak kullanıcının isteğini yerine getir" dersin. LLM durumu değerlendirir, gerekirse kullanıcıdan ek bilgi ister, araçları sırayla çalıştırır.

Örnek vereyim: Kullanıcı "Gelecek hafta İstanbul'dan İzmir'e uçak bileti ara, en ucuz 3 seçeneği göster, benim takvimimde boş saatlerle uyuşsun" dedi. Geleneksel bot bu cümleyi anlamakta zorlanır. AI agent ise şöyle düşünür:

  1. Kullanıcının takvimine bağlanıp gelecek haftaki boşlukları çek (Calendar Tool)
  2. Uçuş API'sini sorgula (Flight API Tool)
  3. Sonuçları filtrele, sırala (Filter Tool)
  4. Kullanıcıya formatlı şekilde sun (Response Formatter)

Bu akışı önceden kodlamazsın. LLM'ye araçları tanıtırsın, o context'e göre kendi planını oluşturur.

Production'a Taşırken Karşılaşacağın 3 Büyük Engel

1. Deterministik Olmama Sorunu

LLM'ler probabilistic. Aynı prompt'u 10 kere verirsen, 10 farklı cevap alabilirsin. Production'da bu kabul edilemez. Müşteri bakiye sorguladığında, bazen doğru bazen yanlış sonuç alamaz.

Çözüm: Agent'ını mümkün olduğunca dar bir alana odakla. "Genel asistan" yapmaya çalışma. Özel araçlar tanımla ve LLM'nin bu araçlar dışına çıkmasını engelle. Ayrıca temperature parametresini düşük tut (0.1-0.3 arası).

2. Latency ve Cost

Basit bir ChatGPT çağrısı 2-3 saniye sürer. Agent ise birden fazla LLM çağrısı yapabilir (düşünme, araç seçme, sonuç değerlendirme). Bu da latency'yi katlayarak artırır. Ayrıca her LLM çağrısı para. GPT-4 ile complex bir agent flow'u 0.50$'a mal olabilir.

Çözüm: Küçük modeller kullan. GPT-3.5-turbo, Claude Haiku gibi. Critical olmayan kararlar için bunları kullan, sadece gerektiğinde büyük modele geç. Ayrıca caching mekanizması kur. Benzer sorgulara cache'ten cevap ver.

# Basit bir cache örneği
from functools import lru_cache
import hashlib

@lru_cache(maxsize=1000)
def cached_agent_response(user_query: str, context: str) -> str:
    query_hash = hashlib.md5(f"{user_query}|{context}".encode()).hexdigest()
    # Cache kontrolü ve LLM çağrısı
    return response

3. Hata Yönetimi ve Monitoring

Agent'ın bir aracı çağırdı, API 500 hatası verdi. Ne olacak? LLM'ye bu hatayı nasıl ileteceksin? Agent'ın kendi kendine recovery mekanizması olmalı.

Çözüm: Her tool call için retry mekanizması kur. Max 3 deneme gibi. Ayrıca agent'ın tüm adımlarını logla. LangSmith veya benzeri bir tool kullanarak agent'ının nasıl karar verdiğini trace et.

Gerçek Bir Agent Mimarisi Kuralım: FastAPI + LangGraph

Teoriden pratiğe geçelim. Basit bir customer support agent'ı yapalım. Araçlarımız: Ticket açma (Zendesk API), Knowledge base search (Elasticsearch), Escalation (İnsana yönlendirme).

LangGraph kullanacağım çünkü complex agent flow'larını state machine olarak modellemek için ideal. FastAPI ile de API endpoint'imizi oluşturacağız.

from langgraph.graph import StateGraph, END
from typing import TypedDict
from langchain_openai import ChatOpenAI

class AgentState(TypedDict):
    user_query: str
    conversation_history: list
    tools_called: list
    final_response: str
    needs_human: bool

def route_query(state: AgentState):
    """LLM'ye sorguyu analiz ettir, hangi tool'u kullanacağına karar verdir"""
    llm = ChatOpenAI(model="gpt-3.5-turbo")
    # Prompt engineering ile tool seçimi
    # ...
    return {"next_step": "search_knowledge_base"}

def search_knowledge_base(state: AgentState):
    """Knowledge base'de ara"""
    # Elasticsearch sorgusu
    # ...
    return {"next_step": "check_if_sufficient"}

# Graph'ı oluştur
workflow = StateGraph(AgentState)
workflow.add_node("route", route_query)
workflow.add_node("search_kb", search_knowledge_base)
workflow.set_entry_point("route")
workflow.add_conditional_edges(
    "route",
    lambda x: x["next_step"],
    {"search_knowledge_base": "search_kb", "create_ticket": "create_ticket"}
)
workflow.add_edge("search_kb", END)

app = FastAPI()
agent = workflow.compile()

@app.post("/support-agent")
async def handle_query(query: str):
    initial_state = {
        "user_query": query,
        "conversation_history": [],
        "tools_called": [],
        "final_response": "",
        "needs_human": False
    }
    result = agent.invoke(initial_state)
    return {"response": result["final_response"], "needs_human": result["needs_human"]}

Bu mimaride, agent'ın tüm adımlarını kontrol edebiliyorsun. Her node bir fonksiyon, edges'ler de akışı yönlendiriyor. Production'da bu graph'ı scale etmek, monitoring eklemek, hata yönetimi yapmak daha kolay.

Agent'ını Nasıl Test Edersin?

Unit test yazmak zor. Çünkü LLM output'u deterministic değil. Onun yerine evaluation framework'leri kullan. Örneğin:

  1. Scenario-based testing: 10-20 tane gerçekçi kullanıcı senaryosu yaz. Her deploy'dan önce bu senaryoları çalıştır, sonuçları kaydet.
  2. LLM-as-a-judge: Agent'ın cevabını daha büyük bir LLM'ye (GPT-4) ver, "Bu cevap doğru mu?" diye sor. Otomatik evaluation yap.
  3. A/B testing: Canlı trafiğin küçük bir kısmını yeni agent versiyonuna yönlendir. Metric'lerini karşılaştır (resolution rate, customer satisfaction).

Şimdi Başla: İlk Agent'ını Production'a Taşı

En büyük hata, kompleks bir agent ile başlamak. Şöyle yap:

  1. Basit başla: Sadece 1-2 tool'u olan bir agent yap. Örneğin: "FAQ search" + "Ticket creation".
  2. Human-in-the-loop: İlk başta agent'ın tüm cevaplarını insan onayına sun. Sadece %95 confidence'ın üstündeki cevapları otomatik gönder.
  3. Monitoring kur: LangSmith, OpenTelemetry veya custom logging. Agent'ın hangi tool'ları ne sıklıkla çağırdığını, ne kadar sürdüğünü, ne kadar maliyetli olduğunu takip et.
  4. Yavaş scale et: Trafiği yavaş yavaş artır. Her artışta metric'lerini kontrol et.

AI agent'lar, LLM'leri gerçek dünya problemlerine uygulamanın en güçlü yollarından biri. Ama production'da çalıştırmak, notebook'ta oynamaktan çok farklı. Determinizm, latency, cost ve reliability gibi engineering challenge'ları var.

Bugün başla: Mevcut bir chatbot'un varsa, ona basit bir tool ekle. "Bana son ticket'larımı getir" deyince Zendesk API'sini çağırsın. Bu küçük adımla agent dünyasına girmiş olursun. Sonra yavaş yavaş kompleksliği artırırsın.

Unutma: En iyi agent, dar bir alanda mükemmel çalışan agent'tır. Her şeyi yapmaya çalışan agent, hiçbir şeyi iyi yapamaz.