LangChain
LangChain provides composable primitives for LLM applications: models, retrievers, tools, and chains. LCEL pipe syntax connects steps into pipelines.
Recipe
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
llm = ChatOpenAI(model="gpt-4o-mini")
retriever = Chroma(embedding_function=OpenAIEmbeddings()).as_retriever()Working Example
"""langchain.py - RAG chain with LCEL."""
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_text_splitters import RecursiveCharacterTextSplitter
docs = ["pytest runs tests with fixtures.", "FastAPI uses Pydantic for validation."]
splits = RecursiveCharacterTextSplitter(chunk_size=200).split_text("\n".join(docs))
vectorstore = Chroma.from_texts(splits, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
prompt = ChatPromptTemplate.from_template(
"Answer from context only:\n{context}\n\nQuestion: {question}"
)
def format_docs(docs):
return "\n---\n".join(d.page_content for d in docs)
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| ChatOpenAI(model="gpt-4o-mini", temperature=0)
| StrOutputParser()
)
print(chain.invoke("How does pytest work?"))Gotchas
- LangChain version churn - imports change between versions. Fix: pin versions; use
langchain-coreprimitives. - Over-abstraction - simple RAG does not need 10 wrapper classes. Fix: raw OpenAI SDK for prototypes; LangChain when composition grows.
- Hidden token usage - wrappers obscure cost. Fix: enable verbose/callbacks to log usage.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| LangChain | Multi-step LLM pipelines | Single API call |
| LlamaIndex | Data-centric RAG | Simple chains |
| LangGraph | Stateful agents | Linear pipelines |
| Raw SDK | Full control, learning | Complex multi-step apps |
FAQs
LangChain vs LangGraph?
LangChain for linear chains; LangGraph for cycles, state, and agent loops.What is LCEL?
LangChain Expression Language - pipe `|` syntax to chain Runnables.How do I add memory?
RunnableWithMessageHistory or checkpointer in LangGraph.How do I debug chains?
langsmith.com tracing with LANGCHAIN_TRACING_V2=true.Custom retriever?
Subclass BaseRetriever; implement `_get_relevant_documents`.How do I stream?
chain.stream(input) yields tokens progressively.Tool calling in LangChain?
Bind tools to ChatModel; use ToolNode in LangGraph.Is LangChain required for RAG?
No - raw SDK + vector DB works fine for simple cases.How do I test chains?
Mock LLM with FakeListChatModel; assert retrieval separately.Package split?
langchain-core, langchain-openai, langchain-chroma are separate packages.How do I handle errors?
Runnable with fallback: chain.with_fallbacks([backup_chain]).Production deployment?
LangServe exposes chains as FastAPI endpoints.Related
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.