Skip to content

Module 3.2: LangChain Expression Language (LCEL) & Composition ​

Curriculum Alignment: docs/plan/03_phase3_modular_chaining_lcel.md
Topic Scope: Declarative Pipe (|) Syntax, RunnableSequence, RunnableParallel Fan-Out/Fan-In
Level: Advanced AI Engineering / Architecture


1. What is LangChain Expression Language (LCEL)? ​

LangChain Expression Language (LCEL) is a declarative domain-specific language (DSL) designed to compose Runnable components into complex computational Directed Acyclic Graphs (DAGs) using the Unix pipe (|) operator.

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ THE LCEL PIPE OPERATOR: UNIX PHILOSOPHY FOR GENERATIVE AI             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ chain = prompt | model | output_parser                                 β”‚
β”‚                                                                        β”‚
β”‚ Data Flow:                                                             β”‚
β”‚ Input Dict ──> [ PromptTemplate ] ──> PromptValue                      β”‚
β”‚            ──> [ ChatModel      ] ──> AIMessage                        β”‚
β”‚            ──> [ StrOutputParser] ──> Clean Final String               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why Declarative Composition Matters ​

In classical software architecture, pipelines composed via manual imperative functions (out1 = f(x); out2 = g(out1)) obscure the execution topology from observability agents and require custom handling for streaming, batching, and async execution.

Under LCEL:

  • Implicit Protocol Preservation: Piping Runnables automatically inherits streaming, async, and batch capabilities across the entire composite chain.
  • First-Class Tracing: LangFuse and OpenTelemetry automatically detect the DAG structure, creating nested parent-child trace spans without manual instrumentation.
  • Deterministic Contract Handoff: The output schema of node N directly feeds into the input schema of node N+1.

2. Core Composition Primitives ​

1. RunnableSequence: Linear Sequential Execution ​

When you use A | B | C, LangChain automatically constructs a RunnableSequence. Execution is linear: the output of step A is piped directly as input to step B.

python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
parser = StrOutputParser()

prompt = ChatPromptTemplate.from_template("Translate the following architectural pattern to English: {pattern}")

# Linear sequence: Input Dict -> Prompt -> Model -> String
translation_chain = prompt | model | parser

2. RunnableParallel: Concurrent Fan-Out & Fan-In ​

In complex workflows, you often need to execute multiple independent operations concurrently (e.g. summarizing text while simultaneously extracting keywords and calculating sentiment).

RunnableParallel forks execution across multiple branches simultaneously (Fan-Out) and aggregates their outputs into a single unified dictionary (Fan-In):


3. Canonical Architecture: Composing Pipelines (AI Agents and Applications, Ch. 4, Sec. 4.7) ​

In Chapter 4 of the textbook, the author rebuilds an entire research engine by composing modular sub-chains in LCEL. Here is the production pattern showing how RunnableParallel feeds into a downstream RunnableSequence:

python
"""
Composite Multi-Branch Pipeline using LCEL
Demonstrates RunnableParallel fan-out feeding into a sequential synthesis node.
"""
from typing import Any
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
parser = StrOutputParser()

# Branch 1: Technical Risk Assessment
risk_prompt = ChatPromptTemplate.from_template(
    "Analyze the technical risks and single points of failure in this proposal: {proposal}"
)
risk_chain = risk_prompt | model | parser

# Branch 2: Cost & Infrastructure Estimation
cost_prompt = ChatPromptTemplate.from_template(
    "Estimate the cloud infrastructure and compute costs for this proposal: {proposal}"
)
cost_chain = cost_prompt | model | parser

# Parallel Fan-Out: Run risk analysis and cost estimation concurrently
analysis_stage = RunnableParallel({
    "risks": risk_chain,
    "costs": cost_chain,
    "original_proposal": RunnablePassthrough()  # Passes the raw input through unchanged
})

# Final Fan-In Synthesis Chain
synthesis_prompt = ChatPromptTemplate.from_messages([
    ("system", "You are the Principal Architect. Synthesize the findings into an executive decision."),
    ("human", """Proposal: {original_proposal}

Identified Risks:
{risks}

Estimated Costs:
{costs}

Provide the final Go/No-Go architecture review.""")
])

executive_review_chain = analysis_stage | synthesis_prompt | model | parser

Conceptual Mindmap: LCEL & Composition ​


4. Curated Reading & Canonical References ​

ResourceCanonical Reference & LinkSpecific Focus Areas
Primary Curriculum BookAI Agents and Applications (Google Drive)Part 2, Chapter 4, Section 4.7 (pp. 116–128): Reimplementing multi-step pipelines with LCEL (web_searches_chain, summarize_chain).
LangChain Core ReferenceLCEL Composition PrimitivesRunnableSequence, RunnableParallel, and RunnablePassthrough API contracts.
Architecture PatternUnix Philosophy in Modern SoftwareModular programs connected via standard streams and declarative pipelines.

5. Active Recall (Module 3.2 Flashcards) ​

LCEL CompositionClick or press Space to flip β†Ί

What is the difference between RunnableSequence and RunnableParallel?

LCEL Composition β€’ AnswerClick to flip back ↻

RunnableSequence executes components sequentially, passing the output of step N as input to step N+1. RunnableParallel executes multiple branches concurrently with identical input, aggregating their outputs into a single dictionary.

πŸ’‘ Architect Takeaway: Use RunnableParallel for independent analysis branches (fan-out) and RunnableSequence for step-by-step transformations.
LCEL MechanicsClick or press Space to flip β†Ί

What is the role of RunnablePassthrough() in an LCEL pipeline?

LCEL Mechanics β€’ AnswerClick to flip back ↻

RunnablePassthrough() forwards the incoming input dictionary or value unchanged, allowing earlier input parameters to survive through parallel branches into downstream synthesis nodes.

πŸ’‘ Architect Takeaway: Essential when a downstream prompt requires both the raw initial user query and the parallel branch outputs.

6. Hands-on Engineering Exercises ​

Exercise 3.2: Parallel Architecture Review Drill ​

  • Goal: Build a multi-branch review pipeline using RunnableParallel.
  • Task: Create a chain that takes a database migration proposal and evaluates:
    1. Schema Migration Safety (Branch A),
    2. Application Downtime SLA (Branch B),
    3. Rollback Feasibility (Branch C).
  • Verification: Verify that all 3 branches execute concurrently, merging into an aggregated executive evaluation.

Master AI Architecture Training Program