Shameed4/USG_Chatbot

1

stars

23

commits

Python

primary language

May 13, 2026

updated

usg-chatbot-delta.vercel.app

README

USG Chatbot

A RAG chatbot that answers questions about Stony Brook University's Undergraduate Student Government (USG) by reasoning over its real governing documents — the constitution, financial bylaws, procedural manual, standing committee bylaws, and weekly senate meeting minutes.

USG governs how millions of dollars of student activity fees are allocated, and the rules live across dozens of long, jargon-heavy documents. Students and club treasurers routinely need answers like "what's the procedure for requesting a budget reallocation?" or "how did Senator X vote on the IFC budget?" — questions that take a human 20 minutes of cross-referencing PDFs to answer. This project is that human.

Live demo: usg-chatbot.vercel.app — backend is on Render's free tier, so the first request after idle takes ~30s to wake up.

How it works

It's not just naive vector search. The backend is an agentic RAG system where gpt-5.4-mini picks from four retrieval tools depending on the question:

ToolWhen the agent uses it
rag_retrieval_toolSemantic search over FAISS — for conceptual "how do I…" questions
search_directory_toolRegex across a whole folder (e.g. all meeting minutes) — for finding every mention of a person or topic
file_tool (search mode)Regex inside one known file — for precise keyword lookup
file_tool (read_range mode)Read specific line ranges — to pull surrounding context after a match
list_files_toolEnumerates the document set so the model never guesses filenames

The system prompt enforces a three-pass search protocol for questions like voting records: a direct keyword pass, an implicit-group pass (catching "the senate unanimously voted…" when the question was about a specific senator), then a context-resolution pass that expands the read window until the surrounding text actually identifies what was being voted on. This solved the biggest failure mode of pure RAG — confidently answering with chunks that lack enough context to be correct.

Architecture

   Next.js (App Router, React 19, Tailwind)
              │  POST /chat  (SSE stream)
              ▼
   Flask + flask-cors
              │
              ▼
   Agent loop (agent_chatbot.py)
   ├─ gpt-5.4-mini function-calling (up to 15 tool turns)
   ├─ FAISS IndexFlatL2 + text-embedding-3-small
   └─ Sandboxed filesystem tools over /documents
              │
              ▼
   Streamed tokens → SSE → React markdown renderer

Things worth calling out

  • Incremental indexing. vector_creation.py hashes every source file (SHA-256) and stores a per-file → FAISS-ID map in index_state.json. Re-running the build only re-embeds files whose hash changed, and deletes vectors for removed files by reconstructing the index without them. Embedding ~hundreds of chunks against OpenAI isn't free; this makes iteration cheap.
  • Streaming end-to-end. The Flask endpoint streams Server-Sent Events; the frontend renders tokens as they arrive and surfaces the retrieved RAG chunks as citations once the model commits to a final answer.
  • Automated document ingestion. fetch_documents.py authenticates with Google Drive via OAuth, exports the USG senate's shared folder of Google Docs and Sheets, and recursively follows hyperlinks inside those documents to pull in linked bylaws and budget sheets — so the corpus stays in sync with what USG actually publishes.
  • Defensive file access. All filesystem tools resolve paths through os.path.realpath and reject any path that escapes documents/, so the agent can't be prompt-injected into reading .env or token.json.
  • Failure-aware prompting. The system prompt includes an explicit recovery protocol — what to do when a tool returns "file not found" or "no matches" — so the agent retries with a broader strategy instead of giving up.

Tech stack

Backend: Python, Flask, OpenAI (gpt-5.4-mini, text-embedding-3-small), FAISS, tiktoken, Google Drive / Docs / Sheets APIs Frontend: Next.js 15, React 19, TypeScript, Tailwind CSS v4, react-markdown Deployment: Vercel (frontend), Render (backend)

Project layout

app.py                  Flask server + SSE streaming
agent_chatbot.py        Agent loop, tool definitions, RAG retrieval
vector_creation.py      Incremental FAISS index builder
fetch_documents.py      Google Drive ingestion pipeline
prompt.txt              System prompt (search protocol)
documents/              Source corpus (bylaws, minutes, budgets)
frontend/               Next.js app

Running it locally

Prereqs: Python 3.8+, Node 18+, an OpenAI API key.

# Backend
python -m venv venv && source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -r requirements.txt
echo 'OPENAI_API_KEY="sk-..."' > .env
python vector_creation.py    # builds faiss_index.faiss from documents/
python app.py                # serves on :5001

# Frontend (separate terminal)
cd frontend && npm install && npm run dev   # serves on :3000

If faiss-cpu won't install via pip, use conda: conda install -c conda-forge faiss-cpu.

To re-sync the corpus from USG's Google Drive, drop a Google Cloud OAuth credentials.json in the project root and run python fetch_documents.py.

Contributors

Shameed4

21 commits

RawesomE54

1 commits

vercel[bot]

1 commits

Shameed4/USG_Chatbot

1

stars

23

commits

Python

primary language

May 13, 2026

updated

usg-chatbot-delta.vercel.app

README

USG Chatbot

A RAG chatbot that answers questions about Stony Brook University's Undergraduate Student Government (USG) by reasoning over its real governing documents — the constitution, financial bylaws, procedural manual, standing committee bylaws, and weekly senate meeting minutes.

USG governs how millions of dollars of student activity fees are allocated, and the rules live across dozens of long, jargon-heavy documents. Students and club treasurers routinely need answers like "what's the procedure for requesting a budget reallocation?" or "how did Senator X vote on the IFC budget?" — questions that take a human 20 minutes of cross-referencing PDFs to answer. This project is that human.

Live demo: usg-chatbot.vercel.app — backend is on Render's free tier, so the first request after idle takes ~30s to wake up.

How it works

It's not just naive vector search. The backend is an agentic RAG system where gpt-5.4-mini picks from four retrieval tools depending on the question:

ToolWhen the agent uses it
rag_retrieval_toolSemantic search over FAISS — for conceptual "how do I…" questions
search_directory_toolRegex across a whole folder (e.g. all meeting minutes) — for finding every mention of a person or topic
file_tool (search mode)Regex inside one known file — for precise keyword lookup
file_tool (read_range mode)Read specific line ranges — to pull surrounding context after a match
list_files_toolEnumerates the document set so the model never guesses filenames

The system prompt enforces a three-pass search protocol for questions like voting records: a direct keyword pass, an implicit-group pass (catching "the senate unanimously voted…" when the question was about a specific senator), then a context-resolution pass that expands the read window until the surrounding text actually identifies what was being voted on. This solved the biggest failure mode of pure RAG — confidently answering with chunks that lack enough context to be correct.

Architecture

   Next.js (App Router, React 19, Tailwind)
              │  POST /chat  (SSE stream)
              ▼
   Flask + flask-cors
              │
              ▼
   Agent loop (agent_chatbot.py)
   ├─ gpt-5.4-mini function-calling (up to 15 tool turns)
   ├─ FAISS IndexFlatL2 + text-embedding-3-small
   └─ Sandboxed filesystem tools over /documents
              │
              ▼
   Streamed tokens → SSE → React markdown renderer

Things worth calling out

  • Incremental indexing. vector_creation.py hashes every source file (SHA-256) and stores a per-file → FAISS-ID map in index_state.json. Re-running the build only re-embeds files whose hash changed, and deletes vectors for removed files by reconstructing the index without them. Embedding ~hundreds of chunks against OpenAI isn't free; this makes iteration cheap.
  • Streaming end-to-end. The Flask endpoint streams Server-Sent Events; the frontend renders tokens as they arrive and surfaces the retrieved RAG chunks as citations once the model commits to a final answer.
  • Automated document ingestion. fetch_documents.py authenticates with Google Drive via OAuth, exports the USG senate's shared folder of Google Docs and Sheets, and recursively follows hyperlinks inside those documents to pull in linked bylaws and budget sheets — so the corpus stays in sync with what USG actually publishes.
  • Defensive file access. All filesystem tools resolve paths through os.path.realpath and reject any path that escapes documents/, so the agent can't be prompt-injected into reading .env or token.json.
  • Failure-aware prompting. The system prompt includes an explicit recovery protocol — what to do when a tool returns "file not found" or "no matches" — so the agent retries with a broader strategy instead of giving up.

Tech stack

Backend: Python, Flask, OpenAI (gpt-5.4-mini, text-embedding-3-small), FAISS, tiktoken, Google Drive / Docs / Sheets APIs Frontend: Next.js 15, React 19, TypeScript, Tailwind CSS v4, react-markdown Deployment: Vercel (frontend), Render (backend)

Project layout

app.py                  Flask server + SSE streaming
agent_chatbot.py        Agent loop, tool definitions, RAG retrieval
vector_creation.py      Incremental FAISS index builder
fetch_documents.py      Google Drive ingestion pipeline
prompt.txt              System prompt (search protocol)
documents/              Source corpus (bylaws, minutes, budgets)
frontend/               Next.js app

Running it locally

Prereqs: Python 3.8+, Node 18+, an OpenAI API key.

# Backend
python -m venv venv && source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -r requirements.txt
echo 'OPENAI_API_KEY="sk-..."' > .env
python vector_creation.py    # builds faiss_index.faiss from documents/
python app.py                # serves on :5001

# Frontend (separate terminal)
cd frontend && npm install && npm run dev   # serves on :3000

If faiss-cpu won't install via pip, use conda: conda install -c conda-forge faiss-cpu.

To re-sync the corpus from USG's Google Drive, drop a Google Cloud OAuth credentials.json in the project root and run python fetch_documents.py.

Contributors

Shameed4

21 commits

RawesomE54

1 commits

vercel[bot]

1 commits

Languages

Python

77.2%

TypeScript

21.7%