LCEL, Runnables & Chains: overview
- Source
- From the RAG & Agents Engineering course
- By
- Sourav Banerjee
- Last updated
- 8 Nov 2026
LCEL is how LangChain 1.x composes work: prompts, models, parsers and retrievers snap together with |, and the result runs with the same methods as each piece. Every RAG chain from T5.1 onwards is one of these pipes. The T4.2 notebooks build on four ideas: the one interface every component shares, the pipe that joins components into a sequence, the parallel and branching shapes a pipe can take, and map-reduce for documents longer than one prompt.
The running example is the Larkspur Cloud handbook used from T5.1 onwards: a support assistant that answers refund and outage questions, triages tickets, and summarises handbook sections. The lab summarises three handbook documents of 1,111, 1,833 and 2,746 characters.
In short
- A Runnable has one interface:
invokefor one input,batchfor a list,streamfor chunks, and an async twin of each. Prompts, models, parsers, retrievers and whole chains all have it. a | bis Python's__or__returning aRunnableSequence. A dict inside a pipe becomes aRunnableParallel, so{"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | parseris a complete RAG chain.RunnableParallelruns its branches on the same input at once: notebook 03a's description, pros and cons chains plus a merge chain make 4 model calls in 2 rounds.RunnableBranchruns the first branch whose condition is true.LLMChain,RetrievalQAandload_summarize_chainnow live inlangchain-classic, deprecated with removal set for 2.0.0. Each rewrites as a short pipe.- Map-reduce trades calls for a small prompt. In the lab the whole handbook at
chunk_size=400is 10 chunks: map-reduce makes 11 calls in 4 rounds atmax_concurrency=4, refine makes 10 calls in 10 rounds, and stuff makes 1 call that reads all 2,746 characters.
Mental model
- A customer asks “How long does a refund take?” The string is the chain’s only input.
- The dict runs both branches on the same string at once. The retriever finds handbook chunks and format_docs joins them into one string.
- The two results come back as one dict with the keys context and question.
- The prompt fills its two variables and returns a ChatPromptValue.
- The chat model reads the messages and returns an AIMessage.
- StrOutputParser takes the message text and returns a plain string.
- The caller gets the answer string. The whole pipe is one Runnable, called with invoke.
This is the RAG chain from notebook 04a, and every box in it is a Runnable. The dict fans the question out to two branches and hands one dict to the prompt; each later step takes the previous step's output as its only input. Because the whole pipe is also a Runnable, the chain you build here can sit inside a bigger pipe, a RunnableBranch or a LangGraph node without changes.
Interactive lab
Stuff, map-reduce or refine: open the file in a browser. Pick Whole handbook and slide the chunk size from 1200 down to 200: refine's rounds climb from 3 to 21 while map-reduce stays at 2 to 7. Then set max_concurrency to 1 and watch map-reduce take one round more than refine. Finally pick Refunds section to see the router send a short document to stuff.
How it connects
- Before: T4.1 covers the pieces this module pipes together: chat models, prompt templates and output parsers.
- Next: T4.3 and T4.4 move control flow into LangGraph, where a Runnable can be a node. T5.1 composes its baseline RAG chain as exactly this pipe (notebook 05a), and T5.3 explains the splitter the map step depends on. T7.3 turns
RunnableParallelinto the parallelisation workflow pattern, and T13.1 applies recursive summarisation to a whole corpus.
Key Takeaways
- Every component and every chain shares one interface, so test each step alone with
.invoke()before you pipe it. - Build data flow with dicts: a dict fans one input out, and
RunnablePassthrough.assign()adds a key while keeping the rest. - Write new chains as pipes. Treat
langchain_classicimports as a staging post for old code, never as a destination. - Choose a summarisation strategy by length and latency: stuff when it fits, map-reduce when it does not, refine only when order should matter.