Conversational Analytics Platform for Parking Operators (NL-to-SQL)
Elevate Conversational AI is the analytics layer we built for IPS Group, on top of their Elevate data platform. A parking operator asks a plain-English question; seconds later they get a grounded answer and a chart, with the exact query shown so any number can be checked by hand. The Proof of Value won the Phase 1 MVP.
Ask your data, get a cited answer
PoV → MVP
Proof of Value won the next phase
11 checks
SQL guardrail before any query runs
Config, not code
Metrics the client's team can edit
Overview
A conversational analytics layer a city can trust, not a demo
A parking manager asks, in plain English, how a district performed last month. Seconds later they have the number and a chart, plus the exact SQL the system ran and the definition it used, so the answer can be verified before anyone acts on it.
IPS Group's Elevate platform unifies parking data that normally never comes together: meters from multiple vendors, mobile payments, and third-party systems. We built the AI layer on top so an operator can self-serve an answer instead of waiting on an analyst or a multi-vendor reconciliation. The whole engagement was engineered around one standard: the math has to be right first.
Who it serves
- Municipal parking managers
- Parking operations managers
- Tech supervisors
- Private garage operators
What we owned, end to end
The Challenge
The hard part was never the data. It was trusting the answer
Cities run meters from several vendors, plus mobile payments, plus third-party systems, and none of it aggregates. Operators cannot produce a basic revenue report they believe, let alone ask a question and trust the reply. And the obvious way to build this, point a language model at the database, fails in a quiet and dangerous way.
Data that will not add up
The same parking activity is recorded several different ways across vendors and tables. Combine two of them naively and the total silently doubles.
A prior build died on latency
IPS had tried this once already. Responses were too slow for real use, so a 5 to 10 second bar was a hard requirement from day one, not a later optimisation.
Plausible, and wrong
The real risk is not a crash. It is an answer that looks completely reasonable and is off by a factor, a timezone, or a definition, with nothing to warn you.
Experts stuck being a query engine
Non-technical operators waited on analysts for questions a trustworthy system should answer in seconds, so the people were the bottleneck.
The standard we built to
On this data, a wrong number looks exactly like a right one. So we engineered for the answer you can trust, not the demo that impresses.
Outcomes
What it gave IPS Group
These are the platform's design guarantees and the engagement result, not marketing estimates.
The Phase 0 Proof of Value was accepted and became a separately contracted Phase 1 MVP, now in active delivery.
The exact SQL and the definition used are shown on screen and logged, so any number can be reproduced.
New metrics and new regions are configuration changes their own team can make, with no developer in the loop.
Code, semantic layer, and evaluation framework are owned by the client, who can run and grow it independently.
How It Works
How a question becomes an answer you can verify
The model is never the source of truth. A versioned semantic layer tells it what the business words mean, a guardrail inspects every query it writes, and the answer is composed only from rows the database actually returned. Teach the rules up front, enforce them before anything runs, and ground the reply in real data.
Semantic layer (the instruction)
Plain-text, versioned definitions for each business metric: what it means, the exact SQL, what to exclude, what may be summed, and the unit. The model is told the rules before it writes a line.
SQL guardrail (the enforcement)
Every generated query is parsed into a tree and checked against eleven rules. Anything unsafe or wrong-shaped is refused or rewritten before it reaches the database.
Grounded generation (two calls)
The first model call writes the SQL and never sees data. The answer is written by a second call, only from the rows that came back. The system cannot narrate a number it did not compute.
System Architecture
Three layers stand between a question and an answer
A plain-English question passes through a semantic layer that defines the metrics, a guardrail that validates the query, and a read-only execution path, before a two-call engine composes the reply. Every answer stays traceable to the exact query and definition behind it.
A plain-English question
An operator asks about revenue, a district, a time window.
Semantic layer
Versioned metric definitions are injected into the model's instructions, so every query means the same thing the business means. Config files, not code.
SQL guardrail
The generated query is parsed into a tree and run through eleven checks: SELECT only, allowlisted tables, one spatial layer, an enforced row limit, local-time conversion, and more.
Read-only execution
Validated SQL runs as a database user with no write permission at all, off the ORM path, with a timeout. If the guardrail ever failed, the database itself refuses.
Two-call reasoning engine
SQL is written first, blind to the data. The answer is written second, only from the rows returned.
An answer you can verify
The number, a chart, the exact SQL, and the definition it used, all on screen and all logged.
The semantic layer teaches the rules, the guardrail enforces them, and read-only execution is the backstop. Defence in depth, by design.
The Stack
Built to be maintained by the client's own team
The stack was chosen to match IPS's existing codebase, so their engineers can own and extend it. No black-box dependency sits between the client and their own system.
- Python + FastAPI
Backend, matched to the client's platform
- PostgreSQL
Data layer, plus the read-only safety role
- sqlglot
Parses SQL into a tree the guardrail inspects
- Pydantic
Forces the model to return validated structure
- Gemini (model-agnostic)
LLM today, swappable in one class
- Redis
Answer cache: repeat questions are instant
- Next.js + React
Chat interface and server-read definitions
- Recharts
Charts generated from the shape of the result
An architecture test fails the build if metric logic ever leaks out of config and into the application code.
Under the Hood
Where the hard problems were
Making text-to-SQL safe enough for a city to sign off on meant engineering for trust, not just speed. The ones that mattered most:
The challenge
Stopping the model from narrating numbers it never computed
How we solved it
Two model calls, not one. The first writes SQL and never sees data. The answer is written by the second call, only from the rows returned. There is nothing to invent from, and the SQL is shown on screen so any answer can be checked by hand.
The challenge
The same revenue counted seven different ways
How we solved it
The source holds the same parking sessions across several overlapping tables, so a naive join silently doubles the total. The guardrail refuses any query that spans more than one spatial layer, outright, because it is the most natural mistake for a model to make.
The challenge
Answers that are off by exactly one timezone
How we solved it
Timestamps are UTC; the city is hours behind. A day or hour question that skips the conversion looks entirely believable and is wrong. So local-time conversion is a guardrail rule, enforced on the query, not a line in the prompt we hope the model obeys.
The challenge
Proving it can never damage or leak the data
How we solved it
Two independent layers. The guardrail parses every statement and rejects anything that is not a plain read of an approved table. Underneath, queries run as a user with no write permission, so a guardrail defect still cannot change a row.
The challenge
Knowing when to refuse instead of guess
How we solved it
The semantic layer names what the data cannot answer, and why. Ask for something unsupported and the system explains the gap rather than reaching for whichever column sounds closest. A correct refusal counts as a success, not a failure.
The challenge
Isolation that never reveals who else is a customer
How we solved it
Each session is scoped to one region, and a question about any other region is refused. The subtle part: the refusal is worded identically whether or not that other region holds any data at all, so the system can never leak whether a given place is on the platform. Isolation that holds even in what it declines to answer.
End to End
From question to charted answer, step by step
One run, viewed as a pipeline. Every stage is logged: the question, the generated SQL, the rows, the tokens, the cost, and the timings.
Cache lookup
Asked before, return it instantly and for free.
Build the prompt
Schema and metric definitions injected from config.
Write the SQL
The model decides what to ask, or asks you back, or says it can't.
Guardrail
Parse, check against eleven rules, refuse or rewrite.
Run read-only
Execute as a no-write database user, with a timeout.
Pick a chart
Chosen from the shape of the result, not the question.
Compose the answer
A second model call writes prose only from the rows.
Log everything
Every query and output is recorded and re-runnable.
Ownership & Control
The client runs it, and extends it, without calling us
The design decision that matters commercially is that the business logic lives in files a non-engineer can read and change. Improvement does not depend on us.
Metrics live in config, not in the code
Each metric is a plain-text file: definition, SQL, filters, grain, and unit. The client's team adds or edits a metric by editing a file, with no developer and no deploy. The backend and the interface read the same file, so the sidebar shows exactly what was sent to the model, and an automated test fails the build if metric logic ever sneaks into the application.
The tutoring loop
Every definition is versioned and traceable
Each file is versioned, and every logged question records which version answered it. So when a number moves, you can tell whether the data changed or a definition did. Adding a new region is a configuration change, not a code change. The one thing that genuinely needs engineering is a brand-new shape of data no metric yet describes.
Add a metric by editing a file
Business definitions are config, not code, so the people who know the domain own the logic.
Know why a number moved
Every answer records the definition version behind it, so changes are never a mystery.
Nothing is a black box
The generated SQL and the definition used are shown on screen with every answer.
Full IP, no lock-in
Code, definitions, and evaluation framework are the deliverable. The client operates it independently.
Client Feedback
“The MVP shipped more than I expected.”
Jean Kao
Product Manager, Elevate (IPS Group)
“Love the direction. We're looking forward to working together on the next phases.”
Andy Deninger
CTO, IPS Group
Beyond Parking
The same approach fits any 'ask your data' problem
Wherever people need a trustworthy, plain-English answer over operational data, and the math has to be right, the semantic-layer-plus-guardrail pattern behind Elevate applies.
Multi-source operations
Utilities, transit, and logistics data that lives in separate systems and never aggregates cleanly.
Finance & revenue reporting
Self-serve answers where a definition dispute changes the number and the math must be defensible.
Internal BI over a warehouse
An 'ask your data' layer that grounds every answer in real rows and shows the query.
Regulated analytics
Read-only by construction, fully logged, and auditable, with correct refusals where data is missing.
Executive self-serve dashboards
Plain-English questions for leaders who should not have to wait on an analyst or learn SQL.
Common Questions
What buyers ask us about building AI like this
Three things. The answer is written only after the query runs, from the rows that actually came back, so there is nothing to invent from. The generated SQL is shown on screen every time, so any answer can be checked by hand in a minute. And every question, query, and result is logged, so an answer from last week can still be re-run today.
Want a trustworthy 'ask your data' layer over your own systems?
If your team waits on analysts for answers that should take seconds, and the math has to be right, the architecture behind Elevate likely applies. Let's map it to your data.