2.03 – LangChain & LlamaIndex | AI Course

🦜 2.03 – LangChain & LlamaIndex

πŸ“‘ On this page

βš–οΈ Framework Comparison

AspectLangChainLlamaIndex
Primary focusGeneral LLM applicationsRAG and data indexing
Strengths Chains, agents, memory, wide integrations Document loaders, indexing, query engines
Best for Chatbots, multi-step workflows, agents Document Q&A, knowledge bases, retrieval
Learning curve Steeper (many concepts) ηœ‹θ΅·ζ₯很Gentle (more focused)

⛓️ LangChain: Chains

πŸ“Œ What are Chains?

Chains combine multiple LLM calls or tools in sequence. The output of one step becomes the input to the next.

Simple LLMChain:
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI

prompt = PromptTemplate(
    input_variables=["topic"],
    template="Write a short poem about {topic}."
)

chain = LLMChain(
    llm=ChatOpenAI(model="gpt-4"),
    prompt=prompt
)

result = chain.run("artificial intelligence")
print(result)
Sequential Chain (multiple steps):
from langchain.chains import SimpleSequentialChain

# Step 1: Generate a company name
name_prompt = PromptTemplate(
    input_variables=["product"],
    template="Generate a creative company name for a {product} startup."
)
name_chain = LLMChain(llm=ChatOpenAI(), prompt=name_prompt)

# Step 2: Generate a slogan using the company name
slogan_prompt = PromptTemplate(
    input_variables=["company_name"],
    template="Write a catchy slogan for a company called {company_name}."
)
slogan_chain = LLMChain(llm=ChatOpenAI(), prompt=slogan_prompt)

# Combine
overall_chain = SimpleSequentialChain(chains=[name_chain, slogan_chain])
result = overall_chain.run("AI-powered pet feeder")
RAG Chain (RetrievalQA):
from langchain.chains import RetrievalQA
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

# Setup vector store
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())

# Create retrieval chain
qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4"),
    retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
    chain_type="stuff",  # "stuff", "map_reduce", "refine", "map_rerank"
    return_source_documents=True
)

result = qa_chain({"query": "What is our refund policy?"})
print(result["result"])
print(f"Sources: {[doc.metadata for doc in result['source_documents']]}")

🧠 LangChain: Memory

πŸ“Œ Memory Types
Chatbot with Memory:
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain

memory = ConversationBufferMemory(return_messages=True)

conversation = ConversationChain(
    llm=ChatOpenAI(model="gpt-4"),
    memory=memory,
    verbose=True
)

print(conversation.predict(input="Hi! My name is Alice."))
print(conversation.predict(input="What's my name?"))  # Remembers!

πŸ€– LangChain: Agents

πŸ“Œ What are Agents?

Agents use LLMs to decide which tools to call, in what order, and how to combine results. Unlike chains (hard-coded sequence), agents are dynamic.

Creating an Agent with Tools:
from langchain.agents import load_tools, initialize_agent, AgentType
from langchain.llms import OpenAI

# Load tools
tools = load_tools(["serpapi", "llm-math"], llm=OpenAI(temperature=0))

# Initialize agent
agent = initialize_agent(
    tools,
    OpenAI(temperature=0),
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

# Run agent
result = agent.run(
    "What's the current population of France? Then multiply it by 0.05."
)
πŸ“Œ Custom Tools:
from langchain.tools import BaseTool

class WeatherTool(BaseTool):
    name = "WeatherTool"
    description = "Get current weather for a city"

    def _run(self, city: str) -> str:
        # Call weather API
        return f"The weather in {city} is sunny, 22Β°C"

tools = [WeatherTool()]
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)

πŸ¦™ LlamaIndex for RAG

πŸ“Œ LlamaIndex Quick Start:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# Load documents
documents = SimpleDirectoryReader("data").load_data()

# Create index
index = VectorStoreIndex.from_documents(documents)

# Query
query_engine = index.as_query_engine()
response = query_engine.query("What is the main topic?")
print(response)
πŸ“Œ Advanced LlamaIndex Features:
Router Query Engine:
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector

# Create specialized indexes
summary_index = VectorStoreIndex.from_documents(docs_summary)
detailed_index = VectorStoreIndex.from_documents(docs_detailed)

# Router decides which to use
router = RouterQueryEngine(
    selector=LLMSingleSelector.from_defaults(),
    query_engine_tools=[
        QueryEngineTool.from_defaults(
            query_engine=summary_index.as_query_engine(),
            description="For high-level summaries"
        ),
        QueryEngineTool.from_defaults(
            query_engine=detailed_index.as_query_engine(),
            description="For detailed, specific questions"
        )
    ]
)

response = router.query("What are the key findings in section 3?")

βœ… Best Practices

πŸ“Œ LangChain Best Practices

✍️ Exercises

Exercise 2.03.1 – Build a chain

Create a sequential chain that: 1) Asks the user for a product idea, 2) Generates a product name, 3) Writes a marketing tagline.

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

chain1 = LLMChain(llm=llm, prompt=PromptTemplate(
    input_variables=["idea"],
    template="Generate a product name for: {idea}"
))
chain2 = LLMChain(llm=llm, prompt=PromptTemplate(
    input_variables=["product_name"],
    template="Write a tagline for {product_name}"
))

overall = SimpleSequentialChain(chains=[chain1, chain2])
result = overall.run("solar-powered phone charger")
Exercise 2.03.2 – Add memory to a chatbot

Modify the conversation chain to use ConversationSummaryMemory instead of BufferMemory. What's the advantage?

Advantage: ConversationSummaryMemory summarizes long conversations into a concise summary, saving tokens. With BufferMemory, long conversations would exceed context limits. Summary memory scales indefinitely.
Exercise 2.03.3 – Framework choice

You're building a document Q&A system for 10,000 legal contracts. Would you choose LangChain or LlamaIndex? Why?

Recommendation: LlamaIndex
LlamaIndex specializes in document indexing and retrieval. It has excellent support for metadata filtering, hierarchical indexes, and contract-specific parsing. LangChain would also work, but LlamaIndex is more focused for pure RAG.
πŸ“Œ Key Takeaways
πŸ“˜ Next Module: 2.04 – Production AI β†’