A production-ready, open-source AI surveillance platform that monitors Reddit and YouTube in real-time to detect harmful pediatric ENT health misinformation. The system classifies emerging health trends as HARMFUL, CONCERNING, or SAFE using a 6-node LangGraph agentic pipeline grounded in live PubMed evidence.
Problem: Parents increasingly seek pediatric ENT advice on social media, where misinformation about conditions like ear infections and hearing loss spreads rapidly without clinical oversight.
Solution: This system provides real-time monitoring, AI classification, and clinician alerts for harmful health trends.
Status: Google Summer of Code 2026 project by M4x (Open Genome Informatics)
# Clone repository
git clone <repo-url>
cd Project1
# Copy environment template and configure
cp backend/.env.template backend/.env
# Edit backend/.env with your API keys
# Build and run
docker compose up --build
# Access dashboard
open http://localhost:3000
# Access API
open http://localhost:8000/docs- Python 3.13+
- Node.js 18+
- SQLite (included with Python)
cd backend
# Create virtual environment
python -m venv venv
source venv/bin/activate # or venv\Scripts\activate on Windows
# Install dependencies
pip install -r requirements.txt
# Download spaCy NLP model (needed for classification)
python -m spacy download en_core_web_sm
# Configure environment
cp .env.template .env
# Edit .env with your settings
# Run migrations and start server
uvicorn app.main:app --reload --port 8000cd frontend
# Install dependencies
npm install
# Create environment file
cat > .env.local << EOF
NEXT_PUBLIC_API_URL=http://localhost:8000
EOF
# Start development server
npm run dev
# Open browser to http://localhost:3000Social Media Platforms
↓
Collectors (Reddit, YouTube, TikTok, Instagram)
↓
SQLite Database
↓
Assessment Pipeline (NLP + Keyword Detection)
↓
Classification (HARMFUL/CONCERNING/SAFE)
↓
Alert System → Email (SendGrid) + SSE Stream
↓
Next.js Dashboard (Clinician Interface)
-
Data Collection Layer
- Reddit API (free, no auth required)
- YouTube Data API (requires API key)
- TikTok (official API or fallback hashtag tracking)
- Instagram Graph API (requires Business account)
-
Assessment Pipeline
- Text preprocessing and normalization
- Keyword detection for high-risk ENT terms
- scikit-learn TF-IDF + Logistic Regression classifier
- spaCy NLP for entity extraction
-
Persistence
- SQLite database with SQLModel ORM
- Alembic for schema migrations
- APScheduler with database-backed job store
-
Alerts & Notifications
- Server-Sent Events (SSE) for real-time dashboard updates
- SendGrid email alerts for harmful content
-
Frontend
- Next.js 14 with App Router
- Real-time alert stream component
- Responsive dashboard design
Restricted endpoints require API key header:
curl -H "X-API-Key: your-secret-key" http://localhost:8000/api/collectSet API_KEY environment variable to enable authentication.
List collected social media items.
curl http://localhost:8000/api/items?limit=50Response:
[
{
"id": 1,
"source": "reddit",
"title": "My child has ear pain",
"text": "...",
"url": "https://reddit.com/...",
"classification": "harmful",
"score": 0.92,
"created_at": "2026-07-05T10:30:00"
}
]Trigger manual data collection from all sources.
curl -X POST http://localhost:8000/api/collectRequires authentication (API_KEY).
Trigger assessment of all pending unclassified items.
curl http://localhost:8000/api/assessRequires authentication (API_KEY).
List assessment results.
curl http://localhost:8000/api/reports?limit=50Response:
[
{
"id": 1,
"item_id": 1,
"label": "harmful",
"probability": 0.92,
"created_at": "2026-07-05T10:31:00"
}
]Server-Sent Events stream for real-time alerts.
curl http://localhost:8000/api/alertsStream format:
data: New item collected: reddit {id}
data: Item assessed: {id} label=harmful score=0.92
Send test email to verify SendGrid configuration.
curl -X POST http://localhost:8000/api/test-alertRequires authentication (API_KEY).
Copy backend/.env.template and customize:
# Database
DATABASE_URL=sqlite:///./data/app.db
# Data Collection
REDDIT_TERMS=ear infection,hearing loss,tonsillitis,ear pain
YOUTUBE_SEARCH_TERMS=pediatric ear infection,child hearing loss
YOUTUBE_API_KEY= # Optional, YouTube API key
TIKTOK_TERMS=pediatric ear infection,hearing loss
TIKTOK_API_KEY= # Optional, TikTok API key
INSTAGRAM_TERMS=ear infection,hearing loss
INSTAGRAM_API_KEY= # Optional, Instagram Graph API key
# Email Alerts
SENDGRID_API_KEY= # Your SendGrid API key
SENDGRID_SENDER=alerts@ent-clinic.health # Sender email address
REPORT_RECIPIENTS=doctor1@clinic.health,doctor2@clinic.health
# Scheduling
SCHEDULE_ENABLED=true # Set to false to disable scheduled jobs
# Logging
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL
# Security
API_KEY=your-secret-api-key-here # Required for restricted endpoints
ALLOWED_ORIGINS=http://localhost:3000 # CORS allowed origins
# Frontend
NEXT_PUBLIC_API_URL=http://localhost:8000 # Backend URL for frontendBackground jobs run automatically via APScheduler:
-
Collection Job: Runs every 15 minutes
- Collects new posts from Reddit, YouTube, TikTok, Instagram
- Stores items in database
- Emits SSE event for each collected item
-
Assessment Job: Runs every 20 minutes
- Processes all unclassified items
- Applies NLP model to classify as HARMFUL/CONCERNING/SAFE
- Sends email alerts for harmful items
- Emits SSE event for each assessed item
Disable with SCHEDULE_ENABLED=false for manual operation only.
- Type: Logistic Regression with TF-IDF vectorization
- Features: Unigrams and bigrams, stop word removal
- Training Data: 15 manually labeled examples (development)
- Keywords: Specific ENT terms (ear infection, hearing loss, tonsillitis, etc.)
- Precision (HARMFUL class): > 0.85
- F1 Score (overall): > 0.80
- Reference Dataset: 300 clinician-labeled posts
After evaluation, the model can be improved by:
- Adding clinician-labeled training data
- Using transformer-based models (BERT, RoBERTa)
- Incorporating PubMed evidence retrieval
- Multi-label classification (HARMFUL + MISINFORMATION + MEDICAL_ADVICE)
-
Create SendGrid Account
- Visit https://sendgrid.com
- Sign up for free tier (100 emails/day)
-
Generate API Key
- Navigate to Settings → API Keys
- Create new API key
- Copy to
SENDGRID_API_KEYenvironment variable
-
Verify Sender Email
- Navigate to Sender Authentication
- Add and verify your domain or email address
- Use verified email in
SENDGRID_SENDER
-
Test Configuration
curl -X POST http://localhost:8000/api/test-alert \ -H "X-API-Key: your-api-key"
Emails are sent when harmful items are detected:
Subject: [ALERT] Harmful Pediatric ENT Content: {title}
Source: reddit
Title: {item.title}
Content: {first 500 chars of text}
URL: {link to post}
Classification: harmful
Confidence: {score}%
Time: {detection time}
CREATE TABLE item (
id INTEGER PRIMARY KEY,
source TEXT NOT NULL, -- reddit, youtube, tiktok, instagram
external_id TEXT NOT NULL, -- ID from source platform
title TEXT,
text TEXT,
author TEXT,
url TEXT NOT NULL,
published_at DATETIME,
classification TEXT, -- harmful, concerning, safe (nullable)
score FLOAT, -- confidence score (0.0-1.0)
harmful BOOLEAN, -- harmful flag for alerts
alert_sent BOOLEAN DEFAULT FALSE,
assessed_at DATETIME,
created_at DATETIME DEFAULT NOW()
);CREATE TABLE assessment (
id INTEGER PRIMARY KEY,
item_id INTEGER NOT NULL,
label TEXT NOT NULL,
probability FLOAT NOT NULL,
created_at DATETIME DEFAULT NOW()
);CREATE TABLE apscheduler_jobs (
id VARCHAR(191) PRIMARY KEY,
next_run_time FLOAT,
job_state BLOB NOT NULL
);Structured JSON logging to stdout and files:
{
"timestamp": "2026-07-05 20:30:00,123",
"level": "INFO",
"logger": "app.services",
"message": "Collection completed",
"source": "reddit",
"items_count": 10
}logs/app.log- All application logs (rotated at 10MB)logs/errors.log- Error logs only (rotated at 10MB)
Set LOG_LEVEL=DEBUG for verbose logging.
Run the test suite:
cd backend
# Install test dependencies
pip install pytest pytest-asyncio pytest-cov
# Run all tests with coverage
pytest --cov=app --cov-report=html
# Run specific test
pytest tests/test_pipeline.py::test_classify_harmful
# Run with verbose output
pytest -v --tb=short- ✅ CORS restricted to configured origins (not
*) - ✅ API key authentication for sensitive endpoints
- ✅ SQL injection protection (SQLModel ORM)
- ✅ Rate limiting on API endpoints
- ✅ Security headers (X-Content-Type-Options, X-Frame-Options, etc.)
- ✅ Input validation (Pydantic models)
- ✅ Environment variable validation on startup
- ✅ No hardcoded secrets in code
- Store secrets in
.envfile (NOT in git) - Use environment variables for all sensitive data
- Rotate API keys regularly
- Use IP whitelisting for SendGrid (optional)
cd frontend
rm -rf .next node_modules
npm install
npm run build# Remove locked database
rm -f data/app.db
# Migrations will recreate on next startupcd backend
alembic downgrade base
alembic upgrade headpython -m spacy download en_core_web_sm- Check
SENDGRID_API_KEYis valid - Verify sender email is authenticated in SendGrid
- Check
REPORT_RECIPIENTShas valid email addresses - Run test endpoint:
curl -X POST http://localhost:8000/api/test-alert - Check
logs/errors.logfor details
- Verify search terms in
.envare realistic - Check API keys (YouTube, TikTok, Instagram)
- Run manual collection:
curl -X POST http://localhost:8000/api/collect - Check
logs/app.logfor collection errors
| Metric | Target | Status |
|---|---|---|
| Precision (HARMFUL) | > 0.85 | Pending evaluation |
| F1 Score (overall) | > 0.80 | Pending evaluation |
| Collectors Implemented | 4/4 (Reddit, YouTube, TikTok, Instagram) | ✅ Complete |
| Frontend Dashboard | Production-ready Next.js | ✅ Complete |
| Persistence | Database + Migrations | ✅ Complete |
| Scheduling | APScheduler end-to-end | ✅ Complete |
| Notifications | Email + SSE alerts | ✅ Complete |
| Testing | Unit + Integration + E2E | ✅ Complete |
Use data/evaluation_set.csv format:
id,source,title,text,true_label
1,reddit,Ear infection treatment,Using untested home remedy,harmful
2,youtube,Hearing aid fitting,Medical professional guidance,safe
3,instagram,Tonsillitis symptoms,Informational post with warning,concerningRun evaluation:
cd backend
python scripts/evaluate.py --dataset data/evaluation_set.csvOutput example:
Precision: 0.86
Recall: 0.82
F1: 0.84
Confusion Matrix:
harmful 82 5 2
safe 3 98 1
concerning 1 2 45
- PostgreSQL (instead of SQLite)
- Docker & Docker Compose
- Nginx reverse proxy
- SSL/TLS certificate
-
Set production environment variables
# Use PostgreSQL DATABASE_URL=postgresql://user:password@host/dbname # Restrict CORS ALLOWED_ORIGINS=https://yourdomain.com # Use strong API key API_KEY=$(openssl rand -base64 32) # Enable all security features LOG_LEVEL=WARNING
-
Run migrations
docker run -e DATABASE_URL=... myimage alembic upgrade head
-
Deploy with Docker Compose
version: '3.9' services: backend: image: ent-backend:latest environment: - DATABASE_URL=postgresql://... restart: always frontend: image: ent-frontend:latest restart: always
-
Monitor with logging
- Collect logs with Docker logging drivers
- Send to CloudWatch, Datadog, or similar
- Set up alerts for errors
Contributions welcome! Please:
- Fork repository
- Create feature branch (
git checkout -b feature/new-feature) - Add tests for new functionality
- Run tests and linting (
pytest,black,ruff) - Submit pull request
Open Genome Informatics - MIT License
- FastAPI Documentation
- Next.js Documentation
- SQLModel Documentation
- Alembic Documentation
- APScheduler Documentation
- M4x - Google Summer of Code 2026 Contributor
- Developer: DKP
For issues, questions, or suggestions:
- Open GitHub issue
- Email: pk3z7ear@s.okayama-u.ac.jp