Embedded chat reporting for Python backends
Ask for a report in plain language.
The model never writes the SQL.
SageQL turns a Persian or English request into a typed report specification, checks it against what the host registered and what the user may see, then writes a parameterized, read-only query itself. Below are real runs, stage by stage.
How a request becomes a report
- ModelExtract intent Picks registered measures, groupings, period and filters by ID, or asks a question.
- SageQLValidate Every ID must be registered and allowed for this user. Anything else is rejected.
- SageQLResolve Dates, Solar Hijri months and product names are resolved locally.
- SageQLCompile Writes the SQL with the user's row policy and bound parameters.
- SageQLExecute Read-only, with row, time and work limits. Rows never go back to the model.
Examples
Measured results
Frozen synthetic multi-turn conversations, 27 scored reports, low reasoning effort.
| Setup | Correct reports | Model calls / 40 turns | Median turn |
|---|---|---|---|
gpt-5-nano for every stage | 8/27 | 76 | 8–21 s |
gpt-5-mini intent, nano planner and reviewer | 15/27 | 87 | 16–21 s |
gpt-5-mini intent, locally compiled spec, no reviewer | 22/27 | 34 | ~7 s |
Compiling a complete intent locally, instead of asking a second model to plan it, removed more than half the calls. The deterministic side is covered by about 2,200 offline tests in CI on Linux and Windows, Python 3.10–3.15. Full comparison.