Ask a database a question in plain English. A small open model on your laptop writes the SQL, runs it, and reads back the answer. Nothing leaves the machine.
Inkling is a privacy-preserving text-to-SQL workspace that runs entirely on consumer hardware. It orchestrates open-weight small language models (4B–8B parameters) served locally via Ollama, with inference-time augmentations (few-shot retrieval, self-correction, schema linking, SQL repair, and majority voting), evaluated against the BIRD benchmark.
- Chat - conversational workspace with streamed SQL generation, result tables, natural-language answers, bookmarks, and training-data export.
- Evaluation - benchmark launcher against BIRD-dev with live per-question progress, difficulty breakdowns, and CSV export.
A 7B RL-trained SQL specialist (Arctic-Text2SQL-R1) reaches 67.42% execution accuracy on the BIRD california_schools slice, within ~1.5 points of its cloud-served paper result, all running locally on a single GPU.
| Requirement | Version |
|---|---|
| Python | 3.9+ |
| Node.js | 18+ |
| Ollama | Latest, running on default port |
cd backend
.\pull-models.batcd backend
.\run-backend.bat
# → http://localhost:8000
# → API docs at http://localhost:8000/docscd frontend
.\run-frontend.bat
# → http://localhost:5173Open http://localhost:5173 and start a session.
# Backend
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
python -m uvicorn api.main:app --reload --port 8000
# Frontend (in a separate terminal)
cd frontend
npm install
npm run dev---
config:
theme: base
flowchart:
curve: basis
nodeSpacing: 50
rankSpacing: 70
themeVariables:
fontFamily: "Inter, system-ui, sans-serif"
fontSize: "14px"
primaryColor: "#1a1f2a"
primaryBorderColor: "#e74c3c"
primaryTextColor: "#e7e6dd"
lineColor: "#87867c"
edgeLabelBackground: "#0e1117"
clusterBkg: "#161b22"
clusterBorder: "#3a3a35"
---
flowchart TB
Browser(["Browser · localhost:5173<br/>React 19 · TypeScript · Tailwind 4 · Vite<br/>Landing · Setup · Chat · Eval"])
subgraph API["FastAPI · localhost:8000"]
direction TB
Routers["Typed Routers<br/>chat · eval · sessions · databases<br/>prompts · bookmarks · meta · models"]
Services["Service Layer<br/>classifier · pipeline · summarize<br/>preprocess · upload · session"]
Routers --> Services
end
subgraph Core["Research Core - Python"]
direction TB
Modules["prompt_styles · schema_utils · sql_utils<br/>self_correction · sql_repair · schema_linking<br/>few_shot · evaluate"]
end
Ollama[("Ollama · :11434<br/>Arctic · Qwen3 · OmniSQL<br/>nomic-embed-text")]
SQLite[("SQLite Databases<br/>BIRD-dev + user uploads<br/>read-only mode")]
Meta[("metadata.db<br/>sessions · messages<br/>bookmarks · eval runs")]
Browser -->|"HTTP /api/*"| Routers
Browser -->|"WS /ws/chat<br/>WS /ws/eval/:id"| Routers
Services --> Core
Core --> Ollama
Core --> SQLite
Services --> Meta
flowchart LR
Q["User question"] --> Cls{"Classifier<br/>general vs SQL"}
Cls -->|general| Gen["General Chat<br/>streamed response"]
Cls -->|SQL| SL["Schema Linking<br/><i>optional</i>"]
SL --> FS["Few-Shot Retrieval<br/><i>optional</i>"]
FS --> SQL["SQL Generation<br/>n samples · major-vote"]
SQL --> SC["Self-Correction<br/><i>optional, retry on error</i>"]
SC --> Rep["SQL Repair<br/><i>regex post-process</i>"]
Rep --> Gate{"Safe-Mode<br/>Gate"}
Gate -->|block| Refuse["Refusal + reason"]
Gate -->|allow| Exec[("Execute<br/>SQLite · read-only")]
Exec --> Sum["Summarize<br/>natural language"]
Sum --> Out["Streamed back<br/>over WebSocket"]
Gen --> Out
| Model | Params | Accuracy (BIRD · california_schools) |
|---|---|---|
| Arctic-Text2SQL-R1-7B | 7B | 67.42% |
| OmniSQL-7B | 7B | 57.30% |
| Qwen3-4B fine-tune (n=8 vote) | 4B | 51.69% |
| Qwen3-8B base | 8B | 40.45% |
Seven prompt style families, auto-detected per model. Five inference-time augmentations (self-correct, few-shot, schema-link, SQL repair, majority voting), all opt-in.
inkling/
├── backend/ ← FastAPI + Python research pipeline
│ ├── api/ routers, schemas, services, storage
│ │ ├── routers/ 8 HTTP/WS endpoint files
│ │ ├── schemas/ Pydantic v2 request/response models
│ │ ├── services/ 12 business logic modules
│ │ └── storage/ SQLite metadata + user databases
│ ├── *.py research core (prompts, eval, utils)
│ ├── test_*.py unit + integration tests
│ ├── requirements.txt
│ ├── run-backend.bat Windows one-shot launcher
│ ├── pull-models.bat Ollama model puller
│ └── README.md full backend documentation (765 lines)
│
├── frontend/ ← React 19 + TypeScript + Vite + Tailwind 4
│ ├── src/
│ │ ├── pages/ Landing, Setup, Chat, Eval
│ │ ├── components/ UI primitives + feature components
│ │ └── lib/ typed API client, types, CSV export
│ ├── package.json
│ ├── run-frontend.bat Windows one-shot launcher
│ └── README.md full frontend documentation (459 lines)
│
├── showcase/ ← screenshots for documentation
├── LICENSE MIT
└── README.md this file
Both halves of the system have their own comprehensive README:
Backend README (765 lines)
Research methodology, BIRD evaluation results, system architecture with Mermaid diagrams, full API surface (36 endpoints), WebSocket event protocol, prompt style registry, safety model, internal model assignments, quick start, troubleshooting.
Frontend README (459 lines)
Screen walkthroughs with screenshots, design system (color tokens, typography, Pill component), information architecture diagram, streaming state machine, per-turn agent pipeline diagram, TanStack Query integration, project structure, configuration.
BIRD-dev is required only for the Evaluation workspace. Chat works without it against your own uploaded SQLite files.
Download from bird-bench.github.io, then configure paths in backend/.env (see backend/.env.example for the template).
MIT. See LICENSE.
The BIRD benchmark, prompt templates from OmniSQL and Arctic-R1, and model weights retain their respective upstream licenses.
Inkling: text-to-SQL, on your machine.


