Mastering LangChain

Mastering LangChain: A Full In-Depth Guide

00-Models: Understanding Models in LangChain

In LangChain, Models refer to the Language Models (LLMs) or Chat Models you use to perform tasks like text generation, summarization, answering questions, and more. LangChain abstracts the interaction with models like OpenAI’s GPT, Anthropic’s Claude, HuggingFace models, Cohere, and others to make integration seamless.

Key Concepts

  • LLM Interface: A unified way to interact with different LLMs and ChatModels.
  • Prompt Management: Standardizing how you send structured prompts to models.
  • Output Parsing: Extracting structured outputs like JSON, numbers, or lists from the model’s response.

Example

from langchain_openai import OpenAI
from langchain.prompts import PromptTemplate

llm = OpenAI(model="gpt-4", temperature=0.3)

prompt = PromptTemplate.from_template("Tell me a fun fact about {topic}")
prompt_text = prompt.format(topic="space")

response = llm.invoke(prompt_text)
print(response)

Advanced Usage
Use Output Parsers to automatically extract structured information from the model’s response.
Use Streaming Outputs to process token-by-token outputs for real-time applications.
Batch multiple prompts together to maximize speed and efficiency.

Best Practices
Always design clean and focused prompts.
Adjust temperature based on the need: low for accuracy, high for creativity.
Use output parsing if you expect structured, machine-readable answers.

01-Data-Connections: Enriching Language Models with Real-World Data

Language Models are trained on static data and cannot access real-time or private information. Data Connections allow you to pull in documents, APIs, databases, or live websites to enhance your model’s responses.

Key Concepts

  • Document Loaders: Load data from PDFs, websites, Notion, Google Docs, SQL databases, etc.
  • Retrievers: Find and retrieve the most relevant document chunks when a query is made.
  • Tools/APIs: Connect models to external APIs such as weather, finance, or search engines.

Example

from langchain.document_loaders import WebBaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

loader = WebBaseLoader("https://www.python.org/")
documents = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(documents)

print(chunks[0].page_content)

Advanced Usage
Embed documents into vector stores for semantic search (e.g., Chroma, FAISS).
Combine multiple sources and filter documents at retrieval time.
Dynamically call APIs and use real-time data inside prompts.

Best Practices
Clean and preprocess documents before use.
Always chunk large documents before embedding.
Use Retrieval Augmented Generation (RAG) to build factual and updated systems.

02-Chains: Building Logical Workflows in LangChain

Chains combine multiple operations together in a logical sequence, feeding the output of one step as the input to another. Chains are essential for building structured workflows where the model must reason step-by-step.

Key Concepts

  • LLMChain: A single model call with a structured prompt.
  • SequentialChain: Multiple steps chained one after another.
  • RouterChain: Directs inputs to different chains based on rules.
  • CustomChain: Create your own complex logic.

Example

from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain, SimpleSequentialChain

first_prompt = PromptTemplate.from_template("Suggest a name for a {business_type} company.")
first_chain = LLMChain(llm=llm, prompt=first_prompt)

second_prompt = PromptTemplate.from_template("Create a tagline for a company called {company_name}.")
second_chain = LLMChain(llm=llm, prompt=second_prompt)

overall_chain = SimpleSequentialChain(chains=[first_chain, second_chain], verbose=True)

response = overall_chain.invoke({"business_type": "eco-friendly cleaning"})
print(response)

Advanced Usage
Handle multi-hop reasoning across multiple LLM calls.
Build conditional logic with Router Chains.
Customize your own chain classes if needed.

Best Practices
Keep each step focused and modular.
Break big tasks into smaller, manageable prompts.
Use verbose mode while debugging chains.

03-Memory: Giving LangChain Apps a Mind

Memory allows your application to remember past user inputs, outputs, and facts, enabling coherent multi-turn conversations. Without memory, every interaction is stateless and disconnected.

Key Concepts

  • ConversationBufferMemory: Stores the entire conversation history verbatim.
  • ConversationSummaryMemory: Summarizes the conversation to save space.
  • EntityMemory: Tracks and remembers specific entities like names, places, or dates.

Example

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain

memory = ConversationBufferMemory()
conversation = ConversationChain(llm=llm, memory=memory)

conversation.invoke({"input": "Hello, I'm Alice."})
conversation.invoke({"input": "What is my name?"})

Advanced Usage
Customize memory summaries for long conversations.
Persist memory in databases for long-running apps.
Create hybrid memories that mix structured and conversational data.

Best Practices
For short chats, use BufferMemory.
For long sessions, prefer SummaryMemory to manage token limits.
Use EntityMemory when tracking key facts over multiple turns.

04-Agents: Enabling Autonomous Decision-Making

Agents allow a model to decide its next action dynamically based on the situation. They can call tools, run code, access databases, fetch live data, and retry or correct themselves, making them highly autonomous.

Key Concepts

  • Zero-shot Agent: Executes tasks without requiring examples or previous training.
  • ReAct Agent: Thinks (reasoning), acts (tool call), and observes (tool output) iteratively.
  • Conversational Agent: Memory-enabled agents designed for continuous chat-based interactions.

Example

from langchain.agents import initialize_agent, Tool
from langchain.tools import tool

@tool
def multiply_numbers(a: int, b: int) -> int:
    return a * b

tools = [multiply_numbers]
agent = initialize_agent(tools=tools, llm=llm, agent_type="zero-shot-react-description")

response = agent.invoke({"input": "What is 6 times 9?"})
print(response["output"])

Advanced Usage
Agents can self-correct when an action fails.
Build agents that access databases, perform API queries, and reason through multi-step tasks.
Chain multiple tools together to solve complex workflows.

Best Practices
Keep tool descriptions clear and simple to help the agent choose properly.
Add guardrails to prevent infinite loops or unsafe operations.
Always monitor agent decisions during development and debugging.

How Everything Fits Together

First, you connect to a Model.
Then you use Chains to structure reasoning.
You enrich it with external Data Connections if needed.
You add Memory to maintain context.
You add an Agent when you need your app to dynamically make decisions among multiple actions.