Skip to main content

NL2BI — Natural Language to Business Intelligence

Ask questions in plain English. Get tables, charts, and answers — directly from your database.

PyPI version Python


What it does

NL2BI translates natural language questions into validated, read-only SQL queries, executes them, and returns structured results with chart recommendations — no dashboards, no SQL knowledge required.

"Show me the top 5 suppliers by contract value this quarter"
        ↓
  Intent classified (TopN) → hint steers SQL generation
        ↓
  Relevant schema retrieved → SQL planned → validated (read-only) → executed
        ↓
  Table + bar chart recommendation + NL summary

Architecture

A sequential multi-stage pipeline, plain Python (no agent framework):

Stage Component What it does
1 Schema Extractor Introspects the DB once at startup; retrieves just the relevant tables per query (lexical + business-term scoring)
2 Intent Classifier Classifies into one of 10 question types, which nudges SQL generation with a type-specific hint
3 SQL Planner Generates SQL from the query + retrieved schema + intent hint
4 Validator Rejects anything that isn't a single read-only SELECT/WITH statement (AST-checked via sqlglot — catches statement-stacking and DML hidden in CTEs)
5 Executor Runs the validated query, returns structured results
6 Self-Correction On a validation or execution failure, feeds the error back to the SQL Planner and retries (bounded by max_sql_retries, default 2)
7 Chart Reasoner Recommends a visualization type for the result columns

10 question types: Filter, KPI, Grouping, TopN, Comparison, CrossEntity, RiskAlert, Financial, Drilldown, Recommendation

Semantic layer: Map business vocabulary to schema elements the LLM would never guess from column names alone — see Business terms below.

Memory: Short-term — the last 5 turns of a conversation are always included as context. Long-term — optional (memory=True), stores past queries in a lightweight JSON-persisted embedding store and recalls similar ones on future queries.

Guardrails: Read-only execution enforcement (Stage 4) and structured JSON output from the LLM at every stage.

Observability: Every query returns result.metrics (question type, retry count, validation/execution pass-fail, latency) and emits one structured log line via logging.getLogger("nl2bi"). This is retry/latency tracking, not a golden-dataset eval harness — there's no SQL-correctness or hallucination-rate scoring yet, since that needs ground truth this project doesn't have.


Install

pip install nl2bi

For Anthropic support: pip install nl2bi[llm]. OpenAI and local (Ollama) providers need no extra install.


Quick Start

from nl2bi import NL2BI

# Connect to your database
agent = NL2BI(
    db_url="postgresql://user:password@localhost/mydb",
    llm="openai",  # or "anthropic", "local"
    api_key="your-api-key"
)

# Ask a question
result = agent.query("What are the top 10 customers by revenue last month?")

print(result.table)        # structured data (pandas DataFrame)
print(result.sql)          # generated SQL
print(result.summary)      # NL explanation
print(result.chart_type)   # recommended visualisation
print(result.metrics)      # question_type, retry_count, latency_seconds, ...

Multi-turn conversation (short-term memory is always on):

result1 = agent.query("Show me contracts expiring this quarter")
result2 = agent.query("Now filter those above $50K")  # prior turn is in context

Long-term memory (opt-in — costs one extra embedding call per query):

agent = NL2BI(db_url="...", memory=True, memory_path="memory.json")

Local models via Ollama (llm="local" expects Ollama running at http://localhost:11434 with the model already pulled):

agent = NL2BI(db_url="...", llm="local")

Business terms

Map domain vocabulary to schema elements before querying, so "churn" resolves to the right table even if no column is named that:

result = agent.query("...")  # after connecting

# Access the underlying schema extractor for glossary/description setup:
extractor = agent._orchestrator.schema_extractor
extractor.add_business_term("churn", "subscriptions.cancelled_at", "customers who stopped paying")
extractor.add_table_description("subscriptions", "Active and cancelled customer subscriptions")

Supported Databases

Any database supported by SQLAlchemy:

  • PostgreSQL
  • MySQL
  • SQLite
  • MS SQL Server
  • Oracle

Supported LLMs

  • OpenAI (GPT-4o, GPT-4o-mini)
  • Anthropic (Claude) — requires pip install nl2bi[llm]
  • Local models via Ollama (uses Ollama's OpenAI-compatible endpoint, no extra dependency)

Why not just use text-to-SQL?

Plain text-to-SQL breaks on ambiguous queries, complex joins, and multi-step questions. NL2BI adds:

  • Intent classification before SQL generation — different question types get a tailored prompt hint
  • Self-correction loops — if the SQL fails validation or execution, the agent sees why and retries
  • Session memory — follow-up questions work naturally
  • Guardrails — a rejected write/delete never reaches your database

License

MIT


Built by Mithran Bala

Metadata

Release files for nl2bi 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nl2bi 0.2.0
File Size Uploaded Provenance
nl2bi-0.2.0.tar.gz 25.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for nl2bi 0.2.0
File Interpreter ABI Platform
nl2bi-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.0 kB

Release files / nl2bi-0.2.0.tar.gz

Download URL nl2bi-0.2.0.tar.gz
Size 25.3 kB
Tags Source
SHA-256 checksum
How to use checksums
52b0f4623798b4f6ca6ebffa91b00a2e75b2878fb18b55c57cb9f68e98115858
BLAKE2b-256 checksum
How to use checksums
c4d371d30014908a42bb0f81100970619b56ad544555449b77309e3b52294631
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release files / nl2bi-0.2.0-py3-none-any.whl

Download URL nl2bi-0.2.0-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
417c0b6e2be448bea9f8e1ddd9bb0d4f0c926fff722b99fa21b12fe77a9079e7
BLAKE2b-256 checksum
How to use checksums
8023de21e4c9a70c1b14c80a1500983b96f695e2ecc30b5765688e6e1c54958c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Security for nl2bi 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page