# Clone the repository
git clone https://github.com/momalekpour/vortosql.git
cd vortosql
# Install dependencies (uv manages the virtualenv and Python version automatically)
# Install uv first if needed: https://docs.astral.sh/uv/getting-started/installation/
uv sync
# Optional extras — only needed if you use the HuggingFace provider or few-shot examples:
# uv sync --extra huggingface # transformers (~1 GB with torch)
# uv sync --extra examples # datasets (BIRD few-shot loader)
# (Optional) Install pre-commit hooks for auto linting (ruff) and formatting (black) for development
uv run pre-commit install# Copy the example env file and set your OPENAI_API_KEY
cp .env.example .env
# Web UI (recommended)
bash scripts/run_ui.sh
# CLI REPL
bash scripts/run_cli.shcp .env.example .env # fill in OPENAI_API_KEY
# Web UI → http://localhost:8501
docker compose up ui
# Interactive CLI
docker compose run --rm cli
# PostgreSQL only (for development/testing)
docker compose up postgres -dSee docs/architecture.md for full details. The application is built around a composable operator pipeline configured via config.yaml — each operator's model provider, technique, and behaviour is plug-and-play; the default setup is ready to run as-is. Each operator implements an execute(context) method that reads from and writes to a shared context dictionary. The pipeline runs the following operators in order:
- IntentGuardrail - Optional LLM-based scope classifier; rejects out-of-scope questions via early-stop. Skipped when no scope is configured.
- SchemaLinker - Resolves which tables/columns are relevant to the question
- ExampleSelector - Retrieves similar few-shot examples (skipped in zero-shot mode)
- SQLGenerator - LLM generates a SQL query from the question, schema, and examples
- SQLCorrector - Validates and auto-corrects SQL errors via retry loop
- SQLExecutor - Executes the final SQL against the database
- AnswerGenerator - LLM summarises the query results into a natural language answer
Two opt-in defences, both controlled by config.yaml (or by overrides passed to NL2SQLApp):
- Layer 0 — Intent gate (IntentGuardrail, soft): when
scopeis set, the LLM checks whether the question fits the described scope and triggers an early-stop if not.scope: nulldisables the operator entirely. - Layer 1 — Schema restriction (SchemaLinker, hard): when
schema_guardrailsis set, only allowlisted tables/columns are exposed to the LLM.schema_guardrails: nullexposes the full schema.
Opt-in: set VORTOSQL_DUMP_SESSION_LOGS=1 and every pipeline run will write its full config and context to logs/<timestamp>.json for traceability.