Sankalp.irl_new: LokAyukt: The Open-Source Civic OS That Tries to Prove a Complaint Was Actually Fixed

A multimodal grievance platform pairs LangGraph agents, PostGIS routing, and AI verification to turn municipal complaints into a traceable, spatially aware workflow.

8 to 10 min read • View on GitHub • More from aryan252006-creator

A citizen complaint moves through a proof corridor. On the left, a resident drops in a crumpled report with a phone image, voice waveform, and location pin. In the middle, lenses and scoring dials inspect the evidence. On the right, a ward officer receives a stamped task while a city admin watches a heatmap fill in behind it. The scene explains that LokAyukt is built around verified closure, not just ticket intake.
LokAyukt treats resolution as a proof problem. The system is designed to route messy complaints into a workflow that can verify whether work was actually done.
Key Takeaways

Why municipal software usually fails at the last mile

Most grievance systems are optimized for intake. They make it easy to file a ticket, assign a number, and move on. The weak point is closure, because the easiest thing in the world is to mark an issue resolved without proving that anything changed.

That is the problem LokAyukt targets. Its core idea is not “AI for civic support.” It is a trust machine for government work, built around the uncomfortable question that most portals avoid: how do you know the job was actually done?

SystemWhat it optimizesWhat it misses
Traditional grievance portalTicket creation and status updatesWhether the issue was genuinely fixed
Basic AI chatbot frontendFaster intake and conversational UXRouting quality, spatial context, proof of resolution
LokAyuktVerified closure and spatially aware escalationIt still depends on adoption and disciplined field execution

LokAyukt’s real innovation: resolution has to survive verification

The interesting part is the trust loop. A citizen can submit text, voice, or image. But a resolution does not become real just because a ward officer says it is done. LokAyukt tries to verify the claim with evidence.

The repo’s verification flow uses a cheap first pass, then a more expensive judgment. First, it checks whether an image looks suspiciously flat or synthetic. Then it compares before and after evidence with vision reasoning. That ordering matters. It avoids spending model effort on images that already look wrong.

This diagram shows LokAyukt as a chain of trust gates, not a single chatbot. Each step turns raw citizen input into something the city can route, verify, and escalate.

A close-up of two municipal repair photos being judged by a split lens. The left image shows a rough pothole surface. The right image shows the repaired road. Between them sit a tiny noise meter and a flatness gauge, suggesting the system checks image plausibility before judging whether the fix is real. The image explains LokAyukt’s anti-fraud verification loop.
LokAyukt does not trust evidence by default. It tries to screen for fake-looking images first, then asks whether the before-and-after pair actually proves a repair.

How the verification layer works

The repo’s AI layer, in `Unified-AI/ai_models.py`, combines two different checks. One is statistical: `detect_fake_image` looks at pixel variation and flags images that are too smooth to be believable. The other is semantic: Groq’s Llama 3 Vision compares before and after images to judge whether the reported repair holds up.

That pairing is the key. The statistical check is cheap and blunt. The vision model is slower and smarter. Together they create a practical filter for a municipal setting where bad actors could try to fake evidence of work.

def verify_issue(before_image, after_image):
    if detect_fake_image(after_image):
        return {
            'status': 'flagged',
            'reason': 'suspicious image texture'
        }

    result = vision_model.compare(
        before=before_image,
        after=after_image,
        task='verify whether the issue was actually resolved'
    )
    return result

How the complaint becomes a routed municipal task

LokAyukt’s intake path is multimodal by design. Citizens can submit text, voice, or image. The FastAPI service in `Unified-AI/main.py` normalizes that input into structured issue data, then routes it into the workflow that follows.

The point is not just conversion. It is classification with enough confidence to support action. A complaint has to become a department-ready object, with issue type, confidence, and location attached, before anyone can do anything useful with it.

POST /classify/audio
POST /classify/image

# Core path
transcribe_audio() -> classify_text() -> issue_type, department, confidence

# Agent layer
citizen_agent
ward_agent
admin_agent
StageWhat gets addedWhy it matters
Text, voice, image intakeRaw complaint contentLets citizens report in the format they already have
NormalizationTranscript, label, confidenceTurns messy reports into structured tasks
Agent routingRole-specific actionKeeps citizens, ward officers, and admins in separate lanes
VerificationBefore/after proof, fraud screeningMakes closure harder to fake

Why geography is treated as data, not decoration

The spatial layer is one of the repo’s strongest choices. `Backend/services/geoService.js` and `wardService.js` use PostGIS to locate a complaint inside a ward polygon, so routing is based on geometry rather than manual lookup.

That changes the whole feel of the system. A map is no longer just a dashboard skin. It becomes part of the workflow, because geometry determines where the complaint goes, how it is visualized, and how patterns get aggregated across the city.

The database schema treats wards as polygons and complaints as points, which is exactly the kind of data model a civic system needs if it wants location-aware prioritization and accurate heatmaps.

Map as UIMap as system
Shows where something happenedHelps decide who owns the task
Useful for browsingUseful for routing and escalation
Decorative layerOperational layer

The priority engine does more than sort by urgency

Priority in LokAyukt is not a simple severity label. In `Backend/services/priorityService.js`, the score combines hardcoded issue weights, complaint volume over the last 48 hours, and recurrence over a 7-day history. The result is a rough model of systemic failure, not just complaint intensity.

That matters because repeated leaks, contamination, or waste issues are not isolated events. They are signals. A good civic system should surface that pattern and push it up the queue before the situation turns into a citywide problem.

function calculatePriority(issue, count48h, recurrence7d) {
  const urgency = ISSUE_WEIGHTS[issue] || 50;
  const impact = Math.log10(count48h + 1) * 20;
  const recurrence = recurrence7d * 5;
  return Math.min(100, urgency + impact + recurrence);
}
SignalWhat it capturesWhy it helps
Issue weightIntrinsic severityKeeps obviously dangerous problems near the top
48-hour volumeLocal clusteringSurfaces bursts of neighborhood-level failure
7-day recurrenceChronic repetitionDistinguishes one-off noise from structural breakdown

From chatbot to agents: three roles, three different kinds of intelligence

LokAyukt does not treat every user as the same kind of actor. The system defines separate citizen, ward, and admin agents with different responsibilities. That is a better fit for government work than a single catch-all assistant.

The citizen agent is there to help file and clarify. The ward agent is there to manage action. The admin agent is closer to a strategic analyst, because it can synthesize city-wide patterns, spot clusters, and support planning rather than just answering questions.

That separation is subtle but important. It keeps the interface simple for residents while giving officials a more serious operational layer underneath.

What LokAyukt gets right, and what remains unresolved

The repo is structurally thoughtful. The split between Node, Python, and PostGIS is sensible. The use of agents, geometry, and verification shows real product intent, not just demo code.

But the public footprint is thin. There is no visible ecosystem around it, and the project still reads like an early-release prototype. That does not weaken the idea, but it does put the burden of proof back on future adoption.

StrengthOpen question
Strong architecture across intake, routing, and verificationWill field teams actually use the verification loop?
Clear spatial modelHow much manual cleanup will real municipal data need?
Serious anti-fraud logicCan the system avoid becoming too complex for daily operations?

LokAyukt is trying to make municipal closure trustworthy, not just efficient. That is a meaningful shift, because it changes the unit of value from “ticket created” to “work proven.”