Skip to content

Commit 8a944fc

Browse files
authored
Merge pull request #35 from Mirrowel/feature/filtering-tool
Add Model Filter GUI for visual configuration of provider model filtering
2 parents c745d73 + b7df2fe commit 8a944fc

File tree

7 files changed

+3799
-52
lines changed

7 files changed

+3799
-52
lines changed

DOCUMENTATION.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The project is a monorepo containing two primary components:
1010
* **Batch Manager**: Optimizes high-volume embedding requests.
1111
* **Detailed Logger**: Provides per-request file logging for debugging.
1212
* **OpenAI-Compatible Endpoints**: `/v1/chat/completions`, `/v1/embeddings`, etc.
13+
* **Model Filter GUI**: Visual interface for configuring model ignore/whitelist rules per provider (see Section 6).
1314
2. **The Resilience Library (`rotator_library`)**: This is the core engine that provides high availability. It is consumed by the proxy app to manage a pool of API keys, handle errors gracefully, and ensure requests are completed successfully even when individual keys or provider endpoints face issues.
1415

1516
This architecture cleanly separates the API interface from the resilience logic, making the library a portable and powerful tool for any application needing robust API key management.
@@ -1245,3 +1246,83 @@ stats = cache.get_stats()
12451246
# Includes: {"disk_available": True, "disk_errors": 0, ...}
12461247
```
12471248

1249+
---
1250+
1251+
## 6. Model Filter GUI
1252+
1253+
The Model Filter GUI (`model_filter_gui.py`) provides a visual interface for configuring model ignore and whitelist rules per provider. It replaces the need to manually edit `IGNORE_MODELS_*` and `WHITELIST_MODELS_*` environment variables.
1254+
1255+
### 6.1. Overview
1256+
1257+
**Purpose**: Visually manage which models are exposed via the `/v1/models` endpoint for each provider.
1258+
1259+
**Launch**:
1260+
```bash
1261+
python -c "from src.proxy_app.model_filter_gui import run_model_filter_gui; run_model_filter_gui()"
1262+
```
1263+
1264+
Or via the launcher TUI if integrated.
1265+
1266+
### 6.2. Features
1267+
1268+
#### Core Functionality
1269+
1270+
- **Provider Selection**: Dropdown to switch between available providers with automatic model fetching
1271+
- **Ignore Rules**: Pattern-based rules (supports wildcards like `*-preview`, `gpt-4*`) to exclude models
1272+
- **Whitelist Rules**: Pattern-based rules to explicitly include models, overriding ignore rules
1273+
- **Real-time Preview**: Typing in rule input fields highlights affected models before committing
1274+
- **Rule-Model Linking**: Click a model to highlight the affecting rule; click a rule to highlight all affected models
1275+
- **Persistence**: Rules saved to `.env` file in standard `IGNORE_MODELS_<PROVIDER>` and `WHITELIST_MODELS_<PROVIDER>` format
1276+
1277+
#### Dual-Pane Model View
1278+
1279+
The interface displays two synchronized lists:
1280+
1281+
| Left Pane | Right Pane |
1282+
|-----------|------------|
1283+
| All fetched models (plain text) | Same models with color-coded status |
1284+
| Shows total count | Shows available/ignored count |
1285+
| Scrolls in sync with right pane | Color indicates affecting rule |
1286+
1287+
**Color Coding**:
1288+
- **Green**: Model is available (no rule affects it, or whitelisted)
1289+
- **Red/Orange tones**: Model is ignored (color matches the specific ignore rule)
1290+
- **Blue/Teal tones**: Model is explicitly whitelisted (color matches the whitelist rule)
1291+
1292+
#### Rule Management
1293+
1294+
- **Comma-separated input**: Add multiple rules at once (e.g., `*-preview, *-beta, gpt-3.5*`)
1295+
- **Wildcard support**: `*` matches any characters (e.g., `gemini-*-preview`)
1296+
- **Affected count**: Each rule shows how many models it affects
1297+
- **Tooltips**: Hover over a rule to see the list of affected models
1298+
- **Instant delete**: Click the × button to remove a rule immediately
1299+
1300+
### 6.3. Keyboard Shortcuts
1301+
1302+
| Shortcut | Action |
1303+
|----------|--------|
1304+
| `Ctrl+S` | Save changes to `.env` |
1305+
| `Ctrl+R` | Refresh models from provider |
1306+
| `Ctrl+F` | Focus search field |
1307+
| `F1` | Show help dialog |
1308+
| `Escape` | Clear search / Clear highlights |
1309+
1310+
### 6.4. Context Menu
1311+
1312+
Right-click on any model to access:
1313+
1314+
- **Add to Ignore List**: Creates an ignore rule for the exact model name
1315+
- **Add to Whitelist**: Creates a whitelist rule for the exact model name
1316+
- **View Affecting Rule**: Highlights the rule that affects this model
1317+
- **Copy Model Name**: Copies the full model ID to clipboard
1318+
1319+
### 6.5. Integration with Proxy
1320+
1321+
The GUI modifies the same environment variables that the `RotatingClient` reads:
1322+
1323+
1. **GUI saves rules** → Updates `.env` file
1324+
2. **Proxy reads on startup** → Loads `IGNORE_MODELS_*` and `WHITELIST_MODELS_*`
1325+
3. **Proxy applies rules**`get_available_models()` filters based on rules
1326+
1327+
**Note**: The proxy must be restarted to pick up rule changes made via the GUI (or use the Launcher TUI's reload functionality if available).
1328+

requirements.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ aiohttp
1919
colorlog
2020

2121
rich
22+
23+
# GUI for model filter configuration
24+
customtkinter
25+
26+
# For building the executable
27+
pyinstaller

src/proxy_app/build.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import platform
44
import subprocess
55

6+
67
def get_providers():
78
"""
89
Scans the 'src/rotator_library/providers' directory to find all provider modules.
@@ -24,6 +25,7 @@ def get_providers():
2425
hidden_imports.append(f"--hidden-import={module_name}")
2526
return hidden_imports
2627

28+
2729
def main():
2830
"""
2931
Constructs and runs the PyInstaller command to build the executable.
@@ -47,22 +49,27 @@ def main():
4749
"--collect-data",
4850
"litellm",
4951
# Optimization: Exclude unused heavy modules
50-
"--exclude-module=tkinter",
5152
"--exclude-module=matplotlib",
5253
"--exclude-module=IPython",
5354
"--exclude-module=jupyter",
5455
"--exclude-module=notebook",
5556
"--exclude-module=PIL.ImageTk",
5657
# Optimization: Enable UPX compression (if available)
57-
"--upx-dir=upx" if platform.system() != "Darwin" else "--noupx", # macOS has issues with UPX
58+
"--upx-dir=upx"
59+
if platform.system() != "Darwin"
60+
else "--noupx", # macOS has issues with UPX
5861
# Optimization: Strip debug symbols (smaller binary)
59-
"--strip" if platform.system() != "Windows" else "--console", # Windows gets clean console
62+
"--strip"
63+
if platform.system() != "Windows"
64+
else "--console", # Windows gets clean console
6065
]
6166

6267
# Add hidden imports for providers
6368
provider_imports = get_providers()
6469
if not provider_imports:
65-
print("Warning: No providers found. The build might not include any LLM providers.")
70+
print(
71+
"Warning: No providers found. The build might not include any LLM providers."
72+
)
6673
command.extend(provider_imports)
6774

6875
# Add the main script
@@ -80,5 +87,6 @@ def main():
8087
except FileNotFoundError:
8188
print("Error: PyInstaller is not installed or not in the system's PATH.")
8289

90+
8391
if __name__ == "__main__":
8492
main()

0 commit comments

Comments
 (0)