Alright, let's put the theory of LangChain chains into practice. We've discussed how chains allow us to connect multiple calls to LLMs or other components in a defined sequence. This is fundamental for building applications that require more than a single interaction with a language model.
In this hands-on exercise, we will construct a SequentialChain
. This type of chain executes its constituent chains in order, passing the output of one chain as the input to the next. Our goal is to create a two-step workflow:
This requires two distinct LLM interactions, where the second interaction depends directly on the output of the first.
Before we begin, ensure you have your Python environment set up as described in Chapter 2, including:
pip install langchain langchain-openai
).# Basic imports and environment setup
import os
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain, SequentialChain
# Ensure your OPENAI_API_KEY environment variable is set
# For example: os.environ["OPENAI_API_KEY"] = "your_api_key_here"
# Or load from a .env file using python-dotenv
# Initialize the LLM
# We'll use a ChatOpenAI model
llm = ChatOpenAI(temperature=0.7, model_name="gpt-3.5-turbo")
Note: Remember to replace "your_api_key_here"
with your actual key if you are not using environment variables loaded previously. Adjust the model_name
if needed.
First, we need a chain that takes a technical topic and generates a suitable blog post title. This involves defining a prompt template and an LLMChain
.
# --- Chain 1: Generate Blog Post Title ---
# Prompt template for title generation
title_template_string = """
You are an expert technical writer. Given the following topic, create a catchy and informative blog post title.
Topic: {topic}
Blog Post Title:
"""
title_prompt_template = PromptTemplate(
input_variables=["topic"],
template=title_template_string
)
# Create the first LLMChain
# We explicitly name the output key 'blog_title'
title_chain = LLMChain(
llm=llm,
prompt=title_prompt_template,
output_key="blog_title" # This key holds the output of this chain
)
# Test this chain independently (optional)
# result_title = title_chain.invoke({"topic": "Vector Databases"})
# print(f"Generated Title: {result_title['blog_title']}")
Here, we create a PromptTemplate
expecting a topic
variable. We then instantiate LLMChain
with our LLM and this prompt. Critically, we specify output_key="blog_title"
. This assigns a name to the output of this chain, which is essential for passing it correctly to the next chain in the sequence.
Next, we create a chain that takes the blog post title (generated by the first chain) and crafts a short tweet announcing it.
# --- Chain 2: Generate Tweet ---
# Prompt template for tweet generation
tweet_template_string = """
You are a social media expert specializing in tech promotion.
Given the blog post title below, write a concise and engaging tweet (under 280 characters) announcing it.
Include relevant hashtags.
Blog Post Title: {blog_title}
Tweet:
"""
tweet_prompt_template = PromptTemplate(
input_variables=["blog_title"], # Input comes from the previous chain's output
template=tweet_template_string
)
# Create the second LLMChain
# The output key here will be the final output of the sequence
tweet_chain = LLMChain(
llm=llm,
prompt=tweet_prompt_template,
output_key="tweet" # This key holds the final output
)
# Test this chain independently (optional)
# Example title: "Unlocking Semantic Search: A Deep Dive into Vector Databases"
# result_tweet = tweet_chain.invoke({"blog_title": "Unlocking Semantic Search: A Deep Dive into Vector Databases"})
# print(f"Generated Tweet: {result_tweet['tweet']}")
This chain's PromptTemplate
expects an input variable named blog_title
, which perfectly matches the output_key
we defined for title_chain
. Its own output is named tweet
.
Now, we combine these two chains into a single workflow using SequentialChain
. This class handles the execution order and the passing of outputs to inputs between the constituent chains.
# --- Combine Chains into a SequentialChain ---
# Create the SequentialChain
# It takes the list of chains to run in order
# Input variables are those needed by the *first* chain
# Output variables are those produced by the *last* chain (or intermediate ones if needed)
overall_chain = SequentialChain(
chains=[title_chain, tweet_chain],
input_variables=["topic"], # Input required by the first chain (title_chain)
output_variables=["blog_title", "tweet"], # Outputs produced by the sequence
verbose=True # Set to True to see the execution steps
)
We provide the list of chains ([title_chain, tweet_chain]
) in the desired execution order.
input_variables=["topic"]
: Specifies the input(s) the entire sequential chain expects. This must match the input variable(s) of the first chain in the sequence (title_chain
).output_variables=["blog_title", "tweet"]
: Lists the output keys we want the SequentialChain
to return. This includes the final output (tweet
) and can optionally include intermediate outputs (blog_title
).verbose=True
: This is helpful for debugging as it prints information about each step being executed.Finally, we can run our overall_chain
by providing the initial input topic.
# --- Execute the Sequential Chain ---
# Define the input topic
input_topic = "The role of Embeddings in RAG systems"
# Run the chain
# Use .invoke() for execution
result = overall_chain.invoke({"topic": input_topic})
# Print the results
print("\n--- Results ---")
print(f"Input Topic: {input_topic}")
print(f"Generated Blog Title: {result['blog_title']}")
print(f"Generated Tweet: {result['tweet']}")
Running this code will trigger the following sequence:
input_topic
is passed to title_chain
.title_chain
interacts with the LLM using its prompt template and generates a title. This title is stored internally associated with the key blog_title
.SequentialChain
automatically passes the value associated with blog_title
as input to tweet_chain
.tweet_chain
interacts with the LLM using its prompt template and the provided title, generating a tweet. This tweet is stored internally associated with the key tweet
.SequentialChain
returns a dictionary containing the specified output_variables
: blog_title
and tweet
.Flow diagram of the two-step sequential chain implementation.
In this practice session, you successfully implemented a multi-step workflow using LangChain's SequentialChain
. You defined individual LLMChain
components, each responsible for a specific task, and linked them together so that the output of one step serves as the input for the next. You also learned the importance of naming input and output variables correctly (input_variables
, output_key
) to ensure smooth data flow between chains.
This pattern is incredibly useful for automating processes that involve sequential reasoning or generation steps, forming a core building block for more sophisticated LLM applications. You can extend this by adding more chains, incorporating different types of chains (like TransformChain
for data manipulation), or using the more flexible SequentialChain
which allows for more complex input/output handling if needed.
© 2025 ApX Machine Learning