A rule-based web application for finding alternative flights during cancellations and delays.
Intelligent heuristic flight recovery system using keyword matching, SQL query generation, and multi-factor scoring with real-time disruption news feeds.
- π¨ Disruption Recovery Mode - Enter a flight ID and instantly get best alternatives
- π Smart Flight Search - Keyword-based queries for flight searches
- π― Intent Detection - Pattern matching to detect search vs recovery mode
- β Intelligent Ranking - Flights scored on 5 factors: seats, timing, weather, congestion, reliability
- π‘ Explainability - Click "Why this flight?" to see scoring breakdown
- β‘ Lightning Fast - Rule-based processing with caching for instant responses
- Clean Streamlit chat interface
- SQLite database with 150+ realistic Indian domestic flights
- Risk labels (Low/Medium/High) instead of raw numbers
- Afternoon time preference optimization (12-17)
- Airport congestion and delay probability scoring
- Weather risk assessment
- Connecting flight fallback (MVP)
Python 3.10+
Streamlit 1.40+ (UI framework)
SQLite3 (database)
Flask (RSS API server)
feedparser (RSS parsing)
deep-translator (i18n support)
requests (HTTP client)
Architecture Pattern: Rule-based agent workflow (no LLMs or RAG)
- Keyword tokenization for intent detection
- Dictionary-based parameter extraction
- Parameterized SQL query generation
- Heuristic-based multi-factor scoring
The app includes a dual-source real-time news feature that fetches disruption updates from both Google News RSS and Twitter/X with intelligent query building.
Professional Design
- Modern gradient styling - Teal/turquoise color scheme with professional gradients
- Enhanced cards - Hover effects, smooth transitions, and better spacing
- Responsive layout - Mobile-friendly design that adapts to all screen sizes
- Better typography - Improved readability with proper font sizing and weights
- Custom scrollbars - Styled scrollbars matching the design system
- Smooth interactions - Button animations and visual feedback
- Dark sidebar - Professional sidebar with white text and gradient
- Alert improvements - Better styled success/error/warning messages
- π± Dual-Source News - RSS feeds (Google News) + Twitter/X searches side-by-side
- β‘ 5-minute Caching - Reduces API rate limiting (RSS only)
- π Smart Detection - Auto-detects flight numbers, airlines, and disruption keywords
- π― Advanced Search Operators - Twitter searches use: OR, from:, lang:, quotes
- β±οΈ Real-time Updates - Live Twitter searches and cached RSS results
- π Direct Links - Click through to articles or open searches on Twitter/X
- π Global Coverage - Search any flight number or travel keyword
- π Beautiful Results - Enhanced display with source badges and metadata
The system automatically detects:
- π¨ Disruption Keywords: "cancelled", "delayed", "diverted", "stranded"
βοΈ Airline Handles: Infers Twitter handles from flight prefixes (AAβ@AmericanAir, AIβ@SpiceJet)- π’ News Requests: Keywords like "news", "report", "update", "alert"
-
Start the API server (in separate terminal):
python api_server.py
Runs Flask on
http://127.0.0.1:5000 -
Run the Streamlit app:
streamlit run app.py
-
Navigate to π° Disruption News from sidebar
-
Search:
- Flight numbers:
AA100,AI203,BA747 - Keywords:
flight delays,airport closures,weather disruption
- Flight numbers:
-
View Results:
- RSS Tab (π°): Google News articles with source and publish time
- Twitter Tab (π): Live searches on Twitter/X with advanced operators
Flight Disruption
Query: AA100
Auto-detects:
- Airline: American Airlines (@AmericanAir)
- Search terms: delay OR diverted OR cancelled
- Twitter search: AA100 (delay OR diverted OR cancelled) from:AmericanAir
Keyword Search
Query: Delhi airport closure
Auto-detects:
- Disruption type: Airport issue
- Twitter search: "Delhi airport closure" (news OR disruption)
The system uses these advanced operators for better results:
| Operator | Example | Meaning |
|---|---|---|
OR |
delay OR diverted | Any condition |
from: |
from:AmericanAir | From specific account |
lang: |
lang:en | Language filter |
"..." |
"flight delay" | Exact phrase |
- |
-spam | Exclude terms |
&f=live |
&f=live | Live results only |
RSS Feed API:
GET /api/news/rss?q=<query>
Response:
{
"query": "AA100",
"items": [
{
"title": "Flight AA100 faces 2-hour delay due to weather",
"link": "https://news.google.com/...",
"publishedAt": "2026-02-22T10:30:00",
"source": "Aviation Today",
"snippet": "Heavy snow at Denver forced delays..."
}
],
"count": 12,
"cached": false
}Health Check:
GET /api/health
- In-memory cache: 5-minute TTL per query
- Thread-safe: Locks for concurrent requests
- Automatic cleanup: Expired entries removed on access
- Benefits: Reduces Google News rate limits and improves response
Use the convenience script to start both services:
python run_all.pyThis starts:
- Flask API on
http://127.0.0.1:5000 - Streamlit on
http://localhost:8501
Best-Effort Service
- RSS feed availability may change
- Google News can block requests during high traffic
- Twitter searches are live on Twitter/X servers
- Graceful fallback to cached results when unavailable
Rate Limiting
- Google News has rate limits (~30-60 requests/minute)
- 5-minute caching significantly reduces load
- Reuse search queries to hit cache
Privacy
- No user data is logged
- RSS fetches happen server-side
- All processing is local
git clone <repo-url>
cd Tech-Banditspython -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activatepip install -r requirements.txtThis installs:
streamlit- UI frameworkfeedparser- RSS parsingflask- API server for newsrequests- HTTP clientdeep-translator- Translation support
python database.pyThis creates flights.db with 150 realistic Indian flights. Run automatically on first app start.
python run_all.pyThis starts both the Flask API server and Streamlit app.
Terminal 1 - Flask API Server:
python api_server.pyRuns on http://127.0.0.1:5000
Terminal 2 - Streamlit App:
streamlit run app.pyOpens on http://localhost:8501
- Main chat interface: http://localhost:8501
- Disruption News: http://localhost:8501/News
- API health check: http://127.0.0.1:5000/api/health
This app features a hybrid offline/online architecture using real-time flight data from OpenSky Network API:
- Online Mode (WiFi ON): Click "Sync Live Planes" to fetch current aircraft from OpenSky API
- Offline Mode (WiFi OFF): Browse previously synced flight data from local database
- Storage: SQLite database (
flights.db) - all data is cached locally on your machine
- Connect to internet (WiFi/mobile data)
- Launch app:
streamlit run app.py - Sidebar β Click "Sync Live Planes (OpenSky)"
- Wait 5-10 seconds - fetches ~150-200 aircraft over India
- Data saved to local database - no cloud storage needed
- Now works offline - browse and search without internet
The app uses a snapshot-based caching model:
flights.dbis a local SQLite file on your computer- Streamlit runs on
localhost:8501(your own machine) - No internet needed to query the local database
- Think of it like downloading a video vs streaming - once synced, it's yours
Sync fresh data when:
- Aircraft positions are stale (after several hours)
- Before demos/presentations to show current flights
- After major time zone changes (morning vs evening traffic patterns)
- To capture peak flight hours (7-9 AM, 5-7 PM is best)
The app supports dual data sources:
- Live Data (OpenSky Network) - Real aircraft with actual positions, speed, altitude
- Fake Data (Synthetic Database) - 300 realistic Indian flights for testing
Default filter: "Live Only" mode (synced flights take priority)
Toggle in siKeyword-Based Search
User: "Show flights from Delhi to Pune tomorrow afternoon"
β System extracts via pattern matching
## π How to Use
### Mode 1: Natural Language Search
User: "Show flights from Delhi to Pune tomorrow afternoon" β Agent extracts: source=Delhi, destination=Pune, date=tomorrow, time=afternoon β System extracts flight ID via regex pattern β Fetches original flight from databasexplanations
### Mode 2: Disruption Recovery (Main Demo)
User: "My flight AI203 got cancelled" β Agent fetches original flight β Finds alternatives on same route/date β Ranks and displays best 3 options
### Mode 3: Direct Flight ID (Fastest)
- Enter "AI203" in sidebar Disruption Mode
- Click "Find Alternatives"
- Instantly see best recovery options
### Mode 4: Click "Why this flight?"
Each flight has explainability button Shows: "Selected due to low weather risk, available seats, and optimal afternoon timing."
### Mode 5: Sync Live Flights (NEW)
- Ensure internet connection
- Sidebar β "Sync Live Planes (OpenSky)"
- Wait for sync to complete
- See real aircraft over India
- Works offline after sync
---
## ποΈ Architecture
```Rule-based workflow - no LLMs)
βββ intent_extractor: Keyword matching for search vs recovery
βββ _extract_search_params: Dictionary-based city/time extraction
βββ db_query_node: Execute parameterized SQL queries
βββ ranking_node: Heuristic-based flight scoring
βββ Live data sync controls (OpenSky integration)
βββ Caching for performance
agent.py (LangGraph-like workflow)
βββ intent_extractor: Classify search vs recovery
βββ db_query_node: Execute parameterized SQL
βββ ranking_node: Score and rank flights
βββ response_generator_node: Format for UI
ranking_engine.py
βββ Seat availability scoring
βββ Time preference scoring (afternoon preferred)
βββ Weather risk scoring
βββ Congestion scoring
βββ Reliability scoring (delay probability inverse)
βββ Explainability generation
sql_generator.py
βββ Safe parameterized SQL queries
βββ Search flights with optional filters
βββ Get alternatives for disrupted flights
βββ Handle "Unknown" destinations (OpenSky live data)
βββ Prevent SQL injection
database.py
βββ SQLite schema initialization
βββ Flight data generation (300 realistic flights)
βββ OpenSky live data sync (fetch_india_flights)
βββ Data source column migration (fake vs live)
βββ City and time generation
βββ Database seeding
providers/opensky.py (NEW)
βββ fetch_india_flights: Real-time aircraft tracking
βββ India bounding box: 6.5-35.5Β°N, 68.0-97.5Β°E
βββ infer_airline_from_callsign: AIβAir India, 6EβIndiGo
βββ infer_nearest_city: Distance calculation to 9 major cities
βββ No authentication required (public API)
utils.py
βββ Risk label mapping (numeric β Low/Medium/High)
βββ Weather score calculation
βββ Flight display formatting
βββ Time preference utilities
Each flight is scored on 5 weighted factors:
score = (0.35 * seat_score) +
(0.25 * time_score) +
(0.20 * weather_score_adj) +
(0.10 * congestion_score) +
(0.10 * reliability_score)
Where:
- seat_score: Normalized available seats (0-1)
- time_score: Preference for afternoon 12-17 (0-1)
- weather_score_adj: Inverse of weather risk (0-1)
- congestion_score: Inverse of airport congestion (0-1)
- reliability_score: Inverse of delay probability (0-1)Top 3 flights are returned to user.
CREATE TABLE flights (
flight_id TEXT PRIMARY KEY,
source TEXT NOT NULL,
destination TEXT NOT NULL,
date TEXT NOT NULL,
departure_time TEXT NOT NULL,
arrival_time TEXT NOT NULL,
seats_available INTEGER,
price INTEGER,
status TEXT,
fog_risk REAL,
rain_risk REAL,
wind_risk REAL,
airport_congestion REAL,
previous_flight_delay REAL,
delay_probability REAL,
-- New columns for OpenSky integration
data_source TEXT DEFAULT 'fake', -- 'fake' or 'opensky'
raw_json TEXT, -- Original API response
last_updated_utc TEXT -- Sync timestamp
);
Indexes on: source, destination, date, departure_time, status, flight_id, data_sourceSample Data:
- 189 live flights from OpenSky Network (after sync)
- 300 fake flights for testing and demos
- Routes: Delhi, Mumbai, Bangalore, Hyderabad, Chennai, etc.
- Realistic times, prices, and risk values
- Mix of Active/Cancelled flights
Live Flight Columns:
- Live flights may have
destination = 'Unknown'(inferred from nearest city) raw_jsonstores original OpenSky API responselast_updated_utctracks when data was synced
-
Streamlit Caching
@st.cache_resource- Agent initialization (once per app)@st.cache_data- Flight count lookup
-
Database Optimization
- Indexed columns for fast queries
- Parameterized queries prevent SQL injection
- Fast city-to-city lookups
-
Session State
- Chat history caching
- Flight explanations stored
- Disruption mode quick access
Result: Instant response (<200ms) for most queries
- Clean Chat Interface - Familiar chat experience
- Flight Cards - Formatted with departure, seats, risks, price
- Color-coded Risks - Low/Medium/High labels (no raw numbers)
- Explainability Buttons - "Why this flight?" on each option
- Disruption Sidebar - Quick access for emergency recovery
- Responsive Layout - Works on desktop and tablet
python agent.py
# Output: Test recovery and search modespython database.py
# Output: Database initialization and flight countpython ranking_engine.py
# Output: Ranking scores and explanationsEdit ranking_engine.py:
SEAT_WEIGHT = 0.35 # Increase for seat availability priority
TIME_WEIGHT = 0.25 # Increase for timing preference
WEATHER_WEIGHT = 0.20 # Increase for weather priorityEdit database.py:
flights = generate_flights(300) # Generate 300 instead of 150Edit utils.py:
time_preference_score() # Modify afternoon windowTech-Bandits/
βββ app.py # Streamlit UI - main entry point
βββ agent.py # Agent workflow for flight recovery
βββ ranking_engine.py # Flight scoring and ranking algorithm
βββ sql_generator.py # Safe SQL query builder
βββ database.py # SQLite schema and data seeding
βββ utils.py # Utility functions
βββ custom_css.py # Professional UI/UX styling
βββ api_server.py # Flask REST API for news feeds
βββ twitter_utils.py # Twitter search URL builder
βββ providers/
β βββ opensky.py # OpenSky Network API integration
βββ pages/
β βββ news.py # Disruption news page (RSS + Twitter)
βββ requirements.txt # Python dependencies
βββ README.md # Project documentation
βββ flights.db # SQLite database (auto-generated)
Contributions are welcome! Please feel free to submit a Pull Request.
Open source - use freely for learning and development.
# 1. Install dependencies
pip install -r requirements.txt
# 2. Start services
python run_all.py
# 3. Access application
# Main app: http://localhost:8501
# News page: http://localhost:8501/News
# API: http://127.0.0.1:5000/api/healthFor offline use, sync live flights first (requires internet), then the app works without connectivity using cached data.

