Skip to content

Repository files navigation

Course Copilot AI

A role-based, source-grounded AI course assistant for university project courses. Professors create courses, upload materials, and invite students. Students ask AI questions inside module workspaces and get citation-backed answers from course documents.

Team

Name GitHub Responsibilities
Dipesh Gupta dgupta98 Backend architecture, RAG pipeline, LLM integration (Anthropic Claude), embedding service, ChromaDB persistence, demo seed pipeline, cloud deployment (Render + Vercel), CI/CD, Docker setup, E2E tests, README
Rahul Reddy Chitla rchitla62 Frontend features (settings navigation, user icon routing), test suite maintenance, FastAPI/httpx compatibility fixes, frontend startup improvements
Anand Kumar akuma579 Settings pages (professor + student), password strength checklist, profile UI, professor dashboard course card UI
Vishesh Reddy Lekkala vlekkal3 Document ingestion integration (post-upload RAG trigger)

Repo: https://github.com/dgupta98/SER594-Team5-CourseCopilotAI


Deployment Status

Service URL
Frontend (Vercel) https://coursecopilotai.vercel.app/
Backend API (Render) https://ser594-team5-coursecopilotai.onrender.com
API Docs (Swagger) https://ser594-team5-coursecopilotai.onrender.com/docs

See the Cloud Deployment section for deployment instructions.


Development Environment

Required Tools

  • Docker Desktop (latest stable)
  • Docker Compose v2 (docker compose)
  • Git
  • Node.js and npm (optional on host — required only for host-side frontend build/test)
  • An Anthropic API key (set ANTHROPIC_API_KEY in .env)

Runtime Stack

Layer Technology
Frontend Next.js 15, React 19, TypeScript, Tailwind CSS
Backend FastAPI (Python 3.11+), SQLAlchemy, SQLite
Auth JWT (PyJWT), bcrypt
Vector Store ChromaDB (Docker service locally; embedded mode on Render)
LLM Anthropic Claude (claude-haiku-4-5-20251001)
Embeddings fastembed (BAAI/bge-small-en-v1.5, ONNX — no torch)
Document Parsing PyMuPDF, python-docx
Containerization Docker, Docker Compose

First-Time Setup

1. Clone and configure

git clone https://github.com/dgupta98/SER594-Team5-CourseCopilotAI.git
cd SER594-Team5-CourseCopilotAI
cp .env.example .env

Edit .env and set your Anthropic API key:

ANTHROPIC_API_KEY=sk-ant-...

2. Build and start (first time only)

./start.sh --build

This builds Docker images and starts all services. Takes 2–3 minutes the first time.

3. Verify services

Service URL
Frontend http://localhost:3000
Backend API http://localhost:8000
API Docs (Swagger) http://localhost:8000/docs
ChromaDB http://localhost:8001

Daily Usage

./start.sh          # start all services (fast, no rebuild)
./stop.sh           # stop all services
./start.sh --build  # rebuild images (needed after requirements.txt or package.json changes)

Architecture

CourseCopilotAI Architecture

Services

┌─────────────┐      ┌──────────────┐      ┌─────────────┐
│   Next.js   │─────▶│   FastAPI    │─────▶│   SQLite    │
│  Frontend   │      │   Backend    │      │  Database   │
│ :3000       │      │  :8000       │      └─────────────┘
└─────────────┘      └──────────────┘
                            │
                            ├─────▶ ChromaDB :8001      (vector store, Docker-only)
                            │         OR embedded ChromaDB (Render / no Docker)
                            │
                            └─────▶ Anthropic Claude API (LLM)

ChromaDB runs as a separate Docker service locally (port 8001). When CHROMA_HOST is empty the backend uses ChromaDB in embedded persistent mode — no separate service needed (used on Render).

Middleware Stack (applied in order)

  1. JWT Auth — validates token from Authorization: Bearer header or cookie; attaches user to request state
  2. Request Logging — structured JSON logs with method, path, user_id, status, and duration_ms
  3. Security Headers — X-Content-Type-Options, X-Frame-Options: DENY, HSTS
  4. Rate Limiting — 100 req/min general; 10 req/min for /chat/ask; per-user sliding 60s window

Project Structure

.
├── start.sh                    # Start all Docker services
├── stop.sh                     # Stop all Docker services
├── docker-compose.yml
├── Dockerfile.render           # Render-specific Dockerfile (bundles demo PDFs)
├── render.yaml                 # One-click Render backend deployment config
├── .env.example
├── CLAUDE.md                   # Developer reference (architecture, data flow, design decisions)
├── backend/
│   ├── Dockerfile
│   ├── requirements.txt
│   └── app/
│       ├── main.py             # FastAPI app entry point
│       ├── config.py           # Pydantic settings (reads from .env)
│       ├── database.py         # SQLAlchemy engine + session factory
│       ├── auth/               # JWT guards (require_role, require_course_ownership, etc.)
│       ├── middleware/         # Auth, logging, rate limit, security headers
│       ├── models/             # SQLAlchemy ORM models + Pydantic schemas
│       │   └── db_models.py    # includes DocumentChunk table for embedding persistence
│       ├── routers/            # auth, courses, modules, invitations, chat
│       ├── services/           # RAG pipeline, LLM, embeddings, chunking, vector store
│       └── tests/              # ~20+ test files covering all layers
└── frontend/
    └── src/
        ├── app/
        │   ├── page.tsx            # Landing page
        │   ├── login/              # Login page (includes one-click demo buttons)
        │   ├── register/           # Register page (role selection)
        │   ├── professor/
        │   │   ├── dashboard/      # Owned courses (card grid UI)
        │   │   ├── courses/        # Course detail, modules, students, invitations
        │   │   └── settings/       # Profile + password change with strength checklist
        │   └── student/
        │       ├── dashboard/      # Enrolled courses + pending invitations
        │       ├── courses/        # Module workspace (AI chat)
        │       └── settings/       # Profile + password change with strength checklist
        ├── components/
        │   ├── AppShell.tsx        # App layout shell; user icon navigates to settings
        │   └── NavBar.tsx          # Responsive sidebar/hamburger with accessibility
        ├── contexts/
        │   └── AuthContext.tsx     # JWT auth state + auto-refresh + localStorage hydration
        ├── hooks/
        │   ├── useAuth.ts
        │   └── useConversation.ts  # Chat state + optimistic message handling
        ├── lib/
        │   └── api.ts              # ApiClient (GET/POST/PUT/DELETE/uploadFile)
        └── types/
            └── index.ts            # TypeScript interfaces mirroring all backend models

Features

Professor

  • Register / login as professor
  • Create and manage courses (card-grid dashboard UI)
  • Add and reorder modules within courses
  • Upload documents (PDF, DOCX, TXT) to modules — processed asynchronously
  • Invite students by email (7-day expiry, duplicate prevention)
  • View enrolled students with Revoke access per student
  • View and manage pending invitations
  • Settings page: update profile and change password (with live password-strength checklist)

Student

  • Register / login as student
  • Accept or decline course invitations from dashboard
  • Browse enrolled courses and modules
  • Ask AI questions in module workspace
  • Get Markdown-rendered, citation-backed answers from course documents
  • Inline citation badges [1] [2] with modal viewer showing source chunk text
  • Relative timestamps: just now / 5m ago / 2h ago / 3d ago
  • Conversation history preserved across sessions
  • Settings page: update profile and change password (with live password-strength checklist)

Navigation

  • Clicking the user avatar/icon in the app shell navigates directly to the settings page
  • Responsive nav: hamburger menu on mobile, sidebar on desktop with focus trap and Escape-key close

AI Pipeline (RAG)

Document ingestion:

  1. Upload returns immediately (status = PENDING); processing runs in background
  2. Text extracted per-page (PDF with slide title prefix), paragraph (DOCX), or raw (TXT)
  3. Semantic chunking: sentences embedded → cosine similarity → topic boundaries detected at 25th percentile threshold → 400–2000 char chunks
  4. Chunks and their embeddings saved to the DocumentChunk table in the database for fast restore
  5. Embeddings stored in ChromaDB, scoped per module

Question answering:

  1. Broad vs. specific detection → retrieval strategy:
    • Broad: top_k=50, threshold=0.0
    • Specific: top_k=5, threshold=0.4
  2. No relevant context → "insufficient information" response
  3. Ambiguous question → clarification response
  4. 10 chunks → K-means cluster by topic, top-3 per cluster

  5. Claude (claude-haiku-4-5-20251001) generates answer with [Document: name, Chunk: N] citations
  6. Citations extracted, stored as JSON, rendered as clickable badges in UI

LLM response modes (inferred from question phrasing):

Mode Template
explain Key Idea / What This Means / Example / Check Your Understanding
summary Overview / Topics Covered / Check Your Understanding
step_by_step Numbered steps + worked example
quiz 3 self-check questions only
default Conversational, no forced template

Running the Service: Authentication and AI Technique

Authentication Flow

  1. Open http://localhost:3000
  2. Create an account from Register — select Professor to create courses, Student to join them
  3. Sign in from Login using email/password
  4. The frontend stores a JWT token in local storage (24h expiry, auto-refreshed when <1h remaining)

AI Technique: RAG Q&A in Module Workspace

The primary AI feature is Retrieval-Augmented Generation (RAG).

Recommended First-Time Test Flow

Create two accounts to test the full workflow:

Professor flow

  1. Register and log in as Professor
  2. Create a course
  3. Add at least one module
  4. Upload one or more documents (.pdf, .docx, .txt)
  5. Send an invitation to a student email

Student flow

  1. Register and log in as Student
  2. Accept the pending invitation from the dashboard
  3. Open the enrolled course → open the module workspace
  4. Ask a question about the uploaded documents

This exercises: authentication, course creation, module setup, document upload, asynchronous RAG processing, invitation handling, and AI question answering with citations.


Demo Accounts

When the backend starts for the first time it automatically seeds three demo accounts, two courses, and all course documents. No manual setup required.

Credentials

Role Name Email Password Courses
Professor Prof Dr Ajay Bansal prof@demo.coursepilot.com Demo@1234 SER-502, SER-594
Student Alex Chen alex@demo.coursepilot.com Demo@1234 SER-502, SER-594
Student Sam Rivera sam@demo.coursepilot.com Demo@1234 SER-502 only

Demo Courses

SER-502: Languages and Paradigms (professor-owned)

Module Document(s)
Module 1: Introduction M1.1_Introduction.pdf
Module 2: Language Design Criteria M1.2_Language_Design_Criteria.pdf
Module 3: Declarative Programming M1.3_Declarative_Programming.pdf
Module 4: Logic Programming M1.4_Logic_Programming.pdf

SER-594: AI for Software Engineers (professor-owned)

Module Document(s)
Module 1: Machine Learning Overview M1-ML_Overview.pdf
Module 2: Classification and Regression M2-Classification_Regression_V1.pdf · M2-Classification_Regression_V2.pdf
Module 3: Features and Dimensionality Reduction M3_FeaturesAndDimensionalityReduction.pdf
Module 4: Neural Networks M4_NeuralNetworks.pdf

PDFs are sourced from the SER-502/ and SER-594/ directories in the repo root, copied into the uploads tree, and ingested through the full RAG pipeline on first startup. The seed is resumable — if a restart interrupts it, it continues from where it left off rather than re-processing already-completed documents.


Cloud Deployment

Backend → Render (free tier)

A render.yaml and Dockerfile.render are included for one-click Render deployment.

  1. Push the repo to GitHub.
  2. In the Render dashboard, choose New → Blueprint and point it at the repo — Render reads render.yaml automatically.
  3. Set the following environment variables in the Render dashboard (not committed to the repo):
    • ANTHROPIC_API_KEY — your Anthropic key
    • ALLOWED_ORIGINS — your Vercel frontend URL, e.g. https://coursecopilotai.vercel.app
  4. Deploy. JWT_SECRET is auto-generated by Render.

Key differences from local Docker:

  • CHROMA_HOST is empty → ChromaDB runs in embedded persistent mode (no separate service).
  • DocumentChunk table persists chunk embeddings to the database, so ChromaDB is restored in seconds from the DB on every restart — no re-embedding cost.
  • The seed pipeline is resumable: interrupted seeding continues from the last completed document on the next restart.

Frontend → Vercel

  1. Import the repo on Vercel.
  2. Set the root directory to frontend.
  3. Add the environment variable: NEXT_PUBLIC_API_BASE_URL=https://ser594-team5-coursecopilotai.onrender.com
  4. Deploy.

Environment Variables

Full reference (see .env.example for a ready-to-copy template):

Variable Default Description
APP_ENV development development or production
DATABASE_URL sqlite:///./course_copilot.db SQLite (dev) or PostgreSQL URL (prod)
JWT_SECRET — Secret for signing JWTs; auto-generated by Render
JWT_ALGORITHM HS256 JWT signing algorithm
ACCESS_TOKEN_EXPIRE_MINUTES 1440 Token lifetime (24 h)
ANTHROPIC_API_KEY — Required. Anthropic API key
ANTHROPIC_MODEL claude-haiku-4-5-20251001 Claude model ID
CHROMA_HOST `` (empty) Empty → embedded ChromaDB; http://chromadb:8000 when using Docker Compose
CHROMA_PERSIST_DIR ./chroma_data Path for ChromaDB persistence
ALLOWED_ORIGINS http://localhost:3000,... Comma-separated CORS origins; add Vercel URL for production
UPLOAD_DIR ./uploads Document upload directory
MAX_FILE_SIZE_MB 50 Maximum upload size
NEXT_PUBLIC_API_BASE_URL http://localhost:8000 Backend URL seen by the browser

Testing

Run locally

# All backend tests
cd backend
pytest

# With coverage report
pytest tests/ --cov=app --cov-report=term-missing

# Specific file
pytest tests/test_chat_router.py -v

# Filter by name
pytest tests/ -k "rag" -v

423 tests across 27 files covering every layer: auth, all routers, RAG pipeline (ingestion + MMR reranking), LLM service, chunking, embedding, vector store, text extraction, middleware, data models, and end-to-end workflows.

CI — runs on every push

▶ View Test Suite Runs

The Test Suite GitHub Actions workflow runs on every push and pull request:

  • black --check — enforces consistent formatting
  • pytest --cov=app — runs all 423 tests with coverage report
  • Coverage XML uploaded as a downloadable artifact on each run
Where to view How
Live run logs + coverage summary Actions tab → Test Suite → select run → backend-tests job
Coverage XML artifact Actions tab → select run → scroll to Artifacts → download coverage-report

Evaluation Suite

The eval/ directory measures RAG pipeline quality using LLM-as-judge metrics across 8 fixed questions, with a zero-shot baseline comparison.

Pre-computed results are committed at eval/eval_results.json — inspect scores directly without running anything.

RAG Evaluation Metrics

Metric RAG Baseline What it measures
Response Relevancy 0.803 0.740 Does the answer directly address the question?
Faithfulness 0.797 0.000 Are all claims grounded in retrieved course chunks?
Context Precision 0.719 0.000 Are the most relevant chunks ranked first?
Context Recall 0.337 0.000 Do the retrieved chunks cover the reference answer?

Each question is run twice — RAG pipeline (embed → MMR rerank → generate with context) vs zero-shot baseline (no retrieval) — proving the concrete improvement retrieval provides.

Run via GitHub Actions (recommended)

▶ Run RAG Evaluation

No local setup needed. The workflow:

  1. Seeds an embedded ChromaDB with all 8 demo module PDFs
  2. Runs all 8 questions × 2 passes (RAG + baseline) — ~15–25 min
  3. Posts a formatted results table as the Job Summary
  4. Commits eval/eval_results.json back to the repo automatically
Where to view results How
Formatted table (Job Summary) Actions tab → RAG Evaluation → select run → Summary
Downloadable JSON Actions tab → select run → Artifacts → eval-results
Committed JSON (permanent) eval/eval_results.json in this repo

Run locally

# 1. Start all services (seeds ChromaDB with demo course data on first run)
./start.sh

# 2. Run the RAG evaluation (8 questions × RAG + baseline)
python eval/run_eval.py

# 3. Run system evaluation (latency p50/p95 + error rate)
python eval/system_eval.py

See eval/README.md for full methodology, metric definitions, and output format.


Troubleshooting

"Failed to fetch" on dashboard

docker compose ps                            # check all containers are Up
curl http://localhost:8000/health            # check backend
./stop.sh && ./start.sh                      # restart if needed

Document stuck in PENDING/PROCESSING

docker compose logs backend --tail=50        # look for extraction or ChromaDB errors
# POST /documents/{id}/reprocess to retry

AI responses not using document content

  • Confirm document status is COMPLETE (visible in module documents list)
  • Check that the question is specific enough — vague questions may return "insufficient information"

Anthropic API errors

  • Verify ANTHROPIC_API_KEY is set correctly in .env
  • Check the key has not expired or hit its usage limit

Need to rebuild after dependency changes

./stop.sh
./start.sh --build

View logs

docker compose logs backend --tail=50
docker compose logs frontend --tail=50

Reset demo data (local)

./stop.sh
rm -f backend/course_copilot.db
rm -rf chroma_data
./start.sh --build

License

Developed as part of SER 594 coursework at Arizona State University.

About

A source-grounded course assistant that answers student questions from syllabus and milestone documents, remembers prior context, and escalates unclear cases to TAs or professors.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages