A production-style conversational RAG agent β grounded answers, verifiable citations, and multi-turn memory, built on LangChain LCEL and served through Streamlit.
Live demo: https://support-rag-agent.streamlit.app/
Most "RAG demo" repos hallucinate sources and forget what the user just said. This one doesn't:
- Every claim is traceable. Answers cite the exact FAQ section and line number they came from β not a vague "according to our docs."
- It actually remembers. Ask "Do you ship to India?" then "How much does that cost?" β the second question resolves correctly using conversation history, not a fresh, context-free query.
- It fails safely. No API key configured, missing data, or an unanswerable question β the agent tells you plainly instead of guessing.
User question
β
βΌ
History-aware retriever β rewrites "how much does that cost?" into a standalone
query using prior turns, then retrieves matching FAQ
sections from FAISS
β
βΌ
Cited answer chain β LLM answers strictly from retrieved context, required
to cite (Source, Section, Line) for every claim
β
βΌ
Per-session memory β both the rewrite step and the answer step see the
full chat history, keyed by session_id
| Path | Responsibility |
|---|---|
app.py |
Streamlit UI β rendering only, zero business logic |
src/config.py |
Env-driven Settings, fails loudly if an API key is missing |
src/knowledge_base.py |
Parses the FAQ into cited sections, builds the FAISS index |
src/chat_agent.py |
SupportAgent β wraps LangChain's retrieval + memory chains behind one .ask() call |
tests/test_knowledge_base.py |
Unit tests for the FAQ parser, no network or API key required |
data/gigacorp_faq.txt |
Mock knowledge base: shipping, returns, hours, tiers, tracking, billing |
requirements.txt |
All Python dependencies, pinned to exact versions |
| Layer | Choice | Why |
|---|---|---|
| Orchestration | LangChain LCEL (create_history_aware_retriever, create_retrieval_chain, RunnableWithMessageHistory) |
Composable, testable chains instead of one monolithic prompt |
| LLM | Groq β Llama 3.3 70B (default) | Free tier, fast inference; swappable to OpenAI or Anthropic via one env var, zero code changes |
| Vector store | FAISS | Local, no external service, instant cold start |
| Embeddings | sentence-transformers/all-MiniLM-L6-v2 |
Runs locally β no embedding API key or cost |
| UI | Streamlit | Free hosting, minimal boilerplate, ships in one file |
The FAQ is split by ## Section headers. Each chunk retains source, section, and line_start metadata, which is rendered back into the LLM's context and enforced in the system prompt β the model is instructed to cite only sections that actually appear in front of it, never to invent one:
Shipping to India costs $24.99 (Source: gigacorp_faq.txt, Section: "Shipping Policy", line ~1).
Prerequisites: Python 3.12, a free Groq API key (or an OpenAI/Anthropic key if you prefer).
1. Clone the repository
git clone https://github.com/kailashv2/support-rag-agent.git
cd support-rag-agent2. Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\Activate.ps13. Install dependencies
All dependencies are listed in requirements.txt, pinned to exact versions for reproducibility:
pip install -r requirements.txt4. Configure your API key
Copy the example env file and add your key:
cp .env.example .envOpen .env and set:
GROQ_API_KEY=your-key-here
Alternatively, skip this and paste the key directly into the app's sidebar at runtime.
5. Run the app
streamlit run app.pyOpens at http://localhost:8501.
6. Run the tests (optional but recommended)
pytest tests/ -vCovers section parsing, metadata integrity, and failure handling on malformed input β no API key or network call required.
- Push this repo to GitHub.
- share.streamlit.io β New app β select this repo, branch
main, fileapp.py. - Under Advanced settings, set the Python version to 3.12 and add a secret:
GROQ_API_KEY = "your-key-here"- Deploy β first load downloads the embedding model (~90MB), expect a 30β60s cold start.
- New Space β SDK: Streamlit.
- Push this repo's contents to the Space.
- Settings β Repository secrets β add
GROQ_API_KEY.
- PDF instead of .txt: swap
parse_sections()insrc/knowledge_base.pyforPyPDFLoader+RecursiveCharacterTextSplitter, keep page number in metadata. - Scale beyond one instance: replace the in-memory
_sessionsdict inSupportAgentwith a Redis-backedChatMessageHistory. - New LLM provider: add a branch to
_load_llm()insrc/chat_agent.pyand an entry toPROVIDER_KEY_NAMESinapp.py.
MIT β use freely, attribution appreciated.