An AI-powered emergency message triage system that classifies and ranks incoming emergency messages by urgency level using three machine learning models. Designed for dispatchers, analysts, and first responders to quickly identify and act on critical situations.
Models used:
- RoBERTa (primary — fine-tuned transformer, 87.3% accuracy)
- Logistic Regression (comparison baseline, 80.5% accuracy)
- Random Forest (comparison baseline, 78.0% accuracy)
PRIORITYMSGAI/
├── backend/
│ ├── main.py # FastAPI app entry point
│ ├── classifier.py # Model inference + Critical override
│ ├── database.py # SQLAlchemy models (SQLite)
│ ├── requirements.txt # Python dependencies
│ ├── .env # Environment secrets (not in GitHub)
│ ├── data/
│ │ ├── training_data.csv # Labeled fake test messages
│ │ └── combine_crisislex.py # Script to combine CrisisLex datasets
│ ├── models/
│ │ ├── roberta_triage/ # Fine-tuned RoBERTa weights (not in GitHub)
│ │ ├── lr_model.pkl # Trained LR model (not in GitHub)
│ │ ├── rf_model.pkl # Trained RF model (not in GitHub)
│ │ └── tfidf_vectorizer.pkl # TF-IDF vectorizer (not in GitHub)
│ ├── routes/
│ │ ├── auth.py # Register + login endpoints
│ │ ├── classify.py # Message classification endpoints
│ │ ├── notifications.py # Notification endpoints
│ │ └── analytics.py # Analytics endpoints
│ └── utils/
│ └── preprocess.py # Text cleaning pipeline
├── frontend (tentative)/
├── model_training/
│ ├── notebooks/
│ │ ├── exploration.ipynb # Dataset exploration + charts
│ │ ├── model_training.ipynb # LR + RF training
│ │ ├── roberta_training.ipynb # RoBERTa fine-tuning (run on Google Colab)
│ │ └── evaluation.ipynb # Model comparison + evaluation
└── README.md
| Layer | Technology |
|---|---|
| Frontend | React, Vite |
| Backend | Python, FastAPI, SQLAlchemy |
| Database | SQLite |
| Primary Model | RoBERTa (HuggingFace Transformers) |
| Comparison Models | Logistic Regression, Random Forest (scikit-learn) |
| Auth | JWT (python-jose) |
| Version Control | GitHub |
Make sure you have the following installed before starting:
- Python 3.10+ → check with
python3 --version - Node.js 18+ → check with
node --version - Git → check with
git --version
- Python 3.10+ → download from https://python.org (check "Add to PATH" during install)
- Node.js 18+ → download from https://nodejs.org
- Git → download from https://git-scm.com
Mac/Linux:
git clone https://github.com/ayyc808/PriorityMsgAI.git
cd PriorityMsgAIWindows:
git clone https://github.com/ayyc808/PriorityMsgAI.git
cd PriorityMsgAIMac/Linux:
python3 -m venv venv
source venv/bin/activateWindows:
python -m venv venv
venv\Scripts\activateYou should see (venv) at the start of your terminal prompt.
Mac/Linux:
cd backend
pip install -r requirements.txtWindows:
cd backend
pip install -r requirements.txtWARNING: torch is a large package (~700MB). Installation may take 3-5 minutes.
Create a file called .env inside the backend/ folder with the following content:
SECRET_KEY=rapidrelief_super_secret_key_change_this_later
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=60
WARNING: Do not commit this file to GitHub. It is already blocked by .gitignore.
Mac/Linux:
python3 database.pyWindows:
python database.pyYou should see: Database initialized — prioritymsgai.db created.
The large dataset files are not stored in GitHub. Each teammate must download them locally.
| Dataset | Source | Rename to |
|---|---|---|
| Disaster Tweets | https://www.kaggle.com/datasets/vstepanenko/disaster-tweets | kaggle_disaster.csv |
| CrisisLexT26 | https://crisislex.org/data-collections.html | (folder — see below) |
| CrisisNLP Benchmark | https://crisisnlp.qcri.org/data/crisis_datasets_benchmarks/crisis_datasets_benchmarks_v1.0.tar.gz | (extract — see below) |
After downloading and extracting CrisisLexT26, run:
Mac/Linux:
python3 data/combine_crisislex.py /path/to/your/CrisisLexT26Windows:
python data/combine_crisislex.py C:\path\to\your\CrisisLexT26This creates backend/data/crisislex_combined.csv.
Mac/Linux:
tar -xvf ~/Downloads/crisis_datasets_benchmarks.tar.gz -C ~/Downloads/
cp ~/Downloads/data/all_data_en/crisis_consolidated_humanitarian_filtered_lang_en_train.tsv backend/data/crisisnlp_train.tsv
cp ~/Downloads/data/all_data_en/crisis_consolidated_humanitarian_filtered_lang_en_test.tsv backend/data/crisisnlp_test.tsv
cp ~/Downloads/data/all_data_en/crisis_consolidated_humanitarian_filtered_lang_en_dev.tsv backend/data/crisisnlp_dev.tsvWindows (PowerShell):
tar -xvf crisis_datasets_benchmarks.tar.gz
copy data\all_data_en\crisis_consolidated_humanitarian_filtered_lang_en_train.tsv backend\data\crisisnlp_train.tsv
copy data\all_data_en\crisis_consolidated_humanitarian_filtered_lang_en_test.tsv backend\data\crisisnlp_test.tsv
copy data\all_data_en\crisis_consolidated_humanitarian_filtered_lang_en_dev.tsv backend\data\crisisnlp_dev.tsvThe trained model files are not stored in GitHub (as it is too large). You have two options you can do, Option A or Option B (for practice and understanding on training models (Google Colab recommended for T4 GPU as training large amt of data takes time - its free!)):
Ask a teammate who has already trained the models to share:
backend/models/lr_model.pklbackend/models/rf_model.pklbackend/models/tfidf_vectorizer.pklbackend/models/roberta_triage/(entire folder)
Place them in the correct locations inside backend/models/.
Train LR and RF locally:
Open model_training/notebooks/model_training.ipynb in VSCode and run all cells. This saves lr_model.pkl, rf_model.pkl, and tfidf_vectorizer.pkl to backend/models/.
Train RoBERTa on Google Colab (requires GPU):
- Go to https://colab.research.google.com
- Upload
model_training/notebooks/roberta_training.ipynb - Set Runtime → Change runtime type → T4 GPU
- Run all cells
- Download the generated
roberta_triage_final.zip - Extract and place contents into
backend/models/roberta_triage/
Mac/Linux:
cd ../frontend
npm installWindows:
cd ..\frontend
npm installMac/Linux:
cd backend
source ../venv/bin/activate
uvicorn main:app --reloadWindows:
cd backend
..\venv\Scripts\activate
uvicorn main:app --reloadWARNIING: First startup takes 30-60 seconds to load all three ML models.
Backend runs at: http://localhost:8000 API docs (Swagger UI): http://localhost:8000/docs
Open a new terminal window:
Mac/Linux:
cd frontend
npm run devWindows:
cd frontend
npm run devFrontend runs at: http://localhost:5173
Once the backend is running, you can visit http://localhost:8000/docs for the full interactive Swagger UI with all available endpoints:
| Section | Endpoints |
|---|---|
| Auth | POST /auth/register, POST /auth/login |
| Classify | POST /classify, GET /messages, POST /messages/{id}/save, POST /messages/{id}/archive, GET /messages/saved |
| Notifications | GET /notifications, GET /notifications/unread-count, PATCH /notifications/{id}/read, PATCH /notifications/read-all |
| Analytics | GET /analytics/overview, GET /analytics/urgency-distribution, GET /analytics/message-trends, GET /analytics/model-performance, GET /analytics/confidence-distribution, GET /analytics/category-breakdown, GET /analytics/recent-activity |
Once the backend is running, go to http://localhost:8000/docs to test all endpoints interactively.
- Click
POST /auth/register→ Try it out - Paste the following into the request body:
{
"first_name": "John",
"last_name": "Doe",
"email": "john@test.com",
"password": "Test1234",
"confirm_password": "Test1234",
"organization": "Fire",
"role": "Dispatcher"
}- Click Execute
- Expected response
201:
{
"message": "Account created successfully. Please log in.",
"user_id": 1
}- Click
POST /auth/login→ Try it out - Paste:
{
"email": "john@test.com",
"password": "Test1234"
}- Click Execute
- Copy the
access_tokenvalue from the response (without the quotes)
- Click the Authorize button at the top right of the Swagger UI page
- Paste the copied token into the value field
- Click Authorize then Close
All subsequent requests will now include your JWT token automatically.
- Click
POST /classify→ Try it out - Paste:
{
"text": "Building collapsed downtown people trapped inside need help immediately"
}- Click Execute
- Expected response includes:
urgency_label— Critical, High, Medium, or Lowcategory— Collapse, Fire, Flood, Medical, etc.roberta_label,lr_label,rf_label— all three model predictionsoverride_applied— true if Critical override keyword was triggeredmessage_id— ID saved to the database
- Click
GET /messages→ Try it out - Leave parameters as default or filter by urgency (Critical/High/Medium/Low)
- Click Execute
- Returns all classified messages sorted by urgency score (highest first)
- Click
POST /messages/{message_id}/save→ Try it out - Enter the
message_idfrom Step 4 (e.g.1) - Click Execute
- Expected response:
{
"message": "Message saved successfully",
"message_id": 1
}- Click
GET /notifications→ Try it out - Click Execute
- Returns all notifications — Critical and High urgency messages auto-create notifications
- Check
is_read: falsefor unread notifications
- Click
PATCH /notifications/{notification_id}/read→ Try it out - Enter
1in thenotification_idfield - Click Execute
- Expected response:
{
"message": "Notification marked as read",
"id": 1
}Test each analytics endpoint by clicking Try it out → Execute:
| Endpoint | What it returns |
|---|---|
GET /analytics/overview |
Total messages, urgency counts, avg confidence |
GET /analytics/urgency-distribution |
Counts and percentages per urgency level |
GET /analytics/message-trends |
Daily message volume for last 7 days |
GET /analytics/model-performance |
Agreement rates and confidence per model |
GET /analytics/confidence-distribution |
RoBERTa confidence score histogram |
GET /analytics/category-breakdown |
Emergency type distribution |
GET /analytics/recent-activity |
Last 10 classified messages |
- Click
POST /messages/{message_id}/archive→ Try it out - Enter the
message_id - Click Execute
- Message is hidden from active feed but kept in database for analytics
python command not found (Mac):
Use python3 instead of python on Mac/Linux.
torch install fails:
Make sure you are using Python 3.10-3.13. Run python3 --version to check.
uvicorn can't find main module:
Make sure you are inside the backend/ folder when running uvicorn.
Models not found error on startup:
Make sure all model files are in backend/models/ — see Model Setup section above.
Database not found:
Run python3 database.py (Mac) or python database.py (Windows) from inside backend/.
| Name | Role |
|---|---|
| Alvin C | Software Developer |
| Malcolm D | Software Developer |
| Minh T | SW QA Test Engr |
| Richard P | System Architect |
| Chan L | Software Developer |