AI Asistent Učitelj Vasa: Praktična obuka za početnike (32 dana)

Dan 7/28: Napredna personalizacija učitelja Vase

Dan 7/28: Napredna personalizacija učitelja Vase

Vreme potrebno: 90 – 180 minuta

Gde je Učitelj Vasa danas?

Učitelj Vasa je stabilan i pouzdan AI asistent sa multi-provider podrškom, automatskom optimizacijom performansi i naprednim sistemom za rukovanje greškama. Može da prebacuje između OpenAI i Gemini servisa, automatski pokušava ponovo pri greškama i gracefully degradira kada servisi nisu dostupni. Ali još uvek pristupa svima isto – ne pamti ko mu postavlja pitanja niti prilagođava svoje ponašanje različitim korisnicima. Danas menjamo to!

Cilj današnje lekcije

Danas ćeš kreirati sistem korisničkih profila koji pamti preference svakog korisnika, implementirati kontekstualno svesno ponašanje koje se prilagođava iskustvu korisnika, i omogućiti Vasi da prepozna da li razgovara sa početnikom ili naprednim korisnikom. Nakon ove lekcije, Učitelj Vasa će postati personalizovan asistent koji se prilagođava svakom korisniku ponaosob!

Predznanja

  • Funkcionalan resilient AI sistem (Dan 6)
  • Razumevanje Config modula i čuvanja podataka (Dan 3)
  • Factory pattern i BaseAIService interfejs (Dan 4)
  • JSON format za čuvanje podataka (Dan 2)
  • Osnovno razumevanje dictionary struktura u Python-u

Glavni sadržaj

Zašto je personalizacija važna za AI asistente?

Pre nego što krenemo sa implementacijom, hajde da razumemo zašto uopšte želimo da personalizujemo Učitelja Vasu.

📚 NIVO 1 – Osnovno objašnjenje

Zamisli dva učenika u razredu:

  • Marko je tek počeo da uči programiranje – treba mu detaljno objašnjenje svake sitnice
  • Ana programira godinu dana – želi brže, konkretnije odgovore bez osnovnih objašnjenja

Dobar učitelj prilagođava svoj pristup svakom učeniku. Isto treba da radi i Učitelj Vasa! Umesto da svima odgovara isto, trebalo bi da:

  • Početnicima daje detaljnije objašnjenje sa više primera
  • Naprednijima daje koncizniji odgovor sa fokusom na suštinu
  • Pamti šta je ko pitao ranije i gradi na tom znanju

🚀 NIVO 2 – Dublje razumevanje

Personalizacija u AI sistemima omogućava:

  1. Adaptive Learning – sistem uči o korisniku tokom vremena
  2. Context Awareness – razumevanje trenutne situacije korisnika
  3. Preference Management – pamćenje kako korisnik voli da prima informacije
  4. Skill Level Tracking – praćenje napretka korisnika

Ovo se postiže kroz kombinaciju:

  • User profila (trajno čuvanje podataka)
  • Session konteksta (privremeni podaci tokom razgovora)
  • Behavioral patterns (prepoznavanje obrazaca ponašanja)

🔍 UVID: Personalizacija nije samo “luksuz” – ona fundamentalno menja korisnost AI asistenta. Istraživanja pokazuju da personalizovani AI sistemi imaju 40-60% veću retenciju korisnika. Razlog je jednostavan: ljudi žele da se osećaju viđeni i razumljeni. Kada AI pamti tvoje preference i prilagođava se tvom nivou znanja, stvara se osećaj da imaš ličnog mentora, a ne generički alat.

💡 PRO TIP: Personalizaciju uvek započni sa “opt-in” pristupom. Pitaj korisnika da li želi da sistem pamti njegove preference. Transparentnost gradi poverenje, a poverenje je ključ dugotrajnog odnosa sa AI asistentom.

🎈 ZABAVNA ČINJENICA: Prvi personalizovani AI asistent bio je ELIZA iz 1966. godine. Iako je imala samo 200 linija koda, ljudi su satima razgovarali sa njom jer je “pamtila” delove razgovora i vraćala ih u pitanjima, stvarajući iluziju razumevanja!

Kreiranje sistema korisničkih profila

Počnimo sa implementacijom sistema koji će pamtiti informacije o svakom korisniku.

📚 NIVO 1 – Osnovno objašnjenje

Korisnički profil je kao karton u školi – sadrži osnovne informacije o učeniku i prati njegov napredak. Za Učitelja Vasu ćemo čuvati:

  • Ime korisnika
  • Nivo znanja (početnik, srednji, napredni)
  • Broj postavljenih pitanja
  • Omiljene teme
  • Način na koji voli da prima objašnjenja

Sve ovo ćemo čuvati u JSON fajlu, baš kao što škola čuva kartone u ormaru.

🚀 NIVO 2 – Dublje razumevanje

Sistem profila će koristiti slojevitu arhitekturu:

  1. UserProfile klasa – predstavlja jednog korisnika
  2. ProfileManager – upravlja svim profilima
  3. ProfileAnalyzer – analizira ponašanje i predlaže prilagođavanja
  4. PreferenceEngine – primenjuje preference na AI odgovore

Podatke ćemo čuvati lokalno u JSON formatu, sa mogućnošću lake migracije na bazu podataka kasnije.

📊 DIJAGRAM: Tok podataka u sistemu profila

     [Korisnički unos]
             |
             v
+-----------------------+      +--------------------------+
|    ProfileManager     |----->|   UserProfile Objekat    |
| (Upravljač Profila)   |      |   (Podaci u memoriji)    |
+-----------------------+      +--------------------------+
      ^           |                       ^
      | (load)    | (save)                | (ažuriranje)
      |           v                       |
+-----------------------+      +--------------------------+
|  korisnik_profile.json|----->|         Aplikacija         |
|   (Fajl na disku)     |      |      (Glavni program)      |
+-----------------------+      +--------------------------+

🔍 UVID: Trenutni pristup sa JSON fajlovima je odličan za početak – jednostavan je i ne zahteva eksterne zavisnosti. Međutim, važno je razumeti njegove sistemske limite. Svako čuvanje i učitavanje je I/O (Input/Output) operacija na disku, što je relativno sporo. Takođe, ako bi više korisnika istovremeno pristupalo sistemu, moglo bi doći do konflikta pri pisanju u fajl. Arhitektura koju gradimo sa ProfileManager klasom je ključna, jer ona služi kao “adapter”. Kasnije, možemo zameniti logiku unutar ProfileManager-a da koristi pravu bazu podataka (npr. SQLite ili cloud bazu), bez potrebe da menjamo ostatak aplikacije.

💡 PRO TIP: Koristi @dataclass dekorator za klase koje prvenstveno čuvaju podatke. Automatski generiše __init__, __repr__ i druge metode, što čini kod kraćim i manje sklonim greškama. Dodatno, asdict() funkcija olakšava serijalizaciju u JSON.

SAVET ZA OPTIMIZACIJU: Keširanje profila u memoriji (self._current_profile) je pametan potez. Pristup memoriji je hiljadama puta brži od pristupa disku. Ipak, imaj na umu da save_profile i dalje piše na disk svaki put. Za aplikaciju sa jednim korisnikom, ovo je u redu. U sistemu sa više korisnika, razmislio bi o strategiji “lazy saving” – čuvanje promena tek na kraju sesije ili nakon određenog broja interakcija, kako bi se smanjio broj sporih I/O operacija.

🎯 ALTERNATIVNO REŠENJE: Ako više voliš “pravo” skladištenje od JSON-a, probaj mini SQLite bazu:

import sqlite3

def init_db(path="data/profiles.db"):
    conn = sqlite3.connect(path)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS profiles (
            username TEXT PRIMARY KEY,
            data     TEXT NOT NULL
        )
    """)
    return conn

def save_profile_sql(conn, profile):
    conn.execute(
        "REPLACE INTO profiles (username, data) VALUES (?, ?)",
        (profile.username, json.dumps(profile.to_dict(), ensure_ascii=False))
    )
    conn.commit()

def load_profile_sql(conn, username):
    cur = conn.execute(
        "SELECT data FROM profiles WHERE username = ?", (username,)
    )
    row = cur.fetchone()
    return (UserProfile.from_dict(json.loads(row[0]))
            if row else None)

SQLite je ugrađen u Python standardnu biblioteku, pa nema dodatnih zavisnosti, a kasnije možeš migrirati na “pravu” bazu bez promene ostatka koda.

Kreiranje sistema za analizu korisničkog ponašanja

Sada ćemo kreirati sistem koji analizira kako korisnik interaguje sa Vasom i predlaže prilagođavanja.

📚 NIVO 1 – Osnovno objašnjenje

Ovaj sistem je kao posmatrač koji prati kako učenik uči:

  • Da li postavlja kratka ili duga pitanja?
  • Da li često traži primere koda?
  • Da li mu trebaju detaljnija objašnjenja?
  • Koliko brzo napreduje?

Na osnovu ovoga, sistem automatski prilagođava način na koji Vasa odgovara.

🚀 NIVO 2 – Dublje razumevanje

ProfileAnalyzer koristi heuristike i pattern recognition da identifikuje korisničke potrebe. Analizira:

  • Lingvističke karakteristike pitanja
  • Frekvenciju određenih tipova zahteva
  • Brzinu napredovanja kroz teme
  • Feedback patterns (implicitni kroz follow-up pitanja)

📊 DIJAGRAM: Proces analize korisničke poruke

["Šta je python funkcija i kako da je koristim?"]  <-- Korisnička poruka
                    |
                    v
+---------------------------------------------+
|        ProfileAnalyzer.analyze_message()    |
|   (Analizira tekst poruke po pravilima)     |
+---------------------------------------------+
                    |
                    v
+---------------------------------------------+
|             Rezultat Analize (dict)         |
|---------------------------------------------|
| "topics": ["funkcije", "python_osnove"]     |
| "skill_indicators": {"beginner": 2, ...}    |
| "characteristics": {"length": 45, ...}      |
+---------------------------------------------+

🎈 ZABAVNA ČINJENICA: IBM-ov Watson je tokom istorijskog nastupa na kvizu Jeopardy! (2011) patio od “personalizacije u suprotnom smeru”: tim je morao da ograniči koliko se Watson prilagođava stilu pitanja da ne bi previše optimizovao na istorijske podatke i počeo da pravi čudne greške uživo. Personalizacija je moćna – ali samo dok je pod kontrolom!

💡 PRO TIP: Koristi Counter iz collections modula za brzo brojanje elemenata. Mnogo je efikasniji od ručnog brojanja i ima korisne metode kao most_common() koje automatski sortiraju rezultate. Takođe, prilikom izgradnje personalizovanog system prompta, ubaci delić “meta-podatka” koji kaže kada je profil poslednji put ažuriran. Na taj način možeš lako debug-ovati situacije u kojima korisnik vidi “stari stil” odgovora.

Integracija personalizacije sa AI servisima

Sada ćemo integrisati sistem profila sa postojećim AI servisima.

📚 NIVO 1 – Osnovno objašnjenje

Do sada je Vasa svima odgovarao isto. Sada ćemo ga naučiti da:

  1. Pita za ime na početku
  2. Učita ili kreira profil za tog korisnika
  3. Prilagodi svoje odgovore prema profilu
  4. Ažurira profil nakon svakog razgovora

To je kao kada učitelj pamti svakog učenika i zna kako ko najbolje uči.

🚀 NIVO 2 – Dublje razumevanje

Integrisaćemo personalizaciju na tri nivoa:

  1. System prompt modifikacija – dinamički menjamo Vasinu ličnost
  2. Parameter tuning – prilagođavamo temperature i max_tokens
  3. Response filtering – post-procesiramo odgovore prema preferencama

 

Praktična implementacija

Kreiranje sistema za adaptive learning

Na kraju, kreirajmo sistem koji automatski prilagođava Vasino ponašanje tokom razgovora.

📊 DIJAGRAM: Adaptivna petlja učenja

                               +-------------------------------------+
                               |         AI daje odgovor             |
                               +-------------------------------------+
                                                 |
                                                 v
+-----------------------------+     +-------------------------------------+
| Korisnik reaguje:           | --> |       AdaptiveEngine analizira      |
| "Ne razumem...", "Jasno!"   |     |          reakciju korisnika         |
+-----------------------------+     +-------------------------------------+
             ^                                     |
             |                                     v
+-----------------------------+     +-------------------------------------+
| AI generiše prilagođen      | <-- |    Predlaže se adaptacija:          |
| sledeći odgovor             |     |    "Pojednostavi", "Proširi"        |
+-----------------------------+     +-------------------------------------+

SAVET ZA OPTIMIZACIJU: Adaptive engine trenutno analizira samo eksplicitne indikatore (“ne razumem”, “jasno”). Napredna verzija bi mogla da meri i implicitne signale: brzinu odgovora (brz odgovor = verovatno razume), dužinu follow-up pitanja (kratka = specific confusion), ili čak sentiment analizu. Ovo bi zahtevalo ML model, ali za početak, rule-based pristup odlično funkcioniše.

🔄 VEŽBA: Implementiraj jednostavnu enkripciju profila.

  1. Instaliraj biblioteku cryptography (biće potrebna tek na Dan 23, ali ovde je u edukativne svrhe).
  2. Dodaj metodu encrypt_data(data: str) -> bytes koja AES-om šifruje JSON pre upisa na disk.
  3. Modifikuj save_profile() i load_profile() da transparentno kriptuju/dekriptuju sadržaj.
  4. Razmisli: kako ćeš rotirati ključ ako korisnik resetuje lozinku?

Hint: za početnike dovoljno je da koristiš Fernet iz cryptography.fernet. Napredniji mogu probati čuvanje ključa u .env fajlu i rotaciju preko verzionisanih ključeva.

Optimizacija i najbolje prakse

Ova sekcija sadrži dodatne savete za unapređenje sistema personalizacije koji si danas izgradio.

SAVET ZA OPTIMIZACIJU: U trenutnoj implementaciji, svaki put kada ažuriraš profil (npr. update_activity), poziva se save_profile(), što rezultuje upisom na disk. Za jednu sesiju sa 10 pitanja, to je 10 I/O operacija. Bolja strategija bi bila da se profil čuva samo jednom, na kraju sesije (npr. kada korisnik izabere opciju “Izađi”) ili nakon što se napravi značajniji broj promena. Ovo drastično smanjuje opterećenje na disku i čini aplikaciju bržom.

Dan 7: Kompletna implementacija sistema personalizacije

Ovaj dokument sadrži sve fajlove potrebne za implementaciju sistema personalizacije u projektu Učitelj Vasa.

Struktura fajlova

ucitelj-vasa/
├── src/
│   ├── personalization/
│   │   ├── __init__.py
│   │   ├── user_profile.py
│   │   ├── profile_analyzer.py
│   │   └── adaptive_engine.py
│   ├── ai_services/
│   │   └── base_service.py (ažuriran)
│   └── main.py (ažuriran)
└── data/
    └── profiles/ (automatski se kreira)

1. src/personalization/init.py

"""
Personalization modul za Učitelja Vasu
"""

from .user_profile import UserProfile, ProfileManager, profile_manager
from .profile_analyzer import ProfileAnalyzer
from .adaptive_engine import AdaptiveEngine

__all__ = [
    'UserProfile',
    'ProfileManager', 
    'profile_manager',
    'ProfileAnalyzer',
    'AdaptiveEngine'
]

2. src/personalization/user_profile.py

"""
User Profile sistem za Učitelja Vasu
Omogućava personalizaciju iskustva za svakog korisnika
"""

import json
import os
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field, asdict
from enum import Enum


class SkillLevel(Enum):
    """Nivoi znanja korisnika."""
    BEGINNER = "beginner"
    INTERMEDIATE = "intermediate"
    ADVANCED = "advanced"
    
    def to_serbian(self) -> str:
        """Vraća naziv na srpskom."""
        translations = {
            "beginner": "Početnik",
            "intermediate": "Srednji nivo",
            "advanced": "Napredni"
        }
        return translations.get(self.value, self.value)


class LearningStyle(Enum):
    """Stilovi učenja korisnika."""
    VISUAL = "visual"          # Voli dijagrame i ilustracije
    TEXTUAL = "textual"        # Preferira detaljne tekstualne opise
    PRACTICAL = "practical"    # Želi kod primere odmah
    THEORETICAL = "theoretical" # Voli da razume teoriju prvo
    
    def to_serbian(self) -> str:
        """Vraća naziv na srpskom."""
        translations = {
            "visual": "Vizuelni",
            "textual": "Tekstualni",
            "practical": "Praktični",
            "theoretical": "Teorijski"
        }
        return translations.get(self.value, self.value)


@dataclass
class UserPreferences:
    """Korisničke preference za AI odgovore."""
    response_length: str = "medium"  # short, medium, long
    code_examples: bool = True       # Da li želi primere koda
    use_analogies: bool = True       # Da li voli analogije
    language_mix: str = "mixed"      # serbian, english, mixed
    detail_level: int = 5           # 1-10 skala
    
    def to_system_prompt_addon(self) -> str:
        """Konvertuje preference u dodatak za system prompt."""
        prompt_parts = []
        
        # Dužina odgovora
        if self.response_length == "short":
            prompt_parts.append("Daj kratke, koncizne odgovore.")
        elif self.response_length == "long":
            prompt_parts.append("Daj detaljne, opširne odgovore.")
        
        # Primeri koda
        if not self.code_examples:
            prompt_parts.append("Izbegavaj primere koda osim ako nisu eksplicitno traženi.")
        else:
            prompt_parts.append("Uvek uključi relevantne primere koda.")
        
        # Analogije
        if not self.use_analogies:
            prompt_parts.append("Fokusiraj se na tehničke detalje bez analogija.")
        else:
            prompt_parts.append("Koristi analogije iz svakodnevnog života za objašnjenja.")
        
        # Jezik
        if self.language_mix == "serbian":
            prompt_parts.append("Koristi isključivo srpski jezik, čak i za tehničke termine.")
        elif self.language_mix == "english":
            prompt_parts.append("Koristi engleski za sve tehničke termine i objašnjenja.")
        
        # Nivo detalja
        if self.detail_level <= 3:
            prompt_parts.append("Drži se samo osnova bez ulaženja u detalje.")
        elif self.detail_level >= 8:
            prompt_parts.append("Daj vrlo detaljne tehničke informacije.")
        
        return " ".join(prompt_parts)


@dataclass
class UserProfile:
    """Profil korisnika sa svim relevantnim informacijama."""
    username: str
    created_at: str = field(default_factory=lambda: datetime.now().isoformat())
    skill_level: SkillLevel = SkillLevel.BEGINNER
    learning_style: LearningStyle = LearningStyle.PRACTICAL
    preferences: UserPreferences = field(default_factory=UserPreferences)
    
    # Statistike
    total_questions: int = 0
    topics_count: Dict[str, int] = field(default_factory=dict)
    last_active: str = field(default_factory=lambda: datetime.now().isoformat())
    session_count: int = 0
    
    # Napredak
    completed_topics: List[str] = field(default_factory=list)
    current_learning_path: Optional[str] = None
    achievements: List[str] = field(default_factory=list)
    
    def update_activity(self, topic: Optional[str] = None):
        """Ažurira aktivnost korisnika."""
        self.last_active = datetime.now().isoformat()
        self.total_questions += 1
        
        if topic:
            self.topics_count[topic] = self.topics_count.get(topic, 0) + 1
    
    def get_favorite_topics(self, limit: int = 3) -> List[str]:
        """Vraća omiljene teme korisnika."""
        sorted_topics = sorted(
            self.topics_count.items(), 
            key=lambda x: x[1], 
            reverse=True
        )
        return [topic for topic, _ in sorted_topics[:limit]]
    
    def calculate_engagement_score(self) -> float:
        """Računa skor angažovanosti korisnika (0-100)."""
        score = 0.0
        
        # Aktivnost u poslednjih 7 dana
        last_active_date = datetime.fromisoformat(self.last_active)
        days_inactive = (datetime.now() - last_active_date).days
        
        if days_inactive == 0:
            score += 30
        elif days_inactive <= 3:
            score += 20
        elif days_inactive <= 7:
            score += 10
        
        # Broj pitanja
        if self.total_questions >= 50:
            score += 20
        elif self.total_questions >= 20:
            score += 15
        elif self.total_questions >= 10:
            score += 10
        elif self.total_questions >= 5:
            score += 5
        
        # Raznovrsnost tema
        topic_diversity = len(self.topics_count)
        if topic_diversity >= 10:
            score += 20
        elif topic_diversity >= 5:
            score += 15
        elif topic_diversity >= 3:
            score += 10
        
        # Achievements
        score += min(30, len(self.achievements) * 5)
        
        return min(100, score)
    
    def should_level_up(self) -> bool:
        """Proverava da li korisnik treba da pređe na viši nivo."""
        if self.skill_level == SkillLevel.BEGINNER:
            return (self.total_questions >= 30 and 
                   len(self.completed_topics) >= 5)
        elif self.skill_level == SkillLevel.INTERMEDIATE:
            return (self.total_questions >= 100 and 
                   len(self.completed_topics) >= 15)
        return False
    
    def level_up(self):
        """Podiže korisnika na viši nivo."""
        if self.skill_level == SkillLevel.BEGINNER:
            self.skill_level = SkillLevel.INTERMEDIATE
            self.achievements.append("intermediate_level_reached")
        elif self.skill_level == SkillLevel.INTERMEDIATE:
            self.skill_level = SkillLevel.ADVANCED
            self.achievements.append("advanced_level_reached")
    
    def to_dict(self) -> Dict[str, Any]:
        """Konvertuje profil u dictionary za čuvanje."""
        data = asdict(self)
        data['skill_level'] = self.skill_level.value
        data['learning_style'] = self.learning_style.value
        return data
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'UserProfile':
        """Kreira profil iz dictionary podataka."""
        # Konvertuj enum vrednosti
        if 'skill_level' in data:
            data['skill_level'] = SkillLevel(data['skill_level'])
        if 'learning_style' in data:
            data['learning_style'] = LearningStyle(data['learning_style'])
        
        # Konvertuj preferences
        if 'preferences' in data and isinstance(data['preferences'], dict):
            data['preferences'] = UserPreferences(**data['preferences'])
        
        return cls(**data)


class ProfileManager:
    """Upravlja svim korisničkim profilima."""
    
    def __init__(self, storage_path: Optional[Path] = None):
        """
        Inicijalizuje ProfileManager.
        
        Args:
            storage_path: Putanja do foldera za čuvanje profila
        """
        if storage_path is None:
            # Default putanja
            self.storage_path = Path(__file__).parent.parent.parent / "data" / "profiles"
        else:
            self.storage_path = storage_path
        
        # Kreiraj folder ako ne postoji
        self.storage_path.mkdir(parents=True, exist_ok=True)
        
        # Keširan trenutni profil
        self._current_profile: Optional[UserProfile] = None
    
    def _get_profile_path(self, username: str) -> Path:
        """Vraća putanju do fajla profila."""
        # Sanitizuj username za bezbedno ime fajla
        safe_username = "".join(c for c in username if c.isalnum() or c in "._-")
        return self.storage_path / f"{safe_username}_profile.json"
    
    def create_profile(self, username: str) -> UserProfile:
        """
        Kreira novi profil korisnika.
        
        Args:
            username: Korisničko ime
            
        Returns:
            Novi UserProfile objekat
        """
        profile = UserProfile(username=username)
        self.save_profile(profile)
        return profile
    
    def load_profile(self, username: str) -> Optional[UserProfile]:
        """
        Učitava postojeći profil.
        
        Args:
            username: Korisničko ime
            
        Returns:
            UserProfile ili None ako ne postoji
        """
        profile_path = self._get_profile_path(username)
        
        if not profile_path.exists():
            return None
        
        try:
            with open(profile_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                return UserProfile.from_dict(data)
        except Exception as e:
            print(f"⚠️ Greška pri učitavanju profila: {e}")
            return None
    
    def save_profile(self, profile: UserProfile):
        """
        Čuva profil na disk.
        
        Args:
            profile: UserProfile objekat za čuvanje
        """
        profile_path = self._get_profile_path(profile.username)
        
        try:
            with open(profile_path, 'w', encoding='utf-8') as f:
                json.dump(profile.to_dict(), f, indent=2, ensure_ascii=False)
        except Exception as e:
            print(f"❌ Greška pri čuvanju profila: {e}")
    
    def get_or_create_profile(self, username: str) -> UserProfile:
        """
        Učitava postojeći ili kreira novi profil.
        
        Args:
            username: Korisničko ime
            
        Returns:
            UserProfile objekat
        """
        profile = self.load_profile(username)
        if profile is None:
            print(f"🆕 Kreiram novi profil za: {username}")
            profile = self.create_profile(username)
        else:
            print(f"✅ Učitan postojeći profil za: {username}")
            profile.session_count += 1
            self.save_profile(profile)
        
        self._current_profile = profile
        return profile
    
    def get_current_profile(self) -> Optional[UserProfile]:
        """Vraća trenutno aktivni profil."""
        return self._current_profile
    
    def list_all_profiles(self) -> List[str]:
        """
        Lista sva korisnička imena sa profilima.
        
        Returns:
            Lista korisničkih imena
        """
        profiles = []
        for profile_file in self.storage_path.glob("*_profile.json"):
            username = profile_file.stem.replace("_profile", "")
            profiles.append(username)
        return sorted(profiles)
    
    def delete_profile(self, username: str) -> bool:
        """
        Briše profil korisnika.
        
        Args:
            username: Korisničko ime
            
        Returns:
            True ako je uspešno obrisano
        """
        profile_path = self._get_profile_path(username)
        
        if profile_path.exists():
            try:
                profile_path.unlink()
                if self._current_profile and self._current_profile.username == username:
                    self._current_profile = None
                return True
            except Exception as e:
                print(f"❌ Greška pri brisanju profila: {e}")
        
        return False
    
    def get_profile_summary(self, username: str) -> str:
        """
        Vraća kratak pregled profila.
        
        Args:
            username: Korisničko ime
            
        Returns:
            Formatiran string sa pregledom
        """
        profile = self.load_profile(username)
        if not profile:
            return f"Profil '{username}' ne postoji."
        
        favorite_topics = profile.get_favorite_topics()
        engagement = profile.calculate_engagement_score()
        
        summary = f"""
📊 PROFIL: {profile.username}
{'=' * 40}
📚 Nivo: {profile.skill_level.to_serbian()}
🎯 Stil učenja: {profile.learning_style.to_serbian()}
❓ Ukupno pitanja: {profile.total_questions}
🏆 Dostignuća: {len(profile.achievements)}
💯 Angažovanost: {engagement:.0f}%
⭐ Omiljene teme: {', '.join(favorite_topics) if favorite_topics else 'Nema još'}
📅 Poslednja aktivnost: {profile.last_active[:10]}
        """
        
        return summary.strip()


# Globalna instanca
profile_manager = ProfileManager()

3. src/personalization/profile_analyzer.py

"""
Profile Analyzer za Učitelja Vasu
Analizira korisničko ponašanje i predlaže prilagođavanja
"""

import re
from typing import Dict, List, Tuple, Optional
from collections import Counter
from datetime import datetime, timedelta

from .user_profile import UserProfile, SkillLevel, LearningStyle


class ProfileAnalyzer:
    """Analizira korisničke profile i ponašanje."""
    
    # Ključne reči za detekciju tema
    TOPIC_KEYWORDS = {
        "python_osnove": ["python", "promenljiv", "variable", "tip", "string", "broj", "lista"],
        "funkcije": ["funkcij", "def", "return", "parametar", "argument"],
        "klase": ["klasa", "class", "objekat", "metod", "nasledjivanje"],
        "greske": ["greška", "error", "exception", "try", "except", "debug"],
        "api": ["api", "request", "response", "endpoint", "json"],
        "git": ["git", "commit", "branch", "merge", "repository"],
        "web": ["web", "html", "css", "javascript", "frontend", "backend"],
        "baze": ["baza", "sql", "database", "query", "tabela"],
        "ai": ["ai", "veštačk", "inteligencij", "machine learning", "neural"]
    }
    
    # Indikatori nivoa znanja
    SKILL_INDICATORS = {
        "beginner": [
            "šta je", "kako da", "ne razumem", "objasni", "pokaži primer",
            "prvi put", "početnik", "osnov", "jednostavn"
        ],
        "intermediate": [
            "zašto", "razlika između", "kada koristiti", "najbolja praksa",
            "efikasnij", "alternativ", "kako funkcioniše"
        ],
        "advanced": [
            "optimizacij", "performans", "složenost", "algoritam",
            "arhitektur", "pattern", "skalabilnost", "concurrency"
        ]
    }
    
    def analyze_message(self, message: str) -> Dict[str, any]:
        """
        Analizira pojedinačnu poruku korisnika.
        
        Args:
            message: Poruka za analizu
            
        Returns:
            Dict sa rezultatima analize
        """
        message_lower = message.lower()
        
        # Detektuj temu
        detected_topics = []
        for topic, keywords in self.TOPIC_KEYWORDS.items():
            if any(keyword in message_lower for keyword in keywords):
                detected_topics.append(topic)
        
        # Detektuj nivo
        skill_scores = {
            "beginner": 0,
            "intermediate": 0,
            "advanced": 0
        }
        
        for level, indicators in self.SKILL_INDICATORS.items():
            for indicator in indicators:
                if indicator in message_lower:
                    skill_scores[level] += 1
        
        # Analiziraj karakteristike pitanja
        characteristics = {
            "length": len(message),
            "has_code": bool(re.search(r'`.*?`|def\s+\w+|class\s+\w+', message)),
            "is_question": message.strip().endswith("?"),
            "complexity": self._calculate_complexity(message),
            "requests_example": any(word in message_lower for word in 
                                  ["primer", "pokaži", "demonstr", "kako izgleda"])
        }
        
        return {
            "topics": detected_topics,
            "skill_indicators": skill_scores,
            "characteristics": characteristics,
            "suggested_level": max(skill_scores, key=skill_scores.get)
        }
    
    def _calculate_complexity(self, message: str) -> float:
        """
        Računa složenost pitanja (0-10 skala).
        
        Args:
            message: Poruka za analizu
            
        Returns:
            Skor složenosti
        """
        score = 0.0
        
        # Dužina doprinosi složenosti
        if len(message) > 200:
            score += 2
        elif len(message) > 100:
            score += 1
        
        # Tehničke reči
        tech_words = ["algoritam", "struktur", "implement", "optimiz", 
                     "performans", "async", "thread", "memory"]
        tech_count = sum(1 for word in tech_words if word in message.lower())
        score += min(3, tech_count)
        
        # Više rečenica = veća složenost
        sentences = len(re.split(r'[.!?]+', message))
        if sentences > 3:
            score += 2
        elif sentences > 1:
            score += 1
        
        # Kod blokovi
        if re.search(r'```.*?```', message, re.DOTALL):
            score += 2
        
        return min(10, score)
    
    def analyze_conversation_history(
        self, 
        messages: List[str], 
        profile: UserProfile
    ) -> Dict[str, any]:
        """
        Analizira celu istoriju razgovora.
        
        Args:
            messages: Lista poruka korisnika
            profile: Korisnički profil
            
        Returns:
            Agregirana analiza
        """
        if not messages:
            return {}
        
        # Analiziraj svaku poruku
        analyses = [self.analyze_message(msg) for msg in messages]
        
        # Agregiraj teme
        all_topics = []
        for analysis in analyses:
            all_topics.extend(analysis["topics"])
        topic_counts = Counter(all_topics)
        
        # Prosečna složenost
        avg_complexity = sum(a["characteristics"]["complexity"] 
                           for a in analyses) / len(analyses)
        
        # Učestalost traženja primera
        example_rate = sum(1 for a in analyses 
                         if a["characteristics"]["requests_example"]) / len(analyses)
        
        # Preporučeni nivo na osnovu svih poruka
        skill_totals = {"beginner": 0, "intermediate": 0, "advanced": 0}
        for analysis in analyses:
            for level, score in analysis["skill_indicators"].items():
                skill_totals[level] += score
        
        recommended_level = max(skill_totals, key=skill_totals.get)
        
        return {
            "total_messages": len(messages),
            "top_topics": topic_counts.most_common(3),
            "average_complexity": avg_complexity,
            "example_request_rate": example_rate,
            "recommended_skill_level": recommended_level,
            "skill_confidence": skill_totals[recommended_level] / sum(skill_totals.values())
                               if sum(skill_totals.values()) > 0 else 0
        }
    
    def suggest_profile_updates(
        self, 
        profile: UserProfile, 
        recent_messages: List[str]
    ) -> List[Tuple[str, any]]:
        """
        Predlaže ažuriranja profila na osnovu skorašnje aktivnosti.
        
        Args:
            profile: Trenutni profil
            recent_messages: Poslednjih N poruka
            
        Returns:
            Lista (atribut, nova_vrednost) tuplova
        """
        suggestions = []
        
        if len(recent_messages) < 5:
            return suggestions  # Premalo podataka
        
        # Analiziraj skorašnje poruke
        analysis = self.analyze_conversation_history(recent_messages, profile)
        
        # Predlog za skill level
        if analysis["skill_confidence"] > 0.7:
            recommended = analysis["recommended_skill_level"]
            current = profile.skill_level.value
            
            if recommended != current:
                if recommended == "intermediate" and current == "beginner":
                    suggestions.append(("skill_level", SkillLevel.INTERMEDIATE))
                elif recommended == "advanced" and current == "intermediate":
                    suggestions.append(("skill_level", SkillLevel.ADVANCED))
        
        # Predlog za learning style
        if analysis["example_request_rate"] > 0.6:
            if profile.learning_style != LearningStyle.PRACTICAL:
                suggestions.append(("learning_style", LearningStyle.PRACTICAL))
        elif analysis["average_complexity"] > 7:
            if profile.learning_style != LearningStyle.THEORETICAL:
                suggestions.append(("learning_style", LearningStyle.THEORETICAL))
        
        # Predlog za response length
        avg_msg_length = sum(len(msg) for msg in recent_messages) / len(recent_messages)
        if avg_msg_length < 50 and profile.preferences.response_length != "short":
            suggestions.append(("preferences.response_length", "short"))
        elif avg_msg_length > 150 and profile.preferences.response_length != "long":
            suggestions.append(("preferences.response_length", "long"))
        
        return suggestions
    
    def generate_personalized_prompt_addon(
        self, 
        profile: UserProfile,
        current_topic: Optional[str] = None
    ) -> str:
        """
        Generiše personalizovan dodatak za system prompt.
        
        Args:
            profile: Korisnički profil
            current_topic: Trenutna tema razgovora
            
        Returns:
            Dodatak za system prompt
        """
        parts = []
        
        # Osnovno prilagođavanje nivou
        if profile.skill_level == SkillLevel.BEGINNER:
            parts.append(
                "Korisnik je početnik. Koristi jednostavne termine, "
                "daj detaljne korake i izbegavaj napredne koncepte."
            )
        elif profile.skill_level == SkillLevel.INTERMEDIATE:
            parts.append(
                "Korisnik ima osnovno znanje. Možeš koristiti tehničke termine "
                "ali ih objasni kada su novi. Fokusiraj se na praktičnu primenu."
            )
        else:  # ADVANCED
            parts.append(
                "Korisnik je napredan. Možeš koristiti složene koncepte, "
                "govoriti o optimizaciji i arhitekturi bez detaljnih objašnjenja osnova."
            )
        
        # Prilagođavanje stilu učenja
        if profile.learning_style == LearningStyle.VISUAL:
            parts.append("Koristi ASCII dijagrame i vizuelne reprezentacije kad god je moguće.")
        elif profile.learning_style == LearningStyle.PRACTICAL:
            parts.append("Fokusiraj se na praktične primere koda koje korisnik može odmah isprobati.")
        elif profile.learning_style == LearningStyle.THEORETICAL:
            parts.append("Objasni teorijske osnove i razloge zašto nešto funkcioniše kako funkcioniše.")
        
        # Dodaj preference
        parts.append(profile.preferences.to_system_prompt_addon())
        
        # Kontekstualne informacije
        if current_topic and current_topic in profile.topics_count:
            times = profile.topics_count[current_topic]
            if times > 5:
                parts.append(f"Korisnik je već postavljao pitanja o ovoj temi {times} puta, "
                           "tako da možeš graditi na prethodnom znanju.")
        
        # Personalizovani pozdrav
        if profile.total_questions < 5:
            parts.append("Korisnik je nov, budi posebno ljubazan i ohrabrujući.")
        elif profile.total_questions > 50:
            parts.append(f"Pozdravi korisnika kao 'dragi {profile.username}' - već se dobro poznajete.")
        
        return " ".join(parts)

4. src/personalization/adaptive_engine.py

"""
Adaptive Learning Engine za Učitelja Vasu
Automatski prilagođava ponašanje tokom razgovora
"""

from typing import List, Dict, Optional, Tuple
from datetime import datetime
import json

from .user_profile import UserProfile, SkillLevel
from .profile_analyzer import ProfileAnalyzer


class AdaptiveEngine:
    """Engine koji dinamički prilagođava AI ponašanje."""
    
    def __init__(self):
        self.analyzer = ProfileAnalyzer()
        self.session_data = {
            "confusion_indicators": 0,
            "understanding_indicators": 0,
            "questions_asked": 0,
            "topics_covered": set(),
            "adaptations_made": []
        }
    
    def analyze_user_response(self, response: str) -> Dict[str, any]:
        """
        Analizira korisnikov odgovor na AI objašnjenje.
        
        Args:
            response: Korisnička poruka
            
        Returns:
            Analiza sa indikatorima razumevanja
        """
        response_lower = response.lower()
        
        # Indikatori konfuzije
        confusion_words = [
            "ne razumem", "nije jasno", "zbunjuje", "komplikovano",
            "možeš li ponovo", "ne kapiram", "šta", "kako to",
            "zašto baš tako", "previše informacija"
        ]
        
        # Indikatori razumevanja
        understanding_words = [
            "razumem", "jasno", "ima smisla", "okej", "važi",
            "super", "hvala", "shvatam", "logično", "aha"
        ]
        
        # Follow-up pitanja
        is_followup = "?" in response and len(response) < 100
        
        # Brojanje indikatora
        confusion_count = sum(1 for word in confusion_words if word in response_lower)
        understanding_count = sum(1 for word in understanding_words if word in response_lower)
        
        # Ažuriraj session data
        self.session_data["confusion_indicators"] += confusion_count
        self.session_data["understanding_indicators"] += understanding_count
        
        return {
            "shows_confusion": confusion_count > 0,
            "shows_understanding": understanding_count > 0,
            "is_followup_question": is_followup,
            "confidence_score": self._calculate_confidence_score()
        }
    
    def _calculate_confidence_score(self) -> float:
        """Računa skor poverenja korisnika (0-1)."""
        total = (self.session_data["confusion_indicators"] + 
                self.session_data["understanding_indicators"])
        
        if total == 0:
            return 0.5  # Neutralno
        
        return self.session_data["understanding_indicators"] / total
    
    def suggest_adaptation(
        self, 
        profile: UserProfile,
        last_response_analysis: Dict[str, any]
    ) -> Optional[Dict[str, any]]:
        """
        Predlaže prilagođavanje na osnovu analize.
        
        Args:
            profile: Korisnički profil
            last_response_analysis: Analiza poslednjeg odgovora
            
        Returns:
            Predlog prilagođavanja ili None
        """
        if last_response_analysis["shows_confusion"]:
            # Korisnik je zbunjen
            if profile.skill_level == SkillLevel.BEGINNER:
                return {
                    "action": "simplify",
                    "suggestion": "Koristi još jednostavnije objašnjenje sa analogijom",
                    "prompt_addon": "Objasni ponovo, ali još jednostavnije. "
                                  "Koristi analogiju iz svakodnevnog života."
                }
            else:
                return {
                    "action": "clarify",
                    "suggestion": "Razloži na korake",
                    "prompt_addon": "Razloži objašnjenje na numerisane korake."
                }
        
        elif last_response_analysis["is_followup_question"]:
            # Dublje objašnjenje
            return {
                "action": "elaborate",
                "suggestion": "Daj detaljnije objašnjenje",
                "prompt_addon": "Daj detaljnije objašnjenje sa fokusom na pitanje korisnika."
            }
        
        elif last_response_analysis["confidence_score"] > 0.8:
            # Korisnik dobro razume
            if self.session_data["questions_asked"] > 5:
                return {
                    "action": "advance",
                    "suggestion": "Pređi na naprednije koncepte",
                    "prompt_addon": "Korisnik dobro razume. Možeš preći na naprednije aspekte."
                }
        
        return None
    
    def apply_adaptation(
        self,
        adaptation: Dict[str, any],
        original_prompt: str
    ) -> str:
        """
        Primenjuje prilagođavanje na prompt.
        
        Args:
            adaptation: Predlog prilagođavanja
            original_prompt: Originalni prompt
            
        Returns:
            Prilagođen prompt
        """
        # Zapamti prilagođavanje
        self.session_data["adaptations_made"].append({
            "time": datetime.now().isoformat(),
            "action": adaptation["action"]
        })
        
        # Primeni na prompt
        return f"{original_prompt}\n\n[PRILAGOĐAVANJE: {adaptation['prompt_addon']}]"
    
    def generate_session_summary(self) -> Dict[str, any]:
        """Generiše rezime sesije za čuvanje u profilu."""
        confidence = self._calculate_confidence_score()
        
        return {
            "duration_questions": self.session_data["questions_asked"],
            "final_confidence": confidence,
            "topics_covered": list(self.session_data["topics_covered"]),
            "adaptations_count": len(self.session_data["adaptations_made"]),
            "recommendation": self._generate_recommendation(confidence)
        }
    
    def _generate_recommendation(self, confidence: float) -> str:
        """Generiše preporuku za dalji rad."""
        if confidence < 0.3:
            return "Preporučujem dodatno vežbanje osnova pre novih tema."
        elif confidence < 0.7:
            return "Solidno napredovanje, nastavi trenutnim tempom."
        else:
            return "Odlično razumevanje! Spreman si za naprednije teme."
    
    def reset_session(self):
        """Resetuje session podatke za novi razgovor."""
        self.session_data = {
            "confusion_indicators": 0,
            "understanding_indicators": 0,
            "questions_asked": 0,
            "topics_covered": set(),
            "adaptations_made": []
        }

5. Ažuriran src/ai_services/base_service.py

Dodajte ovu metodu u postojeću BaseAIService klasu:

# Na početak fajla dodajte import:
import re

# U klasu BaseAIService dodajte ovu metodu:
def pozovi_ai_personalizovano(
    self,
    poruka: str,
    profile: 'UserProfile',
    base_system_prompt: str
) -> str:
    """
    Poziva AI sa personalizovanim podešavanjima.
    
    Args:
        poruka: Korisnikova poruka
        profile: Korisnički profil
        base_system_prompt: Osnovni system prompt
        
    Returns:
        Personalizovan AI odgovor
    """
    # Import ovde da izbegnemo ciklične importe
    from personalization.user_profile import UserProfile
    from personalization.profile_analyzer import ProfileAnalyzer
    
    # Generiši personalizovan system prompt
    analyzer = ProfileAnalyzer()
    
    # Detektuj temu trenutnog pitanja
    message_analysis = analyzer.analyze_message(poruka)
    current_topic = message_analysis["topics"][0] if message_analysis["topics"] else None
    
    # Dodaj personalizaciju na base prompt
    personalized_addon = analyzer.generate_personalized_prompt_addon(profile, current_topic)
    full_system_prompt = f"{base_system_prompt}\n\n{personalized_addon}"
    
    # Prilagodi parametre prema profilu
    original_settings = self.get_current_settings()
    
    # Prilagodi temperature prema skill level
    if profile.skill_level.value == "beginner":
        self.apply_settings({"temperature": 0.5})  # Konzistentniji odgovori
    elif profile.skill_level.value == "advanced":
        self.apply_settings({"temperature": 0.8})  # Kreativniji odgovori
    
    # Prilagodi max_tokens prema preferencama
    if profile.preferences.response_length == "short":
        self.apply_settings({"max_tokens": 100})
    elif profile.preferences.response_length == "long":
        self.apply_settings({"max_tokens": 300})
    
    try:
        # Pozovi AI sa personalizovanim postavkama
        response = self.pozovi_ai(poruka, full_system_prompt)
        
        # Post-procesiranje prema preferencama
        if not profile.preferences.code_examples and "```" in response:
            # Ukloni code blokove ako korisnik ne želi primere
            response = re.sub(r'```[\s\S]*?```', '[kod primer uklonjen]', response)
        
        return response
        
    finally:
        # Vrati originalne postavke
        self.apply_settings(original_settings)

6. Kompletni ažurirani main.py

"""
Glavni program za Učitelja Vasu
Sa podrškom za profilisanje, optimizaciju i personalizaciju
"""

# Dodaj src folder u Python path
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

import re
from vasa_core import pozdrav, predstavi_se, VASA_LICNOST
from ai_simulator import simuliraj_ai_odgovor
from utils.config import Config
from utils.performance_tracker import tracker
from utils.optimization_profiles import profile_manager as optimization_manager, ProfileType
from utils.ai_benchmark import AIBenchmark
from ai_services.ai_factory import AIServiceFactory
from ai_services.base_service import BaseAIService
from typing import Optional

# Resilience importi
from utils.circuit_breaker import get_all_circuits_status, CircuitOpenError
from utils.fallback_manager import fallback_manager
from utils.retry_handler import smart_retry

# Personalizacija importi - sa preimenovanjem da izbegnemo konflikte
from personalization.user_profile import profile_manager as user_profile_manager, SkillLevel, LearningStyle
from personalization.profile_analyzer import ProfileAnalyzer
from personalization.adaptive_engine import AdaptiveEngine

# Globalne varijable
ai_service: Optional[BaseAIService] = None
optimization_profile: Optional[ProfileType] = None  # Za optimizacione profile
current_user_profile = None  # Za korisničke profile
conversation_history = []
analyzer = ProfileAnalyzer()
adaptive_engine = AdaptiveEngine()


def dobrodoslica_i_profil():
    """Pozdravlja korisnika i učitava/kreira profil."""
    global current_user_profile

    print("\n" + "🎓" * 25)
    print("Dobrodošao u Učitelja Vasu - tvog personalnog AI asistenta!")
    print("🎓" * 25 + "\n")

    # Prikaži postojeće profile
    existing_profiles = user_profile_manager.list_all_profiles()

    if existing_profiles:
        print("📚 Postojeći profili:")
        for i, username in enumerate(existing_profiles, 1):
            print(f"   {i}. {username}")
        print(f"   {len(existing_profiles) + 1}. Kreiraj novi profil")

        while True:
            izbor = input("\nIzaberi opciju (broj): ").strip()
            try:
                idx = int(izbor) - 1
                if 0 <= idx < len(existing_profiles):
                    username = existing_profiles[idx]
                    current_user_profile = user_profile_manager.get_or_create_profile(username)
                    break
                elif idx == len(existing_profiles):
                    # Novi profil
                    username = input("\nUnesi svoje ime: ").strip()
                    if username:
                        current_user_profile = user_profile_manager.get_or_create_profile(username)
                        postavi_pocetne_preference()
                        break
            except ValueError:
                print("❌ Molim te unesi broj.")
    else:
        print("🆕 Izgleda da si nov ovde!")
        username = input("Kako se zoveš? ").strip()
        if username:
            current_user_profile = user_profile_manager.get_or_create_profile(username)
            postavi_pocetne_preference()

    # Prikaži personalizovan pozdrav
    if current_user_profile:
        print(f"\n✨ Zdravo {current_user_profile.username}!")
        print(user_profile_manager.get_profile_summary(current_user_profile.username))


def postavi_pocetne_preference():
    """Postavlja početne preference za novog korisnika."""
    global current_user_profile

    print("\n🎯 Hajde da podesimo tvoje preference!")
    print("=" * 50)

    # Nivo znanja
    print("\n📚 Koji je tvoj nivo programiranja?")
    print("1. Početnik - tek počinjem")
    print("2. Srednji - znam osnove")
    print("3. Napredni - imam iskustva")

    while True:
        nivo = input("\nTvoj izbor (1-3): ").strip()
        if nivo == "1":
            current_user_profile.skill_level = SkillLevel.BEGINNER
            break
        elif nivo == "2":
            current_user_profile.skill_level = SkillLevel.INTERMEDIATE
            break
        elif nivo == "3":
            current_user_profile.skill_level = SkillLevel.ADVANCED
            break

    # Stil učenja
    print("\n🎨 Kako najlakše učiš?")
    print("1. Kroz praktične primere koda")
    print("2. Kroz detaljne tekstualne opise")
    print("3. Kroz dijagrame i vizuelne prikaze")
    print("4. Kroz teorijske koncepte")

    while True:
        stil = input("\nTvoj izbor (1-4): ").strip()
        if stil == "1":
            current_user_profile.learning_style = LearningStyle.PRACTICAL
            break
        elif stil == "2":
            current_user_profile.learning_style = LearningStyle.TEXTUAL
            break
        elif stil == "3":
            current_user_profile.learning_style = LearningStyle.VISUAL
            break
        elif stil == "4":
            current_user_profile.learning_style = LearningStyle.THEORETICAL
            break

    # Dužina odgovora
    print("\n📏 Kakve odgovore preferiraš?")
    print("1. Kratke i koncizne")
    print("2. Umerene dužine")
    print("3. Detaljne i opširne")

    while True:
        duzina = input("\nTvoj izbor (1-3): ").strip()
        if duzina == "1":
            current_user_profile.preferences.response_length = "short"
            break
        elif duzina == "2":
            current_user_profile.preferences.response_length = "medium"
            break
        elif duzina == "3":
            current_user_profile.preferences.response_length = "long"
            break

    # Sačuvaj profil
    user_profile_manager.save_profile(current_user_profile)
    print("\n✅ Tvoje preference su sačuvane!")


def postavi_pitanje_vasi(pitanje: str, auto_optimize: bool = True) -> str:
    """
    Postavlja pitanje Vasi sa personalizacijom i optimizacijom.
    
    Args:
        pitanje: Korisnikovo pitanje
        auto_optimize: Da li automatski optimizovati postavke
        
    Returns:
        AI odgovor
    """
    global optimization_profile, current_user_profile, conversation_history
    
    if not ai_service:
        # Fallback na simulaciju
        print("🎭 [Koristim simulaciju...]")
        return simuliraj_ai_odgovor(pitanje)
    
    # Ažuriraj korisničku aktivnost ako postoji profil
    topic = None
    if current_user_profile:
        conversation_history.append(pitanje)
        message_analysis = analyzer.analyze_message(pitanje)
        topic = message_analysis["topics"][0] if message_analysis["topics"] else None
        current_user_profile.update_activity(topic)
        
        # Proveri da li treba prilagoditi tokom razgovora
        if len(conversation_history) > 1:
            # Analiziraj poslednji odgovor korisnika
            response_analysis = adaptive_engine.analyze_user_response(pitanje)
            adaptation = adaptive_engine.suggest_adaptation(current_user_profile, response_analysis)
            
            if adaptation:
                print(f"\n💡 [Prilagođavam: {adaptation['suggestion']}]")
    
    # Počni sa osnovnim system promptom
    system_prompt = VASA_LICNOST
    
    # Dodaj personalizaciju ako postoji korisnički profil
    if current_user_profile:
        addon = analyzer.generate_personalized_prompt_addon(
            current_user_profile,
            topic
        )
        system_prompt += "\n\n" + addon
    
    # Dodaj optimizacioni profil ako je omogućen
    if auto_optimize:
        suggested_profile = optimization_manager.analyze_question(pitanje)
        profile_info = optimization_manager.get_profile(suggested_profile)
        print(f"📋 [Koristim optimizacioni profil: {profile_info.name}]")
        
        settings = optimization_manager.apply_profile(
            suggested_profile,
            ai_service.get_current_settings()
        )
        ai_service.apply_settings(settings)
        optimization_profile = suggested_profile
        
        system_prompt += profile_info.system_prompt_addon
    
    # Pozovi AI
    print(f"🤖 [Koristim {Config.AI_PROVIDER.upper()} AI model...]")
    
    try:
        # Koristi personalizovan poziv ako je dostupan
        if current_user_profile and hasattr(ai_service, 'pozovi_ai_personalizovano'):
            return ai_service.pozovi_ai_personalizovano(
                pitanje,
                current_user_profile,
                system_prompt
            )
        else:
            return ai_service.pozovi_ai(pitanje, system_prompt=system_prompt)
    except Exception as e:
        print(f"\n⚠️ Greška pri pozivu AI servisa: {e}")
        return simuliraj_ai_odgovor(pitanje)


def prikazi_i_uredi_profil():
    """Prikazuje i omogućava uređivanje profila."""
    global current_user_profile

    if not current_user_profile:
        print("❌ Nema učitanog profila!")
        return

    while True:
        print("\n" + user_profile_manager.get_profile_summary(current_user_profile.username))

        print("\n📝 OPCIJE:")
        print("1. Promeni nivo znanja")
        print("2. Promeni stil učenja")
        print("3. Promeni dužinu odgovora")
        print("4. Vidi moje dostignuća")
        print("5. Analiza napretka")
        print("6. Nazad")

        izbor = input("\nTvoj izbor: ").strip()

        if izbor == "1":
            print("\nTrenutni nivo:", current_user_profile.skill_level.to_serbian())
            print("1. Početnik")
            print("2. Srednji")
            print("3. Napredni")

            novi_nivo = input("Novi nivo (1-3): ").strip()
            if novi_nivo == "1":
                current_user_profile.skill_level = SkillLevel.BEGINNER
            elif novi_nivo == "2":
                current_user_profile.skill_level = SkillLevel.INTERMEDIATE
            elif novi_nivo == "3":
                current_user_profile.skill_level = SkillLevel.ADVANCED

            try:
                user_profile_manager.save_profile(current_user_profile)
                print("✅ Nivo ažuriran!")
            except Exception as e:
                print(f"⚠️ Greška pri čuvanju: {e}")

        elif izbor == "2":
            print("\nTrenutni stil:", current_user_profile.learning_style.to_serbian())
            print("1. Praktični")
            print("2. Tekstualni")
            print("3. Vizuelni")
            print("4. Teorijski")

            novi_stil = input("Novi stil (1-4): ").strip()
            if novi_stil == "1":
                current_user_profile.learning_style = LearningStyle.PRACTICAL
            elif novi_stil == "2":
                current_user_profile.learning_style = LearningStyle.TEXTUAL
            elif novi_stil == "3":
                current_user_profile.learning_style = LearningStyle.VISUAL
            elif novi_stil == "4":
                current_user_profile.learning_style = LearningStyle.THEORETICAL

            try:
                user_profile_manager.save_profile(current_user_profile)
                print("✅ Stil učenja ažuriran!")
            except Exception as e:
                print(f"⚠️ Greška pri čuvanju: {e}")

        elif izbor == "3":
            print("\nTrenutna dužina:", current_user_profile.preferences.response_length)
            print("1. Kratki odgovori")
            print("2. Srednji odgovori")
            print("3. Dugi odgovori")

            nova_duzina = input("Nova dužina (1-3): ").strip()
            if nova_duzina == "1":
                current_user_profile.preferences.response_length = "short"
            elif nova_duzina == "2":
                current_user_profile.preferences.response_length = "medium"
            elif nova_duzina == "3":
                current_user_profile.preferences.response_length = "long"

            try:
                user_profile_manager.save_profile(current_user_profile)
                print("✅ Preferenca dužine ažurirana!")
            except Exception as e:
                print(f"⚠️ Greška pri čuvanju: {e}")

        elif izbor == "4":
            print("\n🏆 TVOJA DOSTIGNUĆA:")
            if current_user_profile.achievements:
                for achievement in current_user_profile.achievements:
                    print(f"   ⭐ {achievement}")
            else:
                print("   Nemaš još dostignuća - nastavi da učiš!")

        elif izbor == "5":
            # Analiza napretka
            if conversation_history:
                analysis = analyzer.analyze_conversation_history(
                    conversation_history[-10:],  # Poslednjih 10 poruka
                    current_user_profile
                )

                print("\n📈 ANALIZA NAPRETKA:")
                print(f"Prosečna složenost pitanja: {analysis['average_complexity']:.1f}/10")
                print(f"Najčešće teme: ", end="")
                for topic, count in analysis['top_topics']:
                    print(f"{topic} ({count}x), ", end="")
                print()

                # Proveri da li treba level up
                if current_user_profile.should_level_up():
                    print("\n🎉 ČESTITAM! Spreman si za viši nivo!")
                    current_user_profile.level_up()
                    try:
                        user_profile_manager.save_profile(current_user_profile)
                    except Exception as e:
                        print(f"⚠️ Greška pri čuvanju napretka: {e}")

        elif izbor == "6":
            break


def inicijalizuj_ai_servis():
    """Pokušava da kreira resilient AI servis."""
    global ai_service

    print("\n🔧 Inicijalizujem AI servis sa naprednom zaštitom...")

    try:
        # Koristi resilient factory
        ai_service = AIServiceFactory.create_resilient_service()

        print(f"✅ {Config.AI_PROVIDER.upper()} servis pokrenut sa:")
        print("   ✓ Retry logikom (automatski pokušaji)")
        print("   ✓ Circuit breaker zaštitom")
        print("   ✓ Fallback strategijama")
        print("   ✓ Graceful degradation podrškom")

        # Test da li radi
        if ai_service.test_konekcija():
            print("   ✓ Konekcija stabilna!")
        else:
            print("   ⚠️ Konekcija nestabilna, ali sistem će pokušati da radi")

        return True

    except Exception as e:
        print(f"⚠️ Problem pri inicijalizaciji: {e}")
        print("📌 Sistem će raditi u degradiranom režimu")

        # Čak i ako inicijalizacija ne uspe, imamo degraded servis
        from ai_services.ai_factory import DegradedAIService
        ai_service = DegradedAIService()

        return False


def prikazi_sistem_zdravlje():
    """Prikazuje zdravlje i status svih resilience komponenti."""
    print("\n🏥 ZDRAVLJE SISTEMA")
    print("=" * 60)

    # Circuit breakers status
    print("\n" + get_all_circuits_status())

    # Fallback statistike
    print(fallback_manager.get_health_report())

    # Retry statistike
    if hasattr(ai_service, '_circuit_breaker_call'):
        cb = ai_service._circuit_breaker_call.circuit_breaker
        print(f"📊 Pouzdanost glavnog servisa: {100 - cb.stats.get_failure_rate():.1f}%")

    # Degradacija status
    if hasattr(ai_service, 'get_current_settings'):
        settings = ai_service.get_current_settings()
        if settings.get('status') == 'limited_functionality':
            print("\n⚠️ UPOZORENJE: Sistem radi u DEGRADIRANOM režimu!")
            print("   Funkcionalnosti su ograničene.")


def prikazi_performanse():
    """Prikazuje statistiku performansi."""
    print("\n" + tracker.compare_providers())

    # Prikaži preporuke
    recommendations = tracker.get_recommendations()
    if recommendations:
        print("💡 PREPORUKE NA OSNOVU ANALIZE:")
        for scenario, rec in recommendations.items():
            print(f"   • {scenario.replace('_', ' ').title()}: {rec}")


def upravljanje_profilima():
    """Omogućava upravljanje optimizacionim profilima."""
    while True:
        print("\n🎯 UPRAVLJANJE OPTIMIZACIONIM PROFILIMA")
        print("=" * 50)
        print(optimization_manager.list_profiles())

        print("Opcije:")
        print("1. Testiraj profil sa prilagođenim pitanjem")
        print("2. Uporedi profile")
        print("3. Vrati se u glavni meni")

        izbor = input("\nTvoj izbor: ").strip()

        if izbor == "1":
            print("\nIzaberi profil (1-7): ", end="")
            try:
                profile_idx = int(input().strip()) - 1
                profile_type = list(ProfileType)[profile_idx]

                print(f"\nUnesi pitanje za testiranje: ", end="")
                test_pitanje = input().strip()

                if test_pitanje:
                    # Primeni profil i testiraj
                    settings = optimization_manager.apply_profile(
                        profile_type,
                        ai_service.get_current_settings()
                    )
                    ai_service.apply_settings(settings)

                    profile_info = optimization_manager.get_profile(profile_type)
                    modified_prompt = VASA_LICNOST + profile_info.system_prompt_addon
                    
                    odgovor = ai_service.pozovi_ai(test_pitanje, modified_prompt)

                    print(f"\n🤖 Odgovor sa profilom '{profile_info.name}':")
                    print(odgovor)

            except (ValueError, IndexError):
                print("❌ Nevaljan izbor profila.")

        elif izbor == "2":
            print("\nUnesi pitanje za poređenje: ", end="")
            test_pitanje = input().strip()

            if test_pitanje and ai_service:
                print("\n📊 POREĐENJE PROFILA")
                print("=" * 50)

                original_settings = ai_service.get_current_settings()

                for profile_type in [ProfileType.QUICK_ANSWER,
                                   ProfileType.DETAILED_EXPLANATION]:
                    profile = optimization_manager.get_profile(profile_type)

                    # Primeni profil
                    settings = optimization_manager.apply_profile(
                        profile_type,
                        original_settings
                    )
                    ai_service.apply_settings(settings)

                    print(f"\n🎯 {profile.name}:")
                    print(f"   Temperature: {settings['temperature']}")
                    print(f"   Max tokens: {settings['max_tokens']}")

                    # Dobij odgovor
                    modified_prompt = VASA_LICNOST + profile.system_prompt_addon
                    odgovor = ai_service.pozovi_ai(test_pitanje, modified_prompt)

                    print(f"   Odgovor ({len(odgovor)} karaktera):")
                    print(f"   {odgovor[:200]}..." if len(odgovor) > 200 else f"   {odgovor}")

                # Vrati originalne postavke
                ai_service.apply_settings(original_settings)

        elif izbor == "3":
            break
        else:
            print("❌ Nepoznata opcija.")


def pokreni_benchmark():
    """Pokreće benchmark testiranje."""
    print("\n🏁 BENCHMARK TESTIRANJE")
    print("=" * 50)

    if not (Config.OPENAI_API_KEY and Config.GEMINI_API_KEY):
        print("❌ Za benchmark su potrebna oba API ključa!")
        print("   Trenutno imaš:")
        if Config.OPENAI_API_KEY:
            print("   ✓ OpenAI")
        if Config.GEMINI_API_KEY:
            print("   ✓ Gemini")
        return

    print("⚠️  Benchmark će pokrenuti seriju testova na oba servisa.")
    print("   Ovo može potrajati nekoliko minuta.")
    print("\nDa li želiš da nastaviš? (da/ne): ", end="")

    if input().strip().lower() in ['da', 'd', 'yes', 'y']:
        benchmark = AIBenchmark()
        results_file = benchmark.run_full_benchmark()

        if results_file:
            print(f"\n📁 Detaljni rezultati sačuvani u: {results_file}")


def kontinuirani_razgovor():
    """Omogućava kontinuiranu konverzaciju sa Učiteljem Vasom."""
    print("\n💬 KONTINUIRANI RAZGOVOR SA UČITELJEM VASOM")
    print("=" * 50)
    print("Sada možeš da razgovaraš sa mnom kao sa pravim učiteljem!")
    print("Pamtiću kontekst našeg razgovora.")
    print("Kucaj 'izlaz' ili 'exit' kada želiš da završiš razgovor.\n")

    # Lokalna istorija za kontinuirani razgovor
    local_conversation_history = []

    while True:
        # Korisnikov unos
        pitanje = input("👤 Ti: ").strip()

        # Proveri da li korisnik želi da izađe
        if pitanje.lower() in ['izlaz', 'exit', 'kraj', 'quit']:
            print("\n👋 Hvala na razgovoru! Vraćam te u glavni meni.\n")
            
            # Sačuvaj sesiju ako je bila korisna
            if len(local_conversation_history) > 2 and current_user_profile:
                summary = adaptive_engine.generate_session_summary()
                print(f"📊 Rezime sesije: {summary['recommendation']}")
                adaptive_engine.reset_session()
            break

        if not pitanje:
            print("💭 Molim te, postavi pitanje ili napiši komentar.\n")
            continue

        # Dodaj korisnikovo pitanje u lokalnu istoriju
        local_conversation_history.append({
            "role": "user",
            "content": pitanje
        })

        print("\n🤖 Učitelj Vasa: ", end="", flush=True)

        try:
            if ai_service:
                # Pripremi system prompt sa kontekstom
                system_prompt_with_context = VASA_LICNOST
                
                # Dodaj personalizaciju ako postoji
                if current_user_profile:
                    addon = analyzer.generate_personalized_prompt_addon(
                        current_user_profile,
                        None  # Tema će biti detektovana iz pitanja
                    )
                    system_prompt_with_context += "\n\n" + addon
                
                system_prompt_with_context += "\n\nVodi računa o kontekstu prethodnog razgovora."

                # Koristi istoriju razgovora
                odgovor = ai_service.pozovi_sa_istorijom([
                    {"role": "system", "content": system_prompt_with_context},
                    *local_conversation_history
                ])

                # Dodaj Vasin odgovor u lokalnu istoriju
                local_conversation_history.append({
                    "role": "assistant",
                    "content": odgovor
                })

                # Ograniči istoriju na poslednjih 10 razmena (20 poruka)
                if len(local_conversation_history) > 20:
                    local_conversation_history = local_conversation_history[-20:]

                # Ažuriraj globalnu istoriju za analizu
                if current_user_profile:
                    conversation_history.append(pitanje)

            else:
                # Fallback na simulaciju
                odgovor = simuliraj_ai_odgovor(pitanje)

            print(odgovor)

        except Exception as e:
            print(f"\n❌ Greška: {e}")
            print("Pokušaj ponovo sa drugim pitanjem.")

        print()  # Prazan red za preglednost


def prikazi_ai_status():
    """Prikazuje trenutni status AI servisa."""
    print("\n🔍 STATUS AI SERVISA")
    print("=" * 50)

    # Trenutni provider
    print(f"📡 Trenutni provider: {Config.AI_PROVIDER.upper()}")

    # Status servisa
    if ai_service:
        print("✅ AI servis je aktivan")

        # Trenutne postavke
        settings = ai_service.get_current_settings()
        print(f"🤖 Model: {settings.get('model', 'nepoznat')}")
        print(f"🌡️ Temperature: {settings.get('temperature', 'N/A')}")
        print(f"📏 Max tokena: {settings.get('max_tokens', 'N/A')}")

        # Test konekcije
        print("\n🔌 Testiram konekciju...")
        if ai_service.test_konekcija():
            print("✅ Konekcija sa AI servisom je stabilna!")
        else:
            print("❌ Problem sa konekcijom. Proveri API ključ i internet vezu.")
    else:
        print("❌ AI servis nije aktivan")
        print("📚 Koristim simulaciju umesto pravog AI-ja")

    # Dostupni provideri
    print("\n📋 Dostupni provideri:")
    if Config.OPENAI_API_KEY:
        print("   ✓ OpenAI")
    else:
        print("   ✗ OpenAI (nedostaje API ključ)")

    if Config.GEMINI_API_KEY:
        print("   ✓ Gemini")
    else:
        print("   ✗ Gemini (nedostaje API ključ)")

    print()  # Prazan red


def promeni_ai_servis():
    """Omogućava promenu AI servisa tokom rada."""
    global ai_service

    print("\n🔄 PROMENA AI SERVISA")
    print("=" * 50)

    # Prikaži trenutni servis
    print(f"Trenutno koristiš: {Config.AI_PROVIDER.upper()}")

    # Proveri dostupne opcije
    dostupni = []
    if Config.OPENAI_API_KEY:
        dostupni.append("openai")
    if Config.GEMINI_API_KEY:
        dostupni.append("gemini")

    if len(dostupni) < 2:
        print("\n⚠️ Nemaš konfigurisan drugi AI servis!")
        print("Potreban ti je API ključ za oba servisa da bi mogao da menjaš između njih.")
        return

    # Ponudi opcije
    print("\nDostupni servisi:")
    for i, servis in enumerate(dostupni, 1):
        print(f"{i}. {servis.upper()}")

    # Zatraži izbor
    try:
        izbor = input("\nIzaberi servis (broj): ").strip()
        idx = int(izbor) - 1

        if 0 <= idx < len(dostupni):
            novi_servis = dostupni[idx]

            if novi_servis == Config.AI_PROVIDER:
                print("ℹ️ Već koristiš taj servis!")
                return

            # Promeni servis
            Config.AI_PROVIDER = novi_servis

            # Resetuj factory (forsiraj novo kreiranje)
            AIServiceFactory.reset()

            # Kreiraj novi servis
            print(f"\n🔄 Prebacujem na {novi_servis.upper()}...")
            try:
                ai_service = AIServiceFactory.create_resilient_service()
                print(f"✅ Uspešno prebačeno na {novi_servis.upper()}!")

                # Test konekcije
                if ai_service.test_konekcija():
                    print("✅ Novi servis radi perfektno!")
                else:
                    print("⚠️ Servis je kreiran ali konekcija nije stabilna.")

            except Exception as e:
                print(f"❌ Greška pri prebacivanju: {e}")
                print("Vraćam se na prethodni servis...")
                # Vrati na stari servis ako ne uspe
                Config.AI_PROVIDER = "openai" if novi_servis == "gemini" else "gemini"
                AIServiceFactory.reset()
                ai_service = AIServiceFactory.get_service()
        else:
            print("❌ Nevaljan izbor!")

    except ValueError:
        print("❌ Molim te unesi broj!")
    except Exception as e:
        print(f"❌ Greška: {e}")


def glavni_meni():
    """Vraća glavni meni sa personalizacijom."""
    ime = current_user_profile.username if current_user_profile else "Korisniče"

    meni = f"""
Zdravo {ime}! Šta želiš da uradiš?
1. Pozdravi me
2. Predstavi se
3. Postavi pitanje Učitelju Vasi
4. Razgovaraj sa Vasom (kontinuirani mod)
5. Proveri AI status
6. Promeni AI servis
7. 📊 Prikaži performanse
8. 🎯 Upravljaj optimizacionim profilima
9. 🏁 Pokreni benchmark
10. 👤 Moj profil
11. 🏥 Zdravlje sistema
12. Izađi

Tvoj izbor: """
    return meni


def pokreni_vasu():
    """Pokreće glavnu petlju programa Učitelj Vasa."""
    # Inicijalizuj AI servis
    ai_dostupan = inicijalizuj_ai_servis()
    
    # Pozovi dobrodošlicu i učitaj profil
    dobrodoslica_i_profil()

    print("\n" + "🎓" * 25)
    print(pozdrav())
    if ai_dostupan:
        provider_info = {
            'openai': "✨ Povezan sa OpenAI GPT - najpoznatiji AI model!",
            'gemini': "✨ Povezan sa Google Gemini - moćan i besplatan!"
        }
        print(provider_info.get(Config.AI_PROVIDER.lower(), "✨ AI je spreman!"))
        print("🎯 Automatska optimizacija je UKLJUČENA")
    else:
        print("📚 Radim u offline modu sa simulacijom.")
    print("🎓" * 25 + "\n")

    # Glavna petlja programa
    while True:
        print(glavni_meni())
        izbor = input().strip()

        if izbor == "1":
            print("\n" + pozdrav() + "\n")

        elif izbor == "2":
            print("\n" + predstavi_se() + "\n")

        elif izbor == "3":
            print("\n💭 Postavi mi bilo koje pitanje o programiranju:")
            pitanje = input("👤 Ti: ").strip()
            if pitanje:
                print("\n🤖 Učitelj Vasa: ", end="", flush=True)
                odgovor = postavi_pitanje_vasi(pitanje)
                print(odgovor)

                # Prikaži metrike ako postoje
                if optimization_profile and ai_service:
                    settings = ai_service.get_current_settings()
                    print(f"\n📊 [Parametri: temp={settings['temperature']}, "
                         f"max_tokens={settings['max_tokens']}]")
            else:
                print("\n❌ Nisi uneo pitanje.")

        elif izbor == "4":
            kontinuirani_razgovor()

        elif izbor == "5":
            prikazi_ai_status()

        elif izbor == "6":
            promeni_ai_servis()

        elif izbor == "7":
            prikazi_performanse()

        elif izbor == "8":
            upravljanje_profilima()

        elif izbor == "9":
            pokreni_benchmark()
            
        elif izbor == "10":
            prikazi_i_uredi_profil()
            
        elif izbor == "11":
            prikazi_sistem_zdravlje()

        elif izbor == "12":
            print("\nHvala što si koristio Učitelja Vasu! ")
            print("Nastavi sa učenjem i ne zaboravi - svaki ekspert je nekad bio početnik! 🌟")

            # Sačuvaj profil pre izlaska
            if current_user_profile:
                try:
                    user_profile_manager.save_profile(current_user_profile)
                    print(f"\n✅ Profil '{current_user_profile.username}' je sačuvan.")
                except Exception as e:
                    print(f"\n⚠️ Greška pri čuvanju profila: {e}")

            # Prikaži finalne statistike ako postoje
            if ai_service and len(tracker.all_metrics) > 0:
                print("\n📊 FINALNE STATISTIKE SESIJE:")
                print(tracker.compare_providers())

            break

        else:
            print("\n❌ Nepoznata opcija. Pokušaj ponovo.\n")

    print("\nProgram završen. Srećno sa programiranjem! 👋")


if __name__ == "__main__":
    pokreni_vasu()

Uputstva za integraciju

1. Kreiraj folder strukturu:

mkdir -p src/personalization
mkdir -p data/profiles

2. Kreiraj fajlove:

  • Kopiraj svaki deo koda u odgovarajući fajl
  • Nemoj zaboraviti __init__.py u personalization folderu

3. Ažuriraj postojeće fajlove:

  • Dodaj pozovi_ai_personalizovano metodu u base_service.py
  • Zameni ceo main.py sa novom verzijom

4. Testiraj integraciju:

python src/main.py

Ključne funkcionalnosti

  1. Korisnički profili – Pamćenje preferencija i praćenje napretka
  2. Analiza ponašanja – Automatsko prepoznavanje nivoa i stilova učenja
  3. Adaptivno učenje – Prilagođavanje tokom razgovora
  4. Integracija sa AI – Personalizovani pozivi i parametri
  5. Persistentnost – Čuvanje profila između sesija

Napomene

  • Profili se čuvaju u data/profiles/ folderu
  • Sistem automatski kreira potrebne foldere
  • Kompatibilan sa postojećim resilience i optimization sistemima
  • Svi moduli koriste type hints za bolju dokumentaciju

Čestitam! Sada imaš potpuno funkcionalan sistem personalizacije! 🎉

Česte greške i rešenja

GREŠKA: FileNotFoundError pri učitavanju profila
💡 REŠENJE:

  • Proveri da li postoji data/profiles folder
  • ProfileManager automatski kreira folder, ali možda nema dozvole
  • Ručno kreiraj: mkdir -p data/profiles

🔬 DETALJNIJE: Greška FileNotFoundError se dešava kada program pokuša da pristupi fajlu na putanji koju operativni sistem ne može da pronađe. Najčešći uzrok je problem sa radnim direktorijumom (working directory). Ako pokreneš skriptu iz ucitelj-vasa/ direktorijuma, relativna putanja data/profiles će raditi. Ali ako je pokreneš iz ucitelj-vasa/src/, sistem će tražiti ucitelj-vasa/src/data/profiles, što ne postoji. Upravo zato koristimo Path(__file__).parent.parent.parent / "data" / "profiles". __file__ je putanja do trenutnog fajla (user_profile.py), .parent se penje jedan nivo gore. Sa tri .parent poziva, dolazimo do korenskog ucitelj-vasa direktorijuma, bez obzira odakle je skripta pokrenuta. Ovo čini kod robusnim i predvidljivim.

GREŠKA: Profil se ne ažurira nakon razgovora
💡 REŠENJE:

  • Proveri da li pozivaš profile_manager.save_profile() nakon izmena
  • UserProfile menja podatke u memoriji, mora eksplicitno da se sačuva

GREŠKA: Personalizacija ne utiče na odgovore
💡 REŠENJE:

  • Proveri da li si implementirao pozovi_ai_personalizovano metodu
  • Možda koristiš staru verziju servisa bez personalizacije
  • Debug: štampaj personalized_prompt da vidiš da li se primenjuje

GREŠKA: Analyzer pogrešno kategoriše nivo korisnika
💡 REŠENJE:

  • Ključne reči možda nisu dovoljne za tvoj slučaj
  • Proširi SKILL_INDICATORS sa više termina
  • Koristi conversation_history umesto pojedinačnih poruka

GREŠKA: Adaptive engine previše često menja ponašanje
💡 REŠENJE:

  • Dodaj “debouncing” – ne prilagođavaj nakon svake poruke
  • Čekaj bar 3-5 poruka pre značajne promene
  • Koristi moving average umesto trenutnih vrednosti

Proveri svoje razumevanje

[NIVO 1]:

  1. Šta sve čuva korisnički profil?
  2. Kako sistem prepoznaje da li je korisnik početnik ili napredni?
  3. Zašto je važno da Vasa pamti prethodne razgovore?
  4. Šta su preference i kako utiču na odgovore?

[NIVO 2]:

  1. Kako bi dodao podršku za više jezika u personalizaciju?
  2. Šta je prednost DataClass-a nad običnim klasama za profile?
  3. Kako bi implementirao “export” profila za backup?
  4. Koje metrike bi dodao za bolje praćenje napretka?
  5. Kako bi zaštitio privatnost korisničkih podataka?

🤔 MINI-KVIZ

  1. Koja metoda u klasi ProfileManager vraća listu svih postojećih profila?
  2. Šta radi to_system_prompt_addon() u klasi UserPreferences i zašto je bitna?
  3. Kako ProfileAnalyzer procenjuje složenost poruke korisnika? Navedi bar dve heuristike.
  4. Ako Adaptivni engine primeti niz od tri poruke sa izrazima “ne razumem” – koji action će najverovatnije predložiti?

(odgovori potraži u kodu iznad – proveri se pre nego što skroluješ nazad!)

Ažuriranje dokumentacije

Ažuriraj README.md:

## 🚀 Trenutni Status

- ✅ Dan -3: Python 3.13+ instaliran
- ✅ Dan -2: PyCharm unified edition podešen  
- ✅ Dan -1: GitHub repository kreiran
- ✅ Dan 0: Profesionalna struktura projekta
- ✅ Dan 1: Prvi Python moduli - Vasa može da pozdravi!
- ✅ Dan 2: Razumevanje AI API-ja - simulacija komunikacije
- ✅ Dan 3: Multi-provider podrška - OpenAI i Gemini
- ✅ Dan 4: Prvi AI poziv - univerzalni sistem sa SSL fix-om
- ✅ Dan 5: Profilisanje i optimizacija - automatski izbor najboljih postavki
- ✅ Dan 6: Resilience sistem - retry, circuit breaker, fallback i graceful degradation
- ✅ Dan 7: Napredna personalizacija - profili, preference i adaptivno učenje! 👤
- ⏳ Dan 8: Uvod u FastAPI (sutra)

## 👤 Personalizacija

Učitelj Vasa sada:
- **Pamti korisnike**: Čuva profile sa preferencama
- **Prepoznaje nivo znanja**: Početnik, srednji, napredni
- **Prilagođava stil**: Praktičan, vizuelni, teorijski
- **Prati napredak**: Omiljene teme, dostignuća, statistike
- **Adaptivno uči**: Prilagođava se tokom razgovora

## 🧠 Arhitektura personalizacije

[Korisnik] → [ProfileManager] → [UserProfile]
↓ ↓
[ProfileAnalyzer] → [PersonalizedPrompt]
↓ ↓
[AdaptiveEngine] → [AI Response]

Dodaj u docs/development_log.md:

## Dan 7: Napredna personalizacija Vase (19.06.2025)

### Šta je urađeno:
- ✅ Kreiran UserProfile sistem sa DataClass
- ✅ Implementiran ProfileManager za CRUD operacije
- ✅ ProfileAnalyzer prepoznaje teme i nivo znanja
- ✅ Sistem preferencija (dužina, stil, jezik)
- ✅ AdaptiveEngine prilagođava tokom razgovora
- ✅ Integracija sa postojećim AI servisima
- ✅ Persistentno čuvanje u JSON
- ✅ UI za upravljanje profilima

### Naučene lekcije:
- Personalizacija drastično poboljšava korisnost AI asistenta
- DataClass idealan za profile (automatski metodi)
- Analiza poruka može da otkrije implicitne potrebe
- Adaptivnost tokom razgovora ključna za učenje
- JSON dovoljan za početak, lako migrirati na DB

### Problemi i rešenja:
- **Problem**: Kako bezbedno čuvati korisničke podatke?
- **Rešenje**: Lokalno čuvanje, sanitizacija imena fajlova
- **Problem**: Kada prilagoditi ponašanje tokom razgovora?
- **Rešenje**: Praćenje indikatora konfuzije/razumevanja

### Testiranje:
- Profili se uspešno čuvaju i učitavaju
- Analyzer tačno prepoznaje 80%+ tema
- Adaptive engine smanjuje konfuziju za 60%
- Personalizovan prompt menja ton odgovora

### Za sutra (Dan 8):
- Uvod u FastAPI
- Pretvaranje Vase u web servis
- RESTful API dizajn

Git commit za danas

git add .
git commit -m "Dan 7: Implementiran sistem personalizacije sa profilima i adaptivnim učenjem!"
git push

ČESTITAM! 🎉 Učitelj Vasa je sada pravi personalizovani AI asistent! Može da:

  • Pamti svakog korisnika ponaosob
  • Prilagođava se nivou znanja i stilu učenja
  • Prati napredak i predlaže sledeće korake
  • Adaptivno menja ponašanje tokom razgovora

Ovo je ogroman korak – od generičkog AI alata do personalnog mentora!

Sutra Učitelj Vasa uči

Sutra ulazimo u svet web development-a! Naučićeš osnove FastAPI framework-a i kako da pretvoriš Učitelja Vasu iz konzolne aplikacije u pravi web servis. To znači da će Vasa moći da odgovara na HTTP zahteve, što otvara vrata za web interfejs, mobilne aplikacije i integracije sa drugim sistemima!

📚 REČNIK DANAŠNJE LEKCIJE:

  • User Profile: Skup podataka o korisniku koji se čuva između sesija
  • Personalizacija: Prilagođavanje ponašanja aplikacije specifičnom korisniku
  • Adaptive Learning: Sistem koji uči o korisniku i prilagođava se tokom vremena
  • DataClass: Python dekorator koji automatski generiše specijalne metode
  • Preference Engine: Sistem koji primenjuje korisničke preference
  • Pattern Recognition: Prepoznavanje obrazaca u korisničkom ponašanju
  • Session Context: Privremeni podaci koji se čuvaju tokom razgovora
  • Engagement Score: Metrika koja meri koliko je korisnik aktivan
  • Skill Level Tracking: Praćenje napretka u veštinama korisnika
  • Profile Persistence: Trajno čuvanje profila između sesija