A production-grade system for monitoring public online sources for mentions of independent directors, detecting good or bad news, and generating readable reports for Managing Directors.
- Daily Monitoring: Automated daily scans at configurable times (default 07:30 IST)
- Multi-Provider Support: GDELT, Bing News Search, SerpAPI, RSS feeds
- Smart Deduplication: URL canonicalization, content hashing, and similarity detection
- Entity Resolution: Reduces false positives through context matching and confidence scoring
- Classification: Heuristic-based + optional LLM-powered sentiment/severity classification
- Reports: HTML and PDF daily digest reports
- Alerts: Immediate email alerts for high-severity items
- Web Dashboard: Admin and MD interfaces for managing directors and viewing reports
- Review Queue: Low-confidence items flagged for manual review
- Python 3.11+
- FastAPI for API server
- PostgreSQL for storage
- Redis + Celery (Celery Beat) for scheduling
- SQLAlchemy + Alembic for ORM/migrations
- Jinja2 for HTML templates
- WeasyPrint for PDF generation
- Trafilatura for article extraction
- Docker + Docker Compose
- Docker and Docker Compose
- Python 3.11+ (for local development)
-
Clone and navigate to the project:
cd director-sentiment-analysis -
Create
.envfile from example:cp .env.example .env
-
Edit
.envand configure:COMPANY_NAME: Your company nameBING_NEWS_KEY: Bing News Search API key (optional)SERPAPI_KEY: SerpAPI key (optional)SMTP_*: Email configurationLLM_API_KEY: OpenAI API key (optional, for LLM classification)
-
Start services:
docker compose up --build
-
Run migrations:
docker compose exec api alembic upgrade head -
Create admin user:
docker compose exec api python -m app.cli create-admin --username admin --password admin123 --email admin@example.com -
Seed sample directors:
docker compose exec api python -m app.seed directors.yaml -
Access the dashboard:
- Web UI: http://localhost:8000
- API docs: http://localhost:8000/docs
See .env.example for all available configuration options. Key variables:
COMPANY_NAME: Company name for reportsRUN_TIME_HHMM: Daily job time (default: 07:30)TIMEZONE: Timezone (default: Asia/Kolkata)PROVIDERS_ENABLED: Comma-separated list (e.g.,gdelt,bing)CONFIDENCE_THRESHOLD_ALERT: Alert threshold (default: 0.75)USE_LLM: Enable LLM classification (default: false)
- Login as admin
- Navigate to "Directors" page
- Click "Add Director"
- Fill in:
- Full name (required)
- Aliases (comma-separated)
- Context terms (e.g., company name, "independent director")
- Negative terms (to exclude false positives)
- Enable/disable providers
Create directors.yaml:
directors:
- full_name: "John Doe"
aliases: ["J. Doe", "John D."]
context_terms: ["ABC Corp", "independent director", "Mumbai"]
negative_terms: ["actor", "footballer"]
known_entities: ["XYZ Ltd", "Board Member"]Then run:
docker compose exec api python -m app.seed directors.yamlTrigger a manual monitoring run:
docker compose exec api python -m app.cli run-scanOr via API:
curl -X POST http://localhost:8000/api/admin/trigger-scan \
-H "Authorization: Bearer <token>"-
Via Web UI:
- Login as MD or Admin
- Navigate to "Reports" page
- Click on any report to view HTML or download PDF
-
Via API:
GET /api/reports GET /api/reports/{report_id} GET /api/reports/{report_id}/pdf
director-media-monitoring/
├── api/ # FastAPI application
├── worker/ # Celery workers
├── providers/ # Search provider implementations
├── core/ # Shared logic (dedupe, classification, etc.)
├── models/ # SQLAlchemy models
├── migrations/ # Alembic migrations
├── templates/ # Jinja2 templates
├── static/ # CSS, JS, images
├── tests/ # Test suite
└── docker-compose.yml
- Query Building: For each director, build multiple search queries (recall + precision)
- Provider Search: Query enabled providers (GDELT, Bing, etc.)
- Article Fetch: Fetch and extract article content
- Entity Resolution: Match articles to directors with confidence scoring
- Deduplication: Remove duplicate articles
- Classification: Determine sentiment, severity, category
- Storage: Store mentions in database
- Report Generation: Generate daily digest (HTML + PDF)
- Email: Send alerts (high severity) and daily digest
- Items are retained for 365 days by default
- Weekly cleanup task removes old data
- Reports are stored indefinitely (configurable)
- Set production environment variables
- Use production-grade secrets management
- Configure S3-compatible storage
- Set up monitoring (Sentry, logs aggregation)
- Configure reverse proxy (nginx) for API
- Set up SSL certificates
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d