AI for Bharat Hackathon | Theme 11 | PAN IIT Bangalore x Government of Karnataka
Karnataka Government departments receive thousands of court judgments annually. Each must be analyzed and converted into departmental compliance actions with strict deadlines — or risk contempt proceedings. LexiPlan automates this entire pipeline with AI while keeping humans in the loop for every decision.
- Problem Statement
- Our Solution
- Key Features
- System Architecture
- Tech Stack
- AI Pipeline — LangGraph
- Project Structure
- Getting Started
- Usage and Demo Flow
- Design Principles
- Data Sovereignty and Compliance
- Scalability and Deployability
- Team
- Acknowledgements
Theme 11 — From Court Judgments to Verified Action Plans
The Karnataka Government's Court Case Monitoring System (CCMS) handles thousands of High Court and Supreme Court judgments each year. Today, each judgment is manually read by a legal officer who must extract case details, map directions to departments, calculate compliance deadlines, assess whether to comply or appeal, and generate a structured action plan — all while avoiding contempt of court for missed deadlines.
This process is slow (2-4 hours per judgment), error-prone (~15% missed deadlines annually, ~20% department routing errors), and unscalable (one officer handles ~3-5 judgments/day).
LexiPlan is an end-to-end AI pipeline that ingests court judgment PDFs, extracts structured legal data with full source traceability, generates department-specific compliance action plans, and presents everything to a human reviewer through an interactive Verification Desk — before any data reaches the compliance dashboard.
| Feature | Why It Matters |
|---|---|
| Zero-Hallucination Architecture | Every extracted field links back to the exact sentence in the PDF via bounding box coordinates (bbox_seq_ids). If the AI can't find it in the source, confidence drops to 0.0. |
| Mandatory Human-in-the-Loop | No AI output reaches the dashboard without human review. LangGraph's interrupt() pauses the pipeline until a reviewer approves. |
| Dual-Factor Confidence Scoring | Each field scored: (LLM confidence x 0.6) + (source quote verification x 0.4). RED fields must be corrected before approval. |
| Karnataka-Specific Domain Knowledge | Hardcoded limitation periods (SLP=90d, Division Bench=30d), 20+ department-to-officer mapping, escalation chains (PS → ACS → CS → CMO). |
| Multi-Provider LLM Failback | Gemma 4 (Vertex AI) → Groq (Llama 3.3 70B) → Gemini 2.5 Flash → MockClient. The system never goes down. |
- Two-phase OCR: Google Cloud Document AI (primary) with Gemma 4 Vision fallback for degraded scans (pages with confidence < 0.70)
- Word-level bounding boxes: Every token gets pixel-precise coordinates (
normalized_vertices) for PDF highlighting - Multi-language: English, Kannada (
kn), Hindi (hi), Tamil (ta) via Document AI — detected using Unicode block heuristics - Async batch processing: PDFs > 15 pages route through Document AI batch API with GCS staging
- Parallel fan-out: Extraction and Context nodes run simultaneously via
Send()API, merged back viamerge_results - Structured output: Pydantic v2 schemas injected into prompts — JSON extracted and validated with tenacity retry (3 attempts)
- Chain-of-thought reasoning: Two-phase generation in action_plan_node —
invoke_with_thinking()for CoT trace, theninvoke_structured()for Pydantic-validated output - 4-stage RAG: Hybrid Search on children (Vector + BM25 via RRF) → Parent document lookup → Cohere reranker → top-5 results
- Split-screen: PDF viewer (pdfjs-dist v5 + react-pdf v10) with bounding box overlay on left, AI-extracted data on right
- Click any source quote → highlights the exact text in the PDF via
bbox_seq_ids - Color-coded confidence badges: GREEN (>=85%) / YELLOW (60-84%) / RED (<60%)
- Three actions: approve, reject, send_back (re-generates with feedback, max 2 retries)
- Real-time case statistics by status and risk level via MongoDB aggregation pipelines
- Upcoming deadline alerts (48h and 7d windows) with background monitor polling every 30 minutes
- External notifications via SendGrid (email) and Twilio (SMS) — graceful no-op when unconfigured
- Exportable Compliance Summary PDF via ReportLab (7 sections: header, summary, actions table, deadlines table, appeal analysis, risk, footer)
- WebSocket endpoint (
/api/v1/ws/{document_id}) broadcasts pipeline stage events to connected clients - Frontend
usePipelineStatushook with auto-reconnect (exponential backoff, max 5 retries) - 7 pipeline stages mapped to progress percentages: OCR Complete (20%) → Extraction (35-50%) → Action Plan (70%) → Awaiting Review (85%) → Verified (100%)
PDF Upload / CCMS Webhook
|
v
GCS Storage --> Document AI OCR --> BBox Storage (MongoDB)
| (Gemma 4 Vision fallback for <70% confidence pages)
|
Cloud Pub/Sub (async decoupling)
|
v
┌─── LangGraph Pipeline (Deterministic StateGraph) ───┐
| |
| fan_out (Send API) |
| ├── extraction_node (Gemma/Groq/Gemini) |
| └── context_node (RAG + dept mapping + limitation) |
| | |
| merge_results |
| | |
| action_plan_node (Two-phase: CoT → Structured) |
| | |
| confidence_node (Dual-factor scoring) |
| | |
| hitl_gate (interrupt() — pipeline halts) |
| | |
| persist_node (MongoDB writes) |
└───────────────────────────────────────────────────────┘
|
v
Frontend (Next.js 14)
Landing → Queue → Verification Desk → Dashboard
| Component | Technology | Details |
|---|---|---|
| Pipeline Orchestration | LangGraph StateGraph | Send() for parallelism, interrupt() for HITL, MongoDBSaver checkpointer |
| Primary LLM | Gemma 4 26B MoE (A4B) | Via Vertex AI Model Garden :predict endpoint, vLLM on GKE with NVIDIA RTX PRO 6000 |
| Fallback LLMs | Groq (Llama 3.3 70B) → Gemini 2.5 Flash | OpenAI-compatible API / google-genai SDK |
| Primary OCR | Google Cloud Document AI | text_anchor.text_segments for text, bounding_poly.normalized_vertices for coordinates |
| Embeddings | Nomic nomic-embed-text-v1.5 (768-dim) |
Via langchain-nomic, stub fallback for offline dev |
| Reranker | Cohere rerank-v3.5 |
Cross-encoder on parent documents |
| Component | Technology |
|---|---|
| Framework | FastAPI 0.136 (Python 3.12), Uvicorn |
| Database | MongoDB Atlas (Motor async driver + PyMongo sync for checkpointer) |
| File Storage | Google Cloud Storage (async via asyncio.to_thread) |
| Task Queue | Cloud Pub/Sub (streaming pull subscriber) |
| PDF Export | ReportLab (A4 compliance summary) |
| Logging | structlog (JSON structured, ISO timestamps) |
| Notifications | SendGrid (email) + Twilio (SMS) |
| Component | Technology |
|---|---|
| Framework | Next.js 14 + TypeScript |
| 3D Landing | Three.js + React Three Fiber + Drei (STL Ashoka Pillar model) |
| PDF Viewer | pdfjs-dist v5 + react-pdf v10 + custom bbox overlay |
| Charts | Recharts (bar charts for department distribution) |
| Animations | Framer Motion (page transitions, scramble text effect) |
| State | Zustand + TanStack React Query |
| Styling | Tailwind CSS (brutalist dark theme, #050505 base) |
| Service | Purpose |
|---|---|
| GKE | Gemma 4 vLLM inference (GPU node pool, nvidia-rtx-pro-6000) |
| Cloud Run | FastAPI backend (serverless, port 8080) |
| Document AI | OCR with word-level bounding boxes |
| Cloud Storage | Raw PDF storage (raw/{document_id}.pdf) |
| Cloud Pub/Sub | Async ingestion queue (judgment-ingestion topic) |
| Cloud Build | CI/CD (Docker build → Artifact Registry → Cloud Run deploy) |
The pipeline is a deterministic StateGraph with fixed edges. Every node runs in a predictable order — no autonomous agent decisions.
| Node | File | Key Logic |
|---|---|---|
fan_out |
graph.py |
Returns [Send("extraction", state), Send("context", state)] for parallel execution |
extraction |
extraction_node.py |
FallbackStructuredClient.invoke_structured() with CaseExtraction schema, Karnataka-specific case type parsing (WP, WA, CRL.P) |
context |
context_node.py |
LegalKnowledgeRetriever.retrieve() (4-stage RAG) + hardcoded limitation table + Karnataka department mapping (20+ departments) |
merge_results |
graph.py |
Collects parallel_results list, maps task_id → state keys |
action_plan |
action_plan_node.py |
Two-phase: invoke_with_thinking() for reasoning trace → invoke_structured() for ActionPlan schema. Post-processes relative deadlines to absolute ISO dates. |
confidence |
confidence_node.py |
Recursive field scanning. score = (llm_conf * 0.6) + (source_match * 0.4). Thresholds: GREEN >= 0.85, YELLOW >= 0.60, RED < 0.60 |
hitl_gate |
hitl_gate.py |
interrupt(hitl_payload) halts pipeline. Resumed via Command(resume=reviewer_response). Routes to: persist (approve), action_plan (send_back, max 2), error_handler (reject/max retries) |
persist |
persist_node.py |
Applies reviewer inline edits, writes to verified_action_plans + individual deadlines documents + audit_log |
Core models: SourcedField (value + source_quote + bbox_seq_ids + confidence), CaseExtraction (case details + parties + directions), ActionPlan (recommendation + compliance_actions + deadlines + appeal_analysis + risk), ConfidenceReport (per-field scores with color coding)
1. Gemma 4 via Vertex AI :predict (10s connect timeout)
↓ on failure
2. Groq via httpx (OpenAI-compatible, Llama 3.3 70B)
↓ on failure
3. Gemini via google-genai SDK (native response_schema)
↓ on failure
4. MockStructuredClient (realistic hardcoded data for demo)
Each provider gets 1 attempt. JSON parse failures retry the full cascade (3 total attempts via tenacity).
LexiPlan/
├── backend/
│ ├── main.py # FastAPI app + lifespan (DB → indexes → graph → Pub/Sub worker → deadline monitor)
│ ├── config.py # Pydantic BaseSettings (96 lines, all env vars)
│ ├── Dockerfile # Python 3.11-slim, Cloud Run port 8080
│ ├── api/
│ │ ├── routers/
│ │ │ ├── ingest.py # POST /upload (multipart PDF), POST /ccms-webhook
│ │ │ ├── review.py # GET /{id}/draft/mock, GET /{id}/draft, POST /{id}/verify
│ │ │ ├── dashboard.py # GET /stats, GET /plans, GET /deadlines/upcoming
│ │ │ ├── documents.py # GET /{id}/status, GET /{id}/pdf, GET /{id}/highlights
│ │ │ ├── export.py # GET /{id}/pdf (ReportLab compliance summary)
│ │ │ └── admin.py # POST /batch-ingest, GET /audit-log
│ │ ├── middleware/
│ │ │ ├── auth.py # Demo mode (pass-through, static demo-user-001)
│ │ │ └── logging.py # structlog request/response logging
│ │ └── websocket.py # WS /{document_id} — pipeline event broadcast
│ ├── pipeline/
│ │ ├── graph.py # StateGraph definition (fan_out → merge → nodes → END)
│ │ ├── state.py # PipelineState TypedDict (14 fields)
│ │ └── nodes/ # extraction, context, action_plan, confidence, hitl_gate, persist, error
│ ├── llm/
│ │ ├── fallback_client.py # Gemma → Groq → Gemini cascade (595 lines)
│ │ ├── gemma_client.py # Vertex AI :predict wrapper (llm_heavy + llm_light)
│ │ ├── structured_output.py # Gemma4StructuredClient with JSON extraction + tenacity retry
│ │ ├── langchain_adapter.py # Convenience wrapper returning FallbackStructuredClient
│ │ ├── auth.py # GCP bearer token via google.auth ADC
│ │ └── _mock_structured_client.py # Realistic mock data for CaseExtraction + ActionPlan
│ ├── ingestion/
│ │ ├── service.py # IngestionService (OCR → vision fallback → bbox storage → Pub/Sub publish)
│ │ ├── document_ai.py # Document AI OCR (sync ≤15 pages, batch >15 pages, text_anchor parsing)
│ │ ├── vision_fallback.py # Gemma 4 vision for low-confidence pages (max 5 pages, 300 DPI)
│ │ └── worker.py # Pub/Sub consumer → LangGraph invocation
│ ├── rag/
│ │ └── retriever.py # LegalKnowledgeRetriever (Hybrid → Parent Lookup → Cohere Rerank)
│ ├── models/
│ │ ├── schemas.py # 17 Pydantic v2 models (440 lines)
│ │ └── db_models.py # 8 collection constants + 12 MongoDB indexes
│ └── core/
│ ├── database.py # Motor async + MongoDBSaver for LangGraph checkpoints
│ ├── gcs.py # Upload/download/presigned URL (asyncio.to_thread)
│ ├── alerts.py # Background deadline monitor (30min polling, 48h + 7d alerts)
│ ├── notifications.py # SendGrid email + Twilio SMS dispatcher
│ └── pubsub_publisher.py # Pub/Sub message publisher
├── frontend/
│ └── src/
│ ├── app/
│ │ ├── page.tsx # 3D landing (Three.js STL Ashoka Pillar, scramble text, Chakra halo)
│ │ ├── queue/page.tsx # Upload portal (drag-drop, scan animation, pipeline status bar)
│ │ ├── review/[id]/page.tsx # Verification Desk (split PDF + extraction data)
│ │ └── dashboard/page.tsx # Stats cards + Recharts bar chart + deadline cards
│ ├── components/
│ │ ├── PDFViewerWithHighlights.tsx # react-pdf v10 + bbox overlay (361 lines)
│ │ ├── ActionPlanTable.tsx # Sortable actions + deadlines + risk banner (370 lines)
│ │ ├── ExtractionField.tsx # Editable field with confidence badge
│ │ ├── ConfidenceBadge.tsx # GREEN/YELLOW/RED visual indicator
│ │ ├── DeadlineCard.tsx # Countdown display
│ │ ├── ReasoningTrace.tsx # Collapsible AI reasoning viewer
│ │ ├── PipelineStatusBar.tsx # WebSocket-driven progress bar
│ │ └── ThreeBackground.tsx # Canvas wrapper for 3D scenes
│ └── lib/
│ ├── api.ts # Typed fetch wrapper (all 14 endpoints)
│ ├── types.ts # 245 lines — mirrors schemas.py exactly
│ ├── websocket.ts # usePipelineStatus hook (auto-reconnect)
│ ├── AuthContext.tsx # Demo mode (static user, no Firebase)
│ └── firebase.ts # Stub (exports null)
├── k8s/ # Gemma 4 GKE deployment (vLLM, nvidia-rtx-pro-6000)
├── knowledge_base/ # Limitation Act, CPC, Karnataka HC Rules, CCMS precedents
├── scripts/ # setup_gcp.sh, load_gemma4.sh, verify_infra.sh
├── cloudbuild.yaml # Docker build → Artifact Registry → Cloud Run deploy
└── .env.example # Annotated env template (95 lines)
- Python 3.12+ and Node.js 18+
- MongoDB Atlas account (free tier works) or local MongoDB
- At least one LLM API key:
GROQ_API_KEY(free at console.groq.com) orGEMINI_API_KEY
git clone https://github.com/ayanokojix21/LexiPlan.git
cd LexiPlan
# Backend
python -m venv venv && source venv/bin/activate
pip install -r backend/requirements.txt
# Frontend
cd frontend && npm install && cd ..cp .env.example .env
# Edit .env — minimum required:
# MONGODB_URI=mongodb+srv://...
# GROQ_API_KEY=gsk_... (or GEMINI_API_KEY)# Terminal 1 — Backend
source venv/bin/activate
uvicorn backend.main:app --reload --port 8000
# Terminal 2 — Frontend
cd frontend && npm run dev| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| Swagger Docs | http://localhost:8000/docs |
Without GCP credentials, Document AI OCR and Gemma 4 are unavailable. The system gracefully falls back to Groq/Gemini for LLM and MockClient for demo data.
- Landing (
/) — 3D Ashoka Pillar emblem with scramble text animation - Queue (
/queue) — Drag-and-drop PDF upload. Pipeline status bar tracks progress via WebSocket in real-time - Verification Desk (
/review/{id}) — Split-screen: original PDF with highlight overlays on left, AI-extracted fields with confidence badges on right. Click source quotes to highlight in PDF. Approve, reject, or send back. - Dashboard (
/dashboard) — Case statistics by status, risk distribution chart, upcoming deadline alerts, exportable compliance PDF
-
Zero Hallucinations — Every
SourcedFieldcarriessource_quoteandbbox_seq_ids. The confidence scoring node checks if the source quote actually exists in the document text; if not,source_matchdrops to 0.2 and the field is flagged RED. -
Mandatory Human Gate —
hitl_gate.pycallsinterrupt(hitl_payload)which physically stops the LangGraph execution. No reviewer action = no data in the dashboard. This is architectural, not configurable. -
Deterministic Pipeline — Fixed
StateGraphedges:START → fan_out → [extraction, context] → merge_results → action_plan → confidence → hitl_gate → persist → END. No autonomous agent routing. -
Graceful Degradation — Every component has a fallback: Document AI → Gemma Vision, Gemma → Groq → Gemini → Mock, Nomic → Stub Embeddings, Cohere → No Reranking, Hybrid Search → Vector-Only, SendGrid/Twilio → Audit Log Only.
| Requirement | Implementation |
|---|---|
| Data Residency | GCP services configured to asia-south2 (Delhi). PDFs stored in regional GCS bucket. |
| Audit Trail | Every action logged to audit_log collection with ISO timestamps and user IDs |
| No Data Leakage | PDFs processed by Document AI in asia-south1, LLM inference on GKE within same VPC |
| Explainability | Full reasoning trace stored per document. Every field traceable to source text. |
| Dimension | Design |
|---|---|
| Horizontal Scaling | FastAPI on Cloud Run scales to zero; GKE GPU auto-scales for LLM |
| Async Processing | Cloud Pub/Sub decouples upload from pipeline — upload returns instantly |
| State Persistence | LangGraph MongoDBSaver checkpoints survive server restarts |
| Cost | Document AI at $1.50/1000 pages is 50x cheaper than LLM OCR. GKE Spot instances reduce GPU costs 60% |
| Multi-language | Document AI natively handles Kannada, Hindi, Tamil — critical for Karnataka HC |
| Role | Focus Area |
|---|---|
| Nishschal Chandel | OCR Pipeline + LLM Structured Output + vLLM Deployment |
| Rushil Dhingra | LangGraph Pipeline + Agent Nodes + RAG |
| Vaidik Saxena | GCP Infrastructure + Backend Foundation + Database |
| Vinayak Goel | FastAPI Routers + HITL API + WebSocket |
| Smarak Gartia | Frontend — Verification Desk + Dashboard |
- PAN IIT Bangalore Alumni Association and Government of Karnataka for the AI for Bharat Hackathon
- Google Cloud — Document AI, Vertex AI, GKE
- LangGraph — Deterministic pipeline orchestration with HITL
interrupt()support - Groq — Ultra-fast LLM inference as fallback
- MongoDB Atlas — Vector search + hybrid retrieval + state persistence
- Nomic AI and Cohere — Embeddings and reranking for RAG
Built for Indian Governance
LexiPlan — Because every court direction deserves a verified action plan.