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

# Introduction to LangChain

> Why LangChain, project setup with uv, and connecting to model providers

## 💻 Practice Notebook

Master the concepts from this page with hands-on practice:
[💻 VS Code](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/prompt-engg/prompt-engg-practice-vscode.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/prompt-engg/prompt-engg-practice-colab.ipynb) | <a href="/public/notebooks/prompt-engg/prompt-engg-practice-vscode.ipynb" download>📥 Download Notebook</a>

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:

| Aspect           | Traditional Software                                                    | GenAI Applications                                                                                  |
| ---------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Logic**        | Deterministic and rule-based (defined by code loops, `if-else` blocks). | Probabilistic (guided by LLM semantic reasoning and prompts).                                       |
| **Input/Output** | Structured data (JSON, databases, arguments).                           | Unstructured natural language (text, speech, images).                                               |
| **Execution**    | Consistent and predictable; same inputs yield exact same outputs.       | Dynamic; outputs can vary (non-deterministic) depending on context, temperature, and model updates. |

### 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

```python theme={null}
from openai import OpenAI
client = OpenAI(api_key="your_openai_key")

res = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What is Python?"}]
)
## Accessing content requires deep nesting:
print(res.choices[0].message.content)
```

##### Google Gemini Direct API

```python theme={null}
import google.generativeai as genai
genai.configure(api_key="your_gemini_key")
model = genai.GenerativeModel("gemini-2.5-flash")

res = model.generate_content("What is Python?")
## Accessing content uses .text:
print(res.text)
```

##### Hugging Face Inference API

```python theme={null}
import requests
API_URL = "https://api-inference.huggingface.co/models/gpt2"
headers = {"Authorization": "Bearer your_hf_token"}

res = requests.post(API_URL, headers=headers, json={"inputs": "What is Python?"})
## Accessing content requires list/dictionary parsing:
print(res.json()[0]['generated_text'])
```

#### 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:

```python theme={null}
from langchain.chat_models import init_chat_model

## Standardized Initialization:
llm = init_chat_model("gemini-2.5-flash", model_provider="google_genai")
## To switch to OpenAI: llm = init_chat_model("gpt-4o", model_provider="openai")
## To switch to Groq: llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")

## Standardized Invocation & Response Extraction (.content)
response = llm.invoke("What is Python?")
print(response.content)
```

### 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:

```bash theme={null}
## Initialize a new project directory
uv init genai-app
cd genai-app

## Create and activate a virtual environment
uv venv
source .venv/bin/activate
```

#### Step 6.2: Add Dependencies

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

```bash theme={null}
## Add LangChain core and provider-specific integrations
uv add langchain-core langchain-groq langchain-google-genai python-dotenv
```

#### 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:

```ini theme={null}
## Groq API Key (Fast inference for open models)
GROQ_API_KEY=gsk_your_groq_api_key_here

## Google Gemini API Key
GOOGLE_API_KEY=AIzaSyYourGeminiApiKeyHere
```

#### 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.

```python theme={null}
from dotenv import load_dotenv

# Search and load keys from the local .env file
load_dotenv()
```

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

```python theme={null}
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

## Load variables from .env
load_dotenv()

## Initialize the Groq model
llm = init_chat_model(
    "llama-3.3-70b-versatile",
    model_provider="groq"
)

## Invoke the model
response = llm.invoke("Explain why developers use virtual environments in Python.")
print(response.content)
```

#### 7.2 Initializing with Google Gemini

```python theme={null}
import os
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

## Load variables from .env
load_dotenv()

## Initialize the Gemini model
llm = init_chat_model(
    "gemini-2.5-flash",
    model_provider="google_genai"
)

## Invoke the model
response = llm.invoke("What is the difference between concurrency and parallelism?")
print(response.content)
```

> \[!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.

<Accordion title="Solution">
  ```python theme={null}
  import os
  from dotenv import load_dotenv
  from langchain.chat_models import init_chat_model

  ## Load environment variables
  load_dotenv()

  ## Initialize Groq
  groq_llm = init_chat_model(
      "llama-3.3-70b-versatile",
      model_provider="groq"
  )

  ## Initialize Gemini
  gemini_llm = init_chat_model(
      "gemini-2.5-flash",
      model_provider="google_genai"
  )

  prompt = "State the main goal of prompt engineering in 5 words."

  print("--- Groq Response ---")
  print(groq_llm.invoke(prompt).content.strip())

  print("\n--- Gemini Response ---")
  print(gemini_llm.invoke(prompt).content.strip())
  ```
</Accordion>

## 💻 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](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/prompt-engg/prompt-engg-practice-vscode.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/prompt-engg/prompt-engg-practice-colab.ipynb) | <a href="/public/notebooks/prompt-engg/prompt-engg-practice-vscode.ipynb" download>📥 Download Notebook</a>
