nl2sql-engine
Ask a database questions in English. The model writes a typed query plan, never SQL text; the plan is checked against the real schema and the caller's role before any SQL is generated.
This distribution is the engine: the LangGraph pipeline, the nl2sql CLI with
its browser playground, and the database adapters (PostgreSQL, MySQL, SQL
Server, SQLite, DuckDB). The REST server is the separate nl2sql-api package.
Full README and docs: https://github.com/nadeem4/nl2sql.
Try it in your browser
https://nl2sql.codewithnk.com — the playground on three sample databases, nothing to install.
The server holds no API key: you paste your own into the page, one per provider, and it stays in that browser tab, is used in memory for the question that needs it, and is never stored, logged or traced. Settings also puts each of the five model-using steps on a provider and model of its own.
How it works
- The question is checked for answerability and routed to one of the registered databases, then split into sub-queries, and each gets the part of the schema it needs.
- The model returns a typed plan (a Pydantic
PlanModel), never SQL. It may only name a function from an allow-list, and date work is written portably and rendered by each adapter in its own dialect. - The logical validator checks every table and column against the schema, joins against the declared foreign keys, and every table against the caller's role (RBAC); it also builds the query tree the generator would build, so an unjoinable plan is caught while the planner can still be asked to fix it. A refused plan never becomes SQL.
- Only a plan that passes is rendered to SQL, deterministically, with
sqlglot, then executed and summarised.
The whole pipeline is 13 steps, five of them decided by a model; the playground's Pipeline page lists them.
Quickstart
Requires Python 3.12 or newer.
pip install "nl2sql-engine[demo]"
nl2sql demo
That writes a demo project into ./nl2sql-demo, copies in three SQLite
databases -- Chinook,
support and webanalytics -- indexes their schemas locally (no key; the
first run downloads a ~79 MB ONNX embedding model) and opens the playground on
http://127.0.0.1:8765/.
Answering a question needs a model: --api-key, or OPENAI_API_KEY,
OPENROUTER_API_KEY or ANTHROPIC_API_KEY in the environment (Claude needs
pip install "nl2sql-engine[demo,anthropic]"), a key pasted into the
playground's Settings page, or a reachable Ollama. Without one the demo runs
in replay mode, which has no recorded answers out of the box, so it can show the
schema and the index but answers nothing. nl2sql demo --record (with an
OpenAI, OpenRouter or Anthropic key) records the guided questions for later key-free runs.
nl2sql demo --hosted runs the public variant above yourself: the server holds
no API key, each visitor pastes their own into the page for that question only
(without one, the guided questions replay recorded runs),
the sample databases are opened read-only, questions are rate limited per
visitor and capped per session, and Settings, Rebuild, ratings and --record
are refused. See
Hosted demo
in the full docs.
The playground shows each answer's plan, validation checks, SQL, rows and cost,
a per-node Debug view, a Pipeline page listing every step of a run with the
model each used, a Retrieval inspector over the live index, and a right/wrong
rating per answer that nl2sql feedback stats reports on.
CLI
From the demo folder (cd nl2sql-demo):
nl2sql --env demo run "How many customers do we have, by country?"
nl2sql --env demo run --role viewer "Who are the top 5 customers by total spend?" # refused
nl2sql --env demo run --no-exec "Which artist has the most albums?" # plan only
nl2sql --env demo index # re-index the schema
nl2sql --env demo doctor # check drivers, connectivity, key and index
nl2sql --env demo benchmark --tier 1 # gold plans, no key
nl2sql --env demo benchmark --tier 2 --model gpt-5.4 --max-cost 5
nl2sql --env demo benchmark retrieval # retrieval recall, no key
nl2sql --env demo feedback stats # ratings and guardrail rates
Every command: CLI reference.
Python
from nl2sql import NL2SQL, UserContext
engine = NL2SQL(env="demo") # loads .env.demo from the working directory
result = engine.run_query(
"How many customers are there?",
user_context=UserContext(roles=["admin"]),
)
for sq in result.sub_queries:
print(sq.sql, [c.name for c in sq.validation if c.passed])
print(result.final_answer["summary"] if result.final_answer else result.errors)
Pass a user_context with a role: with none, run_query currently raises a
validation error, and an unknown role is refused.
Install extras
pip install "nl2sql-engine[postgres]" # or [mysql], [mssql], [duckdb]
pip install "nl2sql-engine[all]" # every database driver; not [demo] or [anthropic]
SQLite needs no extra.
Security
- The LLM provider receives the question, the schema the planner needs, sample column values of tables the role may read, and the result rows (for the written answer).
- RBAC is a per-role table allowlist; a plan touching a forbidden table is refused. No column masking or row-level security.
- Read-only is not checked by the executor: only SELECTs are generated, and a
SQLite datasource can be opened read-only with
options.read_only: true(the three sample databases are), but no other dialect is. Give the engine a read-only database user. - No authentication: the caller supplies the role.
- No cross-database questions and no conversation yet: each sub-query is planned against one datasource, and each question is answered on its own.
Status
0.1.x. nl2sql-adapter-sdk, nl2sql-engine and nl2sql-api share one version
and are released together. Known limitations, benchmark results and the
roadmap: https://github.com/nadeem4/nl2sql#project-status-limitations-and-roadmap.
MIT licensed.
Metadata
Release files for nl2sql-engine 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nl2sql_engine-0.3.0.tar.gz | 6.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nl2sql_engine-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.4 MB
Release files / nl2sql_engine-0.3.0.tar.gz
| Download URL | nl2sql_engine-0.3.0.tar.gz |
|---|---|
| Size | 6.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99e9e47f4b60f378c809514599cb75adbb9b742e1482d499b2071cfaf1399d48
|
|
BLAKE2b-256 checksum How to use checksums |
399e8dbcd2d8d10f46c360bc72793ae98d008773c691de4b4f29f9f0b4e795dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / nl2sql_engine-0.3.0-py3-none-any.whl
| Download URL | nl2sql_engine-0.3.0-py3-none-any.whl |
|---|---|
| Size | 6.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b52601efa27b7feaf11c50a2785b644fc9127220f76bb82c71d28613a2f19a97
|
|
BLAKE2b-256 checksum How to use checksums |
888e42ae11521c4a2312adae945d00f7b47792ebbf19c3465ab3720ad2251019
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|