Authors:
This project implements a context-aware travel recommendation system designed to surface "off-the-beaten-path" destinations. Unlike traditional recommendation engines that favor popular tourist spots, our system identifies hidden gems by analyzing travel blogs, structured attributes, and popularity signals to recommend lesser-known destinations that match user interests.
The application combines:
All components are containerized using Docker and orchestrated with Docker Compose for easy deployment and reproducibility.
dsan6700_app_dev_project/
│
├── backend/
│ ├── Dockerfile.api # API container definition
│ ├── configs/
│ │ └── app_config.yaml # Application configuration
│ ├── off_the_path/ # Core package
│ ├── src/
│ │ ├── api/
│ │ │ ├── main.py # FastAPI endpoints
│ │ │ ├── bm25_utils.py # BM25 search utilities
│ │ │ └── __init__.py
│ │ └── features/
│ │ └── engineer.py # Feature engineering
│ └── pyproject.toml # Python dependencies
│
├── frontend/
│ ├── Dockerfile.streamlit # Frontend container definition
│ └── streamlit_app/
│ └── app.py # Streamlit UI
│
├── .dockerignore # Files to ignore in Docker builds
├── .gitignore # Files to ignore in Git
├── .env # Environment variables (DATABASE_URL)
├── docker-compose.yml # Orchestrates all services
└── README.md # This file
BM25 (Best Match 25) is a ranking function used by search engines to estimate the relevance of documents to a given search query. Our implementation:
How It Works:
rank-bm25Features:
A transformer-based semantic retrieval and re-ranking model that captures the meaning of user queries and travel narratives, enabling discovery of destinations that align with “off-the-beaten-path” intent beyond surface-level keyword overlap.
How it Works
Model Capabilities:
Outputs:
The application consists of two Docker containers:
Frontend (Streamlit)
API Layer (FastAPI)
Database
DATABASE_URL environment variableBefore running this project, ensure you have:
Docker Desktop (Windows/Mac) or Docker Engine (Linux)
Docker Compose
Verify Installation:
# Check Docker version
docker --version
# Check Docker Compose version
docker-compose --version
# Verify Docker is running
docker ps
1. Clone the Repository:
# Clone the project repository
git clone https://github.com/your-org/dsan6700_app_dev_project.git
# Navigate to project directory
cd dsan6700_app_dev_project
2. Set Up Environment Variables:
Create a .env file in the project root with your database connection:
DATABASE_URL=postgresql://user:password@host:port/database
3. Build and Start All Services:
# Build images and start containers
docker-compose up --build
# OR run in detached mode (background)
docker-compose up --build -d
What This Does:
backend/Dockerfile.apifrontend/Dockerfile.streamlit4. Wait for Services to Initialize:
The first BM25 search will load ~XX,XXX blog posts from the database and build the index. This takes approximately 30-60 seconds.
Once containers are running:
Travel Recommender Web Interface:
API Documentation:
Health Check:
Check Running Containers:
# View all running containers
docker-compose ps
# Expected output:
# NAME IMAGE STATUS PORTS
# api dsan6700_app_dev_project-api Up 0.0.0.0:8081->8000/tcp
# streamlit dsan6700_app_dev_project-streamlit Up 0.0.0.0:8501->8501/tcp
View Container Logs:
# View logs for all services
docker-compose logs
# View logs for specific service
docker-compose logs api
docker-compose logs streamlit
# Follow logs in real-time (Ctrl+C to exit)
docker-compose logs -f
# View last 50 lines
docker-compose logs --tail=50
Monitor Resource Usage:
# View CPU, memory, and network usage
docker stats
Inspect Container Details:
# List all Docker containers (including stopped)
docker ps -a
# Execute commands inside container
docker exec -it api bash
Stop Containers (Preserves Data):
# Stop all services
docker-compose down
# Stop specific service
docker-compose stop api
Complete Cleanup (Remove Everything):
# Stop containers and remove volumes
docker-compose down -v
# Remove all unused Docker resources
docker system prune -a --volumes
Restart Services:
# Restart all services
docker-compose restart
# Restart specific service
docker-compose restart api
Open your browser and navigate to http://localhost:8501
Choose between:
Query:
Filters:
The application returns:
Results Tab:
Maps Tab:
Diagnostics Tab:
You can also interact directly with the API:
BM25 Search:
curl -X POST "http://localhost:8081/search" \
-H "Content-Type: application/json" \
-d '{
"query": "temples in Kyoto Japan",
"retrieval": {
"model": "bm25",
"k": 10
}
}'
Attribute+Context Search:
curl -X POST "http://localhost:8081/search" \
-H "Content-Type: application/json" \
-d '{
"query": "quiet coastal villages with local markets",
"retrieval": {
"model": "faiss",
"k": 12
}
}'
{
"query": "quiet coastal villages with local markets",
"params": {
"retrieval": {
"model": "faiss",
"k": 12
},
"model_used": "faiss"
},
"results": [
{
"destination": "Ninh Binh",
"country": "Vietnam",
"lat": 20.25,
"lon": 105.9,
"distance": 0.1342,
"snippets": [
"A quiet region of limestone karsts and river villages.",
"Local markets operate daily with minimal tourism."
],
"full_content": "Full blog text...",
"why": {
"model": "FAISS",
"page_title": "Hidden Northern Vietnam",
"page_url": "https://example.com/blog/post",
"blog_url": "https://example.com",
"author": "Travel Blogger"
}
}
],
"explanations": [
"This destination aligns with your query due to its emphasis on quiet local villages and authentic market culture..."
]
}
This project includes a documentation site built with MkDocs.
From the project root directory, run:
mkdocs serve
Open your browser and navigate to:
http://127.0.0.1:8000/
To generate a static version of the documentation:
mkdocs build
This creates a site/ directory containing the compiled HTML files. You can open site/index.html directly in a browser or deploy the folder to any static hosting service.
1. Set up Python environment:
# Using Poetry
poetry install
poetry shell
# Or using pip
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e .
2. Run API locally:
cd backend/src/api
uvicorn main:app --reload --port 8000
3. Run Streamlit locally:
cd frontend/streamlit_app
streamlit run app.py
HTML
59.2%
Python
37.1%
Jupyter Notebook
3.6%
Authors:
This project implements a context-aware travel recommendation system designed to surface "off-the-beaten-path" destinations. Unlike traditional recommendation engines that favor popular tourist spots, our system identifies hidden gems by analyzing travel blogs, structured attributes, and popularity signals to recommend lesser-known destinations that match user interests.
The application combines:
All components are containerized using Docker and orchestrated with Docker Compose for easy deployment and reproducibility.
dsan6700_app_dev_project/
│
├── backend/
│ ├── Dockerfile.api # API container definition
│ ├── configs/
│ │ └── app_config.yaml # Application configuration
│ ├── off_the_path/ # Core package
│ ├── src/
│ │ ├── api/
│ │ │ ├── main.py # FastAPI endpoints
│ │ │ ├── bm25_utils.py # BM25 search utilities
│ │ │ └── __init__.py
│ │ └── features/
│ │ └── engineer.py # Feature engineering
│ └── pyproject.toml # Python dependencies
│
├── frontend/
│ ├── Dockerfile.streamlit # Frontend container definition
│ └── streamlit_app/
│ └── app.py # Streamlit UI
│
├── .dockerignore # Files to ignore in Docker builds
├── .gitignore # Files to ignore in Git
├── .env # Environment variables (DATABASE_URL)
├── docker-compose.yml # Orchestrates all services
└── README.md # This file
BM25 (Best Match 25) is a ranking function used by search engines to estimate the relevance of documents to a given search query. Our implementation:
How It Works:
rank-bm25Features:
A transformer-based semantic retrieval and re-ranking model that captures the meaning of user queries and travel narratives, enabling discovery of destinations that align with “off-the-beaten-path” intent beyond surface-level keyword overlap.
How it Works
Model Capabilities:
Outputs:
The application consists of two Docker containers:
Frontend (Streamlit)
API Layer (FastAPI)
Database
DATABASE_URL environment variableBefore running this project, ensure you have:
Docker Desktop (Windows/Mac) or Docker Engine (Linux)
Docker Compose
Verify Installation:
# Check Docker version
docker --version
# Check Docker Compose version
docker-compose --version
# Verify Docker is running
docker ps
1. Clone the Repository:
# Clone the project repository
git clone https://github.com/your-org/dsan6700_app_dev_project.git
# Navigate to project directory
cd dsan6700_app_dev_project
2. Set Up Environment Variables:
Create a .env file in the project root with your database connection:
DATABASE_URL=postgresql://user:password@host:port/database
3. Build and Start All Services:
# Build images and start containers
docker-compose up --build
# OR run in detached mode (background)
docker-compose up --build -d
What This Does:
backend/Dockerfile.apifrontend/Dockerfile.streamlit4. Wait for Services to Initialize:
The first BM25 search will load ~XX,XXX blog posts from the database and build the index. This takes approximately 30-60 seconds.
Once containers are running:
Travel Recommender Web Interface:
API Documentation:
Health Check:
Check Running Containers:
# View all running containers
docker-compose ps
# Expected output:
# NAME IMAGE STATUS PORTS
# api dsan6700_app_dev_project-api Up 0.0.0.0:8081->8000/tcp
# streamlit dsan6700_app_dev_project-streamlit Up 0.0.0.0:8501->8501/tcp
View Container Logs:
# View logs for all services
docker-compose logs
# View logs for specific service
docker-compose logs api
docker-compose logs streamlit
# Follow logs in real-time (Ctrl+C to exit)
docker-compose logs -f
# View last 50 lines
docker-compose logs --tail=50
Monitor Resource Usage:
# View CPU, memory, and network usage
docker stats
Inspect Container Details:
# List all Docker containers (including stopped)
docker ps -a
# Execute commands inside container
docker exec -it api bash
Stop Containers (Preserves Data):
# Stop all services
docker-compose down
# Stop specific service
docker-compose stop api
Complete Cleanup (Remove Everything):
# Stop containers and remove volumes
docker-compose down -v
# Remove all unused Docker resources
docker system prune -a --volumes
Restart Services:
# Restart all services
docker-compose restart
# Restart specific service
docker-compose restart api
Open your browser and navigate to http://localhost:8501
Choose between:
Query:
Filters:
The application returns:
Results Tab:
Maps Tab:
Diagnostics Tab:
You can also interact directly with the API:
BM25 Search:
curl -X POST "http://localhost:8081/search" \
-H "Content-Type: application/json" \
-d '{
"query": "temples in Kyoto Japan",
"retrieval": {
"model": "bm25",
"k": 10
}
}'
Attribute+Context Search:
curl -X POST "http://localhost:8081/search" \
-H "Content-Type: application/json" \
-d '{
"query": "quiet coastal villages with local markets",
"retrieval": {
"model": "faiss",
"k": 12
}
}'
{
"query": "quiet coastal villages with local markets",
"params": {
"retrieval": {
"model": "faiss",
"k": 12
},
"model_used": "faiss"
},
"results": [
{
"destination": "Ninh Binh",
"country": "Vietnam",
"lat": 20.25,
"lon": 105.9,
"distance": 0.1342,
"snippets": [
"A quiet region of limestone karsts and river villages.",
"Local markets operate daily with minimal tourism."
],
"full_content": "Full blog text...",
"why": {
"model": "FAISS",
"page_title": "Hidden Northern Vietnam",
"page_url": "https://example.com/blog/post",
"blog_url": "https://example.com",
"author": "Travel Blogger"
}
}
],
"explanations": [
"This destination aligns with your query due to its emphasis on quiet local villages and authentic market culture..."
]
}
This project includes a documentation site built with MkDocs.
From the project root directory, run:
mkdocs serve
Open your browser and navigate to:
http://127.0.0.1:8000/
To generate a static version of the documentation:
mkdocs build
This creates a site/ directory containing the compiled HTML files. You can open site/index.html directly in a browser or deploy the folder to any static hosting service.
1. Set up Python environment:
# Using Poetry
poetry install
poetry shell
# Or using pip
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e .
2. Run API locally:
cd backend/src/api
uvicorn main:app --reload --port 8000
3. Run Streamlit locally:
cd frontend/streamlit_app
streamlit run app.py
HTML
59.2%
Python
37.1%
Jupyter Notebook
3.6%