Track: Voice AI Agent for Accessibility & Societal Impact
The Problem: India has 1,200+ government schemes, yet millions remain unaware of their eligibility because documentation is overwhelmingly stored in complex English PDFs. For the last-mile citizen—especially the rural, elderly, or non-literate—this creates a Digital & Linguistic Barrier to their basic rights.
The Solution: SahayakSetu is a demo-hardened, voice-first digital concierge built with production-style patterns (grounding, timeouts, quotas) to dismantle the 'last-mile' information barrier. By combining high-precision Vector RAG with real-time script-aware intelligence, we enable citizens to translate complex government bureaucracy into clear, actionable roadmaps in their native dialect—reimagining the relationship between citizen and state from a passive search for 'answers' to an empowered pursuit of 'action'.
- Frontend (Production): https://sahayak-setu.vercel.app
- Backend (Render API): https://sahayaksetu-backend-3kxl.onrender.com/health
- Knowledge Base: 38 Verified Scheme Chunks (Qdrant)
Serverless hosts spin down idle services; the first request after idle can take 30–60+ seconds. No repo change fixes this by itself. Use an external uptime monitor to GET your /health or /ready URL every 10–14 minutes (e.g. UptimeRobot, Better Stack, or a cron) so the instance stays warm before demos and judging.
- What: The system captures the user's voice in 6 core Indian languages.
- How: Using Vapi.ai integrated with Azure Neural STT, we achieve sub-second latency for regional dialects, supporting real-time "interim results" for a responsive UI.
- What: We don't just search keywords; we search meaning.
- How: User queries are converted into 384-dimensional dense vectors using FastEmbed. These are searched against a Qdrant Vector Database containing 35+ high-precision, verified government scheme chunks with a strict 0.2 similarity threshold to ensure precise grounding.
- What: Heavyweight reasoning and conversational continuity.
- How: We use Gemini 2.0 Flash as our primary brain. Our system maintains an in-memory Session Store that preserves context across exchanges, allowing for natural follow-up questions like "What about my documents?". If rate limits are hit, we instantly fall back to Groq (Llama 3.3 70B).
- What: The AI responds in the exact language & script used by the user.
- How: A custom-prompted Master Orchestrator detects the query script and mirrors the response. If the query is Hindi/Kannada/Bengali, the answer is fluently mirrored in that specific script with total empathy.
- What: High-fidelity regional speech response.
- How: Our frontend uses a RegEx Script Detector to analyze the AI's response text. It then forces the browser to load the matching regional neural voice (e.g., Azure Swara for Hindi), ensuring that technical data is read with a perfect cultural accent.
Judges often ask: "How is this different from Google Voice Search?"
- Synthesized Action vs. Blue Links: SahayakSetu provides a verified action plan (Eligibility ➜ Benefits ➜ Next Step), not just a list of websites to read.
- "Expert" RAG vs. General Crawling: We search a high-confidence, curated Vector DB of verified scheme documentation with code-enforced grounding.
- Conversational Continuity: Unlike static QA bots, our Active History Store allows users to have a back-and-forth dialogue about their welfare options.
- Trust Infrastructure: Every answer is tagged with a Semantic Match %, proving the transparency and source-grounding of the AI's logic.
- Grounding-first transparency: Every response includes a semantic match % tied to retrieved catalogue text (this is retrieval confidence, not a legal guarantee). The main answer path is grounded and verified; some action-plan fields are model-generated with URL filtering — see limitation below.
- In-Memory Scalability: Optimized for low-footprint deployment on Render Free Tier (~200MB RAM usage).
- Sustainable Scaling: Built entirely on Free Tier infrastructure (Google AI Studio, Groq Free, Qdrant Cloud), making it viable for 100% free deployment to millions of citizens.
AgentPlanfields likedocuments_neededand criteria explanations are model-generated from grounded sources; they are filtered for source references/URLs, but not yet claim-by-claim grounded with the same strict verifier used for final answer claims.
Choose Option A (Docker — recommended, zero dependency headaches) or Option B (bare-metal Python).
Docker bundles the backend, Qdrant vector DB, and Redis cache together. You only need Docker Desktop installed.
git clone https://github.com/bansalbhunesh/SahayakSetu.git
cd SahayakSetuCopy the template and fill in your API keys:
cp .env.example .env # or manually create .envMinimum required keys:
# At least one LLM key is required (Gemini preferred, Groq as fallback)
GEMINI_API_KEY=your_google_ai_studio_key
GROQ_API_KEY=your_groq_key # fallback if Gemini quota runs out
# Qdrant — use the Docker URL below when running via docker-compose
QDRANT_URL=http://localhost:6333
QDRANT_API_KEY= # leave blank for local Docker Qdrant
# App settings
ENV=development
MODERATION_STRICT=false
SESSION_SECRET=any_random_string_here
REDIS_URL=redis://localhost:6379/0
FRONTEND_ORIGIN=http://127.0.0.1:5500Get API keys:
- Gemini: aistudio.google.com/apikey (free tier available)
- Groq: console.groq.com (free tier, very fast)
docker-compose up -dThis starts three containers: backend (port 8000), qdrant (port 6333), redis (port 6379).
Wait ~15 seconds for the backend to finish loading the embedding model, then verify:
curl http://localhost:8000/health
# Expected: {"status":"online","model":"gemini-2.0-flash",...}Run this once (and re-run whenever you update scripts/data/schemes.json):
QDRANT_URL=http://localhost:6333 QDRANT_API_KEY= python scripts/ingest.pyYou should see: [SUCCESS] ... Repository Ready!
Open frontend/index.html directly in your browser, or use a live server (e.g. VS Code Live Server extension on port 5500). Make sure FRONTEND_ORIGIN in .env matches whatever address you use.
curl -s -X POST http://localhost:8000/api/search \
-H "Content-Type: application/json" \
-d '{"query": "PM Kisan benefits eligibility", "language": "en"}'Use this if you prefer to run without Docker. You'll need Python 3.12+ and either a local Qdrant binary or a Qdrant Cloud account.
git clone https://github.com/bansalbhunesh/SahayakSetu.git
cd SahayakSetu
pip install -r requirements.txt- Cloud (easiest): Create a free cluster at cloud.qdrant.io. Copy the cluster URL and API key.
- Local binary: Download from qdrant.tech/documentation/guides/installation and run
./qdrant(listens onlocalhost:6333).
GEMINI_API_KEY=your_google_ai_studio_key
GROQ_API_KEY=your_groq_key
# For Qdrant Cloud:
QDRANT_URL=https://your-cluster.qdrant.io
QDRANT_API_KEY=your_qdrant_api_key
# For local Qdrant binary:
# QDRANT_URL=http://localhost:6333
# QDRANT_API_KEY=
ENV=development
MODERATION_STRICT=false
SESSION_SECRET=any_random_string_here
REDIS_URL=redis://localhost:6379/0 # optional; remove if no Redis
FRONTEND_ORIGIN=http://127.0.0.1:5500python scripts/ingest.pyuvicorn backend.main:app --host 0.0.0.0 --port 8000 --reloadOpen frontend/index.html in your browser or via VS Code Live Server.
Whenever you edit scripts/data/schemes.json (to add or update schemes), re-run the ingest script:
# Docker:
QDRANT_URL=http://localhost:6333 QDRANT_API_KEY= python scripts/ingest.py
# Bare-metal (keys already in .env):
python scripts/ingest.pyThen flush the Redis answer cache so stale responses don't persist:
# Docker:
docker exec sahayaksetu-redis-1 redis-cli FLUSHALL
# Bare-metal:
redis-cli FLUSHALL# Stop all containers
docker-compose down
# Start again (skips image rebuild if nothing changed)
docker-compose up -d
# Force rebuild after code changes
docker-compose up -d --build| Variable | Required | Description |
|---|---|---|
GEMINI_API_KEY |
Yes* | Google AI Studio key for Gemini 2.0 Flash |
GROQ_API_KEY |
Yes* | Groq key for Llama 3.3 70B fallback |
QDRANT_URL |
Yes | http://qdrant:6333 (Docker) or Qdrant Cloud URL |
QDRANT_API_KEY |
No | Leave blank for local Docker Qdrant |
REDIS_URL |
Yes | redis://redis:6379/0 (Docker) or local Redis |
REDIS_QUOTA_STRICT |
No | When unset: strict in ENV=production (Redis errors deny LLM quotas). Set false for fail-open if Redis is optional. |
SESSION_SECRET |
Yes | Any random string for session signing |
ENV |
No | development or production |
MODERATION_STRICT |
No | false (dev) / true (prod — fails closed on LLM errors) |
AGENT_PLAN_CALL_TIMEOUT_S |
No | Max seconds for action-plan JSON LLM calls (default 90) |
NEAR_MISS_SCORE_FLOOR |
No | Min retrieval score for near-miss rows (default 0.15) |
VAPI_WEBHOOK_MAX_SKEW_S |
No | Max age skew for signed webhook JSON timestamps (default 300 seconds) |
VAPI_WEBHOOK_REQUIRE_TIMESTAMP |
No | If true, webhook JSON must include a parseable createdAt / timestamp |
RATE_LIMIT_USE_REDIS |
No | When true (default in ENV=production), use REDIS_URL for SlowAPI limits. Override with RATE_LIMIT_STORAGE_URI. |
FRONTEND_ORIGIN |
No | URL of frontend for CORS (e.g. http://127.0.0.1:5500) |
VAPI_API_KEY |
No | Only needed for voice call feature via Vapi.ai |
VAPI_ASSISTANT_ID |
No | Only needed for voice call feature |
VAPI_WEBHOOK_SECRET |
No | Validates incoming Vapi webhook signatures |
*At least one of GEMINI_API_KEY or GROQ_API_KEY is required.
From the repo root (requires Node 18+):
npm ci
npx playwright install chromium
npm run test:e2eTests serve the static frontend/ folder and mock POST /api/search, so no local backend is required.
Streaming: POST /api/search/stream returns application/x-ndjson: first line {"type":"meta","trace_id":"..."}; while the LLM runs, zero or more lines {"type":"token","text":"..."} (Gemini or Groq streaming); final line {"type":"complete","data":{...same shape as /api/search...}}. Cache hits emit {"type":"phase","name":"cache_hit"} then a single token with the cached answer when present, then complete (no LLM). Errors use {"type":"error","status_code":...,"detail":...}.
- Backend → Render: Push to
main; Render auto-deploys viarender.yaml. Set all env vars in the Render dashboard. SetMODERATION_STRICT=trueandQDRANT_URLto your Qdrant Cloud URL. - Frontend → Vercel: Run
vercel --prodfrom the repo root.vercel.jsonhandles all routing. - After deploying backend, update
BACKEND_URLin your.envand re-deploy frontend so it points to the live API.
Built for Hackblr 2026 — Bridging the gap for a Digital, Inclusive India. 🇮🇳🏆