Everything going on in AI - updated daily from 500+ sources
LangChain Series #4: Chains Explained — Building AI Workflows with LCEL
This is the fourth article in my LangChain learning series. In the previous article, we explored prompts and learned how to communicate effectively with language models. Now it’s time to connect those components into complete AI workflows. In this article, we’ll explore Chains in LangChain and learn how to build Simple, Sequential, Parallel, and Conditional Chains using the LangChain Expression Language (LCEL). Through practical Python examples, you’ll understand how these chain patterns simplify the development of scalable, maintainable AI applications. 1. Introduction In the previous article, we learned how to create prompts using PromptTemplate, ChatPromptTemplate, and Output Parsers. But a real AI application doesn’t stop after sending a single prompt to an LLM. Most applications involve multiple steps: Generate content Summarize it Translate it Extract structured data Route it based on the result This is exactly what Chains helps us accomplish. A Chain connects multiple LangChain components into a single executable workflow. What is a Chain? A Chain is a sequence of connected components where the output of one component becomes the input of the next. Instead of manually calling every component, LangChain lets us connect them using the LangChain Expression Language (LCEL) . Simple Visulaization Why Use Chains? Without chains: prompt.invoke() model.invoke() parser.invoke() We manually call every component. With chains: chain = prompt | model | parser One line executes the entire workflow. Benefits: Cleaner code Better readability Easy debugging Reusable pipelines Seamless LangChain integration LangChain Expression Language (LCEL) LCEL introduces the | operator. Instead of writing nested function calls, we compose pipelines. chain = prompt | model | parser Each component automatically passes its output to the next component. This makes AI workflows easier to build and maintain. Simple Chain A Simple Chain is the most basic LangChain workflow. It connects a prompt, an LLM, and an output parser into a single pipeline. The output of one component automatically becomes the input of the next. from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint from dotenv import load_dotenv from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser # Load environment variables load_dotenv() # Prompt template prompt = PromptTemplate( template="Generate 5 interesting facts about {topic}", input_variables=["topic"] ) # Load Hugging Face model llm = HuggingFaceEndpoint( repo_id="Qwen/Qwen2.5-7B-Instruct", task="text-generation" ) model = ChatHuggingFace(llm=llm) # Convert AIMessage -> String parser = StrOutputParser() # Build the chain chain = prompt | model | parser # Execute result = chain.invoke({ "topic": "cricket" }) print(result) # Visualize chain chain.get_graph().print_ascii() WorkFlow_SimpleChain Sequential Chain A Sequential Chain is a workflow where the output of one chain becomes the input of the next chain . Unlike a Simple Chain, which performs only one task, a Sequential Chain breaks a complex problem into multiple steps, with each step depending on the previous one. For example, instead of asking an LLM to generate a report and summarize it in a single prompt, we can split the task into two stages: Generate a detailed report. Summarize the generated report. This approach makes the workflow more modular, reusable, and easier to maintain. from dotenv import load_dotenv from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser load_dotenv() # --------------------------------------- # Load Hugging Face Model # --------------------------------------- llm = HuggingFaceEndpoint( repo_id="meta-llama/Llama-3.1-8B-Instruct", task="text-generation" ) model = ChatHuggingFace(llm=llm) # --------------------------------------- # Output Parser # --------------------------------------- parser = StrOutputParser() # --------------------------------------- # Prompt 1 # Generate a Detailed Report # --------------------------------------- report_prompt = PromptTemplate( template=""" Write a detailed report about {topic}. Include: - Introduction - Working Principle - Advantages - Applications - Conclusion """, input_variables=["topic"] ) # --------------------------------------- # Prompt 2 # Summarize the Report # --------------------------------------- summary_prompt = PromptTemplate( template=""" Summarize the following report in 5 concise bullet points. Report: {report} """, input_variables=["report"] ) # --------------------------------------- # Sequential Chain # --------------------------------------- chain = ( report_prompt | model | parser | {"report": lambda x: x} | summary_prompt | model | parser ) # --------------------------------------- # Execute Chain # --------------------------------------- result = chain.invoke({ "topic": "Retrieval-Augmented Generation (RAG)" }) print(result) WorkFlow_SequentialChain Parallel Chain A Parallel Chain is a workflow where multiple chains execute simultaneously on the same input , instead of running one after another. Unlike a Sequential Chain, where each step waits for the previous one to finish, a Parallel Chain performs independent tasks at the same time. This reduces execution time and allows you to generate multiple outputs from the same input. When Should You Use a Parallel Chain? Use a Parallel Chain when multiple tasks: Use the same input Are independent of each other Can execute simultaneously Examples Generate Notes and Quiz from a document Translate text into multiple languages Extract keywords and summarize simultaneously Generate a blog title and social media caption together from dotenv import load_dotenv from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnableParallel load_dotenv() # ------------------------------- # Load Hugging Face Model # ------------------------------- llm = HuggingFaceEndpoint( repo_id="Qwen/Qwen2.5-7B-Instruct", task="text-generation" ) model = ChatHuggingFace(llm=llm) parser = StrOutputParser() # ------------------------------- # Prompt 1: Generate Notes # ------------------------------- notes_prompt = PromptTemplate( template=""" Generate concise study notes about the following topic. Topic: {topic} """, input_variables=["topic"] ) # ------------------------------- # Prompt 2: Generate Quiz # ------------------------------- quiz_prompt = PromptTemplate( template=""" Generate five multiple-choice questions about the following topic. Topic: {topic} """, input_variables=["topic"] ) # ------------------------------- # Create Parallel Chain # ------------------------------- parallel_chain = RunnableParallel({ "Notes": notes_prompt | model | parser, "Quiz": quiz_prompt | model | parser }) # ------------------------------- # Execute # ------------------------------- result = parallel_chain.invoke({ "topic": "LangChain" }) print("========== NOTES ==========\n") print(result["Notes"]) print("\n========== QUIZ ==========\n") print(result["Quiz"]) WorkFlow_ParallelChain Conditional Chain A Conditional Chain is a workflow where the next chain is chosen based on a condition or decision . Unlike a Sequential Chain, which always follows the same execution path, a Conditional Chain dynamically decides which branch to execute depending on the output of a previous step. For example, imagine you’re building a customer support system. When a customer submits feedback, the application first analyzes the sentiment. If the sentiment is positive , it sends a thank-you response. If it’s negative , it forwards the complaint to customer support. Instead of executing every chain, LangChain runs only the branch whose condition is satisfied . When Should You Use a Conditional Chain? Use a Conditional Chain whenever your application needs to make decisions before choosing the next action. Examples include: Customer support routing Email classification Sentiment analysis Fraud detection Content moderation AI decision-making systems from dotenv import load_dotenv from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnableBranch load_dotenv() # ------------------------------------ # Load Model # ------------------------------------ llm = HuggingFaceEndpoint( repo_id="Qwen/Qwen2.5-7B-Instruct", task="text-generation" ) model = ChatHuggingFace(llm=llm) parser = StrOutputParser() # ------------------------------------ # Prompt for Positive Feedback # ------------------------------------ positive_prompt = PromptTemplate( template=""" Write a polite thank-you email for the following positive customer feedback. Feedback: {feedback} """, input_variables=["feedback"] ) # ------------------------------------ # Prompt for Negative Feedback # ------------------------------------ negative_prompt = PromptTemplate( template=""" Write an apology email and inform the customer that the issue has been forwarded to customer support. Feedback: {feedback} """, input_variables=["feedback"] ) # ------------------------------------ # Create Conditional Chain # ------------------------------------ chain = RunnableBranch( ( lambda x: "good" in x["feedback"].lower() or "excellent" in x["feedback"].lower() or "amazing" in x["feedback"].lower(), positive_prompt | model | parser ), negative_prompt | model | parser ) # ------------------------------------ # Execute # ------------------------------------ result = chain.invoke({ "feedback": "The service was excellent and your support team was amazing." }) print(result) WorkFlow_ConditionalChain Conclusion Chains are the backbone of LangChain applications. Instead of manually managing prompts, models, and parsers, LCEL allows us to connect components into reusable AI workflows using a simple pipeline syntax. By understanding Simple , Sequential , Parallel , and Conditional Chains, you can build applications ranging from basic chatbots to sophisticated AI systems with multiple decision paths. In the next article, we’ll explore Runnables in LangChain and learn how the Runnable interface powers LCEL through composition, parallel execution, branching, and reusable AI workflows. Code Repository: https://github.com/Atul245/LangChain-for-developers If you found this article helpful, consider: ⭐ Starring the repository 🍴 Forking the repository 👤 Following me for more content on LangChain, Generative AI, and AI Engineering Connect with me on LinkedIn: https://www.linkedin.com/in/atulkumar8/ 🚀 LangChain Series #4: Chains Explained — Building AI Workflows with LCEL was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.
Read Original Article →