A markdown-driven, self-hosted quiz platform powered by Streamlit + SQLite. Turn any markdown content into an interactive quiz — lectures, notes, documentation, or anything you want to master.
- Python
- Streamlit (Web UI)
- SQLite (local database)
QuizKit is a local-first quiz system for turning markdown lecture notes into a reusable question bank, then using that bank for exam generation, review, wrong-question practice, and optional LLM-assisted study workflows.
Core responsibilities:
UI: Streamlit pages for exam generation, answering, review, stats, and wrongbook practiceApplication: quiz indexing, exam generation, scoring, history/statistics, and LLM workflowsDomain: markdown quiz parsing and question normalizationInfrastructure: SQLite schema/bootstrap and external LLM provider access
quizkit/
├── app.py # Thin Streamlit entrypoint
├── quizkit/
│ ├── config.py # App configuration loading
│ ├── application/
│ │ ├── quiz_service.py # Quiz indexing/exam/history/statistics services
│ │ ├── llm_service.py # LLM workflows, cache, audit, draft operations
│ │ └── services.py # Compatibility re-export layer
│ ├── domain/
│ │ └── parser.py # Markdown question parsing
│ ├── infrastructure/
│ │ ├── db.py # SQLite schema and migrations bootstrap
│ │ └── llm_client.py # LLM provider adapters
│ └── ui/
│ ├── streamlit_app.py # Streamlit app bootstrap and route dispatch
│ ├── context.py # UI shared context object (cfg + db conn)
│ ├── state.py # Session state bootstrap and page navigation
│ ├── helpers.py # Shared UI helper functions
│ └── pages/
│ ├── home_page.py
│ ├── exam_page.py
│ ├── result_page.py
│ ├── history_page.py
│ ├── stats_page.py
│ └── wrongbook_page.py
├── migrations/
│ └── migrate.py
├── config.yaml
├── config.example.yaml
└── data/
Rule of thumb:
- Keep runnable entry scripts in the repository root.
- Put business logic under
quizkit/application. - Put parsing or pure rules under
quizkit/domain. - Put database and external service adapters under
quizkit/infrastructure.
- Reindex lecture markdown files into a local question bank
- Generate exams by lecture range
- Submit answers and auto-score
- View per-question result and answer review
- History of attempts
- Stats by lecture and tag
- Wrongbook and wrong-question practice mode
- Question type labels (True/False, Single Choice)
- Exam countdown timer
- Quick select by lecture number (Lecture1-Lecture8)
- CSV export for history and stats
- Database migration script for schema upgrades
LECTURE_DIR:../../blackboard/lectures/markdownEXAM_QUESTION_COUNT:20EXAM_DURATION_MINUTES:40ALLOW_UNDERFILLED_EXAM:falseDB_PATH:./data/app.db
The app supports a YAML config file at config.yaml.
Priority order (high to low):
- Environment variables
config.yaml- Built-in defaults
Path policy:
- Absolute paths are recommended.
- Relative paths are allowed and will be resolved to absolute paths based on the config file directory.
You can set a custom config file path with:
export APP_CONFIG_FILE=/absolute/path/to/config.yamlUse config.example.yaml as a template.
This version supports optional LLM integration for:
- Question optimization (preview only, does not overwrite source markdown)
- Missing explanation generation (writes to DB
questions.explanation) - Study recommendation generation after an attempt
Built-in reliability features:
- LLM response cache (prevents duplicate calls)
- LLM audit logs (task status, cache hit, retries, latency, tokens)
- One-click apply optimized output into
question_drafts(requires UI confirmation) - Batch cap and item-level retry strategy
Supported providers:
openai_compatible(oropenai)anthropic
Enable in config.yaml:
llm:
enabled: true
provider: openai_compatible
api_key: "YOUR_KEY"
base_url: https://api.openai.com/v1
model: gpt-4o-miniRelated environment variables (override YAML):
LLM_ENABLEDLLM_PROVIDERLLM_API_KEYLLM_BASE_URLLLM_MODELLLM_TIMEOUT_SECONDSLLM_MAX_RETRIESLLM_TEMPERATURELLM_MAX_TOKENSLLM_MAX_BATCH_ITEMSLLM_ITEM_MAX_RETRIESLLM_RETRY_BACKOFF_SECONDSLLM_ENABLE_QUESTION_OPTIMIZATIONLLM_ENABLE_EXPLANATION_GENERATIONLLM_ENABLE_STUDY_RECOMMENDATION
cd quizkit
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 -m streamlit run app.pyIf you already have an old local DB and upgrade code, run:
python3 migrations/migrate.py- Current parser supports:
:::quizblocks- legacy numbered quiz format from
in-class_quiz.md
- Questions are versioned by source hash to preserve attempt traceability.
- Short-answer questions are indexed but excluded from MVP auto-graded exams.