Skip to main content

📋 Table of Contents

💻 Workshop Practice Notebook

Master all the concepts from this guide with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook

Chapter 1: Introduction to LangChain

Large Language Models (LLMs) have transformed how we build software. However, building production-grade GenAI applications requires orchestration. This module introduces the fundamentals of LangChain, explains the problems it solves, and walks you through setting up a modern GenAI project.

1. Traditional vs. GenAI Applications

Building applications with Generative AI requires a paradigm shift from traditional software development:

2. Two Kinds of GenAI Applications

LLM-powered systems are generally categorized into two workflow architectures:
  1. Sequential Workflows (Deterministic): The execution path is hardcoded and predefined by the developer. The inputs and outputs flow sequentially from one step to another (e.g., Prompt -> LLM -> Parser -> Database).
  2. Agentic Workflows (Autonomous): The LLM operates as an autonomous agent inside a loop. Given a task, the model evaluates the current state and dynamically decides which actions to take or tools (such as web search, calculator, or DB query) to invoke at runtime.

3. The Challenges of Raw API Integrations

Directly writing code against raw LLM provider APIs (like OpenAI, Google, or Anthropic) introduces several challenges in real-world software engineering:
  • API Fragmentation: Every model provider has its own proprietary SDK, request payload structure, and response format. Switching providers means rewriting your entire code integration.
  • Complex Pipeline Orchestration: Real-world GenAI applications rarely rely on a single API call. They require linking prompts, vector search retrievers, output parsers, and custom tools in sequence.
  • State & Memory Management: LLMs are stateless by design. Developers must manually manage conversation history and context window limits.

How LangChain Solves This

LangChain acts as a unified abstraction layer over LLMs:
  1. Standardized Interfaces: Write code against generic classes (ChatModel, PromptTemplate, BaseOutputParser) and easily swap underlying models/providers with a single line of code.
  2. LangChain Expression Language (LCEL): A declarative composition system utilizing the pipe operator (|) to build and stream multi-step GenAI pipelines.
  3. Ecosystem Modularity: It splits components into light, specialized libraries (langchain-core, provider packages like langchain-groq, and langchain-community).

4. Direct APIs vs. LangChain

To understand why LangChain is needed, let’s compare direct API integrations for three popular providers (OpenAI, Gemini, Hugging Face) against LangChain’s unified syntax.

3.1 Direct Provider APIs (Fragmentation)

Every provider requires a unique SDK, setup protocol, and response extraction syntax:
OpenAI Direct API
Google Gemini Direct API
Hugging Face Inference API

3.2 LangChain’s Simplified & Unified Syntax

LangChain unifies all these disparate APIs behind a single interface. Switching between providers only requires changing model configuration variables:

5. Main LangChain Modules

LangChain divides its components into specialized modules for clean dependency management:
  • langchain-core: The foundational package defining interfaces for models (BaseChatModel), templates (BasePromptTemplate), and the LCEL chaining logic.
  • Provider Integration Packages: Specific packages (e.g. langchain-google-genai, langchain-groq) containing lightweight wrapper logic for provider-specific APIs.
  • langchain-community: Integrations maintained by the community for third-party vector databases, document loaders, and tools.

6. Setting Up a GenAI Project (Step-by-Step)

We will use uv, a fast, modern package and project manager for Python, to set up our application.

Step 6.1: Initialize the Project & Virtual Environment

Open your terminal and run the following commands:

Step 6.2: Add Dependencies

Add the core LangChain package, provider integration packages, and a library to read environment variables:

Step 6.3: Set Up Your Keys (.env)

Create a file named .env in the root of your project directory and add your API keys:

Step 6.4: Load Environment Variables in Python

To read the keys from your .env file and make them available to your application:
  1. Import load_dotenv from the dotenv library.
  2. Call load_dotenv() at the very start of your python script.
This loads your secret API keys into Python’s os.environ system dictionary. LangChain automatically looks for variables named GROQ_API_KEY and GOOGLE_API_KEY in os.environ, allowing you to initialize models without hardcoding credentials in your source code.

7. Initializing and Calling Models

Here is how to write python scripts to call either Groq or Google Gemini using LangChain.

7.1 Initializing with Groq

7.2 Initializing with Google Gemini

[!NOTE] When using init_chat_model, LangChain automatically detects the GROQ_API_KEY or GOOGLE_API_KEY from your environment variables.

8. Practice Exercises

Practice 1: Dual-Provider Setup & Comparison

Write a script that loads environment variables, prompts both Groq (llama-3.3-70b-versatile) and Google (gemini-2.5-flash) with the question "State the main goal of prompt engineering in 5 words.", and prints the response from each model.

💻 Practice Notebooks

Master all the concepts from this module with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook Back to Top

Chapter 2: Prompt Templates & Message Structures

When building LLM applications, managing prompts dynamically is essential. LangChain provides powerful abstractions like PromptTemplate and ChatPromptTemplate to build reusable prompts, manage conversation messages, and parse variables.

1. PromptTemplate (String-Based Prompts)

PromptTemplate is used to create simple, string-based prompts. It is ideal for non-conversational LLMs or basic text generation pipelines.

1.1 Code Examples

Example 1: Concept Explanation

Output:

Example 2: Automated Code Reviewer

Create a prompt template that takes language and code variables and instructs the model to review the code.
Output:

1.2 Exercises for PromptTemplate

Exercise 1: Recipe Generator

Define a PromptTemplate that takes an ingredients list (e.g., “tomato, cheese, basil”) and a cuisine type (e.g., “Italian”), and prompts the model to generate a recipe.

Exercise 2: Technical Definition Writer

Define a PromptTemplate that takes a term and an audience_level (e.g., “5-year-old” or “PhD student”) and generates a customized definition.

2. Message Types & Chat Structures

Chat models communicate using lists of structured messages rather than a single block of text. This helps maintain role-based boundaries and conversational context. LangChain provides three main message classes in langchain_core.messages:
  • SystemMessage: Sets the behavior, persona, rules, or constraints for the assistant. This message is usually sent first.
  • HumanMessage: Represents input sent by the user.
  • AIMessage: Represents responses generated by the model.

2.1 Why Message Objects are Important

Message objects allow API providers (like Google Gemini, OpenAI, or Anthropic) to handle conversations structure-selectively. They let the backend know exactly who said what, which prevents the LLM from confusing system guardrails with user input.

2.2 Invoking ChatModels with Message Objects

You can pass a list of message objects directly to a Chat Model to initiate or continue a multi-turn conversation.

3. ChatPromptTemplate (Message-Based Prompts)

ChatPromptTemplate structures conversation flows for Chat Models using lists of system, human, and AI instructions.

3.1 Code Examples

Example 1: Customer Service Ticket Auto-Classifier

Categorize customer support tickets into Hardware, Software, or Billing issues.

Example 2: Geography Expert (Few-Shot Chat)

Simulate flag color retrieval with few-shot examples embedded inside a chat dialogue.

3.2 Exercises for ChatPromptTemplate

Exercise 1: History Guide Roleplay

Create a ChatPromptTemplate simulating a historical dialogue.
  • System message: "You are \{historical_figure\}, a historical figure. Answer in their character."
  • Human: "What was your greatest achievement?"
  • AI: "My greatest achievement was \{achievement\}."
  • Human: "Why was \{achievement\} important?"
Invoke this template with historical_figure="Julius Caesar" and achievement="crossing the Rubicon". Print the generated list of messages.

Exercise 2: Code Translator

Create a ChatPromptTemplate representing a code translation engine.
  • System message: "You are an expert software engineer that translates source code from \{source_lang\} to \{target_lang\}."
  • Human: "Translate this code:\n\n\{code\}"
Invoke this template with source_lang="Python", target_lang="JavaScript", and code="print('Hello World')" and print the messages.

4. Variable Passing Mechanisms

When invoking templates or chains, you pass variables depending on the count of placeholders:
  • Single-Variable Shortcut: If the template has exactly one placeholder (e.g., \{variable\}), you can pass a raw string. LangChain maps it automatically.
  • Multi-Variable Dictionary: If the template has multiple placeholders, you must pass a dictionary of key-value pairs.

5. Extracting Responses: .content vs .text vs Direct Output

Depending on the component you invoke, the returned value has different structures. It is crucial to know how to extract the raw text response:

5.1 Use .content (For ChatModels)

When you invoke a Chat Model (e.g., initialized using init_chat_model for Groq or Gemini), the return value is an AIMessage object. To access the generated text, you must use .content.

5.2 Use .text (For Few-Shot / Legacy formatting and outputs)

When formatting older or specific templates (like FewShotPromptTemplate), the formatted result is a PromptValue object. In these cases, you access the raw string representation using .text. Additionally, some legacy LLM completion model classes (as opposed to modern ChatModel classes) or generation results return response structures where the generated text output itself is accessed via .text.

5.3 Direct Output

If you are invoking a local pipeline (e.g., HuggingFacePipeline) or a chain containing a StrOutputParser, the return value is already a plain Python string (str), so you can print or use it directly.

💻 Practice Notebooks

Master all the concepts from this page with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook Back to Top

Chapter 3: LCEL & Runnables

LangChain Expression Language (LCEL) is a declarative way to build LLM applications, allowing you to compose components using the pipe operator (|).

1. What is LCEL & Why Use It?

Instead of writing imperative code to link prompts, models, and parsers, you connect them together like a Unix pipeline:

Why Use LCEL?

  • Simple: Chain complex components in just a few lines of code.
  • Readable: Easy to inspect the flow of inputs and outputs.
  • Composable: Swap prompts, LLMs, retrievers, or parsers effortlessly.
  • Built-in Support: Handles streaming and parallel operations out of the box.

2. LCEL Code Examples

Example 1: Basic QA Chain

A simple chain that takes a topic, formats a prompt, invokes the model, and extracts the response content.

Example 2: Subject Line Generator

Generate a professional email subject line using dynamic topic and tone variables.

3. Exercises for LCEL

Exercise 1: Marketing Pitch Generator

Create a chain that takes a product name and a target audience and generates a catchy marketing slogan. Instructions:
  1. Import PromptTemplate and init_chat_model.
  2. Define a string prompt template containing two variables: {product_name} and {target_audience}.
  3. Initialize the Groq model llama-3.3-70b-versatile.
  4. Compose an LCEL chain linking the prompt template and the chat model.
  5. Invoke the chain passing a dictionary with values for "product_name" (e.g., "EcoWater Bottle") and "target_audience" (e.g., "fitness enthusiasts").
  6. Print the model’s text response using .content.

Exercise 2: Tech Tag Extractor

Create a chain that takes an article excerpt and lists the top 3 technology keywords mentioned. Instructions:
  1. Import PromptTemplate and init_chat_model.
  2. Define a string prompt template containing a variable {text} that asks the model to list the top 3 technology keywords mentioned in the text.
  3. Initialize the Groq model llama-3.3-70b-versatile.
  4. Compose an LCEL chain linking the prompt template and the chat model.
  5. Invoke the chain passing a dictionary containing a sample text paragraph.
  6. Print the model’s text response using .content.

4. Invoking vs. Streaming

4.1 invoke()

Waits for the entire model execution to complete and returns the full response at once.

4.2 stream()

Yields the response progressively, token-by-token. This is crucial for interactive chat interfaces to improve perceived user latency.

Invocation Input Cheat Sheet

5. LangChain Runnables

A Runnable is the fundamental building block in LangChain. Any component that implements invoke(), batch(), or stream() is a Runnable.

5.1 RunnableSequence

Chains multiple runnables sequentially so the output of one component becomes the input of the next. The pipe operator (|) automatically creates a RunnableSequence.

5.2 RunnablePassthrough

Forwards the input value as-is. This is useful for passing unchanged variables down a chain or creating multi-keyed inputs.
Output:

5.3 RunnableParallel

Executes multiple runnables concurrently on the same input, returning their outputs as a unified dictionary.
Output:

6. Practice Exercises

Practice 1: Basic LCEL Translation Pipeline

Create a simple LCEL chain combining a prompt template ("Translate the word '{word}' into German.") and a chat model. Invoke it with the word "apple" and print the response content.

💻 Practice Notebooks

Master all the concepts from this page with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook Back to Top

Chapter 4: Output Parsers

Large Language Models output plain text. However, applications often require structured data to feed into APIs, databases, or frontend components. Output Parsers bridge this gap.

1. Introduction to Output Parsers

LangChain provides several output parsers to structure model outputs:

2. Using Output Parsers

2.1 StrOutputParser

Converts the output of a chat model (AIMessage) into a clean, raw string.

2.2 JsonOutputParser

Parses JSON-formatted strings generated by LLMs into a native Python dictionary.

2.3 PydanticOutputParser

Validates the output against a Pydantic model definition. This ensures type safety and field presence.

2.4 CommaSeparatedListOutputParser

Splits comma-separated lists generated by the model into a Python list of strings.

3. Practice Exercises

Practice 1: Comma Separated List Parsing

Create a prompt template that requests the model to list the top 3 programming languages for web development, and chain it with the CommaSeparatedListOutputParser to obtain a Python list.

💻 Practice Notebooks

Master all the concepts from this page with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook Back to Top

Chapter 5: Model Hyperparameters

When invoking Large Language Models, various hyperparameters control how the model selects the next token. Tuning these parameters is vital for tailoring responses to fit specific use cases (e.g., deterministic code generation vs. creative brainstorming).

1. Key Hyperparameters

1.1 Temperature

Controls the randomness of predictions.
  • Low Temperature (closer to 0): The model behaves deterministically, favoring the highest-probability tokens.
  • High Temperature (closer to 1 or higher): The model flattens token probability distributions, allowing less common words to be chosen, creating creative or diverse responses.

Example Scenario:

Given the following vocabulary probabilities:
  • cat: 0.70
  • dog: 0.20
  • tiger: 0.08
  • elephant: 0.02
  • Temperature = 0: Always outputs cat (deterministic).
  • Temperature = 0.2: Mostly outputs cat, occasionally dog.
  • Temperature = 1.0: Uses original probabilities as-is.
  • Temperature = 2.0: The probabilities flatten out, making even elephant highly possible.

Typical Values

1.2 Max Tokens

Sets the maximum limit on the number of tokens the model is allowed to generate in a single request. This prevents excessive cost and runtime.

1.3 Top-K Sampling

Limits token selection to the K most likely tokens. Unlikely tokens outside the top K are discarded entirely, preventing the model from generating random gibberish.
  • Top-K = 2: If the top tokens are cat (0.40), dog (0.30), and tiger (0.15), only cat and dog are kept. The rest are ignored.

1.4 Top-P (Nucleus Sampling)

Instead of keeping a static count like Top-K, Top-P selects enough tokens to reach a cumulative probability threshold P.
  • Top-P = 0.8: If cat (0.40), dog (0.30), and tiger (0.15) sum to 0.85, the model stops adding tokens and samples only from these three.
  • Top-P = 0.95: Includes a wider pool of less-likely tokens.

2. Summary Table

3. Practice Exercises

Practice 1: Configuring Parameters in LangChain

Configure a chat model using init_chat_model with a temperature of 0.0 and a max token limit of 100 to answer the question: "State the value of Pi to 10 decimal places."

💻 Practice Notebooks

Master all the concepts from this page with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook Back to Top

Chapter 6: Few-Shot & Sequential Prompting

This section covers advanced prompting patterns: guiding model output format using examples (Few-Shot Prompting) and linking prompts in sequence where the output of one step informs the next (Sequential Prompting).

1. Few-Shot Prompting

“Shots” refer to the examples provided to the model inside the prompt to show it how to perform a task.
  • Zero-Shot Prompting: No examples are provided. The model relies entirely on pre-trained instructions.
  • One-Shot Prompting: One example is provided to illustrate the target structure.
  • Few-Shot Prompting: Multiple examples are provided. This is highly recommended for complex logic, custom styles, or structural outputs.

1.1 Why Few-Shot Prompting is Required & Its Advantages

While modern LLMs are capable of zero-shot completions, they often struggle when:
  • Complex Formatting: You need the model to return data in a highly specific structure or syntax (e.g., custom JSON format, exact punctuation, or nested schemas) that is hard to explain in instructions alone.
  • Domain Specificity: The task requires adhering to a specific company tone, shorthand notation, or industry-specific classification schemas.
  • Edge-Case Safety: You want to train the model’s behavior on complex logic boundaries (e.g., math problems or entity relationships) by showing correct resolutions.

Key Advantages:

  1. Structural Consistency: Forces the model to align with the visual and structural formatting of your examples.
  2. Improved Accuracy: Demonstrating tasks reduces reasoning errors and context hallucination.
  3. No Fine-Tuning Required: Achieve custom model behaviors inside the context window at runtime, avoiding the cost of fine-tuning the model weights.

1.2 Few-Shot Code Examples

Example 1: Math Assistant

Create a few-shot prompt to demonstrate basic math calculations and then execute the prompt using a chat model.
Output:

Example 2: Sentiment Classifier

Demonstrate sentiment analysis classification (Positive/Negative) using few-shot templates.
Output:

1.3 Few-Shot Practice Exercise

Exercise: Few-Shot Entity Extraction

Create a few-shot prompt using FewShotPromptTemplate that formats examples for extracting a person and their company from text. Instructions:
  1. Import PromptTemplate and FewShotPromptTemplate.
  2. Define a list containing two example dictionaries matching variables text and output.
    • Example 1: "John works at Google." -> {"person": "John", "company": "Google"}
    • Example 2: "Alice joined Microsoft." -> {"person": "Alice", "company": "Microsoft"}
  3. Configure the example_prompt template formatting.
  4. Assemble the FewShotPromptTemplate specifying a suffix to query for "Bob works at Amazon.".
  5. Invoke a chat model using this formatted template and print the result.

2. Sequential Prompting

Sequential prompting chains multiple prompts together so the output of one LLM call is automatically passed as an input variable into the next.

2.1 Sequential Chains using LCEL

You can construct sequential chains cleanly using LangChain Expression Language:

2.2 Sequential Practice Exercise

Exercise: Sequential Learning Planner

Write a sequential chain that takes a goal activity (e.g., "learn to swim"), asks the LLM to write a comprehensive learning guide, and then passes that guide to a second prompt that formats it as a 1-week crash course schedule. Instructions:
  1. Import PromptTemplate, StrOutputParser, and init_chat_model.
  2. Define learning_prompt using PromptTemplate to suggest a step-by-step plan for learning {activity}.
  3. Define time_prompt using PromptTemplate to create a concise 1-week schedule for a {learning_plan}.
  4. Compose the sequential chain using LCEL, mapping the first sub-chain output to the variable "learning_plan".
  5. Call .invoke() passing "learn to swim" and print the response.

💻 Practice Notebooks

Master all the concepts from this page with hands-on practice:
  • Practice in VS Code: Open the notebook in your local editor. Requires a local .env file containing your API keys.
  • Practice in Google Colab: Open the notebook directly in Colab. Setup cells are included to install packages and request API keys.
💻 VS Code | 🚀 Colab | 📥 Download Notebook