Voice and text interface for any SQLite database - fully local, $0, with a human-in-the-loop approval gate on every mutation.
Anyone sitting on a SQLite database - developers, analysts, ops teams - either writes SQL by hand or does nothing. Non-technical users are locked out entirely. And the moment natural language is allowed to touch the database, a wrong or misheard command can silently destroy data with no way back.
VocalOps turns voice or text into database actions on any SQLite file, with zero schema changes or config. Every mutation is generated as a preview first and only executes after explicit human approval. Every committed change is logged and can be undone. It runs entirely offline through Ollama, at $0, with no API keys required.
The router LLM handles both tool selection and read-query SQL generation - the same local or Boost model does both jobs, no separate SQL specialist required by default. Every mutation is staged behind an interrupt_before checkpoint in the LangGraph state machine and only reaches the database after explicit human approval, and mutation execution always runs against the local Ollama model even in Boost mode, so the safety-critical write path never depends on a cloud key. Failure modes are surfaced honestly rather than silently: empty/no-tool-call completions, GraphRecursionError, schema drift since init, and read-only tables all return a specific message instead of failing quietly.
VocalOps never modifies its own repo folder while running. Everything stateful — conversation history, undo logs, the schema manifest, vector indexes, LangGraph checkpoints — lives under ~/.vocalops/, in a per-database sidecar folder keyed by a hash of the database file path (not its contents). Connect orders.db and library.db and each gets its own isolated subdirectory; CLI and web share the same sidecar for a given path.
- Schema-agnostic: works on any SQLite DB with zero config changes
- Voice input with VAD auto-stop and editable transcript echo before send
- Full mutation safety pipeline: propose → preview → approve → commit → undo
- Per-session UUID isolation with persistent SqliteSaver checkpointing (shared across CLI and web)
- Honest-failure guard: vague or unresolvable requests get a clear rephrase prompt, never a silent empty response
- Read-only table detection: composite-key and WITHOUT ROWID tables flagged at
init, never silently attempted - Two operating modes: Local-Only ($0, offline) and Boost (optional cloud keys)
- Web UI with streaming responses, approval panel, schema browser, history panel, database switcher
- CLI with rich table rendering for query results
- Prometheus-format
/metricsendpoint (HITL decisions, schema drift, mutation rows) - Eval harness: three test suites, MLflow provenance tagging
| Component | Local-Only ($0, offline) | Boost (optional) |
|---|---|---|
| Speech-to-text | faster-whisper (CPU) | Deepgram |
| Router LLM | qwen2.5:7b-instruct (Ollama) | llama-3.1-8b-instant (Groq) |
| Mutations | always local (Ollama) | always local (Ollama) |
| Embeddings | nomic-embed-text (Ollama) | nomic-embed-text (Ollama) |
| Cost | $0 | pay-per-use API calls |
Mutations and embeddings always run locally regardless of mode - the safety-critical path never leaves your machine.
| Eval Suite | Cases | Model | Score |
|---|---|---|---|
| Standard | 6 | Local qwen2.5:7b-instruct | 100% |
| Hard (held-out) | 14 | Boost - Groq llama-3.1-8b-instant | 86% |
| Rigorous (held-out) | 30 | Boost - Groq llama-3.1-8b-instant | 83% |
Failures are non-deterministic and fail safe - the model routes to an honest-failure or rejection message rather than executing an incorrect action. No case ever executed a wrong mutation.
- 16 GB RAM recommended
- 8 GB RAM works -
setupautomatically falls back tollama3.2:3b-instructif the qwen2.5:7b smoke test fails - ~8 GB disk for Ollama models
# one-time setup
pip install -e .
vocalops setup
vocalops init --db path/to/your.db
# CLI
vocalops chat
# Web UI (two terminals)
uvicorn vocalops.main:app --host 0.0.0.0 --port 8000
cd vocalops-frontend && npm install && npm run dev
# open http://localhost:5173
- Mutations require a single-column INTEGER PRIMARY KEY (composite-key and WITHOUT ROWID tables are read-only)
- Router routing is probabilistic: 83–86% on held-out hard/rigorous cases in current measurements; missed requests return a rephrase prompt and never execute incorrectly
- Deep multi-hop joins occasionally exceed the model's reasoning depth and fail gracefully with a clear message
- Boost mode rate-limits on Groq's free tier under rapid sequential queries (normal interactive use is unaffected); errors surface as a message, not automatic retries
The full fine-tuning pipeline is built: a synthetic data generator (2000 examples across 8 domains, ~22% subquery WHERE cases), an executing verifier (2000/2000 pass rate), and an Unsloth QLoRA training script plus Modelfile. The router already scores well on held-out cases without it, so the improvement headroom didn't justify shipping and maintaining a second model. The pipeline lives in training/ if you want to run it - the train_unsloth.py step is a stub meant to run interactively on a GPU host; a completed vocalops-sql model would replace the router for mutation proposals only.
- Backend: FastAPI, LangGraph, LangChain, SQLite
- Agent: Groq / Ollama, faster-whisper / Deepgram, ChromaDB
- Frontend: React, Vite
- Observability: Prometheus-format
/metricsendpoint, MLflow - DevOps: Docker, docker-compose, DVC, GitHub Actions
MIT - see LICENSE


