DVP IBM AI Engineering
Course 12 of 13 · Generative AI / LLMs

Fundamentals of AI Agents Using RAG and LangChain

Prompting, agents, and retrieval — where the certificate becomes application engineering

Course 12 ≈ 9 hours Generative AI / LLMs
Motion graphic
Fundamentals of AI Agents Using RAG and LangChain
Retrieval pulls only the relevant documents into the prompt — converting a memory problem into a reading-comprehension problem.

9 hours · 3 modules · LangChain + Hugging Face + IBM watsonx

Where the certificate becomes application engineering. Fine-tuning changes the model; RAG and agents change the system around the model.


Module 1 — Fundamentals of AI Agents

In-context learning

The model learns from examples placed in the prompt, with no weight updates at all. An emergent property of scale — small models can't do it, large ones can.

Classify the sentiment: "The film dragged."

Review: "Brilliant pacing."  Sentiment: positive
Review: "I walked out."      Sentiment: negative
Review: "The film dragged."  Sentiment:

Few-shot's main value is often format control — showing the model the exact output shape you want is more reliable than describing it.

Limits: it consumes context window, it doesn't persist between calls, and beyond a handful of examples returns diminish. When you need consistent behaviour on thousands of calls, fine-tune instead — that's cheaper per call and more reliable.

Prompt engineering

Core components of a good prompt:

  1. Role / persona — "You are a broadcast post-production engineer."
  2. Task — a specific, unambiguous instruction
  3. Context — background, constraints, retrieved documents
  4. Examples — few-shot demonstrations
  5. Output format — explicit; give a schema or a template
  6. Tone / constraints — length, audience, what to avoid

Patterns the course names:

PatternWhat it does
Zero/few-shotexamples in the prompt
Chain-of-Thought (CoT)"Let's think step by step" — makes reasoning explicit; big gains on arithmetic and logic
Self-consistencysample several CoT paths, take the majority answer
ReActinterleave Reasoning and Acting — the basis of tool-using agents
Personaassign a role to shape vocabulary and depth
Template / output-formatforce JSON, tables, a fixed schema
Tree of Thoughtsexplore and evaluate multiple reasoning branches
Instruction-firstput the instruction before the data for long inputs

Why CoT works: the model has a fixed amount of computation per token. Forcing it to write intermediate steps gives it more tokens — therefore more computation — before it must commit to an answer. It isn't "thinking harder"; it's being given room to work.

Practical rules:

Decoding parameters

You'll set these on every LLM call for the rest of the certificate:

ParameterEffect
temperaturescales logits before softmax. 0 = deterministic, 0.7 = balanced, >1 = wild
top_p (nucleus)sample from the smallest set of tokens with cumulative probability ≥ p
top_ksample from the k most likely tokens
max_tokensoutput length cap
frequency/presence penaltydiscourage repetition
stop sequencesstrings that end generation

Rule of thumb: temperature ~0 for extraction, classification and factual QA; 0.7–1.0 for creative work. Tune temperature or top_p, not both.

AI agents

Definition: a system where an LLM decides what to do, not merely what to say — it can choose actions, call tools, observe results, and iterate toward a goal.

The loop:

Goal → Think (plan) → Act (call a tool) → Observe (read the result) → repeat → Answer

Components:

  1. LLM — the reasoning engine
  2. Tools — search, calculator, code execution, database queries, APIs
  3. Memory — conversation history, and longer-term storage
  4. Planning — decomposing a goal into steps
  5. Executor — the loop that runs it

ReAct, the classic agent pattern, made concrete:

Thought: I need current data for this.
Action: search("Cloudflare Pages pricing 2026")
Observation: <results>
Thought: I now have what I need.
Final Answer: ...

Chain vs agent — the distinction that gets quizzed:

capable of looping forever.

Use a chain when you know the steps. Reach for an agent only when you genuinely don't.

Self-check — answer without looking
  1. Few-shot prompting vs fine-tuning — when does each win?
  2. Why does chain-of-thought improve arithmetic accuracy?
  3. Chain or agent for "extract these 6 fields from every invoice"? Why?

Module 2 — RAG Framework

The problem RAG solves

LLM knowledge is frozen at training time, has no access to your private data, hallucinates confidently, and can't cite sources.

RAG (Retrieval-Augmented Generation): retrieve relevant documents at query time and put them in the prompt. The model reads rather than recalls.

Query → embed → search vector DB → top-k chunks → prompt(query + chunks) → LLM → grounded answer

Why it's the default answer to hallucination: you've converted a memory problem into a reading-comprehension problem. Reading comprehension is what these models are best at.

RAG vs fine-tuning — the decision table

The single most examinable table in the second half of the certificate:

RAGFine-tuning
Addsknowledgebehaviour, style, format
Update costre-index a document (seconds)retrain (hours)
Freshnesslivefrozen at training
Citationsyes, naturalno
Hallucinationmuch reducedunchanged or worse
Inference costhigher (long prompts)baseline
Setupvector DB, chunking, retrievalGPU, labelled data
Private datastays in your storebaked into weights

They compose. Fine-tune for domain vocabulary and output format; use RAG for the facts. That's what a production system does.

The two phases

Indexing (offline, once per document):

  1. Load documents
  2. Split into chunks
  3. Embed each chunk into a vector
  4. Store vectors + text + metadata in a vector database

Retrieval + generation (online, per query):

  1. Embed the query with the same embedding model
  2. Similarity-search the store for the top-k chunks
  3. Build a prompt from query + chunks
  4. Generate
  5. Optionally return sources

Embeddings and vector search

Text → dense vector. Semantically similar text → nearby vectors. Compared with cosine similarity.

This is why RAG beats keyword search: a query about "revenue decline" retrieves a passage about "falling sales" even with no shared words.

Non-negotiable rule: query and documents must be embedded by the same model. Different models produce incompatible vector spaces, and the failure is silent — you get results, they're just meaningless.

Vector databases: Chroma (local, simple — what the labs use), FAISS (Meta's library, fast, in-process), Pinecone / Weaviate / Qdrant / Milvus (managed or production-grade), pgvector (Postgres extension). They use approximate nearest-neighbour indexes (HNSW, IVF) because exact search over millions of vectors is too slow — you trade a small amount of recall for enormous speed.

Chunking

The parameter that most determines RAG quality, and the one most people neglect.

and dilute attention

Typical: 500–1000 characters with 10–20% overlap. Overlap prevents a sentence that straddles a boundary from being lost to both chunks.

Strategies (Course 13 covers the code):

can. The sensible default.

Retrieval quality

degrade answers.

identifiers, product codes and names, which pure embeddings often miss.

A cross-encoder reads query and document together, so it's much more accurate but too slow to run over the whole corpus.

five near-identical chunks.

RAG failure modes

Worth knowing because debugging RAG is the actual job:

  1. Retrieval miss — the answer exists but wasn't retrieved → chunking, embedding model, k,

hybrid search

  1. Retrieved but ignored — it's in the context and the model didn't use it → prompt

instruction, chunk ordering ("lost in the middle" — models attend better to the start and end of long contexts)

  1. Contradictory chunks — two sources disagree → metadata, recency filters, tell the model

how to resolve

  1. Generation ignores grounding — model answers from parametric memory → explicit "answer

only from the context provided; if it isn't there, say so"

  1. No answer exists — the model should decline, and usually won't unless told it may
Self-check — answer without looking
  1. RAG or fine-tuning for a chatbot over your company's constantly-changing policy documents?
  2. What breaks if you embed queries with a different model than the documents?
  3. Chunks of 100 characters — what's the specific failure?
  4. Name two fixes for "the right document was retrieved but the answer was still wrong".

Module 3 — Prompt Engineering and LangChain

What LangChain is

A framework for composing LLM applications: a common interface across model providers, plus building blocks for prompts, chains, retrieval, memory and agents.

The pitch: swap OpenAI for watsonx for a local model by changing one line.

The honest caveat, worth holding: LangChain adds abstraction layers that can obscure what's actually being sent to the model. For simple applications, direct API calls are often clearer. Learn it because it's on every job description and because the certificate uses it — but know when it's overhead.

The components

Chat models and LLMs

from langchain_ibm import WatsonxLLM
llm = WatsonxLLM(model_id='meta-llama/llama-3-70b-instruct',
                 url=..., project_id=..., params={'temperature': 0.5, 'max_new_tokens': 500})

Prompt templates

from langchain_core.prompts import PromptTemplate, ChatPromptTemplate

prompt = PromptTemplate(input_variables=['topic', 'audience'],
                        template="Explain {topic} to {audience} in three sentences.")

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a concise technical writer."),
    ("human",  "{question}"),
])

Output parsers — turn text into structured data

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser

LCEL (LangChain Expression Language) — the pipe syntax that composes them:

chain = prompt | llm | StrOutputParser()
chain.invoke({'topic': 'colour grading', 'audience': 'a producer'})

| passes each component's output to the next. Chains built this way support .invoke(), .batch(), .stream() and their async equivalents for free.

Memory — LLM APIs are stateless; memory is what makes a conversation.

from langchain.memory import ConversationBufferMemory, ConversationSummaryMemory

Tools and agents

from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.tools import tool

@tool
def get_frame_rate(codec: str) -> str:
    """Return the standard frame rate for a given broadcast codec."""
    ...

agent = create_react_agent(llm, tools=[get_frame_rate], prompt=react_prompt)
executor = AgentExecutor(agent=agent, tools=[get_frame_rate],
                         verbose=True, max_iterations=5,
                         handle_parsing_errors=True)
executor.invoke({'input': 'What frame rate should I use for XDCAM HD422?'})

The docstring is not documentation — it is the tool's specification to the model. The LLM reads the name, the docstring and the type hints to decide when and how to call it. A vague docstring means a tool that never gets used, or gets used wrongly. This is the highest-leverage detail in agent building.

max_iterations is a required safety valve — agents loop.

Document loaders and retrievers — Course 13's subject:

from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma

A complete RAG chain

The pattern the final project builds on:

from langchain_core.runnables import RunnablePassthrough

retriever = vectorstore.as_retriever(search_kwargs={'k': 4})

template = """Answer the question using only the context below.
If the context does not contain the answer, say you don't know.

Context:
{context}

Question: {question}

Answer:"""
prompt = ChatPromptTemplate.from_template(template)

def format_docs(docs):
    return "\n\n".join(d.page_content for d in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
rag_chain.invoke("What is the retention policy for raw footage?")

RunnablePassthrough() forwards the original input unchanged while the retriever branch runs in parallel — that's how one input feeds two slots in the prompt.

Self-check — answer without looking
  1. What does | do in LCEL?
  2. Why does a tool's docstring matter so much?
  3. Buffer vs summary memory — when does each fail?
  4. What is RunnablePassthrough() doing in the RAG chain above?

Course 12 in one page

Supplemental — verified sources
paper
Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
Lewis et al., 2020 · arXiv:2005.11401
The paper that named RAG. Worth reading for the framing, not the implementation — the modern stack is simpler.
docs
LangChain — Introduction
official documentation
LCEL, chains, retrievers and agents. The labs track this closely.
docs
Retrieval augmented generation (RAG)
LangChain
The indexing and retrieval split exactly as Module 2 teaches it.
article
Lost in the Middle: How Language Models Use Long Contexts
Liu et al., 2023 · arXiv:2307.03172
The evidence for why retrieval beats stuffing a whole document into the prompt, even when it fits.
docs
Prompt engineering overview
Anthropic documentation
Module 3's prompt patterns, written by people who do this for a living. Applies to any model.