A local-first enterprise analytics copilot that turns natural-language business questions into safe SQL and evidence-grounded analytical answers.
This is deliberately not just:
Question → LLM → SQL
The current architecture routes the problem according to its structure:
Question
|
Schema Retrieval
|
Analytical Planner
/ \
match no match
| |
Multi-step analysis Intent Planner
| / \
| known unknown
| | |
| Deterministic LLM
| SQL SQL
| \ /
| \ /
+-------------- SQL Guard
|
Read-only DB
|
Evidence/Result
|
Business Answer
Which stores have the highest sales?Show sales by regionWhich stores had the highest number of orders in January?What is the average promo spend by region?What were total sales last month?
Why did sales decline?
For this question, V0.2.7 uses the explicit assumption:
Compare the latest available week with the immediately preceding available week, then inspect store-level contributions.
The system measures the data rather than accepting the user's premise as fact.
app/
├── agent.py
├── api.py
├── config.py
├── db.py
├── main.py
├── schema.py
└── services/
├── analytical_planner.py
├── cache.py
├── intent_planner.py
├── llm.py
├── providers.py
├── schema_catalog.py
└── sql_guard.py
docs/
├── EVOLUTION.md
├── ARCHITECTURE_DECISIONS.md
├── HLD.md
├── LLD.md
├── EVALUATION.md
├── INTERVIEW_STORY.md
├── TROUBLESHOOTING.md
├── API_EXAMPLES.md
└── decisions/
scripts/
├── init_db.py
├── demo.py
└── evaluate.py
ui/
└── streamlit_app.py
tests/
Windows CMD:
python -m venv .venv
.venv\Scripts\activatepython -m pip install -r requirements.txtCopy:
.env.example → .env
For Ollama:
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://127.0.0.1:11434
OLLAMA_MODEL=llama3.2:1bFor deterministic tests, .env does not matter; pytest forces the Mock provider.
Always run from the repository root:
python -m scripts.init_dbExpected:
Loaded 16 rows into data/analytics.db
python -m pytest -quvicorn app.main:app --reloadOpen:
http://127.0.0.1:8000/docs
In another terminal:
streamlit run ui/streamlit_app.pypython scripts/demo.pypython scripts/evaluate.pyThe result is written to:
artifacts/evaluation.json
GET /api/health
POST /api/query
{
"question": "Why did sales decline?",
"include_sql": true
}The response contains:
- business answer
- generated SQL when applicable
- result rows
- validation status
- latency/tokens/cost
- planner/analysis usage
- agent trace
- retrieved schema
- analytical steps/results when applicable
The included llama3.2:1b configuration is a baseline, not a claim that 1B is the best model for NL2SQL.
V0.2.7 intentionally reduces the amount of work delegated to the model. A stronger model should be selected only after benchmarking the same workload on:
- correctness
- latency
- repair attempts
- token usage
- cost
- local resource requirements
Read these in order:
docs/EVOLUTION.md— what failed and why the architecture changeddocs/decisions/— individual architectural decisionsdocs/HLD.md— current high-level architecturedocs/LLD.md— implementation designdocs/EVALUATION.md— how the system is measureddocs/INTERVIEW_STORY.md— concise explanation for interviews
This is a portfolio/reference implementation, not a production security certification. SQL is parsed, constrained to read-only operations and checked against the demo schema before execution. Production deployment still requires authentication, authorization, tenant isolation, secrets management, database permissions and operational controls.
The analytical reasoning path uses trusted, code-owned multi-step CTE queries. V0.2.8 fixes the SQL guard so CTE/derived-query output columns are recognized in outer query scopes while the read-only and allowed-base-table checks remain in place.