# Prompt dla GitHub Copilot / Copilot Workspace
# Projekt: Banking Assistant (SPSD-2026-01)
# WAT – Standardy projektowania systemów dialogowych

---

## KONTEKST I CEL

Zbuduj kompletny projekt **Banking Assistant** — chatbota dla sektora bankowego, który działa w 100% lokalnie, bez żadnych zewnętrznych API do modeli językowych (brak OpenAI, brak Anthropic, brak Azure AI). System ma dwa "mózgi":

1. **Własna sieć neuronowa** (DistilBERT fine-tuned) do klasyfikacji intencji użytkownika i wykrywania fraudów — trenowana lokalnie
2. **Lokalny LLM** (Phi-3 Mini 3.8B via Ollama) do generowania naturalnych odpowiedzi w języku polskim

Interfejs użytkownika to aplikacja **webowa** dostępna przez przeglądarkę.
System działa na **Windows 10/11** bez Dockera — wszystkie procesy uruchamiane natywnie.

---

## STACK TECHNOLOGICZNY

```
Backend:         Python 3.11 + FastAPI (jeden proces — API + ML w jednym)
ML / NLP:        PyTorch + Hugging Face Transformers (DistilBERT fine-tuned)
Lokalny LLM:     Ollama (model: phi3:mini) — REST API na localhost:11434
Baza danych:     SQLite (via SQLAlchemy async) — plik lokalny, zero instalacji
Cache / Sesje:   słownik in-memory (TTL obsługiwany przez apscheduler)
Frontend:        Vue 3 + TypeScript + Vite + Naive UI
Komunikacja:     WebSocket (natywny FastAPI WebSocket, nie SignalR)
```

---

## ARCHITEKTURA SYSTEMU

```
[Przeglądarka]
     │  HTTP + WebSocket
     ▼
[FastAPI :8000]  ──── SQLite (historia konwersacji, użytkownicy, transakcje mock)
     │            ── In-memory session store (MFA kody, stan konwersacji)
     │
     ├── IntentClassifier
     │       └── DistilBERT fine-tuned (klasyfikacja intencji)
     │           Model: ./models/intent_classifier/
     │
     ├── FraudDetector
     │       └── PyTorch MLP lub sklearn (analiza metadanych sesji)
     │
     ├── OllamaClient
     │       └── HTTP → localhost:11434/api/generate (phi3:mini)
     │
     └── BankMockService
             └── dane mockowe w SQLite (salda, przelewy, historia, produkty, karty)
```

---

## SZCZEGÓŁOWE WYMAGANIA DO IMPLEMENTACJI

### 1. BACKEND (FastAPI — jeden serwis, wszystko razem)

Główna aplikacja FastAPI powinna zawierać:

**Endpointy HTTP:**
```
POST /auth/login              — zwraca JWT token (mock auth)
GET  /health                  — status serwisu + info czy model załadowany
GET  /bank/balance            — saldo konta (wymaga JWT)
GET  /bank/history?days=30    — historia transakcji (wymaga JWT)
GET  /bank/products           — lista produktów bankowych (wymaga JWT)
POST /bank/transfer           — realizacja przelewu (wymaga JWT + MFA)
POST /bank/card/block         — zastrzeżenie karty (wymaga JWT + MFA)
POST /mfa/generate            — generuje i "wysyła" kod MFA
POST /mfa/verify              — weryfikuje kod MFA
GET  /metrics/report          — raport metryk ewaluacji
```

**WebSocket:**
```
WS /ws/chat/{session_id}      — główny kanał czatu
```

Przepływ wiadomości przez WebSocket:
1. Klient wysyła: `{"type": "message", "text": "...", "session_id": "..."}`
2. Backend: klasyfikuje intencję → sprawdza fraud → sprawdza MFA → pyta Ollama
3. Backend streamuje odpowiedź tokenami: `{"type": "token", "text": "..."}`
4. Backend kończy: `{"type": "done", "intent": "...", "confidence": 0.95, "fraud_risk": 0.1}`

### 2. KLASYFIKACJA INTENCJI (DistilBERT)

Klasa `IntentClassifier`:
```python
INTENT_LABELS = [
    "check_balance",        # zapytanie o saldo
    "make_transfer",        # przelew
    "transaction_history",  # historia transakcji
    "product_info",         # informacje o produktach
    "block_card",           # zastrzeżenie karty
    "other"                 # pozostałe
]
# - Model bazowy: "distilbert-base-multilingual-cased"
# - Ładowanie z ./models/intent_classifier/ po wytrenowaniu
# - Device: cuda jeśli dostępne (RTX 4060 8GB VRAM), else cpu
# - predict(text) -> {"intent": str, "confidence": float, "all_scores": dict}
# - Model ładowany przy starcie aplikacji (nie per-request)
```

### 3. FRAUD DETECTION

Klasa `FraudDetector` analizuje metadane sesji (nie treść wiadomości):
```python
FRAUD_FEATURES = {
    "requests_per_minute": float,
    "unique_intents_last_5": int,
    "transfer_amount": float,
    "time_since_last_login": float,   # sekundy
    "mfa_failures": int,
    "session_duration": float,
    "is_new_recipient": bool,
    "hour_of_day": int,
}
# analyze(features) -> {"risk_score": float, "is_fraud": bool, "reasons": list[str]}
# Próg alarmu: risk_score > 0.7
# Model: PyTorch MLP trenowany na fraud_patterns.json
```

### 4. OLLAMA CLIENT

```python
# Klasa OllamaClient:
# - POST http://localhost:11434/api/generate
# - Model: "phi3:mini"
# - stream=True — odpowiedź strumieniowana chunk po chunku
# - System prompt po polsku:
#   "Jesteś Banking Assistant — wirtualnym asystentem bankowym PKO. Odpowiadasz
#    WYŁĄCZNIE po polsku. Jesteś profesjonalny, precyzyjny i pomocny. Nie
#    ujawniasz danych innych klientów. Dane klienta: {banking_context}.
#    Wykryta intencja: {intent}. Odpowiedz zwięźle (max 3 zdania)."
# - temperature=0.3, top_p=0.9
# - Timeout: 30s
# - Jeśli Ollama niedostępna: zwróć odpowiedź szablonową (fallback)
```

### 5. STAN KONWERSACJI (in-memory)

```python
# ConversationState — słownik in-memory per session_id:
{
    "session_id": str,
    "user_id": str,
    "current_intent": str,
    "mfa_verified": bool,
    "mfa_required": bool,
    "mfa_code": str,             # przechowywany tymczasowo
    "mfa_expires_at": datetime,
    "mfa_failures": int,
    "collected_slots": dict,     # np. {"amount": 500, "recipient": "..."}
    "history": list[str],        # ostatnie 10 wiadomości
    "fraud_events": list,
    "last_activity": datetime,
    "requests_timestamps": list[datetime],  # do liczenia req/min
}
# Intencje wymagające MFA: make_transfer, block_card
# Wygasanie sesji: brak aktywności przez 30 minut → usuń z pamięci
```

### 6. MOCK BANK SERVICE

```python
# BankMockService — dane hardcoded lub z pliku JSON:
# Użytkownicy testowi:
#   login: jan.kowalski / hasło: test123  → user_001
#   login: anna.nowak   / hasło: test123  → user_002
#
# Konta user_001:
#   PLN: 12 450.87 zł
#   EUR: 340.00 EUR
#   Karta debetowa: **** **** **** 1234 (aktywna)
#   Karta kredytowa: **** **** **** 5678 (aktywna, limit: 5000 zł)
#
# Historia: 20 losowych transakcji z ostatnich 30 dni
# Metody: get_balance, get_history, execute_transfer, get_products, block_card
# execute_transfer: waliduj kwotę, zapisz do SQLite, zwróć potwierdzenie
```

### 7. MFA SERVICE

```python
# MfaService — in-memory (bez Redis):
# - Generuje losowy 6-cyfrowy kod
# - Przechowuje w słowniku: {user_id: {"code": "123456", "expires": datetime, "failures": 0}}
# - TTL: 5 minut
# - Symulacja SMS: print(f"[SMS MOCK] Kod MFA dla {user_id}: {code}")
# - Po 3 nieudanych próbach: blokada sesji + fraud_event
# - generate_code(user_id) -> str
# - verify_code(user_id, code) -> bool
```

### 8. BAZA DANYCH (SQLite + SQLAlchemy async)

Tabele:
```python
# conversations: id, session_id, user_id, role, content, intent,
#                confidence, timestamp
# transactions:  id, user_id, type, amount, currency, recipient,
#                description, timestamp, status
# metrics:       id, session_id, intent, response_time_ms, confidence,
#                fraud_risk, timestamp
# users:         id, login, password_hash, full_name, created_at
```

### 9. SKRYPT TRENINGU (train.py)

```python
# Osobny skrypt, uruchamiany raz przed startem aplikacji:
# 1. Wczytaj data/training_data.json -> [{"text": str, "intent": str}]
# 2. Split 80/20 train/val
# 3. Fine-tuning DistilBERT ("distilbert-base-multilingual-cased"):
#    - Epochs: 10, Batch: 16, LR: 2e-5, AdamW
#    - Mixed precision (torch.cuda.amp) — kluczowe dla RTX 4060 8GB
#    - Gradient accumulation steps: 2 (gdy batch nie mieści się w VRAM)
# 4. Loguj metryki co epokę: loss, accuracy, F1 per klasę
# 5. Zapisz najlepszy model (wg val accuracy) -> ./models/intent_classifier/
# 6. Zapisz raport -> ./models/metrics_report.json
# Szacowany czas: ~5-10 minut na RTX 4060
```

### 10. FRONTEND (Vue 3 + Naive UI)

Wymagania komponentów:

**ChatWindow** — główny widok czatu:
- Ciemny motyw Naive UI (`n-config-provider` z `darkTheme`)
- Bąbelki wiadomości: użytkownik (prawo, kolor primary), bot (lewo, szary)
- Streaming: tekst pojawia się słowo po słowie przez WebSocket
- Skeleton loader / "Bot pisze..." podczas oczekiwania na odpowiedź
- Pole wpisywania z przyciskiem Wyślij, obsługa Enter

**FraudAlert** — komponent alertu:
- `n-alert` z type="error" gdy fraud_risk > 0.7
- Wyświetla powody alarmu z backendu
- Można zamknąć (dismiss)

**MfaModal** — modal weryfikacji:
- `n-modal` z `n-input` na 6-cyfrowy kod
- Odliczanie 5 minut (`n-countdown` lub własny timer)
- Walidacja: tylko cyfry, dokładnie 6 znaków
- Po 3 błędach: zablokuj pole + pokaż komunikat

**TransactionCard** — potwierdzenie przelewu:
- `n-card` z detalami: odbiorca, kwota, tytuł
- Dwa przyciski: "Potwierdź" (→ generuje MFA) i "Anuluj"

**Panel boczny:**
- Stan sesji: zalogowany użytkownik, czas sesji
- Ostatnie intencje z confidence score (`n-tag`)
- Wskaźnik fraud risk (`n-progress`)

**Połączenie z backendem:**
- WebSocket: `new WebSocket("ws://localhost:8000/ws/chat/{session_id}")`
- REST: axios lub fetch dla endpointów HTTP
- Przechowywanie JWT w sessionStorage (nie localStorage)

### 11. METRYKI (na potrzeby ewaluacji akademickiej)

```python
# Zbieraj w tabeli metrics (SQLite):
# - response_time_ms: czas od otrzymania wiadomości do wysłania done
# - intent + confidence: z klasyfikatora
# - fraud_risk: wynik FraudDetector
#
# GET /metrics/report zwraca:
# {
#   "total_sessions": int,
#   "avg_response_time_ms": float,
#   "intent_distribution": {"check_balance": 45, ...},
#   "avg_confidence": float,
#   "fraud_alerts_count": int,
#   "p95_response_time_ms": float   # target: ≤ 2000ms
# }
```

---

## URUCHAMIANIE NA WINDOWS (bez Dockera)

README musi zawierać instrukcję krok po kroku dla Windows:

```
Wymagania wstępne:
  - Python 3.11 (python.org)
  - Node.js 20 LTS (nodejs.org)
  - Ollama dla Windows (ollama.com/download) — instalator .exe
  - NVIDIA CUDA Toolkit 12.x (dla GPU, opcjonalne)

Kroki:
  1. Pobierz model LLM:
       ollama pull phi3:mini

  2. Zainstaluj zależności Python:
       pip install -r requirements.txt

  3. Wytrenuj model intencji (raz):
       python train.py

  4. Uruchom backend:
       python -m uvicorn main:app --host 0.0.0.0 --port 8000 --reload

  5. Uruchom frontend (osobne okno terminala):
       cd frontend
       npm install
       npm run dev

  6. Otwórz przeglądarkę: http://localhost:5173

Dane testowe:
  Login: jan.kowalski  Hasło: test123
  Login: anna.nowak    Hasło: test123
```

Opcjonalnie: skrypt `start.bat` uruchamiający backend i frontend jednocześnie (dwa okna cmd).

---

## BEZPIECZEŃSTWO

- Endpointy chronione JWT (poza /health, /auth/login)
- Hasła hashowane bcrypt
- Maskowanie numerów kont w logach: `****1234`
- CORS: tylko `http://localhost:5173` (Vite dev server)
- Brak danych wrażliwych w plikach konfiguracyjnych commitowanych do repo

---

## CZEGO NIE ROBIĆ

- ❌ Nie używaj OpenAI API, Azure OpenAI, Anthropic API ani żadnego zewnętrznego LLM
- ❌ Nie używaj Dockera ani docker-compose
- ❌ Nie używaj Redis ani PostgreSQL — tylko SQLite i in-memory
- ❌ Nie używaj React ani żadnego innego frameworku UI — tylko Vue 3 + Naive UI
- ❌ Nie używaj Microsoft Bot Framework
- ❌ Nie przechowuj haseł w plaintext
- ❌ Nie proponuj struktury katalogów — sam zdecyduj jak najlepiej zorganizować projekt
