--- title: Tech Stack category: stack --- # Tech Stack ## Runtime & Language - **Python >=3.13** ## Web Framework - **Streamlit** - Multi-page app with Home, Stemwijzer, Explorer pages ## Data Layer - **DuckDB** - Embedded OLAP database - Tables: motions, mp_votes, svd_vectors, fused_embeddings, embeddings, user_sessions, party_results, mp_metadata - **ibis** - ORM (referenced but DuckDB-native implementation used) ## AI / LLM - **OpenRouter** - API abstraction for AI providers - **QWEN** - Primary model - Embeddings: `qwen/qwen3-embedding-4b` - Chat: `qwen/qwen-2.5-72b-instruct` - **requests** - HTTP client (not raw openai) ## ML / Analytics - **scikit-learn** - KMeans clustering, cosine_similarity, StandardScaler - **scipy** - SVD (scipy.linalg.svd), spatial.procrustes - **umap-learn** - Dimensionality reduction (optional, graceful fallback to SVD) - **numpy** - Numerical computing ## Visualization - **Plotly** - Interactive charts (go.Figure, _DummyTrace fallback) - **matplotlib** - Static plotting (optional) ## HTTP & Parsing - **requests** - Session pooling, retry with backoff - **beautifulsoup4** - HTML parsing - **lxml** - XML/HTML processing ## Key Source Files | File | Purpose | |------|---------| | `database.py` | MotionDatabase singleton, DuckDB connection, 9-table schema | | `explorer.py` | Explorer page with 4 tabs (Motion, MP, Party, Evolution) | | `explorer_helpers.py` | Pure helper functions, Plotly chart builders | | `analysis/` | SVD pipeline, UMAP projection, clustering | | `pipeline/` | Data fetch, transform, store pipeline | | `pages/1_Stemwijzer.py` | Quiz page | | `pages/2_Explorer.py` | Explorer page | | `config.py` | Dataclass Config pattern | | `ai_provider.py` | OpenRouter API wrapper with retry | | `api_client.py` | TweedeKamer OData API client | ## Singleton Instances | Module | Instance | Type | |--------|----------|------| | `database.py` | `db` | `MotionDatabase` | | `config.py` | `config` | `Config` (dataclass) | | `config.py` | `PARTY_COLOURS` | `dict[str, str]` | ## Environment - Python >=3.13 - Environment variables via `.env` (DB path, API keys) - No `.env` values in constraint files (security)