Skip to content
~/sph.sh

LangChain Production'da: Çalışan Patternler ve İşe Yaramayan Anti-Patternler

LangChain uygulamalarını production'a taşırken öğrendiklerim. Başarısızlığa yol açan anti-patternler, başarıyı sağlayan patternler, çalışan kod örnekleri ve maliyet optimizasyon stratejileri.

Production Gap'i

LangChain uygulamalarını prototipten production'a taşıdığında dokümantasyon örnekleri ile gerçek dünya gereksinimleri arasındaki fark ortaya çıkıyor. Development'ta mükemmel çalışan şeyler, production yükü altında pahalı, yavaş veya güvenilmez hale gelebiliyor.

Bunu beklenmedik davranışları ortaya çıkaran deployment'lardan öğrendim: Dakikalarca döngüye giren agentlar, aylık %30-40 artan token maliyetleri ve sadece kullanıcı şikayetleriyle keşfedilen sessiz hatalar. Framework'ün abstraksiyonları prototyping'i hızlandırıyor ama production ölçeğinde kritik sorunları gizleyebiliyor.

Bu yazıda, gerçek production deployment'larından ve onların sağladığı derslerden edindiğim pratik patternleri paylaşacağım. Maliyet, latency ve güvenilirlik odaklı çözümler sunuyorum. Her anti-pattern için hem tespit yöntemleri hem de uygulanabilir çözümler var—böylece mevcut sistemlerinde sorunlu alanları hızlıca belirleyip düzeltebilirsin. Bu patternler özellikle agent tabanlı uygulamalarda kritik; basit chat interface'lerden farklı olarak agentlar birden fazla LLM çağrısı yapar ve hata birikimi katlanır.

Framework Trade-off'unu Anlamak

LangChain, erken dönem LLM entegrasyon karmaşıklığını çözdü: Promptlar, chain'ler, agentlar ve memory yönetimi için standart abstraksiyonlar sundu. Bu prototyping'i önemli ölçüde hızlandırdı; direkt API çağrılarıyla haftalar sürecek işler günlerde yapılabilir hale geldi.

Ancak bu abstraksiyonlar kendi zorluklarını getiriyor:

Velocity-control trade-off'u: Hızlı prototyping, şeffaflık pahasına geliyor. Production'da bir şeyler ters gittiğinde, birden fazla abstraction katmanında debug yapmak direkt API çağrısını debug etmekten çok daha zor.

Gizli davranışlar: Framework içsel kararlar alıyor ve bunlar her zaman görünür değil; memory trimming stratejileri, otomatik retry'lar, callback yürütme sırası. İşler yolunda giderken sorun yok, ama ters gittiğinde nedenini anlamak kaynak koduna dalmayı gerektiriyor.

Performance overhead'i: Her abstraction katmanı latency ekliyor. Memory wrapper'ları, callback sistemleri ve otomatik işlemler istek başına 1+ saniye overhead biriktirebiliyor; prototip için kabul edilebilir, production için sorunlu.

Framework inflection noktası, ekibinin framework davranışını debug etmeye feature geliştirmekten daha fazla zaman harcadığı an. Production'da bu genellikle ilk ciddi latency sorunu veya token faturası şoku ile ortaya çıkar. Bazı ekipler bunu hızlı yaşıyor, bazıları hiç yaşamıyor. Bu çizgiyi ne zaman geçtiğini anlamak kritik; o noktada ya abstraction katmanlarını sadeleştirmek ya da framework'ten vazgeçmek gerekebilir. Bu kararı ertelemek sadece teknik borcu artırır—ekip moralı ve delivery hızı düşer.

7 Ölümcül Anti-Pattern

1. Sınırsız Memory Birikimi

Default ConversationBufferMemory sınırsız konuşma geçmişi saklıyor:

python
from langchain.memory import ConversationBufferMemory
# Anti-pattern: Sınırsız geçmiş biriktiriyor# Not: ConversationBufferMemory deprecated - yeni projeler için# LangGraph persistence veya RunnableWithMessageHistory kullanmemory = ConversationBufferMemory()# 50 mesaj sonrası: Devasa context, yavaş response'lar, yüksek maliyetler

Etki: Token maliyetleri konuşmalar uzadıkça aylık %30-40 artıyor. Her request'in tüm geçmişi içermesi latency'yi düşürüyor. Sonunda context window'lar taşıp hatalara yol açıyor. Özellikle uzun destek konuşmalarında bu pattern maliyet patlamasına neden olur; müşteri her mesajda artan token faturası öder.

Tespit: Token kullanım trendlerini zaman içinde izle. Konuşmalar ilerledikçe artan response sürelerine dikkat et.

Çözüm: Explicit limitlerle ConversationSummaryBufferMemory kullan (veya LangGraph persistence'a migrate et):

python
from langchain.memory import ConversationSummaryBufferMemory
# Not: ConversationSummaryBufferMemory deprecated# Yeni projeler için LangGraph persistence veya RunnableWithMessageHistory kullanmemory = ConversationSummaryBufferMemory(    llm=llm,    max_token_limit=500,  # Son context'i kompakt tut    return_messages=True)# Sonuç: Context kalitesini korurken %30 maliyet düşüşü

2. Korkuluksuz Agent

Execution kontrolleri olmayan agentlar yaratmak:

python
from langchain.agents import AgentExecutor
# Anti-pattern: Execution üzerinde hiç limit yokexecutor = AgentExecutor(agent=agent, tools=tools)# Gerçek olay: Agent search ve summarize tool'lar arasında 14 dakika döngüde kaldı

Etki: Agentlar sonsuz döngüye girebiliyor, bütçeyi tüketiyor ve korkunç kullanıcı deneyimi yaratıyor. Bir deployment'ta agent search ve summarize tool'ları arasında sonuca ulaşamadan 14 dakika döngüde kaldı. max_iterations ve max_execution_time olmadan production'da bu tür vakalar kaçınılmaz; tek bir kullanıcı binlerce token harcayabilir.

Tespit: Production'dan önce maliyet alarmları ve execution süresi izleme kur.

Çözüm: Konfigürasyonda explicit kontroller:

python
from langchain.agents import AgentExecutorfrom langchain.callbacks import get_openai_callback
executor = AgentExecutor(    agent=agent,    tools=tools,    max_iterations=5,              # Sonsuz döngüleri engelle    max_execution_time=30,          # 30 saniye sonra timeout    early_stopping_method="generate")
# Not: get_openai_callback yeni agent tipleriyle maliyetleri yakalamayabilir# Kapsamlı maliyet takibi için LangSmith kullanmayı değerlendirwith get_openai_callback() as cb:    result = executor.run(query)    print(f"Tokens: {cb.total_tokens}, Maliyet: ${cb.total_cost}")

3. Basit Tasklar İçin Aşırı Abstraction

Basit işlemler için full LangChain abstraksiyonları kullanmak:

typescript
// Anti-pattern: Basit completion için 5 katman abstractionimport { ChatOpenAI } from "langchain/chat_models/openai";import { ChatPromptTemplate } from "langchain/prompts";import { StringOutputParser } from "langchain/schema/output_parser";
const chatModel = new ChatOpenAI();const outputParser = new StringOutputParser();const prompt = ChatPromptTemplate.fromMessages([  ["system", "Sen yardımsever bir çevirmensin."],  ["user", "{text} metnini {language} diline çevir"]]);const chain = prompt.pipe(chatModel).pipe(outputParser);
// Direkt API: Aynı sonuç, framework overhead'i yokimport OpenAI from "openai";const openai = new OpenAI();const response = await openai.chat.completions.create({  model: "gpt-4",  messages: [    { role: "system", content: "Sen yardımsever bir çevirmensin." },    { role: "user", content: `${text} metnini ${language} diline çevir` }  ]});

Etki: Gereksiz karmaşıklık, zorlaşan debugging, abstraksiyonlardan fayda görmeyen tasklar için ekip cognitive load'u.

Tespit: Code review; basit işlemler için abstraction katmanlarını say. Basit bir completion için 4+ modül import ediyorsan, direkt API kullanımını değerlendir.

4. Gizli Latency Overhead'i

Framework komponentleri önemli latency ekleyebiliyor:

python
from langchain.memory import ConversationBufferWindowMemory
# Anti-pattern: Memory wrapper çağrı başına 1+ saniye ekliyormemory = ConversationBufferWindowMemory(k=5)# Profiling gösterdi: wrapper işlem süresi > gerçek LLM çağrı süresi

Etki: Kötü kullanıcı deneyimi, yüksek request hacimlerine scale etme zorluğu.

Tespit: Framework komponentleriyle ve olmadan profil. End-to-end latency ile direkt API çağrı süresini ölç.

Çözüm: Performance-critical path'ler için custom lightweight alternatifler:

python
# Custom trimmed memory - son N mesajı verimli tutarclass LightweightMemory:    def __init__(self, max_messages=10):        self.messages = []        self.max_messages = max_messages
    def add_message(self, message):        self.messages.append(message)        if len(self.messages) > self.max_messages:            self.messages = self.messages[-self.max_messages:]
    def get_context(self):        return self.messages
# Sonuç: Request başına latency'de 1.2 saniye düşüş

5. Default Konfigürasyon Körlüğü

Development default'larıyla production deployment'ı:

python
# Anti-pattern: Production'da development default'larıfrom langchain.chat_models import ChatOpenAI
llm = ChatOpenAI()# Caching yok, output limitleri yok, maliyet kontrolleri yok

Etki: Yüksek operasyonel maliyetler, yavaş response'lar, disk'i dolduran verbose logging.

Tespit: Production launch'tan önce maliyet ve latency metrikleri için baseline oluştur.

Çözüm: Explicit production konfigürasyonu:

python
from langchain.chat_models import ChatOpenAIfrom langchain.cache import RedisCachefrom langchain.globals import set_llm_cacheimport redis
# Production-ready konfigürasyonset_llm_cache(RedisCache(    redis_=redis.Redis(host="localhost", port=6379)))
llm = ChatOpenAI(    model="gpt-4",    temperature=0.7,    max_tokens=512,        # Output uzunluğunu sınırla    request_timeout=30,    # API çağrıları için timeout    max_retries=2          # Kontrollü retry davranışı)

6. Black-Box Agent Davranışı

Observability olmadan agent deployment'ı:

python
# Anti-pattern: Agent kararlarına görünürlük yokexecutor = AgentExecutor(agent=agent, tools=tools)result = executor.run(query)# Bu sessizce başarısız olduğunda, nedenini bilemiyorsun

Etki: Sessiz hatalar, imkansız debugging, sadece kullanıcı şikayetleriyle sorun keşfi.

Tespit: Gözlemleyemediğin şeyi tespit edemezsin; sorun bu zaten.

Çözüm: İlk günden LangSmith tracing:

python
import osfrom langchain.callbacks.tracers import LangChainTracer
# Environment'ta tracing'i aktifleştiros.environ["LANGCHAIN_TRACING_V2"] = "true"os.environ["LANGCHAIN_API_KEY"] = "api-anahtarin"
# Tüm chain'ler, agentlar, tool'lar otomatik trace ediliyor# Track: latency, maliyetler, token'lar, hatalar, karar path'leriexecutor = AgentExecutor(agent=agent, tools=tools)result = executor.run(query)# Tüm execution detayları artık LangSmith dashboard'unda görünür

7. Data Ingestion Naifliği

RAG pipeline karmaşıklığını hafife almak:

python
# Anti-pattern: Doküman yüklemenin "öylece çalıştığını" varsaymakfrom langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("document.pdf")documents = loader.load()# Gerçek deneyim: Mühendislik zamanının %40'ı data ingestion sorunlarında geçti

Etki: Doküman tiplerine uygun olmayan PDF parser'ı, uluslararası metinlerde encoding sorunları, retrieval kalitesini düşüren chunking problemleri.

Tespit: Doküman işlemede yüksek hata oranları, kötü retrieval sonuçları.

Çözüm: Birden fazla stratejiyle data loader'ların kapsamlı testi:

python
from langchain.document_loaders import PyPDFLoader, PDFMinerLoader, UnstructuredPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitter
# Birden fazla parser dene, gerçek dokümanlarla test etparsers = [    PyPDFLoader,    PDFMinerLoader,    UnstructuredPDFLoader]
for ParserClass in parsers:    try:        loader = ParserClass("document.pdf")        docs = loader.load()
        # Çıktı kalitesini doğrula        if validate_extraction(docs):            break    except Exception as e:        print(f"{ParserClass.__name__} başarısız oldu: {e}")
# Düşünülmüş chunking stratejisisplitter = RecursiveCharacterTextSplitter(    chunk_size=1000,    chunk_overlap=200,  # Chunk'lar arası context'i koru    length_function=len)chunks = splitter.split_documents(docs)

Production-Ready Patternler

Pattern 1: LCEL-First Architecture

Modern LangChain uygulamaları daha iyi composability için LCEL (LangChain Expression Language) kullanıyor:

python
from langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import ChatOpenAIfrom langchain_core.output_parsers import StrOutputParser
# LCEL: Built-in streaming ile okunabilir pipe syntax'ıchain = (    ChatPromptTemplate.from_template("Analiz et: {input}")    | ChatOpenAI(model="gpt-4", streaming=True)    | StrOutputParser())
# Streaming, batching, async out of the box destekleniyorfor chunk in chain.stream({"input": query}):    print(chunk, end="", flush=True)

Faydalar: Net composition, built-in async desteği, legacy chain'lerle karşılaştırıldığında daha kolay debugging.

Ne zaman kullan: Birden fazla LLM çağrısı, transformation'lar veya conditional logic gerektiren karmaşık workflow'lar.

Pattern 2: Explicit Resource Kontrolleri

Production konfigürasyonu limitleri explicit yapmalı:

python
from langchain.agents import AgentExecutorfrom langchain.callbacks import get_openai_callback
# Tüm limitler explicit ve dokümanteexecutor = AgentExecutor(    agent=agent,    tools=tools,    max_iterations=5,              # 5 tool çağrısından sonra dur    max_execution_time=30,          # 30 saniyede hard timeout    early_stopping_method="generate", # Graceful degradation    verbose=False                   # Production'da debug logging'i kapat)
# Her request'te maliyet trackingwith get_openai_callback() as cb:    result = executor.run(query)
    # Maliyetler threshold'u aşarsa alert    if cb.total_cost > 0.10:        send_alert(f"Yüksek maliyetli request: ${cb.total_cost}")

Implementation checklist:

  • Memory ve output'lar üzerinde token limitleri
  • Agent iteration cap'leri ve timeout'lar
  • Maliyet bütçeleri ve alertler
  • Retry limitleri ve exponential backoff

Pattern 3: Multi-Tier Caching Stratejisi

Caching maliyetleri ve latency'yi dramatik şekilde düşürüyor:

python
from langchain.cache import InMemoryCache, SQLiteCache, RedisCachefrom langchain.globals import set_llm_cacheimport redis
# Development: In-memory cache# set_llm_cache(InMemoryCache())
# Lokal persistence: SQLite# set_llm_cache(SQLiteCache(database_path=".langchain.db"))
# Production: Distributed Redis cacheset_llm_cache(RedisCache(    redis_=redis.Redis(        host="redis.production.internal",        port=6379,        db=0    )))
# Cache konfigürasyonu# TTL: Statik content için 1 yıl, dinamik için 1 gün# Invalidation: Güncellenen content için manual veya event-driven

Gerçek etki: Cache'lenmiş response'lar için %40 maliyet düşüşü ve %80 latency iyileşmesi.

Pattern 4: Observability-First Development

İlk chain'ini yazmadan önce tracing kur:

python
import osfrom langchain.callbacks.base import BaseCallbackHandler
# LangSmith tracing konfigürasyonuos.environ["LANGCHAIN_TRACING_V2"] = "true"os.environ["LANGCHAIN_API_KEY"] = "langsmith-api-anahtarin"os.environ["LANGCHAIN_PROJECT"] = "production-app"
# Business metrikleri için custom callbackclass ProductionMetricsCallback(BaseCallbackHandler):    def on_llm_start(self, serialized, prompts, **kwargs):        self.start_time = time.time()
    def on_llm_end(self, response, **kwargs):        latency = time.time() - self.start_time        tokens = response.llm_output.get("token_usage", {})
        # Monitoring sistemine gönder        metrics.record("llm.latency", latency)        metrics.record("llm.tokens", tokens.get("total_tokens", 0))        metrics.record("llm.cost", calculate_cost(tokens))
# Tüm chain execution'larında kullancallbacks = [ProductionMetricsCallback()]result = chain.invoke({"input": query}, config={"callbacks": callbacks})

İzlenecek key metrikler:

  • Performance: QPS, latency percentile'ları (p50, p95, p99), time-to-first-token
  • Maliyet: Toplam token'lar, request başına maliyet, günlük burn rate
  • Kalite: Hata oranları, retry sayıları, kullanıcı feedback'i
  • Agent davranışı: Tool seçimleri, iteration sayıları, karar path'leri

Pattern 5: Smart Model Routing

Request'leri karmaşıklığa göre uygun modellere yönlendir:

python
from langchain.chat_models import ChatOpenAIfrom langchain.prompts import ChatPromptTemplate
# Maliyet/kabiliyet trade-off'larıyla modelleri tanımlacheap_model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)premium_model = ChatOpenAI(model="gpt-4", temperature=0.7)
def route_to_model(query: str):    """Query karmaşıklığına göre route et"""    complexity_score = analyze_complexity(query)
    if complexity_score < 0.3:        return cheap_model  # GPT-3.5-turbo: $0.0005/1K input, $0.0015/1K output    else:        return premium_model  # GPT-4: $0.03/1K input, $0.06/1K output        # Uygun maliyetli seçenek için GPT-4o mini: $0.00015/1K input, $0.0006/1K output
# Chain'de dinamik routingdef create_chain(query: str):    model = route_to_model(query)    prompt = ChatPromptTemplate.from_template("{input}")    return prompt | model
# Örnek karmaşıklık analizidef analyze_complexity(query: str) -> float:    """Basit heuristic-based karmaşıklık skorlaması"""    score = 0.0
    # Uzunluk-based skorlama    if len(query.split()) > 50:        score += 0.3
    # Teknik terim tespiti    technical_terms = ["mimari", "algoritma", "performans", "optimizasyon"]    if any(term in query.lower() for term in technical_terms):        score += 0.4
    # Multi-step reasoning göstergeleri    if any(word in query.lower() for word in ["karşılaştır", "analiz et", "neden açıkla"]):        score += 0.3
    return min(score, 1.0)

Sonuç: Tipik deployment'lar basit query'leri ucuz modellere yönlendirerek %50-60 maliyet düşüşü görüyor.

Pattern 6: Pydantic ile Structured Output'lar

Type-safe output'lar post-processing bug'larını azaltıyor:

python
from langchain.output_parsers import PydanticOutputParserfrom langchain_core.prompts import PromptTemplatefrom langchain_openai import ChatOpenAIfrom pydantic import BaseModel, Field
# Output schema'sını tanımlaclass UrunAnalizi(BaseModel):    duygu: str = Field(description="pozitif, negatif veya notr")    anahtar_ozellikler: list[str] = Field(description="bahsedilen özelliklerin listesi")    fiyat_bahsedildi: bool = Field(description="fiyatın tartışılıp tartışılmadığı")    guven_skoru: float = Field(description="0'dan 1'e güven skoru")
# Schema validation'lı parserparser = PydanticOutputParser(pydantic_object=UrunAnalizi)
# Prompt format talimatlarını içeriyorprompt = PromptTemplate(    template="Bu ürün yorumunu analiz et:\n{yorum}\n{format_instructions}",    input_variables=["yorum"],    partial_variables={"format_instructions": parser.get_format_instructions()})
chain = prompt | ChatOpenAI(model="gpt-4") | parser
# Type-safe outputresult: UrunAnalizi = chain.invoke({"yorum": yorum_metni})print(f"Duygu: {result.duygu}, Güven: {result.guven_skoru}")

Faydalar: Type safety, otomatik validation, LLM ile downstream kod arasında net contract'lar.

Migration Karar Matrisi

Doğru yaklaşımı seçmek senin spesifik gereksinimlerine bağlı:

LangChain Ne Zaman Kullanılmalı

  • Orchestration gerektiren karmaşık multi-agent sistemler
  • Birden fazla retriever ve re-ranking içeren RAG
  • Collaboration için standart abstraksiyonlara ihtiyaç duyan ekipler
  • Production hardening planlarıyla hızlı prototyping aşaması
  • LangSmith observability ekosisteminden ağır faydalanma

Örnek: LinkedIn'in SQL Bot'u production-grade multi-agent koordinasyonu için LangGraph node'larına sarılmış LangChain chain'leri kullanıyor.

LlamaIndex Ne Zaman Kullanılmalı

  • Search ve retrieval'a birincil odak
  • Büyük dataset indexleme gereksinimleri
  • Verimli semantic similarity search ihtiyacı
  • Genel orchestration'dan daha basit, odaklı use case

Direkt API'ler Ne Zaman Kullanılmalı

  • Basit chatbot veya completion taskları
  • Net, değişmeyen gereksinimler
  • Latency'nin önemli olduğu performance-critical uygulamalar
  • Full kontrol isteyen küçük ekip
  • Minimal external dependency isteniyor

Örnek implementation:

python
from openai import OpenAI
client = OpenAI()
# Net, explicit, hızlıresponse = client.chat.completions.create(    model="gpt-4",    messages=[        {"role": "system", "content": "Sen yardımsever bir asistansın."},        {"role": "user", "content": prompt}    ],    max_tokens=512,    temperature=0.7)
answer = response.choices[0].message.content

LangChain'den Ne Zaman Migrate Edilmeli

Migration'ı düşün:

  • Ekip framework davranışını debug etmeye feature geliştirmekten daha fazla zaman harcıyor
  • Performance profiling framework overhead'ini bottleneck olarak gösteriyor (>1s eklenen latency)
  • Gereksinimler LangChain'in pattern'larına uymuyor ve framework'le savaşıyorsun
  • Dependency yönetimi maintenance yükü haline geldi

Migration yaklaşımı: En yüksek etkili komponentlerden başlayarak incremental replacement. Çalışanı koru, çalışmayanı değiştir.

LangGraph: Production Evrimi

LangGraph 2024'te production odaklı bir evrim olarak ortaya çıktı, LangChain agentlarını deploy ederken öğrenilen derslerden tasarlandı:

Temel farklar:

  • Gizli davranışlar olmadan low-level, kontrol edilebilir framework
  • Gizli prompt'lar veya otomatik cognitive architecture yok
  • Karmaşık agentic sistemler için durable execution
  • Long-running workflow'larda state yönetimi

Hybrid pattern:

python
from langgraph.graph import StateGraph, ENDfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import ChatOpenAI
# State'i tanımlaclass AgentState(dict):    messages: list[str]    current_step: str
# LLM etkileşimleri için LangChain kullananalysis_chain = (    ChatPromptTemplate.from_template("Analiz et: {input}")    | ChatOpenAI(model="gpt-4"))
# Orchestration için LangGraph node'larına sarworkflow = StateGraph(AgentState)
def analyze_node(state: AgentState):    result = analysis_chain.invoke({"input": state["messages"][-1]})    state["messages"].append(result)    return state
workflow.add_node("analyze", analyze_node)workflow.add_edge("analyze", END)workflow.set_entry_point("analyze")
# İkisinin de en iyisi: LangChain composability + LangGraph kontrolapp = workflow.compile()

Ne zaman upgrade et: AgentExecutor'dan LangGraph'e geçiş, multi-agent koordinasyon ihtiyacı, long-running workflow'larda state yönetimi, production güvenilirlik gereksinimleri.

Production'da LangGraph kullanan şirketler: Uber, LinkedIn, Replit, Elastic.

Maliyet Optimizasyon Stratejileri

Token Yönetimi

Token kullanımını agresif şekilde takip et ve kontrol et:

python
from langchain.callbacks import get_openai_callback
# 1. Her şeyi takip et# Not: get_openai_callback yeni agent implementasyonlarıyla limitasyonları var# Tüm agent tiplerinde kapsamlı takip için LangSmith kullanwith get_openai_callback() as cb:    result = chain.invoke({"input": query})    print(f"Token'lar: {cb.total_tokens}, Maliyet: ${cb.total_cost:.4f}")
# 2. Context'i son N exchange'e trim etfrom langchain.memory import ConversationBufferWindowMemory
# Not: ConversationBufferWindowMemory deprecated# Yeni projeler için LangGraph persistence veya RunnableWithMessageHistory kullanmemory = ConversationBufferWindowMemory(    k=5,  # Sadece son 5 exchange'i tut    return_messages=True)
# 3. Eski context için smart summarizationfrom langchain.memory import ConversationSummaryBufferMemory
# Not: ConversationSummaryBufferMemory deprecated# Production uygulamalar için LangGraph persistence'a migrate etmemory = ConversationSummaryBufferMemory(    llm=llm,    max_token_limit=500,    return_messages=True)
# 4. Explicit output limitlerillm = ChatOpenAI(    model="gpt-4",    max_tokens=512  # Kısa response'lar)

Gerçek Maliyet Etkisi

Deployment case study sonuçları:

  • Custom memory implementation: %30 maliyet düşüşü
  • Redis caching: %40 maliyet düşüşü, %80 latency iyileşmesi
  • Model routing: %62 token maliyet düşüşü
  • Kombine yaklaşım: %50-70 toplam maliyet düşüşü

Monitoring ve Observability

Temel Production Metrikleri

python
import timefrom langchain.callbacks.base import BaseCallbackHandler
class ProductionMetrics(BaseCallbackHandler):    """Kapsamlı production monitoring"""
    def on_chain_start(self, serialized, inputs, **kwargs):        self.chain_start = time.time()
    def on_chain_end(self, outputs, **kwargs):        duration = time.time() - self.chain_start        metrics.gauge("chain.duration", duration)
    def on_llm_start(self, serialized, prompts, **kwargs):        self.llm_start = time.time()        metrics.increment("llm.requests")
    def on_llm_end(self, response, **kwargs):        # Performance metrikleri        latency = time.time() - self.llm_start        metrics.gauge("llm.latency", latency)
        # Maliyet metrikleri        usage = response.llm_output.get("token_usage", {})        total_tokens = usage.get("total_tokens", 0)        cost = calculate_cost(usage)
        metrics.gauge("llm.tokens", total_tokens)        metrics.gauge("llm.cost", cost)
    def on_llm_error(self, error, **kwargs):        metrics.increment("llm.errors")        logger.error(f"LLM hatası: {error}")
    def on_tool_start(self, serialized, input_str, **kwargs):        tool_name = serialized.get("name", "unknown")        metrics.increment(f"tool.{tool_name}.calls")
    def on_agent_action(self, action, **kwargs):        metrics.increment("agent.actions")

LangSmith Entegrasyonu

LangSmith kod değişikliği olmadan otomatik tracing sağlıyor:

python
import os
# Environment konfigürasyonuos.environ["LANGCHAIN_TRACING_V2"] = "true"os.environ["LANGCHAIN_API_KEY"] = "langsmith-api-anahtarin"os.environ["LANGCHAIN_PROJECT"] = "production-app"
# Optional: Filtreleme için metadata eklefrom langchain.callbacks.tracers import LangChainTracer
tracer = LangChainTracer(    project_name="production-app",    tags=["prod", "version-2.1"])
# Tüm chain execution'ları otomatik trace ediliyorresult = chain.invoke(    {"input": query},    config={"callbacks": [tracer]})

LangSmith neyi takip ediyor:

  • Her adım için timing'li execution trace'leri
  • Request başına token kullanımı ve maliyetler
  • Agent karar path'leri ve tool seçimleri
  • Hata oranları ve başarısızlık patternleri
  • Metadata tag'leriyle A/B test karşılaştırmaları

Migration Patternleri

LangChain'den Custom Code'a

Kademeli yaklaşım riski minimize ediyor:

python
# Hafta 1: En yüksek maliyetli bileşeni tespit et# Profil: Memory yönetimi 1.2s latency ekliyor
# Hafta 2: Custom replacement oluşturclass EfficientMemory:    def __init__(self, max_messages=10):        self.messages = []        self.max_messages = max_messages
    def add(self, message):        self.messages.append(message)        if len(self.messages) > self.max_messages:            self.messages = self.messages[-self.max_messages:]
    def get_context(self):        return "\n".join(self.messages)
# Hafta 3: A/B test implementasyonları# Grup A: LangChain memory (baseline)# Grup B: Custom memory (test)
# Hafta 4: Sonuçları ölç# Custom memory: -1.2s latency, -30% token, aynı kalite
# Hafta 5+: Kademeli rollout# 2 haftada 10% → 50% → 100%

Legacy Chain'lerden LCEL'e

LangChain migration tooling sunuyor:

bash
# Otomatik migration yardımılangchain migrate --legacy-to-lcel chain.py

Manuel migration örneği:

python
# Legacy: initialize_agent pattern (deprecated)from langchain.agents import initialize_agent, AgentType
agent = initialize_agent(    tools=tools,    llm=llm,    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
# Modern: Direkt LangGraph yaklaşımı (önerilen)from langgraph.prebuilt import create_react_agent
agent = create_react_agent(    model=llm,    tools=tools)

Faydalar: Daha iyi composability, built-in streaming, daha net debugging, agent davranışı üzerinde tam kontrol.

Yaygın Tuzaklar ve Dersler

Tuzak 1: Prototip-Production Tuzağı

Pattern: Default'larla prototip development'ta iyi çalışıyor. Production yüksek maliyetler, yavaş yanıtlar, sessiz hatalar ortaya çıkarıyor.

Ders: İlk günden production için tasarla. İlk production deployment'tan önce resource limitleri belirle, caching implementasyonu yap, observability ekle.

Tuzak 2: Framework Lock-In Körlüğü

Pattern: Hızlı prototyping için LangChain ile başla. Altı ay sonra derinlemesine kenetlenmiş mimari migration'ı aylarca iş haline getiriyor.

Ders: Framework kullanımını sınırlarda tut. Core business logic framework-agnostik olmalı. Bu gelecekteki değişiklikleri yönetilebilir kılar.

Tuzak 3: Observability Sonradan Düşünülmesi

Pattern: Tracing veya monitoring olmadan launch et. Production sorunlarını debug edemeyerek kullanıcı şikayetleriyle keşfet.

Ders: LangSmith veya eşdeğeri proje başından itibaren, sorunlar ortaya çıktıktan sonra değil.

Tuzak 4: Korkuluksuz Agent Özerkliği

Pattern: Agent'ı kontrolsüz "halleder" diye güven. Gerçek incident: 14 dakikalık execution loop, bütçe tüketildi.

Ders: Max iteration, timeout ve maliyet bütçeleri zorunlu, opsiyonel değil. Agentlar güçlü ama explicit kısıtlamalar gerektiriyor.

Key Takeaway'ler

LangChain bir tool, gereklilik değil. Framework overhead'inin senin spesifik use case'in için abstraksiyonları haklı çıkarıp çıkarmadığını değerlendir.

Prototip konfigürasyonları production'da çalışmaz. Default'lar development hızı için optimize edilmiş, production güvenilirliği veya maliyet verimliliği için değil.

Observability zorunlu. Production sorunlarını debug ederken sonradan değil, ilk günden LangSmith veya eşdeğeri.

Agent davranışını explicit kontrol et. Max iteration'lar, timeout'lar ve maliyet bütçeleri pahalı sürprizleri önlüyor.

Memory yönetimi maliyetleri doğrudan etkiliyor. Sınırsız memory sınırsız token kullanımına ve düşen performance'a yol açıyor.

Basit daha iyi olabilir. Direkt API çağrılarının daha net ve hızlı olduğu basit tasklar için framework abstraksiyonları kullanma.

Migration mümkün. Gereksinimler framework'ün pattern'larını aştığında ekipler başarıyla LangChain'den uzaklaşıyor.

Production agentlar için LangGraph. Prototiplerin ötesine geçerken, LangGraph production sistemlerinin ihtiyaç duyduğu kontrol ve dayanıklılığı sağlıyor.

Maliyet optimizasyonu sürekli. İterasyonlar halinde monitor et, profille et, optimize et. İlk deployment sadece başlangıç noktası.

Öğrenme için zaman ayır. Framework abstraksiyonları bazı taskları hızlandırıyor ama gizli davranışları anlamak ve debugging tekniklerinde yatırım gerektiriyor.

LangChain ile production'da çalışmak düşünülmüş mimari kararlar, dikkatli konfigürasyon ve sürekli monitoring gerektiriyor. Framework uygun kullanıldığında değerli abstraksiyonlar sağlıyor, ama başarı onun limitlerini anlamaya ve baştan itibaren bunların etrafında tasarım yapmaya bağlı. Anti-pattern'leri erken tespit etmek—özellikle memory accumulation ve callback overhead—maliyet ve latency sorunlarını önlemek için kritik. Bu rehberdeki pattern'ler gerçek production sistemlerinden uyarlanmış; senin context'inde küçük uyarlamalar gerekebilir ama temel ilkeler geçerli kalacaktır.

İlgili Yazılar