Open-source AI technical interview trainer. Practice from curated YAML question banks, get structured scoring and follow-ups, and optionally use voice — with your own LLM (cloud or local).
Why GrillKit · Quick start · Changelog · Architecture
A general chat assistant is flexible, but it does not run an interview for you.
| What you need | ChatGPT-style chat | GrillKit |
|---|---|---|
| Curated technical questions | You prompt each time | Built-in tracks (Python, Kafka, System Design, …), levels, and topics |
| Interview flow | Free-form thread | Fixed session: N questions, up to 2 AI follow-ups per question, 1–5 scoring, session summary |
| Practice history | Scattered chats | Dashboard with past sessions stored locally |
| Time pressure | None | Optional per-round timer (expired round → 0, move on) |
| Voice practice | Depends on product | Offline Whisper dictation; optional Piper question audio; audio answers when your model supports it |
| Where data lives | Vendor cloud | Self-hosted: SQLite + data/ on your machine; use Ollama, vLLM, or any OpenAI-compatible API |
Structured practice — You pick tracks, difficulty, and topics; GrillKit builds a question plan and keeps score across the whole session, not a single ad-hoc prompt.
Privacy and control — Run via Docker on your laptop or server. API keys and interview history stay under ./data (gitignored). No account or subscription required beyond your LLM provider (if you use a cloud model).
Demo video — full flow from setup to scored feedback
Dashboard — recent sessions and quick start
Interview setup — question-bank tracks, levels, topics, and session options
Interview session — real-time Q&A with AI scoring and final evaluation
- Interviews — multi-track setup, several topics per session, WebSocket Q&A, AI scoring 1–5, up to 2 follow-ups per question
- Question banks — Python, Database/SQL, System Design, Kafka, RabbitMQ, Docker, Kubernetes, Observability, Airflow, and more under
data/questions/{track}/(junior / middle / senior where applicable) - Timer — optional per-round time limit; expired rounds score 0 and the session moves on
- Voice — offline Whisper dictation for typed answers; optional Piper TTS to read questions aloud
- Audio answers — when the configured model supports audio input and Whisper is ready, record and send a WAV answer from the interview page
- Setup — model catalog on
/config, interview locale (AI feedback language), Whisper/Piper downloads from the UI - Dashboard — recent interview history on the home page
- Deployment — Docker Compose on port 8000 with
./datavolume for config, DB, and models
- Docker and Docker Compose
- API key for a cloud provider, or a local OpenAI-compatible server (Ollama, vLLM, …)
git clone https://github.com/yourusername/grillkit.git
cd grillkit
docker compose up --buildOpen http://localhost:8000.
Optional question voice (Piper TTS, same app container):
- Run
docker compose up(oruv run uvicorn app.main:appfor development). - Open
/config, enable Read questions aloud, save. - On the Configuration page, use Download question voice when prompted (~60 MB per locale voice from Hugging Face).
- Start an interview — questions can play aloud; WAV cache lives under
data/tts-cache/v2/{locale}/.
./data on the host holds SQLite, config.json, llm_models.json, Whisper/Piper models, and TTS cache. Question banks, templates, and static files ship in the image.
If bind-mounted data/ is not writable (Linux UID mismatch):
PUID=$(id -u) PGID=$(id -g) docker compose up --build- Configuration (
/config) — add one or more OpenAI-compatible models to the catalog, select an interview model, set interview locale; test connection, then save. - New interview (
/setup) — enable one or more question-bank tracks (level per track), select multiple topics, set total question count (at least one per selected topic; interview locale is read-only from config). - Interview (
/interview/{id}) — page loads history; text answers and completion go over WebSocket.
Without saved provider config, /setup redirects to /config.
For contributors: see CONTRIBUTING.md. Quick run:
uv sync --extra dev
uv run uvicorn app.main:app --reloadSame first-time flow at http://127.0.0.1:8000.
Any OpenAI-compatible HTTP API works:
| Provider | Example base URL |
|---|---|
| OpenAI | https://api.openai.com/v1 |
| Ollama | http://localhost:11434/v1 |
| vLLM / others | your endpoint + /v1 |
On /config:
- Add model to catalog — base URL, model name, optional API key; enable Accepts audio input only if the model supports multimodal audio (and download Whisper for transcription).
- Interview model — pick from the catalog, Test Connection, save.
- Locale — language for AI feedback and speech (stored in
data/config.json, gitignored). - Whisper — choose size (
small,medium,large), download from the UI for dictation and audio answers. - Read questions aloud — enable Piper, download a voice (~60 MB).
Do not commit data/config.json, data/llm_models.json, or API keys.
Optional environment variables (full list in ARCHITECTURE.md):
| Variable | Purpose |
|---|---|
DATABASE_URL |
SQLAlchemy URL (default: SQLite under data/db/) |
HF_TOKEN |
Hugging Face token for faster Whisper/Piper downloads |
WHISPER_DEVICE |
cpu or cuda |
WHISPER_COMPUTE_TYPE |
int8 or float16 |
Planned
- Session-wide time limit (total interview duration)
- More question banks and categories
- Code editor in the interview UI
- Custom question banks, PWA / standalone frontend
| Document | Contents |
|---|---|
| ARCHITECTURE.md | Layers, HTTP/WebSocket routes, data flows, persistence, question banks |
| CONTRIBUTING.md | Dev setup, tests, ruff/mypy/pytest, contribution workflow |
| CHANGELOG.md | Release history |
Report vulnerabilities as described in SECURITY.md. Do not open public issues for security problems.
Apache License 2.0 (see also NOTICE)



