Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

36 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧭 IUE CourseCompass

Python 3.11+ License: MIT Code style: black

A Retrieval-Augmented Generation (RAG) system for querying course information at Izmir University of Economics' Faculty of Engineering.

Ever had trouble navigating course catalogs, figuring out prerequisites, or comparing programs across departments? CourseCompass helps you ask natural language questions about courses and get accurate, citation-backed answers.


πŸ“‹ Table of Contents


✨ Features

Feature Description
🌐 Web Scraping Automated scraping of IUE ECTS course catalogs with rate limiting and caching
πŸ“ Smart Chunking Semantic text chunking that respects document structure and maintains context
πŸ” Vector Search ChromaDB-powered semantic search with SBERT (free, local) or Gemini embeddings
πŸ€– Grounded Generation Gemini-powered answers that cite their sources - no hallucinations
πŸ›‘οΈ Hallucination Prevention Built-in grounding verification and "trap question" detection
πŸ“Š Evaluation Suite Comprehensive metrics including MRR, Recall@K, and grounding rate
πŸ–₯️ Streamlit GUI Interactive web interface for queries, comparisons, and data management
⌨️ CLI Full command-line interface for automation and scripting

πŸ”¬ How It Works

CourseCompass uses a RAG (Retrieval-Augmented Generation) pipeline to answer questions about IUE engineering courses:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           User Interfaces                                   β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚
β”‚                    β”‚  Streamlit  β”‚      β”‚     CLI     β”‚                     β”‚
β”‚                    β”‚     GUI     β”‚      β”‚   (Typer)   β”‚                     β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚                      β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          RAG Pipeline                                       β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚   β”‚ Retrieverβ”‚ β†’ β”‚ Prompts  β”‚ β†’ β”‚Generator β”‚ β†’ β”‚  Grounding  β”‚             β”‚
β”‚   β”‚          β”‚   β”‚ Builder  β”‚   β”‚ (Gemini) β”‚   β”‚   Checker   β”‚             β”‚
β”‚   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Indexing Layer                                       β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚   β”‚ Vector Store β”‚   β”‚  Embeddings  β”‚   β”‚     Manifest     β”‚               β”‚
β”‚   β”‚  (ChromaDB)  β”‚   β”‚ SBERT/Gemini β”‚   β”‚     Manager      β”‚               β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β–²
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Ingestion Pipeline                                    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
β”‚   β”‚ Scraper  β”‚ β†’ β”‚  Parser  β”‚ β†’ β”‚ Cleaner  β”‚ β†’ β”‚ Chunker  β”‚                β”‚
β”‚   β”‚ (ECTS)   β”‚   β”‚  (HTML)  β”‚   β”‚  (Text)  β”‚   β”‚(Semantic)β”‚                β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The flow:

  1. Scrape β†’ Pull course data from IUE's ECTS portal
  2. Parse & Clean β†’ Extract structured information from HTML
  3. Chunk β†’ Split content into semantic chunks for better retrieval
  4. Embed β†’ Convert chunks to vectors using SBERT or Gemini
  5. Retrieve β†’ Find relevant chunks using semantic similarity
  6. Generate β†’ Create grounded answers with citations

πŸš€ Quick Start

Prerequisites

  • Python 3.11+
  • Gemini API Key - Get one free at Google AI Studio (required for answer generation)

Installation

# Clone the repository
git clone https://github.com/mirzaisi/IUE_CourseCompass.git
cd IUE_CourseCompass

# Create and activate virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install the package
pip install -e ".[dev]"

# Set up your API key
cp .env.example .env
# Edit .env and add your GEMINI_API_KEY

First Run

# 1. Scrape course data (takes ~5 minutes)
coursecompass scrape

# 2. Build the search index
coursecompass index --provider sbert  # Free, runs locally

# 3. Start asking questions!
coursecompass query "What are the prerequisites for SE 301?"

# Or launch the web interface
coursecompass gui

πŸ“– Usage

Command Line Interface

# Get system info and status
coursecompass info

# Scrape all departments
coursecompass scrape

# Scrape specific department
coursecompass scrape --department se

# Build index with different embedding providers
coursecompass index --provider sbert   # Free, local (default)
coursecompass index --provider gemini  # Requires API key, better quality

# Ask questions
coursecompass query "What courses cover machine learning?"
coursecompass query "Compare SE and CE database courses" --department se --department ce

# Run the evaluation suite
coursecompass eval --questions data/evaluation_questions.json

Web Interface

Launch the Streamlit GUI for an interactive experience:

coursecompass gui
# Or: make app

The GUI provides:

  • πŸ’¬ Natural language Q&A with source citations
  • πŸ”„ Cross-department course comparisons
  • πŸ“Š Retrieval statistics and confidence scores
  • βš™οΈ Data management (scrape, index, configure)

Python API

from iue_coursecompass.rag import Retriever, Generator
from iue_coursecompass.rag.grounding import check_grounding

# Initialize components
retriever = Retriever()
generator = Generator()

# Retrieve relevant chunks
query = "What is SE 301 about?"
hits = retriever.retrieve(query, top_k=5)

# Generate a grounded answer
response = generator.generate(query, hits)
print(response.answer)

# Verify the answer is grounded in sources
grounding = check_grounding(response.answer, hits)
print(f"Grounded: {grounding.is_grounded} (score: {grounding.grounding_score:.2f})")

βš™οΈ Configuration

Configuration is split between config/settings.yaml and environment variables:

Environment Variables (.env)

# Required for answer generation
GEMINI_API_KEY=your-api-key-here

# Optional: Override defaults
EMBEDDING_PROVIDER=sbert  # or "gemini"
GEMINI_MODEL=gemini-2.0-flash-exp
RETRIEVAL_TOP_K=5

Settings File (config/settings.yaml)

# Departments to scrape
departments:
  - id: "se"
    name: "Software Engineering"
  - id: "ce" 
    name: "Computer Engineering"
  - id: "eee"
    name: "Electrical & Electronics Engineering"
  - id: "ie"
    name: "Industrial Engineering"

# Retrieval settings
retrieval:
  top_k: 5
  similarity_threshold: 0.3

# Generation settings
generation:
  model_name: "gemini-2.0-flash-exp"
  temperature: 0.3

πŸ“ Project Structure

IUE_CourseCompass/
β”œβ”€β”€ config/
β”‚   └── settings.yaml          # Main configuration
β”œβ”€β”€ src/iue_coursecompass/
β”‚   β”œβ”€β”€ ingestion/             # Data pipeline
β”‚   β”‚   β”œβ”€β”€ scraper.py         # Web scraper with caching
β”‚   β”‚   β”œβ”€β”€ parser.py          # HTML β†’ structured data
β”‚   β”‚   β”œβ”€β”€ cleaner.py         # Text normalization
β”‚   β”‚   └── chunker.py         # Semantic chunking
β”‚   β”œβ”€β”€ indexing/              # Vector storage
β”‚   β”‚   β”œβ”€β”€ embeddings_sbert.py   # Local SBERT embeddings
β”‚   β”‚   β”œβ”€β”€ embeddings_gemini.py  # Gemini API embeddings
β”‚   β”‚   β”œβ”€β”€ vector_store.py       # ChromaDB wrapper
β”‚   β”‚   └── manifest.py           # Index versioning
β”‚   β”œβ”€β”€ rag/                   # RAG pipeline
β”‚   β”‚   β”œβ”€β”€ retriever.py       # Semantic search
β”‚   β”‚   β”œβ”€β”€ prompts.py         # Prompt engineering
β”‚   β”‚   β”œβ”€β”€ generator.py       # LLM generation
β”‚   β”‚   β”œβ”€β”€ grounding.py       # Citation verification
β”‚   β”‚   └── quantitative.py    # Counting queries
β”‚   β”œβ”€β”€ evaluation/            # Testing & metrics
β”‚   β”‚   β”œβ”€β”€ questions.py       # Question bank
β”‚   β”‚   β”œβ”€β”€ metrics.py         # MRR, Recall@K, etc.
β”‚   β”‚   └── runner.py          # Evaluation harness
β”‚   β”œβ”€β”€ app/                   # Streamlit GUI
β”‚   └── cli/                   # Command-line interface
β”œβ”€β”€ tests/                     # Unit & integration tests
β”œβ”€β”€ data/                      # Data directory (gitignored)
β”œβ”€β”€ pyproject.toml             # Package config & dependencies
β”œβ”€β”€ Makefile                   # Common commands
└── README.md

πŸ“Š Evaluation

The evaluation suite measures both retrieval quality and generation accuracy:

Metric What it Measures
MRR Mean Reciprocal Rank - how high relevant results appear
Recall@K Fraction of relevant docs found in top-K results
Precision@K Fraction of top-K results that are relevant
Hit Rate Queries with at least one relevant result
Grounding Rate Answers properly cited from sources
Trap Accuracy Correctly refusing to answer unanswerable questions

Run the evaluation:

# Run full evaluation
coursecompass eval --questions data/evaluation_questions.json

# Output results to file
coursecompass eval --output results.json

πŸ› οΈ Development

Setup

# Install with dev dependencies
pip install -e ".[dev]"

# Set up pre-commit hooks (optional)
pre-commit install

Code Quality

# Lint code
make lint

# Format code
make format

# Type checking
make typecheck

# Run all checks
make check

Testing

# Run tests
make test

# Run with coverage
make test-cov
pytest tests/ -v --cov=src/iue_coursecompass --cov-report=html

🀝 Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Test your changes (make lint && make test)
  5. Commit (git commit -m 'Add amazing feature')
  6. Push (git push origin feature/amazing-feature)
  7. Open a Pull Request

Please make sure your code passes linting and tests before submitting.


πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ™ Acknowledgments


Made with β˜• for IUE Engineering students

About

Project for Artificial Intelligence and Expert Systems course. A multi-department Retrieval-Augmented Generation system that scrapes, cleans, embeds, and semantically indexes IUE Engineering course/curriculum pages to answer department-specific questions and produce grounded cross-department comparisons with transparent sources.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages