Lesson 18 LangChain & LlamaIndex
Theme:
Lesson 18 · Slide 1

LangChain & LlamaIndex

LLM orchestration frameworks: when abstraction helps, when it hurts, and how to choose between them and direct API calls.

Learning Objectives

Lesson 18 · Slide 2

Why Orchestration Frameworks?

As LLM applications grow beyond a single API call, you face recurring problems: chaining prompts, managing conversation memory, connecting to external tools, and retrieving context from documents. Orchestration frameworks provide reusable abstractions for these patterns.

Problems They Solve

  • Multi-step prompt chains
  • Conversation memory management
  • Tool calling and function routing
  • Document loading, chunking, indexing
  • Provider-agnostic model switching

Trade-offs

  • Added dependency and complexity
  • Abstractions can obscure what the LLM actually receives
  • Rapid version churn and breaking changes
  • Performance overhead for simple use cases
  • Debugging becomes harder through layers
Notes: Emphasise that frameworks are tools, not requirements. Many production systems use direct API calls. The right choice depends on the complexity of your application.
Lesson 18 · Slide 3

LangChain: Core Concepts

LangChain is the most popular LLM orchestration framework. It provides composable building blocks for chaining LLM calls with tools, memory, and retrieval.

Key Components

from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant that explains {topic} simply."),
    ("human", "{question}")
])
model = ChatAnthropic(model="claude-sonnet-4-20250514")
chain = prompt | model | StrOutputParser()

result = chain.invoke({"topic": "machine learning", "question": "What is overfitting?"})
Lesson 18 · Slide 4

LCEL: LangChain Expression Language

LCEL is LangChain's declarative composition syntax. Every component implements a Runnable interface with .invoke(), .stream(), .batch(), and .ainvoke() methods.

The Pipe Pattern

Input → Prompt Template → Chat Model → Output Parser → Result

Each step transforms the data and passes it to the next. The pipe operator (|) connects them.

Advanced LCEL Patterns

from langchain_core.runnables import RunnablePassthrough, RunnableParallel

# Parallel execution: run two chains simultaneously
parallel = RunnableParallel(
    summary=summary_chain,
    keywords=keyword_chain
)

# Passthrough: keep original input alongside transformations
chain = RunnableParallel(
    context=retriever,
    question=RunnablePassthrough()
) | prompt | model | parser

# Branching: route based on input
from langchain_core.runnables import RunnableBranch
branch = RunnableBranch(
    (lambda x: "code" in x["topic"], code_chain),
    (lambda x: "math" in x["topic"], math_chain),
    default_chain  # fallback
)
Notes: LCEL replaced the older LLMChain / SequentialChain API. Always use LCEL for new projects. The old chain classes are deprecated.
Lesson 18 · Slide 5

LlamaIndex: Core Concepts

LlamaIndex (formerly GPT Index) is purpose-built for connecting LLMs to your data. While LangChain is a general orchestration toolkit, LlamaIndex specialises in retrieval-augmented generation (RAG).

Key Components

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.anthropic import Anthropic

# Load documents, build index, query
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine(
    llm=Anthropic(model="claude-sonnet-4-20250514")
)
response = query_engine.query("What are the key findings?")
Notes: LlamaIndex shines when your primary pattern is "load documents, index them, query them". For that workflow it requires far less boilerplate than LangChain.
Lesson 18 · Slide 6

Framework vs. Direct API Calls

The most important question is not "which framework?" but "do I need a framework at all?" Many production LLM applications use direct API calls and are better for it.

CriteriaDirect APILangChainLlamaIndex
Simple single-call appsBest choiceOverkillOverkill
Multi-step chains with branchingManual wiringBest choiceNot designed for this
RAG over documentsBuild from scratchSupportedBest choice
Agent with tool useManageableBest choiceLimited support
Debugging transparencyFull controlModerateModerate
Switching providersCode changesSwap one lineSwap one line
Dependency footprintMinimalHeavyModerate

Rule of Thumb

Start with direct API calls. Introduce a framework only when you find yourself re-implementing patterns it already provides. If your app is primarily RAG, lean toward LlamaIndex. If it involves complex agent workflows, lean toward LangChain.

Lesson 18 · Slide 7

Multi-Provider Integration

Both frameworks support Claude, OpenAI, and open-source models through a unified interface. This makes it easy to benchmark providers or fall back between them.

LangChain Providers

# Claude
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-20250514")

# OpenAI
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")

# Local / Ollama
from langchain_ollama import ChatOllama
llm = ChatOllama(model="llama3")

LlamaIndex Providers

# Claude
from llama_index.llms.anthropic import Anthropic
llm = Anthropic(model="claude-sonnet-4-20250514")

# OpenAI
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o")

# Local / Ollama
from llama_index.llms.ollama import Ollama
llm = Ollama(model="llama3")

Both read API keys from environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY) automatically.

Notes: The provider-agnostic interface is one of the strongest arguments for frameworks. Swapping from Claude to GPT-4o to a local model is a one-line change.
Lesson 18 · Slide 8

Lab & Homework

Lab Exercises

  1. LangChain Chain — Build a multi-step chain with LCEL: prompt template → Claude → output parser, then add a second step that transforms the output
  2. LlamaIndex RAG — Load a set of text documents, build a vector index, and query it with a natural language question
  3. Direct API Comparison — Implement the same chain from Exercise 1 using only the anthropic SDK, then compare code complexity and readability

Homework Tasks

  1. Add conversation memory to your LangChain chain and implement a multi-turn conversation loop
  2. Swap the LLM provider in both your LangChain and LlamaIndex pipelines (e.g., Claude to OpenAI) and compare output quality
  3. Write a decision memo: given a specific project scenario, argue whether to use a framework or direct API calls
1 / ?