Talk to your data, get answers—not just code.
EzQL is an intelligent, minimalist web application designed to democratize data analytics. Instead of forcing users to learn SQL or complex BI tools, EzQL lets anyone connect a database and ask questions in plain language.
Unlike traditional Text-to-SQL utilities that dump code for developers, EzQL acts as an autonomous data analyst in a chat interface. It aims to hide technical complexity and return business-friendly answers, summaries, and (eventually) visualizations.
EzQL is built with a decoupled architecture, strictly separating the presentation layer from core business logic:
- Backend (FastAPI): The “brain”. Exposes a REST API, handles persistence, database/runtime handling, model orchestration, and returns structured JSON to the UI.
- Frontend (Streamlit MVP): A thin client that talks only to the FastAPI API. This keeps UI replaceable (React/Next/Vue later) without rewriting the backend.
- Plug & play (SQLite-first): Upload a SQLite database file and start chatting.
- Total code abstraction: End-users should not see SQL or Python.
- Implicit statistical intelligence (roadmap): The agent can apply statistical routines when relevant and translate results into plain language.
- Context-aware reasoning: Uses schema metadata to answer business questions without requiring strict column-name phrasing.
- Environment & dependencies: uv (fast Python + dependency management via
pyproject.toml+uv.lock). - Backend: FastAPI + Pydantic/SQLModel.
- LLM orchestration: LangChain (
langchain-openai). - Frontend: Streamlit (MVP).
ezql/
├── README.md
├── pyproject.toml
├── uv.lock
│
├── backend/ # FastAPI application
│ ├── main.py # FastAPI entrypoint
│ ├── routers/ # API routes
│ └── services/ # Service layer
│
└── frontend/ # Streamlit application
├── app.py
├── components/
└── pages/
Run all commands from the repo root (where
pyproject.tomlanduv.locklive).
- uv installed
- (Optional)
sqlite3CLI, if you want to build the bundled sample database locally
The project requires Python
>=3.13(uv will manage this automatically).
uv syncThe frontend reads the backend base URL from Streamlit Secrets (st.secrets["API_BASE_URL"]).
To configure it locally:
- Ensure the folder exists:
frontend/.streamlit/ - Create/edit
frontend/.streamlit/secrets.toml:
# frontend/.streamlit/secrets.toml
API_BASE_URL = "http://localhost:8000/api/v1"Notes:
- If you don’t set anything, the default is
http://localhost:8000/api/v1. frontend/.streamlit/is ignored by git, so this file won’t be committed.
API keys (OpenAI / DeepSeek) are configured inside the web UI on the Settings/Profile screen.
- You do not need environment variables for API keys.
- Keys are stored locally in EzQL’s internal SQLite database (
backend/ezql.db). - If you delete
backend/ezql.db, you’ll need to set the keys again.
EzQL uses two different kinds of databases when running locally:
- File:
backend/ezql.db(SQLite) - Stores: users, chats, messages, and per-user model API keys
- Created/migrated automatically when the backend starts
- Not versioned (SQLite files are ignored via
.gitignore)
Quick reset (wipes local users/chats/keys):
rm -f backend/ezql.dbOptional: you can also initialize it manually:
uv run python backend/init_db.py
In the current MVP, EzQL analyzes SQLite files (.db, .sqlite, .sqlite3).
You can:
- Upload a SQLite file when creating a new chat.
- Use a bundled sample dataset (Netflix).
Important runtime behavior:
- Uploaded SQLite files are treated as temporary runtime databases.
- If the backend process restarts, you must upload the SQLite file again (and typically recreate the chat).
For safety, the SQLite file frontend/test_data/netflix.db is not committed to the repo (all *.db files are ignored). The repo includes the CSV dataset at frontend/test_data/netflix_titles.csv.
To build the sample database locally:
cd frontend/test_data
sqlite3 netflix.dbThen inside the sqlite3 prompt:
CREATE TABLE netflix_titles (
show_id TEXT PRIMARY KEY,
type TEXT,
title TEXT,
director TEXT,
"cast" TEXT,
country TEXT,
date_added TEXT,
release_year INTEGER,
rating TEXT,
duration TEXT,
listed_in TEXT,
description TEXT
);
.mode csv
.import netflix_titles.csv netflix_titlesTerminal 1 (backend):
uv run fastapi dev backend/main.py --host 127.0.0.1 --port 8000Terminal 2 (frontend):
uv run streamlit run frontend/app.pyUseful URLs:
- Frontend (Streamlit):
http://localhost:8501 - API docs (FastAPI):
http://localhost:8000/docs
uv run poe run-appThis task uses
lsof/killto free port 8000. On Windows, use the two-terminal option.
- Open the frontend at
http://localhost:8501. - Create your first local user and log in.
- Go to Settings/Profile and add your OpenAI or DeepSeek API key.
- Create a new chat and choose either:
- the Netflix sample database (if you built
frontend/test_data/netflix.db), or - upload your own SQLite file.
- the Netflix sample database (if you built
- If running in two terminals: press
Ctrl + Cin each terminal. - If running via
uv run poe run-app: pressCtrl + Conce (the task stops Streamlit and terminates the backend).
If a port is stuck (macOS/Linux):
lsof -ti tcp:8000 | xargs kill
lsof -ti tcp:8501 | xargs kill