LangChain Complete Guide | LLM Apps, Chains, Agents, RAG
이 글의 핵심
LangChain is the go-to framework for building LLM applications. This guide covers everything from basic Chains to production-ready RAG pipelines and autonomous Agents.
What This Guide Covers
LangChain is the most popular framework for building LLM-powered applications. This guide walks through the core concepts — Chains, Agents, Memory, and RAG — with practical Python examples you can run today.
Real-world insight: Migrating from raw OpenAI API calls to LangChain reduced our boilerplate by 60% and made complex multi-step workflows dramatically easier to maintain.
Installation
pip install langchain langchain-openai langchain-community chromadb
Set your API key:
export OPENAI_API_KEY="sk-..."
1. Basic Chain
A Chain is the fundamental unit in LangChain — it connects a prompt template to an LLM.
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_messages([
("system", "You are a helpful assistant."),
("human", "{question}")
])
chain = prompt | llm | StrOutputParser()
response = chain.invoke({"question": "What is LangChain?"})
print(response)
The | operator is LangChain Expression Language (LCEL) — it composes components into a pipeline.
2. Memory
Memory lets your chain remember previous messages in a conversation.
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
with_history = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="question",
history_messages_key="history",
)
config = {"configurable": {"session_id": "user-123"}}
with_history.invoke({"question": "My name is Alice."}, config=config)
response = with_history.invoke({"question": "What's my name?"}, config=config)
print(response) # Alice
For production, replace InMemoryChatMessageHistory with a Redis or database-backed store.
3. RAG — Retrieval-Augmented Generation
RAG lets your LLM answer questions based on your own documents.
Step 1: Load and split documents
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = TextLoader("docs/my_document.txt")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
Step 2: Embed and store in a vector DB
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings, persist_directory="./chroma_db")
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
Step 3: Build the RAG chain
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
rag_prompt = ChatPromptTemplate.from_template("""
Answer the question based only on the following context:
{context}
Question: {question}
""")
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| rag_prompt
| llm
| StrOutputParser()
)
response = rag_chain.invoke("What does the document say about X?")
print(response)
4. Agents
Agents can decide which tools to call based on user input — they enable autonomous, multi-step reasoning.
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain.agents import create_tool_calling_agent, AgentExecutor
tools = [TavilySearchResults(max_results=3)]
agent_prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Use tools when needed."),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(llm, tools, agent_prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "What is the latest LangChain version?"})
print(result["output"])
5. Custom Tools
You can give agents access to any Python function.
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
# Call a real weather API here
return f"The weather in {city} is sunny, 22°C."
tools = [get_weather]
agent = create_tool_calling_agent(llm, tools, agent_prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "What's the weather in Seoul?"})
The docstring becomes the tool description that the LLM uses to decide when to call it — write it clearly.
6. Streaming
For responsive UIs, stream tokens as they arrive:
for chunk in chain.stream({"question": "Explain RAG in simple terms"}):
print(chunk, end="", flush=True)
Works with agents too:
for event in executor.stream({"input": "Search for LangChain news"}):
print(event)
Production Patterns
Structured output
from pydantic import BaseModel
class ProductInfo(BaseModel):
name: str
price: float
in_stock: bool
structured_llm = llm.with_structured_output(ProductInfo)
result = structured_llm.invoke("Extract product info: Widget Pro, $29.99, available")
print(result.name, result.price)
Parallel chains
from langchain_core.runnables import RunnableParallel
parallel = RunnableParallel(
summary=chain,
keywords=(prompt | llm | StrOutputParser()),
)
result = parallel.invoke({"question": "Describe LangChain"})
Error handling and retries
chain_with_retry = chain.with_retry(stop_after_attempt=3)
LangSmith Observability
LangSmith traces every chain and agent call — essential for debugging production issues.
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY="ls__..."
That’s all you need. Every invoke is automatically traced.
Key Takeaways
| Concept | Use when |
|---|---|
| Chain | Fixed sequence of steps |
| Memory | Conversational context needed |
| RAG | Answer from your own documents |
| Agent | Dynamic tool selection at runtime |
| Structured output | Need typed, validated responses |
LangChain’s LCEL makes it easy to compose these building blocks. Start with a simple chain, add memory for conversations, layer in RAG for document Q&A, and graduate to agents when you need autonomous decision-making.