Detailed technical reference for developers and contributors.
- System Components
- Configuration Reference
- Database Schema
- AI Processor Details
- Routing Engine
- API Reference
- Telegram Bot
- Admin Dashboard
- Development Guide
SEVAFLOW consists of four main components that work together:
| Component | Technology | Purpose |
|---|---|---|
| Backend API | FastAPI | REST endpoints, admin dashboard serving |
| Telegram Bot | python-telegram-bot | Citizen interface |
| AI Processor | Google Gemini | Complaint classification |
| Database | SQLite + aiosqlite | Persistent storage |
Citizen Message → Telegram Bot → AI Processor → Router → Database
↓
Admin Dashboard
↓
Status Update → Notifier → Citizen
| Variable | Required | Default | Description |
|---|---|---|---|
TELEGRAM_BOT_TOKEN |
✅ | — | Bot token from @BotFather |
GEMINI_API_KEY |
✅ | — | Google Gemini API key |
ADMIN_SECRET |
✅ | — | Secret for admin endpoints |
HOST |
❌ | 0.0.0.0 |
Server bind address |
PORT |
❌ | 8000 |
Server port |
DATABASE_URL |
❌ | sqlite:///./sevaflow.db |
Database path |
Departments are configured in app/config.py. Each department has:
{
"id": "mcd_electrical",
"name": "MCD Electrical",
"keywords": ["streetlight", "lamp", "electricity", "power"],
"sla_hours": 48,
"contact": "mcd-electrical@delhi.gov.in"
}| Column | Type | Description |
|---|---|---|
id |
TEXT | Primary key (SF-XXXX format) |
telegram_user_id |
INTEGER | Citizen's Telegram ID |
raw_text |
TEXT | Original complaint text |
issue_type |
TEXT | AI-classified issue type |
location |
TEXT | Extracted location |
department_id |
TEXT | Assigned department |
priority |
TEXT | low/medium/high/urgent |
status |
TEXT | pending/acknowledged/in_progress/resolved/closed |
confidence |
REAL | AI confidence score (0-1) |
summary |
TEXT | AI-generated summary |
created_at |
TIMESTAMP | Submission time |
updated_at |
TIMESTAMP | Last update time |
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Primary key |
complaint_id |
TEXT | Foreign key to complaints |
old_status |
TEXT | Previous status |
new_status |
TEXT | New status |
changed_at |
TIMESTAMP | Change timestamp |
changed_by |
TEXT | Who made the change |
app/services/ai_processor.py
The AI processor uses Google Gemini to extract structured information from unstructured complaint text.
- Low Temperature (0.1) — Ensures consistent, deterministic outputs
- JSON-Only Output — Structured response format
- Constrained Options — Department list is explicitly provided
- Delhi-Specific — Trained on local government structure
{
"issue_type": "string",
"location": "string | null",
"responsible_department": "string",
"priority": "low | medium | high | urgent",
"confidence": 0.0-1.0,
"summary": "string"
}If AI processing fails:
- Keyword matching is used to identify department
- Priority defaults to "medium"
- Location extraction is skipped
- Complaint is marked with
confidence: 0.0
app/services/router.py
The router uses a deterministic, rule-based approach:
- Priority Override — Emergency keywords trigger high priority regardless of AI output
- Department Matching — Maps AI department suggestion to configured departments
- SLA Assignment — Based on department + priority
- Fallback — Unknown departments route to "General Services"
| Priority | Trigger Words |
|---|---|
urgent |
emergency, danger, life-threatening, fire |
high |
flooding, collapse, accident, burst |
medium |
broken, not working, damaged |
low |
suggestion, improvement, feedback |
Submit a new complaint.
Request:
{
"telegram_user_id": 123456789,
"text": "Streetlight broken at Nehru Place"
}Response:
{
"id": "SF-1234",
"status": "pending",
"department": "MCD Electrical",
"created_at": "2024-01-15T10:30:00Z"
}List complaints with pagination.
Query Parameters:
skip(int, default: 0)limit(int, default: 20)status(string, optional)department(string, optional)
Get complaint details by ID.
Get status change history for a complaint.
All admin endpoints require X-Admin-Secret header.
Dashboard statistics.
Response:
{
"total_complaints": 150,
"pending": 45,
"resolved": 80,
"avg_resolution_hours": 36.5,
"by_department": {...},
"by_priority": {...}
}Update complaint status.
Request:
{
"status": "in_progress",
"note": "Team dispatched"
}app/telegram/bot.py
| Command | Handler | Description |
|---|---|---|
/start |
start_handler |
Welcome message |
/help |
help_handler |
Show commands |
/status <id> |
status_handler |
Check complaint status |
/cancel |
cancel_handler |
Cancel conversation |
User: Hi
Bot: Welcome! Describe your complaint in detail.
User: The streetlight at my colony gate is not working
Bot: Processing your complaint...
Bot: ✅ Complaint registered!
Reference: SF-1234
Department: MCD Electrical
Priority: Medium
Expected response: within 48 hours
Non-command messages are treated as complaints and processed through:
- AI classification
- Department routing
- Database storage
- Confirmation message
admin/ directory
Navigate to http://localhost:8000/admin
- Overview Stats — Total, pending, resolved complaints
- Complaint List — Filterable, sortable table
- Detail View — Full complaint info with history
- Status Update — Change status with notes
- Notification — Trigger citizen notification
Enter the ADMIN_SECRET when prompted.
# With auto-reload (API only)
uvicorn app.main:app --reload --port 8000
# Bot separately
python run.py --bot-only- Edit
app/config.py - Add department to
DEPARTMENTSlist:
{
"id": "new_dept",
"name": "New Department",
"keywords": ["keyword1", "keyword2"],
"sla_hours": 72,
"contact": "new-dept@delhi.gov.in"
}- Restart the application
# Run tests
pytest
# With coverage
pytest --cov=app# Delete database file to reset
rm sevaflow.db
# Database will be recreated on next startup
python run.py- Check
TELEGRAM_BOT_TOKENin.env - Verify bot is not blocked by Telegram
- Check console for error messages
- Verify
GEMINI_API_KEYis valid - Check Google Cloud quotas
- System will fallback to keyword matching
- Ensure
/admindirectory exists - Check
index.htmlis present - Verify CORS settings if accessing from different origin
For more information, see the main README.md