How ranger-drax/ai-powered-chatbot works
1. The repo is split into two independent runtimes plus an offline data pipeline.
The Python side contains both the ingestion/build pipeline (src/) and the serving backend (backend/). The TypeScript side is a separate Next.js frontend (frontend/). They communicate only through the backend HTTP API.
2. The knowledge base is built offline from local course files.
Raw university documents live outside version control in raw/. The pipeline converts them into persistent artifacts in storage/ and vector_store/chroma/, which are then read at runtime. This is a clear boundary: ingestion writes the index, chat serving only reads it.
3. Ingestion is a 3-stage document pipeline.
Stage 1 parses PDFs/DOCX/PPTX into structured elements using Unstructured.io and LlamaIndex. Stage 2 turns those elements into overlap-aware chunks while preserving metadata. Stage 3 embeds chunks with all-MiniLM-L6-v2 and stores them in a local ChromaDB collection named course_knowledge.
4. The src/ingestion package holds the reusable ingestion plumbing.
It contains file discovery, loader integrations, settings, and utility code. The stage scripts (stage1_ingest.py, stage2_chunk.py, stage3_embed_store.py) orchestrate these helpers, while stage4_retrieval_test.py and stage5_rag_answer_groq.py are CLI validation tools for the retrieval and full RAG paths.
5. The backend is a small FastAPI service centered on one chat endpoint.
backend/main.py creates the app, applies startup/lifespan setup, and configures CORS for the frontend. backend/routers/chat.py exposes POST /api/chat. Pydantic models in backend/models/schemas.py define the request and response shapes.
6. The runtime answer flow is retrieval-augmented generation, not direct LLM chat.
The chat service in backend/services/rag_service.py embeds the user question, searches Chroma for relevant chunks, and then sends the retrieved context plus the question to Groq’s hosted LLM (llama-3.3-70b-versatile). The answer returned to the client includes both generated text and provenance data.
7. Course detection is a separate preprocessing step before retrieval.
backend/services/course_detection.py looks for course code patterns like CSE220, CSE 220, CSE-220, or HST103. If a code is found, it resolves it to the indexed metadata course name and switches retrieval into a course-filtered mode; if not, retrieval falls back to a global search over all chunks.
8. The retrieval boundary is local and persistent.
ChromaDB is the only runtime datastore. There is no separate application database. The backend reads from the local Chroma collection, uses a distance threshold to decide whether the retrieved context is good enough, and can return a fallback message when evidence is weak.
9. The frontend is a thin chat shell with no knowledge-base logic.
frontend/app/page.tsx composes the page layout and state. ChatWindow, ChatInput, MessageBubble, and Sidebar handle presentation. frontend/lib/api.ts is the only client-side integration point to the backend. The UI accepts just a question; it does not expose course selection.
10. The user-facing API is intentionally minimal, but the response is rich.
The frontend sends question and optionally session_id. The backend response includes answer, status, detected_course_code, resolved_course, retrieval_mode, retrieved_chunks, best_distance, and sources. Those fields are the main outputs you’d want to show on an architecture diagram.
11. Operationally, the system is designed to run locally with environment-based configuration.
The important runtime dependencies are the Groq API key, the Chroma directory path, embedding model name, retrieval top-k, and token/context limits. Generated data and secrets are excluded from git, so a fresh clone needs either rebuilt embeddings or a copied Chroma store.
12. Tests focus on the orchestration boundary, not external services.
tests/test_chat.py mocks Chroma retrieval and Groq calls, so the normal test suite does not depend on raw documents or live API access. Live RAG checks are optional and gated by environment variables.
Main entry points: chat.py Chat route · rag_service.py RAG service · stage3_embed_store.py Embed stage · api.ts API client
Components 19
Offline ingestion
Builds the local knowledge base from raw course documents into persistent retrieval artifacts.
- Raw docs · Local university PDFs, DOCX, and PPTX sources kept outside version control.
- Discover files · Finds and enumerates source documents for the build pipeline.
src/ingestion/discover.py - Document loaders · Wraps Unstructured.io and LlamaIndex loaders for structured document extraction.
src/ingestion/unstructured_loader.py - Chunk stage · Builds overlap-aware chunks while preserving document metadata.
src/stage2_chunk.py - Embed stage · Embeds chunks with all-MiniLM-L6-v2 and stores vectors locally.
src/stage3_embed_store.py - Storage · Serialized intermediate and derived ingestion artifacts used by the offline pipeline.
- Chroma index · Local ChromaDB collection named course_knowledge containing embedded course chunks.
- Retrieval test · Checks the retrieval path from the local index without full answer generation.
src/stage4_retrieval_test.py - RAG check · Runs an end-to-end local retrieval and Groq answer sanity check.
src/stage5_rag_answer_groq.py
FastAPI backend
Serves chat requests and performs retrieval-augmented generation over the local index.
- FastAPI app · Creates the backend application, lifecycle hooks, and CORS policy.
backend/main.py - Chat route · Exposes the POST /api/chat endpoint for the frontend.
backend/routers/chat.py - API models · Defines request and response payload shapes for chat interactions.
backend/models/schemas.py - Course detect · Detects course codes and resolves them to indexed course names for filtered retrieval.
backend/services/course_detection.py - RAG service · Embeds the query, retrieves evidence from Chroma, and calls Groq to generate the answer.
backend/services/rag_service.py
Next.js frontend
Thin user interface that sends questions to the backend API.
- Page shell · Composes the chat page layout and top-level UI state.
frontend/app/page.tsx - Chat window · Displays conversation history and response state.
frontend/components/ChatWindow.tsx - Chat input · Captures the user's question before sending it to the backend.
frontend/components/ChatInput.tsx - API client · Single client-side integration point to the backend chat API.
frontend/lib/api.ts - Sidebar · Supporting chat UI chrome and presentation.
frontend/components/Sidebar.tsx
Connections 22
- Raw docs → Discover files: source files · The pipeline starts from local raw course documents.
- Discover files → Document loaders: load · Discovered documents are parsed into structured elements.
- Document loaders → Chunk stage: elements · Structured elements are converted into metadata-preserving chunks.
- Chunk stage → Embed stage: chunks · Chunks are embedded and prepared for persistence.
- Embed stage → Storage: artifacts · Intermediate and derived artifacts are written to local storage.
- Embed stage → Chroma index: vectors · Embedded chunks are stored in the local Chroma collection.
- Storage → Retrieval test: read · Validation tools inspect stored artifacts and retrieval behavior.
- Chroma index → Retrieval test: query · Retrieval is tested directly against the local index.
- Chroma index → RAG check: query · The full RAG check uses the same persisted vector store.
- FastAPI app → Chat route: mounts · The FastAPI app registers the chat router.
- Chat route → API models: validates · Request and response payloads are shaped by Pydantic models.
- Chat route → RAG service: delegates · The route forwards chat requests to the answer service.
- RAG service → Course detect: detects course · The answer flow first attempts course-code detection and resolution.
- Course detect → Chroma index: metadata lookup · Resolved course names come from indexed metadata in the local store.
- RAG service → Chroma index: retrieve · The service searches the vector store for relevant chunks.
- RAG service → Chat route: answer payload · Generated text and provenance are returned to the route.
- Page shell → Chat window: renders · The page shell composes the main chat display.
- Page shell → Chat input: renders · The page shell includes the question input control.
- Chat input → API client: send question · User questions are sent through the client API layer.
- API client → Chat route: POST /api/chat · The frontend calls the backend chat endpoint over HTTP.
- API client → Chat window: update UI · Responses are reflected back into the conversation view.
- Sidebar → Page shell: page chrome · Supporting UI elements are part of the same page shell.