HOW-TO · RAG

How to Compose Multiple Chains with Pipe Operator

intermediate15 minBy Fredoline Eruo
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

LangChain installed with LCEL support, Python 3.10+

What this does

LCEL's | operator lets you compose independent chains into pipelines, where the output of one chain feeds into the next. This enables modular, reusable workflow construction.

Steps

  • Create two independent chains. Each should accept and return structured dicts.
from langchain_ollama import ChatOllama
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough

llm = ChatOllama(model="llama3.2", temperature=0.7)

# Chain 1: Summarize input text
summarize_prompt = ChatPromptTemplate.from_template(
    "Summarize the following text in one sentence:\n\n{text}"
)
summarize_chain = summarize_prompt | llm | StrOutputParser()

# Chain 2: Extract keywords from summary
keywords_prompt = ChatPromptTemplate.from_template(
    "Extract 3 keywords from this summary:\n\n{summary}"
)
keywords_chain = keywords_prompt | llm | StrOutputParser()
  • Compose with RunnablePassthrough. Pass summary output as input to the next chain.
from langchain.schema.runnable import RunnableParallel

pipeline = (
    RunnablePassthrough.assign(summary=summarize_chain)
    | RunnablePassthrough.assign(keywords=keywords_chain)
)
  • Run the composed pipeline.
result = pipeline.invoke({"text": "LangChain is a framework for building LLM applications. It provides tools for prompt management, chains, and memory."})
print("Summary:", result["summary"])
print("Keywords:", result["keywords"])
  • Branch into parallel chains. Use RunnableParallel to fan out.
chain_a = summarize_prompt | llm | StrOutputParser()
chain_b = keywords_prompt | llm | StrOutputParser()

parallel = RunnableParallel(summary=chain_a, keywords=chain_b)
result = parallel.invoke({"text": "AI is transforming industries."})
  • Route results conditionally. Use RunnableBranch for if-else logic within the pipeline.
from langchain.schema.runnable import RunnableBranch

branch = RunnableBranch(
    (lambda x: len(x["text"]) > 100, summarize_chain),
    keywords_chain  # default
)

Verification

python -c "
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough
chain = RunnablePassthrough() | RunnableParallel(a=lambda x: x['x'] + 1, b=lambda x: x['x'] * 2)
r = chain.invoke({'x': 5})
print(r)
# Expected: {'a': 6, 'b': 10}
"

Common failures

  • Key propagation breaks. Intermediate chain returns a string but the next chain expects a dict with a specific key. Use RunnablePassthrough.assign() to wrap.
  • Type mismatch in branch conditions. RunnableBranch conditions must return a boolean. Ensure lambda predicates are correct.
  • Parallel chains share state unexpectedly. Each branch in RunnableParallel receives the full input dict — design branch prompts to extract only the keys they need.
  • Version mismatch - The installed package or runtime differs from the command shown; check the version first and rerun the smallest verification command.
  • Local environment drift - Another service, virtual environment, model, or path is being used; print the active binary path and configuration before changing the guide steps.

Related guides

  • How to Create Basic LangChain Chains with LCEL
  • How to Build Custom LLM Chain with Prompt Templates