# ENGIN Diagnostic Console Gotowy do demonstracji system diagnostyki cylindrów przemysłowych silników Diesla. Z pomiaru widma 0–20 kHz rozpoznaje stan każdego cylindra, przewiduje nasilenie usterki i pokazuje mechanikowi, które pasma oraz cylindry wymagają uwagi. ## Uruchomienie Wymagany jest Python 3.12. Artefakt modelu sprawdza zgodność wersji Pythona i bibliotek przed deserializacją. ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements-lock.txt streamlit run app.py ``` Windows PowerShell: ```powershell py -m venv .venv .venv\Scripts\Activate.ps1 pip install -r requirements-lock.txt streamlit run app.py ``` Aplikacja otworzy się pod `http://localhost:8501`. Od razu uruchamia bezpieczne demo na `test.csv`; w panelu bocznym można przełączyć się na własny CSV. Alternatywnie przez Docker: ```bash docker build --target runtime -t engin-console . docker run --rm -p 127.0.0.1:8501:8501 engin-console ``` Zalecane uruchomienie produkcyjne korzysta z `compose.prod.yaml`: kontener działa jako UID/GID `10001`, z systemem plików tylko do odczytu, bez Linux capabilities oraz z limitami CPU, pamięci i procesów. Pełna procedura startu, aktualizacji i rollbacku znajduje się w `docs/PRODUCTION_RUNBOOK.md`. ## Co zawiera produkt - mapa 8-, 12- i 16-cylindrowych silników z diagnozą każdego cylindra, - typ usterki: `ok`, `zakoksowany`, `lejacy`, `pompa`, `iglica` lub `unknown`, - nasilenie: `male`, `srednie`, `duze`; dla `ok` i `unknown` zawsze `nie_dotyczy`, - status silnika, najwyższe rzeczywiste severity i kolejka cylindrów do kontroli, - heatmapa odchyleń całego silnika, - porównanie widma cylindra z medianą pozostałych cylindrów tej samej jednostki, - trzy najbardziej anomalne pasma, niekalibrowany score modelu oraz rekomendowany następny krok, - pobieranie `predictions.csv` i rozszerzonej diagnostyki, - ścisła walidacja CSV i bezpieczne komunikaty błędów, - lokalne działanie na CPU, bez wysyłania danych do zewnętrznych usług. ## Architektura Interfejs jest cienką warstwą prezentacji. Zależności są wstrzykiwane do `DiagnosticService`, dlatego odczyt pliku, walidator i model można niezależnie wymieniać oraz testować. Proces produkcyjny nie trenuje modelu przy starcie. Aplikacja weryfikuje checksumę, schemat wejścia i wersje bibliotek, a następnie ładuje artefakt `engin-2026.08.25-1`. Uszkodzony lub niezgodny artefakt uruchamia ograniczony fallback demonstracyjny. ```mermaid flowchart TD UI["Streamlit UI"] --> S["DiagnosticService"] S --> R["FrameReader"] S --> V["FrameValidator"] S --> M["PredictionModel"] S --> E["Explainability + wykresy"] ``` Najważniejsze katalogi i pliki: ```text app.py cienka warstwa Streamlit engin/io.py adapter odczytu CSV engin/validation.py kontrakt i walidacja danych engin/model.py adapter modelu i fallback demo engin/artifact.py manifest, checksumy i ładowanie artefaktu engin/features.py stabilne transformacje używane w train/inference engin/inference.py runtime predykcji bez zależności od benchmarków engin/service.py przypadek użycia / dependency injection engin/explainability.py status, porządkowy triage i uzasadnienia engin/charts.py czyste, testowalne fabryki Plotly final_pipeline.py finalny pipeline konkursowy tests/ testy aplikacji, błędów i komponentów docs/DEMO_SCENARIO.md gotowy scenariusz prezentacji 3–5 min docs/JURY_QA.md odpowiedzi na typowe pytania jury ``` ## Model i wynik Finalna architektura została wybrana w walidacji `StratifiedGroupKFold` po `engine_id`, bez mieszania cylindrów tego samego silnika: - label: odchylenie od mediany pozostałych cylindrów + Logistic Regression (`C=10`), - OOD: `ok` zmienia się na `unknown` tylko po przekroczeniu progu 7.25 mV oraz 2.5× mediany anomalii własnego silnika, - severity: cechy odchylenia + Extra Trees (`max_features=0.3`), - braki widma: interpolacja wzdłuż częstotliwości z deterministycznym fallbackiem, - inference na CPU, bez CNN i bez GPU. | Scenariusz walidacji | Macro F1 | Severity accuracy | Raw Score | Punkty ML | | --- | ---: | ---: | ---: | ---: | | clean | 0.9811 | 0.9298 | 0.9683 | 33.65/40 | | dokładnie 5% braków | 0.9829 | 0.9333 | 0.9705 | 34.10/40 | To średnie z pięciu seedów walidacji grupowej, nie wynik ukrytego testu. Negative control dla severity pozostaje w okolicy losowego poziomu, co zmniejsza ryzyko pozornego wyniku przez leakage. Jedynym źródłem finalnych metryk jest `ml_polish_benchmark.py` oraz pliki `ml_polish_summary.csv`/`ml_polish_runs.csv`. Starsze eksperymenty zostały przeniesione do `archive/legacy_experiments/` i jawnie oznaczone jako niewłaściwe do raportowania finalnego wyniku. Score zwracany przez `predict_proba` służy tylko do względnego porównania predykcji i nie jest przedstawiany jako skalibrowane prawdopodobieństwo awarii. Dla decyzji OOD score label jest celowo pusty, ponieważ OOD jest regułą bezpieczeństwa, a nie klasą modelu probabilistycznego. Finalne pliki można odtworzyć poleceniem: ```bash python final_pipeline.py ``` Powstają `predictions.csv` (600/600 rekordów, bez duplikatów i braków) oraz `prediction_diagnostics.csv` używany przez aplikację do explainability. Wersjonowany artefakt modelu buduje osobny krok release: ```bash python -m scripts.build_model_artifact \ --source-revision "$(git rev-parse HEAD)" python -m scripts.build_model_artifact --verify-only ``` Druga komenda nie trenuje modelu. Ładuje artefakt, sprawdza manifest i checksumę oraz wymaga dokładnej zgodności wszystkich 600 predykcji z zamrożonym `predictions.csv`. ## Kontrakt danych wejściowych Każdy wiersz reprezentuje cylinder. Wymagane kolumny: - `engine_id`, - `cylinder`, - `n_cylinders` równe 8, 12 albo 16, - `mV_0` … `mV_20`. Każdy silnik musi zawierać dokładnie cylindry `1..n_cylinders`. Aplikacja odrzuca między innymi puste i zbyt duże pliki, brakujące kolumny, duplikaty cylindrów, tekst w widmie, wartości ujemne/nieskończone, niespójny rozmiar jednostki i ponad 50% braków w jednym cylindrze. Mniejsza liczba braków jest uzupełniana tak samo jak podczas walidacji modelu. ## Testy i weryfikacja Pełna kontrola projektu: ```bash python -m unittest discover -v ``` Pakiet zawiera 38 testów: - testy braku leakage, cech, OOD i kontraktu submission, - testy jednostkowe walidatora i błędnych CSV, - testy serwisu z fake reader/validator/model — weryfikują dependency injection, - testy explainability, rankingu i wykresów, - testy smoke Streamlit dla demo, pustego uploadu i synchronizacji mapy cylindrów ze szczegółami. - testy artefaktu: checksumy, zgodność bibliotek, brak odczytu danych treningowych przy starcie i regresja predykcji 600/600. Szybka kontrola serwera: ```bash streamlit run app.py --server.headless true # drugi terminal curl --fail http://localhost:8501/_stcore/health ``` Oczekiwana odpowiedź: `ok`. ## Odporność operacyjna - Model jest trenowany poza aplikacją i ładowany raz z wersjonowanego artefaktu do cache procesu. - Finalny obraz runtime nie zawiera `val.csv`, `train.csv` ani skryptów treningowych. - Proces aplikacji działa jako użytkownik bez uprawnień roota; produkcyjny Compose dodatkowo wymusza read-only root filesystem, usuwa capabilities i ustawia limity zasobów. - Nieoczekiwany błąd inicjalizacji modelu uruchamia read-only fallback dla danych demo. - Nieprawidłowe dane nie docierają do modelu. - Błędy użytkownika mają stabilne kody i nie pokazują tracebacków w interfejsie. - Zależności produkcyjne są przypięte w `requirements-lock.txt`. - Aplikacja nie zmienia przesłanego pliku i nie wykonuje połączeń zewnętrznych.