Spaces:
Sleeping
Sleeping
File size: 23,358 Bytes
597500e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | ---
title: Sonix ML API
emoji: π
colorFrom: blue
colorTo: indigo
sdk: docker
pinned: false
---
# SONIX RUSH AI β Running Shoes Recommender Engine
**SONIX RUSH AI** is a specialized machine learning inference service designed for the SONIX RUSH application. It implements a **Hybrid Recommendation System** that combines **Content-Based Filtering** (via Deep Autoencoders and K-Means Clustering) with **Collaborative Filtering** (User-Based KNN) to deliver personalized running shoe recommendations.
This engine operates as a standalone inference service and communicates with the core backend and frontend via RESTful APIs.
---
## Table of Contents
- [System Overview](#system-overview)
- [Architecture](#architecture)
- [Technology Stack](#technology-stack)
- [Project Structure](#project-structure)
- [Installation Guide](#installation-guide)
- [Configuration](#configuration)
- [Usage Guide](#usage-guide)
- [API Documentation](#api-documentation)
- [Continuous Training](#continuous-training)
- [Error Handling](#error-handling)
- [Docker Deployment](#docker-deployment)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)
---
## System Overview
The SONIX RUSH AI engine isolates high-computational ML workloads from the primary transactional backend. Running as an independent service ensures that model inference and data processing do not impact the performance of the main application.
| Property | Detail |
|---|---|
| **Integration Method** | REST API |
| **Methodology** | Hybrid β Content-Based + Collaborative (separate pipelines) |
| **Optimization** | In-Memory Micro-Caching with TTL (60s) |
| **Continuous Training** | Background CF refresh every 50 interactions |
| **Deployment** | Docker / Hugging Face Spaces |
---
## Architecture
The system uses two **independent** recommendation pipelines, each serving a different use case.
```
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SONIX RUSH AI Engine β
β β
β βββββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β Content-Based Pipeline β β Collaborative Pipeline β β
β β POST /recommend/road β β POST /interact β β
β β POST /recommend/trail β β GET /recommend/feed β β
β β β β β β
β β 1. Map user questionnaire β β 1. Receive interaction β β
β β β numerical vector β β 2. Real-time inject β β
β β 2. Encode β 8D Latent Space β β into user vector β β
β β (Deep Autoencoder) β β 3. KNN: find similar β β
β β 3. Route to nearest clusters β β users (cosine) β β
β β (K-Means, top βK/3β) β β 4. Weighted score β β
β β 4. Masked Cosine Similarity β β aggregation β β
β β 5. Return Top 10 shoes β β 5. Return Top 20 shoes β β
β βββββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββ β
β β
β FastAPI + Uvicorn (4 workers) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
SONIX RUSH Backend SONIX RUSH Frontend
(REST calls) (REST calls)
```
### Content-Based: Training Pipeline (Offline)
```
Supabase β fetch_shoes_by_type() β MinMaxScaler
β Deep Autoencoder (300 epochs, batch=64)
β K-Means (K=5, n_init=20) on 8D latent space
β Save versioned artifacts to model_artifacts/{type}/v_{timestamp}/
```
### Content-Based: Inference Pipeline (Online)
```
User Questionnaire β Heuristic Feature Mapping β Numerical Vector
β Encoder β 8D Latent Vector
β K-Means: select top βK/3β nearest clusters
β Masked Cosine Similarity on candidate pool
β Top 10 shoes
```
Feature masking ensures similarity is computed **only on features the user explicitly provided**, preventing noise from neutral default values.
### Collaborative Filtering Pipeline (Real-Time)
```
POST /interact β Real-Time Injection into user vector
β User-Based KNN (cosine, brute force, sparse CSR matrix)
β Weighted score aggregation from k neighbors
β Filter seen items β Enrich with shoe metadata
β Top 20 shoes (TTL-cached 60s per user)
β Background CT trigger every 50 interactions
```
### Autoencoder Architecture
```
Input (N-dim)
β Dense(32) + BatchNorm + Dropout(0.3) β Encoder
β Dense(16) + BatchNorm + Dropout(0.3) β Encoder
β Dense(8) + BatchNorm + Dropout(0.3) β Latent Space (saved as shoe_encoder.h5)
β Dense(16) + BatchNorm + Dropout(0.3) β Decoder
β Dense(32) + BatchNorm + Dropout(0.3) β Decoder
β Dense(N, sigmoid) β Reconstruction Output
Loss: MSE | Optimizer: Adam (lr=0.001) | Metric: MAE
```
---
## Technology Stack
### Core & Backend
| Library | Version | Purpose |
|---|---|---|
| Python | 3.11 | Primary language β strict version required for TensorFlow 2.15.0 |
| FastAPI | 0.129.0 | High-performance async web framework |
| Uvicorn | 0.40.0 | ASGI web server |
| Gunicorn | 25.1.0 | Process manager |
| Pydantic | 2.12.5 | Request/response schema validation |
| ujson | 5.11.0 | High-speed JSON serialization (`UJSONResponse`) |
### Machine Learning & Data Science
| Library | Version | Purpose |
|---|---|---|
| TensorFlow / Keras | 2.15.0 | Deep Autoencoder for latent space projection |
| Scikit-Learn | 1.5.2 | K-Means Clustering and User-Based KNN |
| Pandas | 2.2.2 | Data manipulation and user-item pivot matrix |
| NumPy | 1.26.4 | Numerical computation and vector operations |
| SciPy | 1.13.1 | Sparse CSR matrix for memory-efficient CF |
### Database & Infrastructure
| Library | Version | Purpose |
|---|---|---|
| Supabase | 2.27.3 | PostgreSQL-based Backend-as-a-Service |
| HTTPX | 0.28.1 | Async HTTP client |
| python-dotenv | 1.0.1 | Environment variable management |
| Docker | latest | Containerization |
### Testing & Quality Assurance
| Library | Version | Purpose |
|---|---|---|
| Pytest | 8.0.2 | Unit and integration testing |
| pytest-mock | 3.12.0 | Supabase client mocking in CI |
| pytest-asyncio | 0.23.5 | Async test support |
| Locust | 2.24.0 | Load testing and benchmarking |
| Flake8 | 7.0.0 | Code linting |
---
## Project Structure
```
sonix-ml/
β
βββ src/
β βββ main.py # FastAPI app, lifespan, all endpoints
β βββ config.py # ROAD_FEATURES and TRAIL_FEATURES definitions
β βββ database.py # Supabase client, interaction aggregation, upsert logic
β β
β βββ recommender/
β β βββ content_based.py # Core pipeline: cluster routing + masked cosine similarity
β β βββ road_recommender.py # Road heuristic mapping + pipeline wrapper
β β βββ trail_recommender.py # Trail heuristic mapping + pipeline wrapper
β β βββ collaborative_filtering.py # UserCollaborativeRecommender (UBCF + TTL cache)
β β
β βββ training/
β βββ architecture.py # Deep Autoencoder definition (build_autoencoder)
β βββ training_engine.py # Full training orchestration (run_training)
β
βββ model_artifacts/
β βββ road/
β β βββ v_YYYYMMDD_HHMMSS/ # Versioned β latest selected automatically on startup
β β βββ shoe_encoder.h5
β β βββ kmeans_model.pkl
β β βββ scaler.pkl
β β βββ shoe_features.pkl
β β βββ shoe_metadata.pkl
β βββ trail/
β βββ v_YYYYMMDD_HHMMSS/ # Same structure as road
β
βββ data/
β βββ road_dataset.csv
β βββ trail_dataset.csv
β βββ unused-data/ # Archived previous dataset versions
β
βββ notebooks/
β βββ data-preparation/
β βββ data-preparation-v2/
β βββ data-preparation-v3/
β βββ modelling/ # road_ml.ipynb, trail_ml.ipynb
β
βββ tests/
β βββ conftest.py # Auto-mocks Supabase for all tests
β βββ test_data_processing.py # Rating conversion + DB error handling
β βββ test_recommender_logic.py # Heuristic mapping + priority logic
β
βββ .github/workflows/
β βββ ci-ml.yml # Continuous Integration (lint + test)
β βββ cd-ml.yml # Continuous Deployment
β βββ ct-ml.yml # Continuous Training trigger
β
βββ locustfile.py
βββ Dockerfile
βββ requirements.txt # Production dependencies (all pinned)
βββ requirements-dev.txt # Dev/test dependencies
βββ README.md
```
---
## Installation Guide
### Prerequisites
- Python **3.11** (strictly required)
- Git
### 1. Clone the Repository
```bash
git clone https://github.com/SONIX-Kelompok-6/sonix-ml
cd sonix-ml
```
### 2. Set Up a Virtual Environment
**Windows (PowerShell):**
```powershell
py -3.11 -m venv env
.\env\Scripts\activate
```
**macOS / Linux:**
```bash
python3.11 -m venv env
source env/bin/activate
```
### 3. Install Dependencies
**Production:**
```bash
pip install -r requirements.txt
```
**Development** (includes testing and linting tools):
```bash
pip install -r requirements-dev.txt
```
---
## Configuration
Create a `.env` file in the root directory:
```bash
cp .env.example .env
```
Then populate it with your credentials:
```env
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_KEY=your-anon-public-key
```
### Environment Variables Reference
| Variable | Required | Description |
|---|---|---|
| `SUPABASE_URL` | β
Yes | Your Supabase project URL |
| `SUPABASE_KEY` | β
Yes | Supabase anon/public API key |
> π Never commit `.env` to version control. Only `.env.example` (with placeholder values) should be committed.
---
## Usage Guide
### 1. Training Pipeline (Offline)
Before starting the API, model artifacts must be generated. This step fetches shoe catalog data from Supabase, trains the Deep Autoencoders, runs K-Means Clustering, and serializes all artifacts with a versioned timestamp.
```bash
python -m src.training.training_engine
```
The engine runs sequentially for both categories:
```
>>> Initializing training sequence for: ROAD
>>> Initializing training sequence for: TRAIL
```
Artifacts are saved to versioned directories:
```
model_artifacts/
βββ road/v_YYYYMMDD_HHMMSS/
βββ trail/v_YYYYMMDD_HHMMSS/
```
**Generated files per category:**
| File | Description |
|---|---|
| `shoe_encoder.h5` | Encoder model β projects features to 8D latent space |
| `kmeans_model.pkl` | K-Means (K=5) β routes inputs to candidate clusters |
| `scaler.pkl` | MinMaxScaler β must be used for inference normalization |
| `shoe_features.pkl` | Scaled feature matrix β used for cosine similarity at inference |
| `shoe_metadata.pkl` | DataFrame with cluster labels + column type definitions |
> β οΈ The API will fail to start if artifacts are missing. Always run training before launching the server.
>
> π‘ The API automatically selects the **latest versioned directory** on startup β no manual version management required.
### 2. Starting the API (Online)
Once artifacts are generated, launch the FastAPI server:
```bash
python -m src.main
```
The server starts at `http://0.0.0.0:7860` with **4 Uvicorn workers**. On startup, the server loads both artifact sets and initializes the CF engine from Supabase interaction data.
---
## API Documentation
Interactive documentation is available at runtime:
- **Swagger UI:** `http://127.0.0.1:7860/docs`
- **ReDoc:** `http://127.0.0.1:7860/redoc`
Visiting `/` auto-redirects to `/docs`.
---
### `GET /health`
Returns service health and Continuous Training sync progress.
**Response `200 OK`:**
```json
{
"status": "healthy",
"ct_sync_progress": "12/50"
}
```
---
### `POST /recommend/road`
Returns Top 10 road shoe recommendations via the Content-Based pipeline. All fields are optional β unset fields are excluded from similarity calculation via feature masking.
**Request Body:**
```json
{
"pace": "Fast",
"arch_type": "Normal",
"strike_pattern": "Mid",
"foot_width": "Regular",
"season": "Summer",
"orthotic_usage": "No",
"running_purpose": "Race",
"cushion_preferences": "Firm",
"stability_need": "Neutral"
}
```
**Request Body Fields:**
| Field | Accepted Values |
|---|---|
| `pace` | `"Easy"`, `"Steady"`, `"Fast"` |
| `arch_type` | `"Flat"`, `"Normal"`, `"High"` |
| `strike_pattern` | `"Heel"`, `"Mid"`, `"Forefoot"` |
| `foot_width` | `"Narrow"`, `"Regular"`, `"Wide"` |
| `season` | `"Summer"`, `"Spring & Fall"`, `"Winter"` |
| `orthotic_usage` | `"Yes"`, `"No"` |
| `running_purpose` | `"Daily"`, `"Tempo"`, `"Race"` |
| `cushion_preferences` | `"Soft"`, `"Balanced"`, `"Firm"` |
| `stability_need` | `"Neutral"`, `"Guided"` |
**Response `200 OK`:**
```json
{
"status": "success",
"data": [
{
"shoe_id": "R045",
"name": "Nike Vaporfly 3",
"brand": "Nike",
"cluster": 2,
"match_score": 0.97
}
]
}
```
---
### `POST /recommend/trail`
Returns Top 10 trail shoe recommendations. Uses trail-specific heuristics for terrain, traction, lug depth, and water resistance.
**Request Body:**
```json
{
"pace": "Steady",
"arch_type": "Normal",
"strike_pattern": "Mid",
"foot_width": "Regular",
"season": "Summer",
"orthotic_usage": "No",
"terrain": "Rocky",
"rock_sensitive": "Yes",
"water_resistance": "Water Repellent"
}
```
**Request Body Fields:**
| Field | Accepted Values |
|---|---|
| `pace` | `"Easy"`, `"Steady"`, `"Fast"` |
| `arch_type` | `"Flat"`, `"Normal"`, `"High"` |
| `strike_pattern` | `"Heel"`, `"Mid"`, `"Forefoot"` |
| `foot_width` | `"Narrow"`, `"Regular"`, `"Wide"` |
| `season` | `"Summer"`, `"Spring & Fall"`, `"Winter"` |
| `orthotic_usage` | `"Yes"`, `"No"` |
| `terrain` | `"Light"`, `"Mixed"`, `"Rocky"`, `"Muddy"` |
| `rock_sensitive` | `"Yes"`, `"No"` |
| `water_resistance` | `"Waterproof"`, `"Water Repellent"` |
**Response `200 OK`:**
```json
{
"status": "success",
"data": [
{
"shoe_id": "T012",
"name": "Hoka Speedgoat 5",
"brand": "Hoka",
"cluster": 4,
"match_score": 0.94
}
]
}
```
---
### `POST /interact`
Records a user interaction (Like or Rating) and immediately returns personalized CF recommendations via **Real-Time Injection** β the new interaction is injected into the user's vector before running KNN, so results reflect the latest signal without waiting for a full rebuild.
Also triggers a **background CT refresh** every 50 interactions (see [Continuous Training](#continuous-training)).
**Request Body:**
```json
{
"user_id": 8,
"shoe_id": "R278",
"action_type": "like",
"value": null
}
```
**Request Body Fields:**
| Field | Type | Required | Description |
|---|---|---|---|
| `user_id` | `integer` | β
Yes | Interacting user's ID |
| `shoe_id` | `string` | β
Yes | Target shoe ID (`R` prefix = road, `T` prefix = trail) |
| `action_type` | `string` | β
Yes | `"like"` or `"rate"` |
| `value` | `integer` | Conditional | Star rating `1β5`. Required when `action_type` is `"rate"` |
**Interaction Score Mapping:**
| Signal | Converted Score |
|---|---|
| Like | `+1.0` |
| Rate 5β
| `+2.0` |
| Rate 4β
| `+1.0` |
| Rate 3β
| `+0.1` (neutral) |
| Rate 2β
| `-1.0` |
| Rate 1β
| `-2.0` |
> If a user has both liked and rated the same shoe, scores are **summed** for higher confidence.
**Response `200 OK`:**
```json
{
"status": "success",
"data": [
{
"shoe_id": "R145",
"name": "ASICS Gel-Kayano 31",
"brand": "ASICS",
"match_score": 1.84
}
]
}
```
---
### `GET /recommend/feed/{user_id}`
Returns a personalized shoe feed from the CF engine. Served from the **60-second TTL cache** if available, otherwise computed fresh.
**Path Parameters:**
| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `integer` | β
Yes | Target user's ID |
**Example Request:**
```
GET /recommend/feed/8
```
**Response `200 OK`:**
```json
{
"status": "success",
"data": [
{
"shoe_id": "R278",
"name": "Nike Pegasus 41",
"brand": "Nike",
"match_score": 2.31
}
]
}
```
**Response `404 Not Found`** β cold-start user with no interaction history.
---
## Continuous Training
Every **50 new interactions** received via `POST /interact`, a non-blocking background task is dispatched that:
1. Fetches fresh interaction data from Supabase (`favorites` + `reviews` tables)
2. Rebuilds `UserCollaborativeRecommender` from the updated data
3. Hot-swaps the global `cf_engine` with zero downtime
The API response is returned immediately β the rebuild happens in the background. Progress is visible in `/health` via `ct_sync_progress`.
---
## Error Handling
All error responses follow a consistent format:
```json
{
"detail": "Human-readable error message."
}
```
| Status Code | Meaning | Common Cause |
|---|---|---|
| `200 OK` | Success | β |
| `404 Not Found` | Resource not found | Cold-start user with no interaction history |
| `422 Unprocessable Entity` | Validation error | Missing or invalid request fields |
| `500 Internal Server Error` | Unexpected error | Check server logs |
| `503 Service Unavailable` | Engine not ready | Run training pipeline first |
---
## Docker Deployment
This service is containerized and compatible with **Hugging Face Spaces** and standard Docker environments.
### Build and Run
```bash
docker build -t sonix-ml .
docker run -p 7860:7860 --env-file .env sonix-ml
```
The service will be accessible at `http://localhost:7860`.
### Docker Compose (Optional)
```yaml
version: "3.9"
services:
rush-ai:
build: .
ports:
- "7860:7860"
env_file:
- .env
restart: unless-stopped
```
```bash
docker compose up --build
```
---
## Testing
### Unit & Integration Tests
`conftest.py` automatically mocks the Supabase client across all tests, preventing real network calls during CI.
```bash
# Run all tests
pytest
# With verbose output and coverage report
pytest -v --tb=short --cov=src --cov-report=term-missing
```
**Test coverage:**
| File | What it tests |
|---|---|
| `test_data_processing.py` | Rating-to-score conversion, empty DataFrame handling from DB |
| `test_recommender_logic.py` | Heuristic priority mapping, fallback defaults, multi-source priority |
### Load Testing
```bash
locust -f locustfile.py
```
Open `http://localhost:8089` to configure and launch. Default scenario:
| Endpoint | Weight | Description |
|---|---|---|
| `POST /interact` | 3Γ | Heaviest endpoint β simulates likes and ratings |
| `GET /recommend/feed/{user_id}` | 1Γ | Feed retrieval |
| `GET /health` | 1Γ | Lightweight health probe |
### Load Test Results
> Total requests: **10,420** across all endpoints β **0 failures** (0% error rate).
> Aggregated throughput: **65.5 RPS**.
#### Request Statistics
| Method | Endpoint | # Requests | Median (ms) | Avg (ms) | Min (ms) | Max (ms) | RPS |
|---|---|---|---|---|---|---|---|
| GET | `/health` | 2,052 | 4 | 27.6 | 2 | 3,014 | 14.3 |
| POST | `/interact` | 6,218 | 23 | 46.93 | 10 | 3,173 | 39.1 |
| GET | `/recommend/feed/8` | 2,150 | 7 | 37.36 | 3 | 2,146 | 12.1 |
| | **Aggregated** | **10,420** | **19** | **41.15** | **2** | **3,173** | **65.5** |
#### Response Time Percentiles
| Method | Endpoint | p50 (ms) | p90 (ms) | p95 (ms) | p99 (ms) |
|---|---|---|---|---|---|
| GET | `/health` | 4 | 13 | 19 | 900 |
| POST | `/interact` | 23 | 41 | 53 | 730 |
| GET | `/recommend/feed/8` | 7 | 23 | 33 | 2,000 |
| | **Aggregated** | **19** | **36** | **46** | **920** |
**Key observations:**
- `POST /interact` handles the highest load (39.1 RPS, 3Γ weight) with a p95 of **53ms** β well within real-time UX thresholds.
- `GET /recommend/feed/8` achieves a p50 of **7ms** for cached responses thanks to the 60-second TTL cache.
- `GET /health` spikes at p99 (900ms) and max (3,014ms) due to occasional GIL contention under high concurrency β negligible for a health probe.
- Zero failures across 10,420 total requests confirms production-grade stability.
### Code Linting
```bash
flake8 src/
```
---
## Contributing
1. Fork the repository.
2. Create a new branch: `git checkout -b feature/your-feature-name`
3. Commit your changes using [Conventional Commits](https://www.conventionalcommits.org/).
4. Push to the branch: `git push origin feature/your-feature-name`
5. Open a Pull Request.
Ensure all code passes `flake8` and `pytest` before submitting.
### Commit Message Convention
| Prefix | Use for |
|---|---|
| `feat:` | New features |
| `fix:` | Bug fixes |
| `docs:` | Documentation changes |
| `refactor:` | Code restructuring without behavior change |
| `test:` | Adding or updating tests |
| `chore:` | Maintenance tasks (deps, CI, config) |
---
## License
This project is licensed under the MIT License.
Copyright (c) 2026 SONIX RUSH
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
*Built with β€οΈ for the SONIX RUSH Application.* |