|
| 1 | +# llm_router_web |
| 2 | + |
| 3 | +**llm_router_web** is the web interface component of the **[llm-router](https://github.com/radlab-dev-group/llm-router) |
| 4 | +** project. |
| 5 | +It provides a Flask‑based UI for managing LLM model configurations, users, and version history. |
| 6 | + |
| 7 | +## Table of Contents |
| 8 | + |
| 9 | +- [Features](#features) |
| 10 | +- [Installation](#installation) |
| 11 | +- [Running the Application](#running-the-application) |
| 12 | +- [Configuration](#configuration) |
| 13 | +- [Endpoints Overview](#endpoints-overview) |
| 14 | +- [Development](#development) |
| 15 | +- [License](#license) |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Features |
| 20 | + |
| 21 | +- **User Management** – Admins can create, edit, block/unblock users and assign roles (`admin` / `user`). |
| 22 | +- **Configuration CRUD** – Create, import, edit, view, export, activate and delete model configurations. |
| 23 | +- **Model & Provider Management** – Add/remove models, manage multiple providers per model, reorder providers via |
| 24 | + drag‑and‑drop. |
| 25 | +- **Versioning** – Automatic snapshot of each change; view history and restore previous versions. |
| 26 | +- **Theme Switching** – Light / dark UI themes toggled client‑side. |
| 27 | +- **Responsive UI** – Built with HTML, CSS, HTMX and Alpine.js for a smooth, single‑page‑like experience. |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## Installation |
| 32 | + |
| 33 | +The project uses **Python 3.10.6** and **virtualenv**. |
| 34 | + |
| 35 | +```shell script |
| 36 | +# Clone the repository |
| 37 | +git clone https://github.com/radlab-dev-group/llm-router.git |
| 38 | +cd llm-router/llm_router_web |
| 39 | + |
| 40 | +# Create and activate a virtual environment |
| 41 | +python3 -m venv venv |
| 42 | +source venv/bin/activate |
| 43 | + |
| 44 | +# Install dependencies |
| 45 | +pip install -r requirements.txt |
| 46 | +``` |
| 47 | + |
| 48 | +> **Note:** The only required packages are listed in `requirements.txt` (`flask` and `flask_sqlalchemy`). All other |
| 49 | +> libraries are part of the broader `llm-router` repository. |
| 50 | +
|
| 51 | +--- |
| 52 | + |
| 53 | +## Running the Application |
| 54 | + |
| 55 | +```shell script |
| 56 | +# Start the Flask development server |
| 57 | +python app.py |
| 58 | +``` |
| 59 | + |
| 60 | +The UI will be available at `http://localhost:8081`. |
| 61 | +The first run will redirect you to a **setup** page where you must create an initial admin user. |
| 62 | + |
| 63 | +### Environment variables |
| 64 | + |
| 65 | +| Variable | Description | Default | |
| 66 | +|--------------------|-----------------------------------------------|------------------------| |
| 67 | +| `FLASK_SECRET_KEY` | Secret key for session signing | `change-me-local` | |
| 68 | +| `DATABASE_URL` | SQLAlchemy database URL (SQLite by default) | `sqlite:///configs.db` | |
| 69 | +| `FLASK_ENV` | Set to `production` for HTTPS scheme handling | – | |
| 70 | + |
| 71 | +--- |
| 72 | + |
| 73 | +## Configuration |
| 74 | + |
| 75 | +All Flask configuration is performed in `web/__init__.py` via `create_app()`. |
| 76 | +Key settings: |
| 77 | + |
| 78 | +- `SQLALCHEMY_DATABASE_URI` – points to the SQLite DB (`configs.db`) unless overridden. |
| 79 | +- `SQLALCHEMY_TRACK_MODIFICATIONS` – disabled for performance. |
| 80 | +- `PREFERRED_URL_SCHEME` – set to `https` when `FLASK_ENV=production`. |
| 81 | + |
| 82 | +The database schema is automatically created on first launch. If the `order` column is missing from the `provider` |
| 83 | +table (e.g., after a schema change), the helper `_ensure_provider_order_column()` adds it on startup. |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## Endpoints Overview |
| 88 | + |
| 89 | +| URL | Methods | Description | |
| 90 | +|----------------------------------------|-----------|--------------------------------------------------------| |
| 91 | +| `/setup` | GET, POST | One‑time admin creation (first run). | |
| 92 | +| `/login` | GET, POST | User authentication. | |
| 93 | +| `/logout` | GET | End session. | |
| 94 | +| `/admin/users` | GET, POST | List users / add new user (admin only). | |
| 95 | +| `/admin/users/<id>/edit` | POST | Edit role or password (admin only). | |
| 96 | +| `/admin/users/<id>/toggle_block` | POST | Block / unblock a user (admin only). | |
| 97 | +| `/` | GET | Dashboard – list of user’s configs. | |
| 98 | +| `/configs` | GET | Same as dashboard (alternative view). | |
| 99 | +| `/configs/new` | GET, POST | Create a new empty configuration. | |
| 100 | +| `/configs/import` | GET, POST | Import configuration from JSON file or text. | |
| 101 | +| `/configs/<id>` | GET | Preview configuration (JSON view). | |
| 102 | +| `/configs/<id>/export` | GET | Download configuration as `models-config.json`. | |
| 103 | +| `/configs/<id>/edit` | GET, POST | Edit active models, rename config, add providers, etc. | |
| 104 | +| `/configs/<id>/models/add` | POST | Add a new model to a configuration. | |
| 105 | +| `/models/<id>/delete` | POST | Delete a model. | |
| 106 | +| `/models/<id>/providers/add` | POST | Add a provider (JSON payload). | |
| 107 | +| `/models/<id>/providers/reorder` | POST | Reorder providers (drag‑and‑drop). | |
| 108 | +| `/providers/<id>/update` | POST | Update provider fields (JSON payload). | |
| 109 | +| `/providers/<id>/delete` | POST | Delete a provider. | |
| 110 | +| `/configs/<id>/activate` | POST | Mark a configuration as the default for the user. | |
| 111 | +| `/configs/<id>/delete` | POST | Delete a configuration. | |
| 112 | +| `/configs/<id>/versions` | GET | List version history (JSON). | |
| 113 | +| `/configs/<id>/versions/<ver>/restore` | POST | Restore a previous version. | |
| 114 | +| `/check_host` | POST | Verify reachability of an API host (used by the UI). | |
| 115 | + |
| 116 | +All routes are protected by session‑based authentication. Admin‑only routes require the `admin` role. |
| 117 | + |
| 118 | +--- |
| 119 | + |
| 120 | +## Development |
| 121 | + |
| 122 | +### Code structure |
| 123 | + |
| 124 | +``` |
| 125 | +llm_router_web/ |
| 126 | +├─ web/ |
| 127 | +│ ├─ static/ # CSS files (dark/light themes) |
| 128 | +│ ├─ templates/ # Jinja2 HTML templates |
| 129 | +│ ├─ __init__.py # Flask app factory |
| 130 | +│ ├─ constants.py |
| 131 | +│ ├─ models.py # SQLAlchemy models |
| 132 | +│ ├─ routes.py # All view functions & API endpoints |
| 133 | +│ └─ utils.py # Helper utilities (JSON export, snapshots, DB migration) |
| 134 | +├─ app.py # Entry point (creates the Flask app) |
| 135 | +└─ requirements.txt |
| 136 | +``` |
| 137 | + |
| 138 | +### Adding new features |
| 139 | + |
| 140 | +1. **Routes** – Add view functions to `web/routes.py` and register them on the `bp` blueprint. |
| 141 | +2. **Templates** – Place new Jinja2 files in `web/templates/`. |
| 142 | +3. **Static assets** – Add CSS/JS files to `web/static/` and reference them via `url_for('static', filename='…')`. |
| 143 | +4. **Database changes** – Extend `web/models.py` and, if needed, modify `_ensure_provider_order_column()` to handle |
| 144 | + migrations for SQLite. |
| 145 | + |
| 146 | +### Testing |
| 147 | + |
| 148 | +The repository includes `pytest` in the installed packages. Write unit tests under a `tests/` directory and run: |
| 149 | + |
| 150 | +```shell script |
| 151 | +pytest |
| 152 | +``` |
| 153 | + |
| 154 | +--- |
| 155 | + |
| 156 | +## License |
| 157 | + |
| 158 | +`llm_router_web` is released under the same license as the parent **llm-router** project (see the repository’s LICENSE |
| 159 | +file). |
0 commit comments