list_altİçindekilerexpand_more
Python ile LLM projesi geliştirmeye başladığınızda önünüze çıkan ilk soru çoğu zaman şu: LangChain mi, LangGraph mi? İsimler çok benziyor, ikisi de aynı ekipten çıkıyor; belgeler arasında gidip gelirken hangisinin neyi yaptığı kolayca karışıyor.
Kısa yanıt: LangChain, LLM’leri zincirlemenize olanak tanır. LangGraph ise bu zincirleri döngüler, koşullar ve kalıcı durum içeren grafiklere dönüştürür. Projenizin ihtiyacına göre biri fazlasıyla yeterliyken öbürü olmadan ilerleyemeyebilirsiniz.

LangChain ve LangGraph: Hızlı Özet
LangChain, 2022 sonunda Harrison Chase tarafından başlatıldı. Hedef net bir problemdi: LLM çağrılarını, belge retrieval’ını ve araç çağrılarını tek bir API altında toplamak. LCEL (LangChain Expression Language) ile bugün prompt | model | parser zincirleri yazıyorsunuz. LangChain hakkında ayrıntılı bilgi için yazımıza bakabilirsiniz.
LangGraph ise 2024 başında aynı ekipten çıktı. Grafik teorisinden ilham alıyor: orkestrasyon akışlarını düğümler ve kenarlardan oluşan bir yapıya dönüştürüyor. LangGraph, LangChain üzerine inşa edilmiş; ikisini birlikte kullanıyorsunuz, ama yalnızca LangChain kullanan bir projede LangGraph zorunlu değil. LangGraph mimarisini inceleyen yazımız da mevcut.
Mimari Fark: Zincir mi, Grafik mi?
LangChain’in temel soyutlaması **zincir (chain)**dir. prompt | model | output_parser yazıp boru operatörü (|) ile adımları birbirine bağlıyorsunuz. Bu yaklaşım doğrusal: veri soldan girer, her adımdan geçer, sağdan çıkar.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("Şu soruyu yanıtla: {question}")
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"question": "Python'da liste kavraması nedir?"})
print(result)
Bu zincir A’dan Z’ye gider. Yeniden A’ya dönemez, bir adımı atlayamaz, bir şarta göre farklı kola ayrılamaz.
LangGraph’ın temel soyutlaması ise **durum grafiği (state graph)**dir. StateGraph nesnesine düğümler ekliyor, kenarlar tanımlıyorsunuz. Bir düğüm, koşula bağlı olarak END’e ya da başka bir düğüme geçiş yapabilir.
from langgraph.graph import StateGraph, END
from typing import TypedDict
class AgentState(TypedDict):
messages: list
tool_calls_made: int
def agent_node(state: AgentState):
# LLM çağrısı + karar
return {"tool_calls_made": state["tool_calls_made"] + 1}
def tool_node(state: AgentState):
# Araç çalıştırma
return state
def should_continue(state: AgentState):
if state["tool_calls_made"] >= 3:
return "end"
return "tool"
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tool", tool_node)
graph.set_entry_point("agent")
graph.add_conditional_edges(
"agent",
should_continue,
{"tool": "tool", "end": END}
)
graph.add_edge("tool", "agent")
app = graph.compile()
Bu grafik döngüseldir: agent → tool → agent → ... akışı bir koşul karşılanana kadar tekrarlayabilir. LangChain LCEL ile bu yapıyı elde etmek mümkün değil.
LangChain Ne Zaman Yeterlidir?
LangChain’in kapsadığı kullanım alanları geniş. Basit bir RAG pipeline kuruyorsanız — soruyu vektör deposundan çekip LLM’e gönderip sonuç alıyorsanız — LCEL bunu on satırda halleder. Döngüye ya da karar noktasına gerek yok.
Metni çevirmek, özetlemek ya da sınıflandırmak gibi tek adımlı işlerde de LCEL yeterli. Adımlar her zaman aynı sırayla çalışıyorsa ve karar noktası yoksa LangChain daha az şişirilmiş bir çözüm.
Projenin nereye gideceğini henüz bilmiyorsanız LangChain ile başlayın. LangGraph’ın yapısal kararlarını erkenden vermeye zorlamadan ilerleyebilirsiniz.
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
vectorstore = Chroma(embedding_function=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
template = """Aşağıdaki bağlamı kullanarak soruyu yanıtla:
Bağlam: {context}
Soru: {question}"""
prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI(model="gpt-4o-mini")
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
)
response = rag_chain.invoke("LangChain nedir?")
Prompt mühendisliği tekniklerini ve structured output kullanımını öğrendikten sonra LangChain kombinasyonları oldukça güçlü hale geliyor.
LangGraph Ne Zaman Gerekir?
LangGraph’ı zorunlu kılan senaryoların hepsi aynı yere çıkıyor: akış düz gitmiyor. AI agent bir araç kullandı, sonuç yeterli değil, tekrar deniyor. Kullanıcının sorusuna göre farklı kola dalmanız gerekiyor. Kullanıcının belirli bir adımda onay vermesi gerekiyor. Uzun süren bir işin yarıda kesilirse kaldığı yerden devam etmesini istiyorsunuz.
Bunların hepsi LCEL ile ifade edilemiyor. conditional_edges, merkezi State nesnesi ve interrupt mekanizması tam da bunlar için var. Bir de multi-agent sistemler: birden fazla uzman agentın koordineli çalışması gerekiyorsa LangGraph’ın düğüm mimarisi bunu doğal şekilde modelliyor. Daha geniş bir framework karşılaştırması için AI agent framework yazımıza bakabilirsiniz.
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
checkpointer = MemorySaver()
app = graph.compile(checkpointer=checkpointer)
# İlk çalıştırma
config = {"configurable": {"thread_id": "session-001"}}
result = app.invoke(initial_state, config=config)
# Aynı thread_id ile tekrar çağrıldığında kaldığı yerden devam eder
result2 = app.invoke(new_input, config=config)
Kod Üzerinden Karşılaştırma
Aynı senaryoyu — kullanıcı sorusunu analiz edip gerekirse web araması yapan ve yanıt üreten bir akış — her iki yaklaşımla görelim.
LangChain ile Araç Destekli Zincir
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.tools.ddg_search import DuckDuckGoSearchRun
tools = [DuckDuckGoSearchRun()]
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_messages([
("system", "Sen yardımcı bir asistandsın. Gerekirse araçları kullan."),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "Bugünkü EUR/TRY kuru nedir?"})
Bu yaklaşım tek seferlik araç çağrısı için çalışır. Ancak “kaç kez araç çağrıldı”, “araç başarısız olursa ne olur” ya da “kullanıcı onayı gerekiyor mu” gibi soruları yanıtlamak için ekstra kod gerekir.
LangGraph ile Durum Takipli Agent
from typing import Annotated
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode, tools_condition
from langchain_openai import ChatOpenAI
from langchain_community.tools.ddg_search import DuckDuckGoSearchRun
from langgraph.graph.message import add_messages
from typing import TypedDict
class State(TypedDict):
messages: Annotated[list, add_messages]
tools = [DuckDuckGoSearchRun()]
llm = ChatOpenAI(model="gpt-4o").bind_tools(tools)
def agent(state: State):
return {"messages": [llm.invoke(state["messages"])]}
tool_node = ToolNode(tools)
graph = StateGraph(State)
graph.add_node("agent", agent)
graph.add_node("tools", tool_node)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", tools_condition)
graph.add_edge("tools", "agent")
app = graph.compile()
result = app.invoke({
"messages": [("human", "Bugünkü EUR/TRY kuru nedir?")]
})
LangGraph versiyonu daha fazla satır içeriyor, ama karşılığında her döngüyü izleyebilir, checkpoint ekleyebilir, belirli bir noktada durup onay isteyebilirsiniz.
Özellik Karşılaştırması
Aşağıdaki tablo iki yaklaşımın temel özelliklerini karşılaştırıyor. Kaynak: LangChain resmi dokümantasyonu ve LangGraph resmi dokümantasyonu.
| Özellik | LangChain (LCEL) | LangGraph |
|---|---|---|
| Temel yapı | Doğrusal zincir | Döngüsel grafik |
| Durum yönetimi | Zincir boyunca geçici | Merkezi State nesnesi |
| Koşullu dallanma | Yok | conditional_edges ile tam destek |
| Döngü desteği | Yok | Tam destek |
| Checkpoint / sürdürme | Yok | MemorySaver, SqliteSaver |
| Human-in-the-loop | Yok | interrupt_before/after |
| Öğrenme eğrisi | Düşük–Orta | Orta–Yüksek |
| Production karmaşıklığı | Düşük | Orta |
| Multi-agent | Kısmi (AgentExecutor) | Tam (supervisor, network) |
| LangSmith entegrasyonu | Var | Var |
Karar Rehberi: Hangisini Seçmeli?
LangChain ile başlayın: tek seferlik veya sıralı LLM çağrısı yapıyorsanız, basit bir RAG sistemi kuruyorsanız, prototip hızını her şeyin önünde tutuyorsanız, ya da ekibinizde LangGraph’a alışma süresi yoksa.
LangGraph’a doğrudan geçin: agentınızın kendi sonuçlarını değerlendirip tekrar denemesi gerekiyorsa, akışınızda birden fazla karar noktası varsa, kullanıcı onayı ya da multi-agent koordinasyonu söz konusuysa.
Bazı projeler ikisini birden kullanır: LangChain LCEL ile basit retrieval ya da formatlama adımları, LangGraph ile karmaşık ajan akışı. Bu kombinasyon, akıl yürüten AI modellerinin gerektirdiği çok adımlı işlemlerde yaygın bir tercih.
Geçiş için pratik bir kontrol: AgentExecutor ile yazmak istediğiniz ama yazamadığınız bir koşul ya da döngü var mı? O noktada LangGraph’a geçin.
LangChain 0.3 ile birlikte AgentExecutor yerine LangGraph resmi olarak önerilen yaklaşım oldu. Yeni proje başlatıyorsanız doğrudan LangGraph’tan başlamak giderek daha makul; en azından karar noktası geldiğinde yeniden yazmak zorunda kalmıyorsunuz. vLLM gibi çıkarım motorları gibi, framework seçimi küçük görünür ama projenin her aşamasında etkisini hissettiriyor.



