An AI-powered data agent that lets you query databases using natural language. Ask questions in plain English and get SQL queries, validated results, and auto-generated visualizations.
- 💬 You ask a question in natural language
- 🔍 Kepler discovers relevant tables and recalls past learnings
- 🧠 The AI agent writes SQL, executes it read-only, and validates the results
- 📊 Results are displayed with suggested charts when appropriate
- 💬 Natural language querying — Ask questions in plain English, get SQL + results
- 🔍 Schema discovery — Automatic introspection of tables, columns, types, and sample data
- ✅ Smart validation — Checks for zero rows, high NULL rates, suspicious aggregations
- 🧠 Persistent memory — Learns corrections, schema notes, and patterns across sessions
- 📂 Query inference — Upload historical SQL files for the agent to learn from
- 🏠 ClickHouse support — Connect to ClickHouse via
CLICKHOUSE_URL; SQLite used when unset - 📤 CSV upload — Import CSV files with automatic type inference (into SQLite or ClickHouse)
- 📊 Auto-generated charts — Bar, line, pie, and area charts via Recharts
- 🔎 Semantic search (RAG) — Qdrant + Ollama embeddings for finding relevant context
- 📝 Annotations — Domain experts can annotate tables and columns with business meaning
- Frontend: Next.js 16, React 19, Tailwind CSS 4, Recharts
- Backend: Next.js API routes, Better-sqlite3, ClickHouse, Vercel AI SDK
- AI: OpenAI GPT-4o with tool-based agentic workflow
- Vector search: Qdrant + Ollama (nomic-embed-text)
- Infrastructure: Docker Compose
- 📦 Node.js 20+
- 📦 pnpm
- 🔑 An OpenAI API key
# Install dependencies
pnpm install
# Configure environment
cp .env.example .env
# Edit .env and add your OPENAI_API_KEY
# Start the dev server
pnpm devThe app will be available at http://localhost:3000. By default it runs in demo mode with sample e-commerce data (customers, products, orders).
# Set your API key
export OPENAI_API_KEY=sk-...
# Start all services (app + Qdrant + Ollama)
docker compose up -d
# Optional: run the enrichment sidecar for semantic search
docker compose --profile enrich up -dThis starts three services:
| Service | Port | Purpose |
|---|---|---|
| 🔭 kepler | 3000 | Next.js application |
| 🗄️ qdrant | 6333 | Vector database |
| 🤖 ollama | 11434 | Local embedding model |
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY |
✅ | — | OpenAI API key |
KEPLER_MODE |
❌ | demo |
demo seeds sample data, service uses existing DB |
QDRANT_URL |
❌ | http://localhost:6333 |
Qdrant vector database URL |
OLLAMA_URL |
❌ | http://localhost:11434 |
Ollama embedding service URL |
EMBEDDING_MODEL |
❌ | nomic-embed-text |
Embedding model name |
CLICKHOUSE_URL |
❌ | — | ClickHouse HTTP URL (enables ClickHouse mode) |
CLICKHOUSE_DATABASE |
❌ | default |
ClickHouse database name |
CLICKHOUSE_USER |
❌ | default |
ClickHouse username |
CLICKHOUSE_PASSWORD |
❌ | — | ClickHouse password |
When CLICKHOUSE_URL is set, data queries run against ClickHouse. Internal tables (memories, query history, annotations) always stay in SQLite. Semantic search is optional — if Qdrant/Ollama are unavailable, Kepler falls back to keyword-based schema matching.
Run make help to see all available commands.
make setup # 🏗️ Full first-time setup: install deps, start infra, pull embedding model
make up # 🚀 Start infra + dev server with ClickHouse
make dev # 💻 Dev server with SQLite only
make dev-ch # 🏠 Dev server with ClickHouse
make infra # 🐳 Start infra services (ClickHouse, Qdrant, Ollama)
make infra-stop # ⏹️ Stop infra services
make pull-model # 📥 Pull the embedding model into Ollama
make enrich # 🔎 Run the RAG enrichment sidecar
make build # 📦 Production build
make start # ▶️ Production server (SQLite)
make start-ch # ▶️ Production server (ClickHouse)
make clean # 🧹 Stop infra and remove volumescp .env.example .env
# Edit .env and add your OPENAI_API_KEY
make setup
make upsrc/
├── app/
│ ├── page.tsx # 🏠 Landing page
│ ├── demo/page.tsx # 💬 Chat interface
│ ├── docs/ # 📖 Documentation pages
│ └── api/
│ ├── chat/route.ts # 🧠 AI agent (streaming, tools)
│ ├── schema/route.ts # 🔍 Table schema endpoint
│ ├── upload/route.ts # 📤 CSV upload
│ ├── queries/route.ts # 📂 Query history
│ ├── memories/route.ts # 🧠 Memory CRUD
│ └── annotations/ # 📝 Annotation CRUD
├── components/ # 🧩 React components
├── lib/
│ ├── db.ts # 🗄️ Database operations (SQLite + ClickHouse delegation)
│ ├── clickhouse.ts # 🏠 ClickHouse client + data functions
│ ├── rag.ts # 🔎 Qdrant vector search
│ ├── enrichment.ts # ✨ Table context builder
│ ├── schema.ts # 📋 Schema formatting & scoring
│ └── types.ts # 📐 TypeScript interfaces
scripts/
└── enrich.ts # 🔄 Enrichment pipeline
data/
└── kepler.db # 💾 SQLite database
pnpm dev # 💻 Start development server
pnpm build # 📦 Production build
pnpm start # ▶️ Start production server
pnpm lint # 🔍 Run ESLint
pnpm enrich # 🔄 Run the enrichment pipelinePrivate
