Dan 9/28: Prvi web endpoint za multi-provider sistem
Vreme potrebno: 90 – 180 minuta
Gde je Učitelj Vasa danas?
Učitelj Vasa je juče postao web servis sa osnovnim endpoint-ima za pozdrav i postavljanje pitanja. Ali trenutno kroz web API ne možeš da vidiš koji AI provideri su dostupni, da proveriš njihovo zdravlje, ili da saznaš koji provider trenutno koristiš. Danas dodajemo endpoint-e koji će omogućiti uvid u multi-provider sistem kroz web!
Cilj današnje lekcije
Danas ćeš naučiti kako da kreiraš FastAPI endpoint-e koji prikazuju informacije o dostupnim AI providerima, njihovom statusu i osnovnim performansama. Nakon ove lekcije, Učitelj Vasa će imati transparentan API koji pokazuje stanje multi-provider sistema!
Predznanja
- Funkcionalan FastAPI server sa osnovnim endpoint-ima (Dan 8)
- Multi-provider sistem sa OpenAI i Gemini (Dan 4)
- Resilience wrapper sa Circuit Breaker (Dan 6)
- Razumevanje GET i POST HTTP metoda
- JSON format za razmenu podataka
Glavni sadržaj
Zašto su provider-specifični endpoint-i važni?
Pre nego što krenemo sa implementacijom, razumimo zašto nam trebaju ovi endpoint-i.
📚 NIVO 1 – Osnovno objašnjenje
Zamisli da imaš auto sa dva rezervoara – jedan za benzin, drugi za gas. Trebaju ti instrumenti koji pokazuju:
- Koji rezervoar trenutno koristiš
- Da li oba rezervoara rade kako treba
- Koliko si puta koristio svaki
Isto važi za AI servise! Kroz web API treba da možeš da:
- Vidiš koji servisi su dostupni
- Proveriš koji je trenutno aktivan
- Vidiš osnovne statistike korišćenja
🚀 NIVO 2 – Dublje razumevanje
Provider-specifični endpoint-i omogućavaju:
- Observability – uvid u stanje sistema u realnom vremenu
- Transparency – korisnici znaju koji AI servis koriste
- Monitoring – praćenje dostupnosti servisa
- Debugging – lakše otkrivanje problema
Ovo je ključno za produkciju gde moraš da znaš šta se dešava sa sistemom u svakom trenutku.
💡 PRO TIP: Kada razmišljaš o observability-ju, zamišljaj svoj API kao pametnu kuhinju. Svaki uređaj (provider) ima lampicu koja svetli zeleno kada je sve u redu, žuto kad je usporen, crveno kada je isključen. Endpoint-i koje uvodiš služe baš kao te lampice – daju ti brz vizuelni pokazatelj stanja sistema pre nego što gosti primete da nešto ne radi. U praksi, to znači da ćeš brže reagovati na preopterećenje ili degradaciju performansi i sprečiti “kuhinjski požar” u produkciji.
🔍 UVID: Ovi endpoint-i su temelj za uspostavljanje “Observability” (posmatranja sistema), što je napredniji koncept od prostog “monitoringa”. Monitoring odgovara na pitanje “Da li sistem radi?”, dok observability odgovara na pitanje “Zašto sistem ne radi?”. Kreiranjem ruta koje izlažu unutrašnje stanje (/status, /providers, /statistics), mi ne pravimo samo API, već gradimo sistem koji može sam sebe da dijagnostikuje. Ovo je fundamentalni princip na kome počivaju veliki, skalabilni sistemi.
🎈 ZABAVNA ČINJENICA: Prvi put kada je tim Netflix-a uveo termin observability u svojoj internoj dokumentaciji, opisali su ga kao “rentgenski snimak” aplikacije koji nam dozvoljava da “vidimo kroz zidove” i uhvatimo bag dok je još mikroskopski! Ta metafora je danas standard u DevOps zajednici.
Kreiranje provider info endpoint-a
Počnimo sa osnovnim endpoint-om koji prikazuje informacije o providerima.
📚 NIVO 1 – Osnovno objašnjenje
Provider info endpoint je kao lista u prodavnici koja pokazuje koje proizvode imaju na stanju. Pokazaće:
- Koji AI servisi su konfigurisani (imaju API ključ)
- Koji servis je trenutno aktivan
- Osnovne informacije o svakom servisu
Sve ovo ćeš moći da vidiš samo otvaranjem jednog URL-a u browseru!
🚀 NIVO 2 – Dublje razumevanje
Ovaj endpoint treba da bude:
- Read-only – samo čita informacije, ne menja stanje
- Brz – vraća podatke koji su već u memoriji
- Informativan – daje dovoljno podataka bez otkrivanja tajnih informacija
📊 DIJAGRAM: Tok GET /providers zahteva
Korisnik (pretraživač/curl) FastAPI Server (app.py) Sistemske komponente
│ │ │
├─ GET /providers ──────────►│ │
│ │───┐ │
│ │ │ Poziva funkciju (runtime)
│ │ │ get_providers() │
│ │ └─────────────────────────┐
│ │ ├─ Čita Config.OPENAI_API_KEY
│ │ ├─ Čita Config.GEMINI_API_KEY
│ │ ├─ Čita Config.AI_PROVIDER
│ │<────────────────────────────┘
│ │───┐
│ │ │ Formira JSON odgovor
│ │ └─────────────────────────┐
│ │ │
◄── { "providers": [...] } ─┴─────────────────────────────┘
💡 PRO TIP: Ako želiš još čistiji kod, razmisli o FastAPI dependency injection mehanizmu. Umesto globalnih promenljivih, možeš definisati get_ai_service() funkciju kao dependency. To olakšava testiranje, jer svaku rutu možeš pozvati sa fake servisom i proveriti da li pravilno hendluje greške – bez pravog poziva ka OpenAI-ju ili Geminiju.
🎯 ALTERNATIVNO REŠENJE: Umesto ručnog građenja JSON-a unutar get_providers, možeš koristiti dataclass modele:
from dataclasses import asdict, dataclass
from typing import List
@dataclass
class ProviderInfo:
name: str
display_name: str
available: bool
is_active: bool
features: List[str]
def _collect_providers() -> List[ProviderInfo]:
providers: List[ProviderInfo] = []
if Config.OPENAI_API_KEY:
providers.append(ProviderInfo("openai", "OpenAI GPT", True, Config.AI_PROVIDER == "openai",
["chat", "code_generation", "analysis"]))
if Config.GEMINI_API_KEY:
providers.append(ProviderInfo("gemini", "Google Gemini", True, Config.AI_PROVIDER == "gemini",
["chat", "multimodal", "fast_responses"]))
return providers or [ProviderInfo("simulation", "Lokalna simulacija", True, True, ["basic_responses"])]
@app.get("/providers", response_model=dict)
async def get_providers():
data = _collect_providers()
return {
"providers": [asdict(p) for p in data],
"active_provider": Config.AI_PROVIDER,
"total_configured": len([p for p in data if p.name != "simulation"])
}
Ovaj pristup smanjuje “stringly-typed” kod i čuva podatke u strukturisanom obliku, što olakšava refaktor i automatsku dokumentaciju.
Proširujemo src/web_api/app.py dodavanjem novih endpoint-a:
# Dodaj ovu globalnu varijablu nakon ai_service
startup_time = None
# Ažuriraj startup_event da zapamti vreme pokretanja
@app.on_event("startup")
async def startup_event():
"""Inicijalizuje AI servis pri pokretanju."""
global ai_service, startup_time
startup_time = datetime.now()
print("🚀 Pokrećem Učitelja Vasu Web API...")
try:
ai_service = AIServiceFactory.create_resilient_service()
print("✅ AI servis spreman!")
except Exception as e:
print(f"⚠️ Problem sa AI servisom: {e}")
print("📌 API će raditi u ograničenom režimu")
# Dodaj import za datetime na početak fajla
from datetime import datetime
# Dodaj nove endpoint-e nakon postojećih
@app.get("/providers")
async def get_providers():
"""Vraća informacije o dostupnim AI providerima."""
providers = []
# Proveri OpenAI
if Config.OPENAI_API_KEY:
providers.append({
"name": "openai",
"display_name": "OpenAI GPT",
"available": True,
"is_active": Config.AI_PROVIDER == "openai",
"features": ["chat", "code_generation", "analysis"]
})
# Proveri Gemini
if Config.GEMINI_API_KEY:
providers.append({
"name": "gemini",
"display_name": "Google Gemini",
"available": True,
"is_active": Config.AI_PROVIDER == "gemini",
"features": ["chat", "multimodal", "fast_responses"]
})
# Ako nijedan nije dostupan
if not providers:
providers.append({
"name": "simulation",
"display_name": "Lokalna simulacija",
"available": True,
"is_active": True,
"features": ["basic_responses"]
})
return {
"providers": providers,
"active_provider": Config.AI_PROVIDER,
"total_configured": len([p for p in providers if p["name"] != "simulation"])
}
@app.get("/providers/current")
async def get_current_provider():
"""Vraća detalje o trenutno aktivnom provideru."""
current = Config.AI_PROVIDER
info = {
"provider": current,
"display_name": "OpenAI GPT" if current == "openai" else "Google Gemini",
"active_since": startup_time.isoformat() if startup_time else None
}
# Dodaj informacije o servisu ako postoji
if ai_service:
try:
settings = ai_service.get_current_settings()
info["model"] = settings.get("model", "nepoznat")
info["service_status"] = "operational"
except:
info["service_status"] = "degraded"
else:
info["service_status"] = "unavailable"
return info
Implementacija osnovnog status endpoint-a
Sada ćemo dodati endpoint koji daje pregled sistema.
📚 NIVO 1 – Osnovno objašnjenje
Status endpoint je kao glavna kontrolna tabla – pokazuje sve važne informacije o sistemu:
- Da li sistem radi
- Koliko dugo radi
- Koji AI koristiš
- Osnovne statistike
To je prvo mesto gde ćeš pogledati da vidiš da li je sve u redu sa Učiteljem Vasom.
🚀 NIVO 2 – Dublje razumevanje
Status endpoint kombinuje podatke iz različitih delova sistema:
- Uptime (vreme rada)
- Provider informacije
- Service health
- Basic metrics
💡 PRO TIP: U status endpoint-u često se dodaje polje git_commit_sha ili build_number. Kada tim za DevOps pogleda status u produkciji, odmah zna koju verziju koda gleda – bez kopanja po CI logovima. Dovoljno je da na build-u upišeš env varijablu GIT_SHA i pročitaš je u endpoint-u.
@app.get("/status")
async def get_status():
"""Vraća osnovni status sistema."""
# Računaj uptime
uptime_seconds = 0
if startup_time:
uptime_seconds = (datetime.now() - startup_time).total_seconds()
# Osnovno stanje
status = {
"status": "operational" if ai_service else "limited",
"uptime_seconds": int(uptime_seconds),
"uptime_human": f"{int(uptime_seconds // 60)} minuta",
"current_provider": Config.AI_PROVIDER,
"api_version": "1.0.0",
"timestamp": datetime.now().isoformat()
}
# Broj dostupnih providera
available_count = 0
if Config.OPENAI_API_KEY:
available_count += 1
if Config.GEMINI_API_KEY:
available_count += 1
status["providers_available"] = available_count
status["multi_provider_enabled"] = available_count > 1
# Circuit breaker status ako postoji
if ai_service and hasattr(ai_service, '_circuit_breaker_call'):
try:
cb = ai_service._circuit_breaker_call.circuit_breaker
status["circuit_breaker"] = cb.state.value
except:
status["circuit_breaker"] = "unknown"
return status
⚡ SAVET ZA OPTIMIZACIJU: Status endpoint-i su često pozivani od strane automatskih monitoring sistema. Iako je naš /status endpoint već brz, u sistemima sa visokim opterećenjem čak i ovakvi pozivi mogu da se akumuliraju. Jedna napredna tehnika je keširanje odgovora na 1-2 sekunde. Time bi se drastično smanjio broj proračuna (npr. uptime-a) i obezbedio skoro trenutan odgovor, čime se oslobađaju resursi servera za obradu važnijih zahteva kao što je /pitaj.
Dodavanje provider statistics endpoint-a
Hajde da dodamo endpoint koji pokazuje osnovne statistike.
📚 NIVO 1 – Osnovno objašnjenje
Statistics endpoint je kao izveštaj o potrošnji goriva – pokazuje:
- Koliko si puta koristio svaki AI servis
- Koliko je bilo uspešnih odgovora
- Osnovne informacije o korišćenju
Ovo ti pomaže da razumeš koji servis koristiš najviše i koliko dobro radi.
🚀 NIVO 2 – Dublje razumevanje
Statistike se čitaju iz postojećeg performance tracker-a koji već beleži sve pozive. Endpoint samo formatira te podatke za lakše čitanje.
📊 DIJAGRAM: Tok GET /providers/statistics zahteva
Korisnik FastAPI Server (app.py) Performance Tracker (u memoriji)
│ │ │
├─ GET /stats ────►│ │
│ │──┐ │
│ │ │ Poziva get_provider_stats() │
│ │ └─────────────────────────────►─┐
│ │ │ │ Iterira kroz
│ │ │ │ listu metrika
│ │ └─◄─ (tracker.all_metrics)
│ │<───────────────────────────────┐
│ │ │ Agregirani podaci
│ │────────────────────────────────┘
│ │──┐
│ │ │ Formira JSON odgovor
│ │ └─────────────────────────────┐
│ │ │
◄─ { "total":.. } ─┴────────────────────────────────┘
# Dodaj import na početak
from utils.performance_tracker import tracker
@app.get("/providers/statistics")
async def get_provider_statistics():
"""Vraća osnovne statistike o korišćenju providera."""
if not hasattr(tracker, 'all_metrics') or not tracker.all_metrics:
return {
"message": "Nema dovoljno podataka",
"total_requests": 0,
"providers": {}
}
# Grupiši podatke po providerima
stats = {}
for metric in tracker.all_metrics:
# Koristi dictionary pristup umesto atributa
provider = metric.get('provider', 'unknown') # Promenjeno sa metric.provider
if provider not in stats:
stats[provider] = {
"total_requests": 0,
"successful_requests": 0,
"failed_requests": 0,
"total_tokens": 0
}
stats[provider]["total_requests"] += 1
# Koristi get() metod za bezbedno čitanje
if metric.get('success', False): # Promenjeno sa metric.success
stats[provider]["successful_requests"] += 1
stats[provider]["total_tokens"] += metric.get('tokens_used', 0) # Promenjeno
else:
stats[provider]["failed_requests"] += 1
# Dodaj procente
for provider, data in stats.items():
if data["total_requests"] > 0:
data["success_rate"] = round(
(data["successful_requests"] / data["total_requests"]) * 100,
2
)
else:
data["success_rate"] = 0
return {
"total_requests": len(tracker.all_metrics),
"providers": stats,
"collection_started": tracker.all_metrics[0].get('timestamp') if tracker.all_metrics else None # Promenjeno
}
🔍 UVID: Trenutni /providers/statistics endpoint čita podatke direktno iz tracker objekta koji živi u memoriji aplikacije. Ovo je jednostavno i brzo, ali ima ključni nedostatak: sve statistike se gube prilikom svakog restarta servera. Ovo je sistemska odlika onoga što se zove “stateless” (bez stanja) aplikacija. U kasnijim fazama razvoja (Nedelja 3 i 4), videćeš kako se ovakvi podaci premeštaju u spoljne, perzistentne sisteme kao što su baze podataka da bi preživeli restart i omogućili dugoročnu analizu.
Kreiranje simple health endpoint-a
Na kraju, dodajmo osnovni health check.
📚 NIVO 1 – Osnovno objašnjenje
Health endpoint je kao brza provera pulsa – samo kaže “živ sam i radim”. Ovo je korisno za:
- Proveru da li server uopšte radi
- Monitoring alate koje prate da li je aplikacija online
- Brzu proveru bez detalja
🚀 NIVO 2 – Dublje razumevanje
Health endpoint mora biti:
- Ekstremno brz (bez složenih provera)
- Uvek dostupan (ne zavisi od drugih servisa)
- Standardizovan format (za monitoring alate)
🌐 GOOGLE CONNECTION: /health endpoint koji pravimo je direktno kompatibilan sa “Liveness Probes” konceptom u Google Kubernetes Engine (GKE) i Google Cloud Run. Ovi servisi periodično pogađaju baš ovakvu /health rutu. Ako ruta odgovori uspešno (HTTP status 200), Google Cloud zna da je tvoja aplikacija “živa”. Ako ne odgovori, automatski će je restartovati. Kreiranjem ove jednostavne rute, Učitelja Vasu činimo spremnim za upravljanje od strane najnaprednijih “production-grade” platformi.
🎈 ZABAVNA ČINJENICA: Amazonov interni guideline zabranjuje reč “OK” u health-u – jer je previše dvosmislena! Umesto toga koriste jasne statuse HEALTHY, UNHEALTHY i DEGRADED.
💡 PRO TIP: Nemoj da zaboraviš rate limiting na health rutama u produkciji. U suprotnom, besplatni online monitoring servisi mogu nesvesno da “DDOS-uju” tvoj server pingovanjem svakih par sekundi. Jednostavna X-RateLimit zaglavlja ili FastAPI middleware čuva te od neprijatnih iznenađenja.
@app.get("/health")
async def health_check():
"""Osnovni health check endpoint."""
return {
"status": "healthy",
"service": "ucitelj-vasa-api",
"timestamp": datetime.now().isoformat()
}
@app.get("/health/ai")
async def ai_service_health():
"""Proverava health AI servisa."""
health_info = {
"service_exists": ai_service is not None,
"provider": Config.AI_PROVIDER,
"timestamp": datetime.now().isoformat()
}
if ai_service:
try:
# Pokušaj da dobiješ postavke kao brzu proveru
settings = ai_service.get_current_settings()
health_info["responsive"] = True
health_info["model"] = settings.get("model", "unknown")
except:
health_info["responsive"] = False
else:
health_info["responsive"] = False
# Određi overall status
if health_info["service_exists"] and health_info["responsive"]:
health_info["status"] = "healthy"
elif health_info["service_exists"]:
health_info["status"] = "degraded"
else:
health_info["status"] = "unavailable"
return health_info
Praktična implementacija
Testiranje novih endpoint-a
Sada kada smo dodali sve endpoint-e, hajde da ih testiramo!
- Pokreni server (ako nije već pokrenut):
cd src
python web_api/run_server.py
- Test provider endpoint-a:
# Lista svih providera
curl http://localhost:8000/providers
# Trenutni provider
curl http://localhost:8000/providers/current
# Statistike
curl http://localhost:8000/providers/statistics
- Test status endpoint-a:
curl http://localhost:8000/status
- Test health endpoint-a:
# Osnovni health
curl http://localhost:8000/health
# AI service health
curl http://localhost:8000/health/ai
🔄 VEŽBA: Podesi dve različite .env konfiguracije – jednu sa samo OpenAI ključem, drugu sa oba ključa. Restartuj server sa svakim od fajlova i obrati pažnju kako GET /providers dinamički menja rezultat. Koja polja se razlikuju? Koji je total_configured broj u oba slučaja? Zabeleži zapažanja u sopstvenom learning journal-u.
Kreiranje jednostavnog monitoring script-a
Za lakše praćenje, možemo kreirati Python skript koji periodično proverava status.
Kreiraj src/web_api/monitor.py:
"""
Jednostavan monitoring skript za Učitelja Vasu API
"""
import requests
import time
from datetime import datetime
def check_api_status(base_url="http://localhost:8000"):
"""Proverava status API-ja i prikazuje rezultate."""
print(f"\n{'='*60}")
print(f"🔍 Učitelj Vasa API Monitor - {datetime.now().strftime('%H:%M:%S')}")
print(f"{'='*60}")
# Proveri osnovni health
try:
response = requests.get(f"{base_url}/health", timeout=2)
if response.status_code == 200:
print("✅ API Server: ONLINE")
else:
print(f"⚠️ API Server: Status {response.status_code}")
except:
print("❌ API Server: OFFLINE")
return
# Proveri AI health
try:
response = requests.get(f"{base_url}/health/ai", timeout=5)
data = response.json()
status_icon = {
"healthy": "✅",
"degraded": "⚠️",
"unavailable": "❌"
}.get(data.get("status", "unknown"), "❓")
print(f"{status_icon} AI Service: {data.get('status', 'unknown').upper()}")
print(f" Provider: {data.get('provider', 'N/A')}")
if data.get("model"):
print(f" Model: {data.get('model')}")
except:
print("❌ AI Service: Ne mogu da proverim")
# Proveri providere
try:
response = requests.get(f"{base_url}/providers", timeout=2)
data = response.json()
print(f"\n📡 Dostupni provideri:")
for provider in data.get("providers", []):
active = " (AKTIVAN)" if provider.get("is_active") else ""
print(f" • {provider.get('display_name', provider.get('name'))}{active}")
except:
print("❌ Ne mogu da dobijem listu providera")
# Proveri statistike
try:
response = requests.get(f"{base_url}/providers/statistics", timeout=2)
data = response.json()
total = data.get("total_requests", 0)
if total > 0:
print(f"\n📊 Statistike:")
print(f" Ukupno zahteva: {total}")
for provider, stats in data.get("providers", {}).items():
print(f" {provider}: {stats.get('success_rate', 0)}% uspešnih")
except:
pass # Statistike nisu kritične
def monitor_loop(interval=10):
"""Pokreće monitoring u petlji."""
print("🚀 Pokrećem monitoring Učitelja Vase...")
print(f" Provera svakih {interval} sekundi")
print(" Pritisni Ctrl+C za prekid")
try:
while True:
check_api_status()
time.sleep(interval)
except KeyboardInterrupt:
print("\n\n👋 Monitoring zaustavljen")
if __name__ == "__main__":
# Možeš pokrenuti samo jednu proveru
# check_api_status()
# Ili monitoring petlju
monitor_loop(interval=15)
Pokreni monitoring:
python src/web_api/monitor.py
⚡ SAVET ZA OPTIMIZACIJU: U monitor.py skripti, parametar interval direktno utiče na opterećenje tvog API-ja. Interval od 15 sekundi je razuman za lokalni razvoj. Međutim, u produkciji, prečesto pozivanje (npr. svake sekunde) može nepotrebno opteretiti sistem. Profesionalni alati često koriste “adaptive polling” – proveravaju ređe kada je sistem stabilan, a češće kada detektuju problem. Za početak, drži interval iznad 10 sekundi.
Integracija sa postojećim sistemima
Ovi endpoint-i elegantno koriste postojeće komponente:
- Config modul – čita koje providere imamo
- Performance tracker – daje statistike
- AI service – proverava trenutno stanje
- Circuit breaker – status resilience sistema
Sve što smo do sada izgradili radi zajedno!
Česte greške i rešenja
❌ GREŠKA: Endpoint vraća {"providers": []}
💡 REŠENJE:
- Proveri da li su API ključevi učitani u .env fajl
- Proveri da li Config modul čita environment varijable
- Restartuj server nakon dodavanja ključeva
❌ GREŠKA: Statistics endpoint vraća prazan objekat
💡 REŠENJE:
- Tracker možda nema podatke – postavi nekoliko pitanja kroz
/pitaj - Proveri da li se metrike uopšte beleže u tracker
- Pogledaj server logove za greške
🔬 DETALJNIJE: Ova greška se dešava jer performance_tracker čuva statistike u RAM memoriji servera. Kada restartuješ run_server.py, Python proces se završava i operativni sistem oslobađa svu memoriju koju je taj proces koristio. Prilikom novog pokretanja, kreira se potpuno novi, “čist” tracker objekat. Ovo nije bug, već fundamentalna karakteristika “stateless” web aplikacija. One ne pamte ništa između zahteva, osim ako se podaci eksplicitno ne sačuvaju u spoljni, trajni medijum (fajl, baza podataka, itd.), što ćemo raditi u kasnijim lekcijama.
❌ GREŠKA: Health check pokazuje “unavailable” iako AI radi
💡 REŠENJE:
- Možda
get_current_settings()baca grešku - Proveri da li je AI servis pravilno inicijalizovan
- Pogledaj server logove za stack trace
❌ GREŠKA: Monitor script ne može da se poveže
💡 REŠENJE:
- Proveri da li server radi na http://localhost:8000
- Možda firewall blokira konekciju
- Proveri da li je tačan base_url
❌ GREŠKA: Uptime pokazuje 0 iako server dugo radi
💡 REŠENJE:
- Proveri da li se
startup_timepostavlja u startup_event - Možda si restartovao server (uptime se resetuje)
- Debug sa print(startup_time) u status endpoint-u
Proveri svoje razumevanje
[NIVO 1]:
- Koji endpoint pokazuje listu svih AI providera?
- Šta vraća health check endpoint?
- Gde možeš videti koliko dugo server radi?
- Šta su osnovne informacije koje vraća status endpoint?
[NIVO 2]:
- Zašto je važno da health endpoint bude brz?
- Kako bi dodao informaciju o verziji modela u provider info?
- Šta bi se desilo sa statistikama nakon restarta servera?
- Kako bi proširio monitoring script da šalje alerte?
- Zašto koristimo try/except blokove u health check-ovima?
🤔 MINI-KVIZ:
- Koja dva cilja postiže dependency injection pristup u FastAPI-ju?
- Zašto statičke health rute moraju imati minimalan odzivni kod?
- Koliko procenata uspešnosti smatraš prihvatljivim pragom u
success_ratepolju i zašto?
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 - Učitelj Vasa je sada web servis!
- ✅ Dan 9: Multi-provider web endpoint-i - transparentnost i monitoring! 📊
- ⏳ Dan 10: Struktura zahteva i provider routing (sutra)
## 📊 Provider Management API
### Informacioni endpoint-i:
- `GET /providers` - Lista dostupnih AI providera
- `GET /providers/current` - Detalji o aktivnom provideru
- `GET /providers/statistics` - Statistike korišćenja
### Status i Health:
- `GET /status` - Kompletan status sistema
- `GET /health` - Osnovni health check
- `GET /health/ai` - Health check AI servisa
### Monitoring:
- Python script za kontinuirano praćenje
- Jednostavna provera svih komponenti
Dodaj u docs/development_log.md:
## Dan 9: Prvi web endpoint za multi-provider sistem (19.06.2025)
### Šta je urađeno:
- ✅ Provider info endpoint-i (/providers, /providers/current)
- ✅ Status endpoint sa osnovnim informacijama
- ✅ Statistics endpoint sa podacima iz tracker-a
- ✅ Health check endpoint-i (osnovni i AI-specific)
- ✅ Python monitoring script
- ✅ Integracija sa postojećim komponentama
### Naučene lekcije:
- Read-only endpoint-i su bezbedni i korisni
- Health check-ovi moraju biti brzi i pouzdani
- Statistike omogućavaju uvid u korišćenje
- Monitoring je ključan za produkciju
- Postojeće komponente se lako integrišu
### Problemi i rešenja:
- **Problem**: Kako prikazati status bez otkrivanja tajnih podataka?
- **Rešenje**: Prikazuj samo javne informacije (ime, status, features)
- **Problem**: Health check može biti spor ako testira AI
- **Rešenje**: Osnovna provera samo proverava postojanje servisa
### Testiranje:
- Svi endpoint-i vraćaju očekivane podatke
- Health check-ovi rade brzo (<100ms)
- Statistics se pravilno agregiraju
- Monitor script uspešno prati status
### Za sutra (Dan 10):
- Struktura zahteva za različite tipove pitanja
- Provider routing logika
- Inteligentno biranje providera
Git commit za danas
git add .
git commit -m "Dan 9: Provider info endpoint-i sa health checks i monitoring!"
git push
ČESTITAM! 🎉 Učitelj Vasa sada ima transparentan multi-provider API sa:
- Jasnim pregledom dostupnih AI servisa
- Statusom i health check-ovima
- Statistikama korišćenja
- Monitoring skriptom za praćenje
Ovo su osnove svakog profesionalnog API-ja – transparentnost i observability!
Sutra Učitelj Vasa uči
Sutra ćemo se fokusirati na strukturu zahteva i implementaciju provider routing logike. Naučićeš kako da kreiraš različite tipove zahteva (za chat, kod generisanje, analizu), kako da implementiraš inteligentno rutiranje koje bira najbolji provider za svaki tip zahteva, i kako da standardizuješ request format za lakšu obradu!
📚 REČNIK DANAŠNJE LEKCIJE:
- Provider endpoint: API ruta koja daje informacije o AI servisima
- Health check: Brza provera da li komponenta radi
- Status endpoint: Pregled trenutnog stanja sistema
- Statistics: Agregacija podataka o korišćenju
- Monitoring: Kontinuirano praćenje sistema
- Read-only endpoint: Endpoint koji samo čita, ne menja podatke
- Uptime: Vreme koliko dugo sistem radi bez prekida
- Circuit breaker state: Trenutno stanje resilience komponente
- Success rate: Procenat uspešnih zahteva
- Observability: Sposobnost uvida u stanje sistema
- Stateless aplikacija: Aplikacija koja ne čuva stanje između zahteva
- Dependency injection: Tehnika prosleđivanja zavisnosti umesto globalnih varijabli
- Adaptive polling: Prilagođavanje učestalosti provera prema stanju sistema