Lab 6 — The Same RAG, with LangChain¶
⏱️ ~30 min
Rebuild Lab 4 using LangChain. Notice how much boilerplate disappears. Uses OpenAI for embeddings + chat.
Requires an OpenAI API key — these labs use OpenAI embeddings / function-calling specifically. (Labs 1–3 work with OpenAI or Anthropic.)
In [ ]:
Copied!
# Tip: pin these to exact versions in real projects — these frameworks ship breaking changes often.
!pip install -q langchain langchain-openai langchain-chroma
import os, getpass
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API key: ")
# Tip: pin these to exact versions in real projects — these frameworks ship breaking changes often.
!pip install -q langchain langchain-openai langchain-chroma
import os, getpass
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API key: ")
1. Same documents as Lab 4¶
In [ ]:
Copied!
documents = [
"The Helios API rate limit is 100 requests per minute per API key.",
"Helios refunds are processed within 5 business days to the original payment method.",
"The Helios SDK supports Python 3.9 and above; Python 3.8 reached end of life.",
"To rotate a Helios API key, go to Settings > Security > Rotate Key. Old keys expire in 24h.",
"Helios stores data in the EU (Frankfurt) region by default for all new accounts.",
]
documents = [
"The Helios API rate limit is 100 requests per minute per API key.",
"Helios refunds are processed within 5 business days to the original payment method.",
"The Helios SDK supports Python 3.9 and above; Python 3.8 reached end of life.",
"To rotate a Helios API key, go to Settings > Security > Rotate Key. Old keys expire in 24h.",
"Helios stores data in the EU (Frankfurt) region by default for all new accounts.",
]
2. Build the vector store in 3 lines¶
In [ ]:
Copied!
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
vectorstore = Chroma.from_texts(documents, embedding=OpenAIEmbeddings(model="text-embedding-3-small"))
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
vectorstore = Chroma.from_texts(documents, embedding=OpenAIEmbeddings(model="text-embedding-3-small"))
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
3. Wire retriever → prompt → model with LCEL¶
In [ ]:
Copied!
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template(
"Answer ONLY from the context. If absent, say you don't know.\n\n"
"Context:\n{context}\n\nQuestion: {question}")
def format_docs(docs):
return "\n".join(f"- {d.page_content}" for d in docs)
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser()
)
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template(
"Answer ONLY from the context. If absent, say you don't know.\n\n"
"Context:\n{context}\n\nQuestion: {question}")
def format_docs(docs):
return "\n".join(f"- {d.page_content}" for d in docs)
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser()
)
In [ ]:
Copied!
print(chain.invoke("How long until my old API key stops working after I rotate it?"))
print(chain.invoke("What is the Helios phone support number?"))
print(chain.invoke("How long until my old API key stops working after I rotate it?"))
print(chain.invoke("What is the Helios phone support number?"))
Takeaway: Lab 4's manual embed/store/retrieve/augment loop is now a few composable lines. The framework owns the plumbing; you own the prompt and the data.
✅ Did it work?¶
- The first
chain.invokeanswered the key-rotation question from the Helios docs (old keys expire in 24h). - The second
chain.invokedeclined the phone-support question — same grounding behavior as Lab 4, far less code.