Building a Simple RAG Chatbot
Put the script from End-to-End RAG Pipeline behind st.chat_input. The demo loads html_notes.txt, builds Chroma once with @st.cache_resource, then calls chain.invoke on each submit.
Before you run
Complete End-to-End RAG Pipeline and Introduction to Streamlit first. Activate the venv from Project Setup, then install:
pip install streamlit langchain-text-splitters chromadb
Keep a valid OPENAI_API_KEY in .env from OpenAI Account Setup.
Same pipeline as End-to-End RAG, plus Streamlit chat:
chain.invoke from st.chat_input, same pattern as Introduction to Streamlit.Load once with cache
Streamlit reruns the script on each submit. Without a cache, TextLoader and Chroma.from_documents would run again on every message. Wrap the setup in @st.cache_resource:
@st.cache_resource
def load_rag_chain():
docs = TextLoader(str(NOTES_PATH), encoding="utf-8").load()
chunks = RecursiveCharacterTextSplitter(
chunk_size=150, chunk_overlap=30
).split_documents(docs)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
persist_directory=str(DB_DIR),
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
prompt = ChatPromptTemplate.from_template(
"Answer in one or two short sentences using only the context below.\n\n"
"Context:\n{context}\n\n"
"Question: {question}"
)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
return (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)Chat input
Store turns in st.session_state. On submit, show the question, call chain.invoke, print the string with st.write:
if "messages" not in st.session_state:
st.session_state.messages = []
for msg in st.session_state.messages:
st.chat_message(msg["role"]).write(msg["content"])
if question := st.chat_input("Ask about HTML tags..."):
st.session_state.messages.append({"role": "human", "content": question})
st.chat_message("human").write(question)
chain = load_rag_chain()
with st.chat_message("ai"):
answer = chain.invoke(question)
st.write(answer)
st.session_state.messages.append({"role": "ai", "content": answer})Run the demo
Download the ZIP so simple_rag_chatbot_samples/ sits next to the script, then run:
simple_rag_chatbot_demo.py
Includes simple_rag_chatbot_samples/html_notes.txt. Creates simple_rag_chatbot_chroma_db/ on first run.
simple_rag_chatbot_samples/ sits next to the script.python simple_rag_chatbot_demo.py
@st.cache_resource loads and embeds html_notes.txt once. Later questions skip that step.Ask How do I make a link on a page?. The reply should mention the <a> tag. Wording may vary slightly if you rerun the script.
If it fails
- Missing file: simple_rag_chatbot_samples/html_notes.txt. Unzip
simple_rag_chatbot_demo.zipso the sample folder sits besidesimple_rag_chatbot_demo.py. - AuthenticationError. Check
OPENAI_API_KEYandload_dotenv(). - ModuleNotFoundError: streamlit. Run
pip install streamlit. - Port already in use. Stop other Streamlit apps or run
streamlit run simple_rag_chatbot_demo.py --server.port 8502.
What's Next
RAG module is done. Next: Agents — when the model picks its own steps.