Course navigation
Embeddings, Vector Stores & RAGLesson 9 of 11

Retrieval-Augmented Generation (RAG)

Vector Databases stored your lines in Chroma. Here you call as_retriever, join the returned chunks into a prompt, and run an LCEL chain with invoke. The demo prints the chunks first, then one answer string.

Before you run

Activate the venv from Project Setup. You need chromadb installed and a valid OPENAI_API_KEY in .env from OpenAI Account Setup.

The chain uses LCEL pipes from LCEL and RunnablePassthrough from RunnablePassthrough.

This lesson (earlier steps in gray):

load file → split → embed → Chroma store
↓ this lesson
retriever.invoke → top k chunks
context + question → prompt → llm → parser
print one answer string
The demo skips loader and splitter — it stores three HTML lines in Chroma, then wires the retriever to a prompt chain. For all six steps in one file, see End-to-End RAG Pipeline.

Document retrieval

A retriever wraps your vector store. Call invoke with a question string and get back Document objects — the same lines Chroma ranked in the last lesson.

retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

docs = retriever.invoke("How do I make a link on a page?")

for doc in docs:
    print(doc.page_content)

retriever.invoke output

[0] The <a> tag creates a hyperlink. Use the href attribute…
[1] The <title> tag sets the page title shown in the browser tab.
With k=2 you get two lines back. Those strings become the context block in the prompt.

Retriever setup

as_retriever turns the store into a Runnable. search_kwargs={"k": 2} limits output to two chunks so the prompt stays short.

Raise k when your notes are longer and you need more context in the prompt.

LLM chain

format_docs joins chunk text into one string. That string fills the context slot in the template. The pipe forwards both keys — context and question — into ChatPromptTemplate, then through ChatOpenAI and StrOutputParser.

LCEL chain:

{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt | llm | StrOutputParser()
context — joined chunk text
question — your input string
Same pipe style as LCEL. RunnablePassthrough forwards the question unchanged.
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

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

prompt = ChatPromptTemplate.from_template(
    "Answer in one short sentence using only the context below.\n\n"
    "Context:\n{context}\n\n"
    "Question: {question}"
)

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

answer = rag_chain.invoke("How do I make a link on a page?")
print(answer)

Run the demo

Download the script, then run:

rag_demo.py

Creates rag_chroma_db/ on each run

Needs chromadb from Vector Databases and OPENAI_API_KEY in .env.
rag_demo.py
"""rag_demo.py"""
# retriever → format_docs → prompt → llm → parser
rag_chain = ({"context": retriever | format_docs, ...} | prompt | llm | parser)
python rag_demo.py
PowerShell — (.venv) active
(.venv) PS C:\projects\langchain-course> python rag_demo.py
=== Retrieved chunks ===
[0] The <a> tag creates a hyperlink. Use the href attribute…
[1] The <title> tag sets the page title shown in the browser tab.
=== Answer ===
Q: How do I make a link on a page?
A: Use the <a> tag with an href attribute to create a hyperlink.
The printed line should mention the <a> tag. Wording may vary slightly if you rerun the script.

If it fails

  • AuthenticationError — check OPENAI_API_KEY and load_dotenv().
  • ModuleNotFoundError: chromadb — run pip install chromadb.
  • Printed line skips context — print retriever.invoke output first. If the wrong chunk is on top, raise k or fix the lines in your store.
  • KeyError on invoke — pass a plain string to rag_chain.invoke, not a dict.

More detail: LangChain retrieval docs.

What's Next

Retriever and chain are working. Next up: run the full pipeline from a text file in one script.