← All posts

Build an AI Data Analyst That Needs No SQL

Natural language to SQL via LLM, in-process DuckDB, a three-stage pipeline, and read-only guardrails for safe analytics.

Build an AI Data Analyst That Needs No SQL
Contents

In brief

A user asks in plain English, an LLM generates SQL, DuckDB runs it in-process — the user sees only the answer. A three-stage architecture (context, generation, execution) plus read-only guardrails removes the bottleneck of “the one person who knows SQL.”

What happened

The usual pain: marketing and ops wait for a dashboard or ticket while data already sits in CSV/Parquet from HubSpot, Stripe, or an ERP. The bottleneck is not the database but translating a business question into a query.

DuckDB fits: in-process, no server, reads CSV, Parquet, and JSON as tables immediately. Exports the team already drops on disk become queryable with zero migration.

A reasoning model sits between the question and DuckDB. It needs schema context: column names, types, a few sample rows — all injected into the system prompt before SQL generation.

The UI is Streamlit (~30 lines of Python): input box and result table. The same pipeline can attach to a Telegram webhook for answers inline in chat.

The author defines three explicit stages:

  1. Context loading — on startup, read the file, infer types, build a metadata block prepended to every prompt.
  2. Query generation — question + metadata → LLM → SQL string. No execution yet: validate first — only existing columns, no writes/deletes, valid syntax.
  3. Execution and formatting — DuckDB runs the validated query; results become a table or plain text (message-safe for Telegram).

Stage separation lets you test generation and execution independently — a lesson from production pipelines where flat architectures broke under load.

Why it matters

Natural language analytics lowers the BI barrier: non-technical users get insights without SQL. Reliability, though, comes from prompt design, validation, and metadata — not Streamlit or model choice alone.

Key limits:

  • Metadata injection works up to ~50 columns; beyond that, context hits token limits — filter to relevant fields.
  • The system prompt must demand SQL only, no markdown or commentary — otherwise validation breaks. A one-shot example in the prompt cuts malformed outputs sharply.
  • Telegram round-trip is 3–8 seconds; for simple aggregations a dashboard is faster; for unpredictable questions, the tradeoff is acceptable.
  • Security: dynamic SQL needs read-only connections, allowlisting, and output size limits — real risk if exposed beyond a trusted team.

Two-tier routing (fast model for simple aggregations, reasoning model for complex joins) keeps median latency low.

In practice

If you build this agent over flat files:

  1. Validation layer first — never wire LLM output straight to DuckDB; check column refs against metadata before execution.
  2. Generate the metadata block at runtime from the actual file, not hardcoded in the prompt.
  3. Add a “show SQL” toggle so non-technical users can audit how their question was interpreted.
  4. Connect to n8n or other ETL: the agent becomes the read layer on whatever pipelines already write to disk.

Code volume is modest (~25 lines UI, ~15 DuckDB, ~30 LLM+validation), but time belongs in prompt engineering and guards.

Takeaway

An AI data analyst without SQL is a practical NL→SQL implementation on DuckDB with strict stage separation and read-only safety. Read the original if you want to give the team ad-hoc analytics without a queue to the sole SQL expert.