Sahaj.blogs
13 Apr 2026 · StudyPhase 13 · LangChain

LangChain · Chains and LCEL

The LangChain Expression Language: composing Runnables with |, parallel branches, passthroughs, output parsers, and the invoke/batch/stream methods every chain inherits.

Everything in LangChain (prompts, models, parsers, retrievers) is a Runnable with the same methods: invoke, batch, stream. LCEL composes them:

  • a | b makes a RunnableSequence: the output of a becomes the input of b
  • a dict, or RunnableParallel, runs several branches on the same input
  • RunnablePassthrough passes the input through unchanged, handy for adding keys
  • RunnableLambda wraps any Python function
  • output parsers turn an AIMessage into a string, JSON and so on

I used a fake chat model so the output is fixed and the plumbing is easy to see. A real model drops in without changing the chain.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda
from langchain_core.language_models.fake_chat_models import FakeListChatModel

prompt = ChatPromptTemplate.from_template("Explain {topic} in one line.")
model = FakeListChatModel(responses=["Attention lets each token look at every other token.",
                                     "Dropout zeroes random activations during training."])
chain = prompt | model | StrOutputParser()
print(type(chain).__name__, "->", chain.invoke({"topic": "attention"}))
print("batch:", chain.batch([{"topic": "dropout"}]))

word_count = RunnableLambda(lambda s: len(s.split()))
both = RunnableParallel(text=chain, topic=RunnablePassthrough() | RunnableLambda(lambda d: d["topic"].upper()))
model.i = 0
out = both.invoke({"topic": "attention"})
print(out, "| words:", word_count.invoke(out["text"]))

json_model = FakeListChatModel(responses=['{"phase": 13, "name": "LangChain"}'])
print((json_model | JsonOutputParser()).invoke("give json"))
print("chain steps:", [type(s).__name__ for s in chain.steps])

Output:

RunnableSequence -> Attention lets each token look at every other token.
batch: ['Dropout zeroes random activations during training.']
{'text': 'Attention lets each token look at every other token.', 'topic': 'ATTENTION'} | words: 9
{'phase': 13, 'name': 'LangChain'}
chain steps: ['ChatPromptTemplate', 'FakeListChatModel', 'StrOutputParser']

#langchain#lcel

Sources

  1. LangChain reference: Runnable interface — LangChain
  2. LangChain reference: RunnableParallel — LangChain
  3. LangChain reference: StrOutputParser — LangChain