5.4 Parallel & Branching Chains
AI-generated content may contain errors. Always verify against official sources.
5.4 Parallel & Branching Chains
Key Concepts: Fan-out/fan-in · Conditional routing · Aspect-based decomposition
Official Docs: LangChain RunnableParallel · LangChain Routing
Fan-Out / Fan-In with RunnableParallel
When independent sub-tasks can run simultaneously, use RunnableParallel to execute them concurrently and merge the results.
Input ─┬── Step A (sentiment) ─┐
├── Step B (entities) ─┤─→ Merge → Output
└── Step C (category) ─┘
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.runnables import RunnableParallel
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
sentiment_chain = (
ChatPromptTemplate.from_template("What is the sentiment of this review? One word: {review}")
| llm | StrOutputParser()
)
entity_chain = (
ChatPromptTemplate.from_template(
"Extract named entities from this review as JSON list: {review}"
)
| llm | JsonOutputParser()
)
category_chain = (
ChatPromptTemplate.from_template(
"Classify this review category (product/service/delivery): {review}"
)
| llm | StrOutputParser()
)
# Run all three in parallel — latency ≈ max(A, B, C), not A + B + C
analysis = RunnableParallel(
sentiment=sentiment_chain,
entities=entity_chain,
category=category_chain,
)
result = analysis.invoke({"review": "Absolutely love the new phone, but delivery took 2 weeks!"})
print(result)
# {"sentiment": "positive", "entities": ["phone"], "category": "product"}
Conditional Routing
Route the input to different chains based on a condition:
from langchain_core.runnables import RunnableLambda
code_chain = (
ChatPromptTemplate.from_template("Answer this coding question with a working Python example: {input}")
| llm | StrOutputParser()
)
general_chain = (
ChatPromptTemplate.from_template("Answer this general question concisely: {input}")
| llm | StrOutputParser()
)
def route(info: dict) -> str:
question = info["input"].lower()
if any(kw in question for kw in ["python", "code", "function", "error", "debug"]):
return "code"
return "general"
router = RunnableLambda(route)
full_chain = {
"input": lambda x: x["input"],
"route": router,
} | RunnableLambda(
lambda x: code_chain.invoke({"input": x["input"]})
if x["route"] == "code"
else general_chain.invoke({"input": x["input"]})
)
print(full_chain.invoke({"input": "How do I sort a list in Python?"}))
print(full_chain.invoke({"input": "What is the capital of Japan?"}))
Aspect-Based Decomposition Pattern
Analyse multiple independent aspects of the same input simultaneously:
aspects = ["grammar", "clarity", "tone", "factual accuracy"]
def make_aspect_chain(aspect: str):
return (
ChatPromptTemplate.from_template(
f"Rate the {{aspect}} of this text from 1-10 and explain in one sentence.\n\nText: {{text}}"
).partial(aspect=aspect)
| llm | StrOutputParser()
)
aspect_analysis = RunnableParallel(
**{aspect: make_aspect_chain(aspect) for aspect in aspects}
)
result = aspect_analysis.invoke({
"text": "The whether was grate today, lots of sun shine everywhere."
})
for aspect, feedback in result.items():
print(f"\n{aspect.upper()}:\n{feedback}")
Common Mistakes
- Using sequential chains for independent tasks — if Steps A, B, C don’t depend on each other, running them sequentially triples your latency. Use
RunnableParallel. - Not handling routing edge cases — always have a default/fallback route for inputs that don’t match any condition.
- Shared mutable state — parallel branches should be stateless functions. Avoid writing to shared variables from parallel branches.
Quick Quiz
Q1. What is the latency of 3 parallel chains (taking 2s, 3s, 4s respectively) vs the same chains run sequentially?
A1. Parallel: ~4s (max). Sequential: ~9s (sum). Parallel is 2.25× faster in this example.
Q2. What LangChain class runs multiple Runnables concurrently on the same input?
A2. RunnableParallel.
Q3. What is aspect-based decomposition?
A3. Analysing multiple independent dimensions of the same input simultaneously using parallel chains — each chain evaluates one aspect.
Student Exercise
Exercise 5.4 — Parallel essay analyser
Build a RunnableParallel chain that analyses a student essay along 4 dimensions simultaneously: (1) grammar score (1-10), (2) argument strength (1-10), (3) evidence quality (1-10), (4) suggested improvements (list of 3 bullets). Combine results into a final feedback JSON.