> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# LCEL Demo 6

> Demonstrates building LCEL pipelines combining prompts, models, parsers, and RunnableLambda functions to transform, inspect, and debug model outputs and visualize pipeline graphs.

This lesson demonstrates more advanced LCEL (LangChain Execution Layer) patterns: building a simple pipeline and extending it with custom runnable components to transform, inspect, and debug model outputs. You'll see how to compose prompts, models, parsers, and Python runnables using the pipe (`|`) operator to create expressive, debuggable pipelines.

## Initial chain

We start with a minimal chain that includes:

* A prompt asking for a one-line description of a topic
* A ChatOpenAI model
* A string output parser

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template("Give me a one-line description of {topic}")
model = ChatOpenAI()
output_parser = StrOutputParser()

chain = prompt | model | output_parser

chain.invoke({"topic": "AI"})
```

Example output:

```plaintext theme={null}
'AI is the simulation of human intelligence processes by machines, especially computer systems.'
```

## Adding a custom runnable to transform the output

Goal: convert the model output to title case by wrapping a simple Python function in `RunnableLambda` and appending it to the chain so it receives the parser output at runtime.

```python theme={null}
from langchain_core.runnables import RunnableLambda

def to_titlecase(text: str) -> str:
    return text.title()
```

Attach the runnable to the chain:

```python theme={null}
chain = prompt | model | output_parser | RunnableLambda(to_titlecase)
result = chain.invoke({"topic": "AI"})
print(result)
```

Observed behavior:

```plaintext theme={null}
'Ai Is The Simulation Of Human Intelligence Processes By Machines, Especially Computer Systems.'
```

Note: Python's `str.title()` transforms `"AI"` into `"Ai"`. That behavior is expected for title-casing with `str.title()`.

<Callout icon="lightbulb" color="#1CB2FE">
  When appending a Python function to an LCEL chain, pass the function reference (e.g., `RunnableLambda(to_titlecase)`), not a function call. LangChain invokes it at runtime as part of the pipeline.
</Callout>

## Adding a second runnable to inspect output length

Next, add a second runnable that logs the transformed text (for debugging) and returns its character length. This shows how to chain multiple custom runnables to both inspect and transform data.

```python theme={null}
from langchain_core.runnables import RunnableLambda

def get_len(text: str) -> int:
    print(text)   # debug printing
    return len(text)
```

Append both runnables to the chain:

```python theme={null}
chain = prompt | model | output_parser | RunnableLambda(to_titlecase) | RunnableLambda(get_len)

# Run the chain
length = chain.invoke({"topic": "AI"})
print(length)
```

Example console output (both printed text and returned length):

```plaintext theme={null}
Ai Is The Simulation Of Human Intelligence Processes By Machines, Especially Computer Systems.
94
```

## Putting it all together (concise example)

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda

def to_titlecase(text: str) -> str:
    return text.title()

def get_len(text: str) -> int:
    print(text)
    return len(text)

prompt = ChatPromptTemplate.from_template("Give me a one-line description of {topic}")
model = ChatOpenAI()
output_parser = StrOutputParser()

chain = prompt | model | output_parser | RunnableLambda(to_titlecase) | RunnableLambda(get_len)

# Invoke and observe both the transformed text (printed) and the returned length
length = chain.invoke({"topic": "AI"})
print("Length returned by pipeline:", length)
```

## Use cases and rationale

Runnable lambdas let you inject arbitrary Python logic into LCEL pipelines to enrich, transform, validate, persist, or debug model outputs. Common use cases include:

| Use Case                         | Why                                                               | Example                                                              |
| -------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------- |
| Transform text                   | Normalize formatting or map outputs into a desired representation | Convert model text to title case with `RunnableLambda(to_titlecase)` |
| Validate or enforce schema       | Ensure model outputs conform to expected formats                  | Parse and validate JSON or enforce allowed tokens                    |
| Enrich context with runtime data | Add live data to prompts or model inputs                          | Call an API for flight status before invoking the model              |
| Persist outputs                  | Save results for auditing or downstream processing                | Write model outputs to a database or file                            |
| Debugging and inspection         | Print or log intermediate values for diagnosis                    | Use a runnable that prints intermediate text and returns its length  |

## Inspecting the LCEL graph

For complex pipelines, visualizing the internal graph is helpful. Install a graph utility (e.g., `grandalf`) to extract and visualize the chain graph.

```python theme={null}
# pip install grandalf
graph = chain.get_graph()
print(graph)              # textual representation
graph.print_ascii()       # ASCII visualization of the pipeline
```

Sample outputs (truncated / representative):

```plaintext theme={null}
Graph(nodes={ ... }, edges=[ ... ])
```

ASCII example (what `print_ascii()` might show):

```plaintext theme={null}
PromptInput -> ChatPromptTemplate -> ChatOpenAI -> StrOutputParser -> RunnableLambda(to_titlecase) -> RunnableLambda(get_len)
```

## Notes about runtime representations

* LCEL may convert some components (including wrapped functions) into internal Pydantic models or other runtime representations to enable type checking, validation, and serialization.
* These runtime conversions are primarily for inspection and validation; they don't change how you write Python functions for `RunnableLambda`.
* Use the graph and runtime representations to debug inputs/outputs and to validate that components are wired as expected.

## Quick reference

| Step | Action                                                              |    |
| ---- | ------------------------------------------------------------------- | -- |
| 1    | Create a prompt using `ChatPromptTemplate.from_template(...)`       |    |
| 2    | Attach a model such as `ChatOpenAI()`                               |    |
| 3    | Add an output parser like `StrOutputParser()`                       |    |
| 4    | Wrap Python functions with `RunnableLambda` and append them with \` | \` |
| 5    | Invoke the pipeline with `chain.invoke({"topic": "..."})`           |    |

## Summary

* LCEL pipelines are highly composable: prompts, models, parsers, and Python runnables can be combined using the pipe (`|`) operator.
* `RunnableLambda` wraps Python functions so they can participate in LCEL chains.
* Chain multiple runnables to transform, inspect, and persist outputs (e.g., title-casing, measuring length, calling external APIs).
* Use graph visualization (via `get_graph()` and `print_ascii()`) for debugging and understanding complex pipelines.

## Links and References

* [LangChain Documentation](https://langchain.readthedocs.io/)
* [ChatOpenAI integration (example)](https://github.com/langchain-ai/langchain)
* [grandalf (graph visualization)](https://pypi.org/project/grandalf/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langchain/module/754457c5-1386-422b-98ad-3342dfc6aab3/lesson/bd770c51-e411-479e-89f1-5c6fd2762abd" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langchain/module/754457c5-1386-422b-98ad-3342dfc6aab3/lesson/d51c42c5-aefd-4edd-a892-ad0294da5d82" />
</CardGroup>
