1f053f7d91bff79832da90789c43a65a88250dfc
Removes embedding-heavy search and generic browser tabs from the Explorer. The project does not currently use embeddings meaningfully, so the similarity search and browser features were dead weight. Changes: - explorer.py: Remove search and browser tabs, keep compass/trajectories/SVD - explorer.py: Remove fused_embeddings and similarity_cache stats from sidebar - Home.py: Update Explorer description to match new focused layout - analysis/tabs/__init__.py: Remove search and browser exports - tests: Update decomposition and import tests for new tab set Result: Explorer now has 3 focused analytical tabs instead of 5.
Stemwijzer
A Dutch parliamentary voting compass that lets you vote on real Tweede Kamer motions and see which parties match your positions.
What is Stemwijzer?
Stemwijzer ingests motions and voting records from the Dutch House of Representatives (Tweede Kamer), stores them in DuckDB, generates AI-powered explanations with an LLM, and presents a Streamlit UI where users can vote on real motions and explore party positions through SVD visualizations, trajectory analysis, and embedding-based similarity search.
Features
- Voting Compass — Vote on real parliamentary motions and see which parties align with your choices
- Explorer — Interactive SVD visualizations, party trajectories over time, motion browser, and semantic search
- Analytics — SVD decomposition of voting patterns, UMAP projections, clustering, and drift analysis
- LLM Enrichment — Automatic generation of layman-friendly motion explanations using QWEN via OpenRouter
Prerequisites
- Python >= 3.13
- uv for dependency management
- (Optional)
OPENROUTER_API_KEYfor LLM enrichment
Quickstart
# Clone and enter the repository
git clone <your-gitea-url>/sgeboers/stemwijzer.git
cd stemwijzer
# Install dependencies
uv sync
# Run the Streamlit app
uv run streamlit run Home.py
# Run the data pipeline (fetch motions, compute embeddings, etc.)
uv run python pipeline/run_pipeline.py
# Run tests
uv run pytest tests/ -q
The app will be available at http://localhost:8501.
Project Structure
├── app.py # Streamlit UI entrypoint
├── database.py # DuckDB schema and queries
├── api_client.py # Tweede Kamer OData API client
├── explorer.py # Explorer page with SVD visualizations
├── pipeline/ # Data ingestion and analysis pipelines
├── analysis/ # SVD, clustering, trajectory modules
├── tests/ # pytest test suite
├── docs/ # Documentation, research, and plans
└── data/motions.db # DuckDB database (~18 GB)
Documentation
- ARCHITECTURE.md — Comprehensive architecture overview, tech stack, and contributor guidance
- CODE_STYLE.md — Coding conventions, naming, typing, and testing standards
- docs/solutions/ — Documented solutions to past bugs and best practices
Tech Stack
- Language: Python 3.13+
- Data: DuckDB via ibis-framework
- UI: Streamlit + Plotly
- ML/Analysis: scipy, scikit-learn, umap-learn
- LLM: QWEN via OpenRouter (OpenAI-compatible)
- Package Manager: uv
Deployment
See docs/deployment/ansible-package-deploy.md for server deployment instructions using the Ansible package.
License
[Your license here]
Languages
HTML
96.7%
Python
3.2%
