zotthytt12 commited on
Commit
573e1e6
verified
1 Parent(s): 1e76509

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -10
app.py CHANGED
@@ -5,7 +5,9 @@ from pydantic import BaseModel, Field
5
  from typing import List
6
  from huggingface_hub import hf_hub_download
7
 
 
8
  MODEL_FILE_NAME = 'model_raport.pkl'
 
9
  MODEL_REPO_ID = 'zotthytt12/model_hr'
10
 
11
  MODEL_FEATURES_ORDER = [
@@ -16,15 +18,16 @@ MODEL_FEATURES_ORDER = [
16
  'React', 'SQL', 'TensorFlow'
17
  ]
18
 
19
-
20
  model = None
21
 
22
-
23
  app = FastAPI(
24
  title="API Rankingu CV",
25
  description="API, kt贸re przyjmuje list臋 kandydat贸w, ocenia ich za pomoc膮 modelu RandomForest i zwraca ranking."
26
  )
27
 
 
28
 
29
  class CandidateFeatures(BaseModel):
30
  """Definiuje cechy JEDNEGO kandydata."""
@@ -54,23 +57,28 @@ class CandidateFeatures(BaseModel):
54
  populate_by_name = True
55
 
56
  class RankingRequest(BaseModel):
 
57
  candidates: List[CandidateFeatures]
58
 
59
  class RankedCandidate(BaseModel):
 
60
  identifier: str
61
  score: float = Field(..., description="Prawdopodobie艅stwo zaproszenia (0.0 do 1.0)")
62
 
63
  class RankingResponse(BaseModel):
 
64
  ranked_candidates: List[RankedCandidate]
65
 
66
 
67
- @app.on_event("startup")
68
- def load_model_from_hub():
69
- """
70
- Pobiera model .pkl z Hugging Face Hub i wczytuje go
71
- przy starcie aplikacji.
72
- """
 
73
  global model
 
74
  try:
75
  model_path = hf_hub_download(
76
  repo_id=MODEL_REPO_ID,
@@ -82,15 +90,29 @@ def load_model_from_hub():
82
 
83
  except Exception as e:
84
  print(f"B艁膭D KRYTYCZNY: Nie mo偶na wczyta膰 modelu z Huba ({MODEL_REPO_ID}). B艂膮d: {e}")
 
 
 
 
 
 
 
85
 
86
 
 
 
87
  @app.get("/")
88
  def read_root():
 
89
  return {"status": "OK", "message": "Witaj w API do Rankingu CV!"}
90
 
91
 
92
  @app.post("/rank", response_model=RankingResponse)
93
  def rank_candidates(request: RankingRequest):
 
 
 
 
94
  global model
95
  if model is None:
96
  # Je艣li model si臋 nie za艂adowa艂 przy starcie, zwr贸膰 b艂膮d
@@ -100,15 +122,23 @@ def rank_candidates(request: RankingRequest):
100
  return {"ranked_candidates": []}
101
 
102
  try:
 
103
  candidate_data_list = [c.model_dump(by_alias=True) for c in request.candidates]
104
  identifiers = [c['identifier'] for c in candidate_data_list]
105
 
 
106
  df = pd.DataFrame(candidate_data_list)
 
 
107
  features_df = df.drop(columns=['identifier'])
 
 
108
  features_df_ordered = features_df[MODEL_FEATURES_ORDER]
109
 
 
110
  probabilities = model.predict_proba(features_df_ordered)[:, 1]
111
 
 
112
  ranked_list = []
113
  for i, identifier in enumerate(identifiers):
114
  ranked_list.append(RankedCandidate(
@@ -116,6 +146,7 @@ def rank_candidates(request: RankingRequest):
116
  score=probabilities[i]
117
  ))
118
 
 
119
  sorted_ranked_list = sorted(ranked_list, key=lambda x: x.score, reverse=True)
120
 
121
  return {"ranked_candidates": sorted_ranked_list}
@@ -128,6 +159,8 @@ def rank_candidates(request: RankingRequest):
128
  # Uruchomienie aplikacji (dla test贸w lokalnych)
129
  if __name__ == "__main__":
130
  import uvicorn
131
- # Uruchom r臋cznie 艂adowanie modelu dla test贸w lokalnych
132
- load_model_from_hub()
 
133
  uvicorn.run(app, host="0.0.0.0", port=8000)
 
 
5
  from typing import List
6
  from huggingface_hub import hf_hub_download
7
 
8
+ # --- Sekcja Konfiguracji Modelu ---
9
  MODEL_FILE_NAME = 'model_raport.pkl'
10
+ # Upewnij si臋, 偶e ta nazwa repozytorium jest poprawna!
11
  MODEL_REPO_ID = 'zotthytt12/model_hr'
12
 
13
  MODEL_FEATURES_ORDER = [
 
18
  'React', 'SQL', 'TensorFlow'
19
  ]
20
 
21
+ # --- Globalna zmienna na model ---
22
  model = None
23
 
24
+ # --- Definicja API (FastAPI) ---
25
  app = FastAPI(
26
  title="API Rankingu CV",
27
  description="API, kt贸re przyjmuje list臋 kandydat贸w, ocenia ich za pomoc膮 modelu RandomForest i zwraca ranking."
28
  )
29
 
30
+ # --- 1. Modele danych (Pydantic) ---
31
 
32
  class CandidateFeatures(BaseModel):
33
  """Definiuje cechy JEDNEGO kandydata."""
 
57
  populate_by_name = True
58
 
59
  class RankingRequest(BaseModel):
60
+ """Definiuje format zapytania - oczekujemy listy kandydat贸w."""
61
  candidates: List[CandidateFeatures]
62
 
63
  class RankedCandidate(BaseModel):
64
+ """Definiuje format odpowiedzi dla jednego kandydata."""
65
  identifier: str
66
  score: float = Field(..., description="Prawdopodobie艅stwo zaproszenia (0.0 do 1.0)")
67
 
68
  class RankingResponse(BaseModel):
69
+ """Definiuje format odpowiedzi - zwracamy list臋 ocenionych kandydat贸w."""
70
  ranked_candidates: List[RankedCandidate]
71
 
72
 
73
+ # --- 2. 艁adowanie modelu ---
74
+ # (U偶ywamy nowszego 'lifespan' zamiast 'on_event')
75
+ from contextlib import asynccontextmanager
76
+
77
+ @asynccontextmanager
78
+ async def lifespan(app: FastAPI):
79
+ # Kod uruchamiany przy starcie
80
  global model
81
+ print("--- Rozpoczynanie 艂adowania modelu z Huba... ---")
82
  try:
83
  model_path = hf_hub_download(
84
  repo_id=MODEL_REPO_ID,
 
90
 
91
  except Exception as e:
92
  print(f"B艁膭D KRYTYCZNY: Nie mo偶na wczyta膰 modelu z Huba ({MODEL_REPO_ID}). B艂膮d: {e}")
93
+
94
+ yield
95
+ # Kod uruchamiany przy zamkni臋ciu (je艣li potrzebny)
96
+ print("--- Zamykanie aplikacji ---")
97
+
98
+ # Przypisz funkcj臋 lifespan do aplikacji
99
+ app.router.lifespan_context = lifespan
100
 
101
 
102
+ # --- 3. Punkty ko艅cowe API (Endpoints) ---
103
+
104
  @app.get("/")
105
  def read_root():
106
+ """Podstawowy endpoint (g艂贸wna strona) do sprawdzania, czy API dzia艂a."""
107
  return {"status": "OK", "message": "Witaj w API do Rankingu CV!"}
108
 
109
 
110
  @app.post("/rank", response_model=RankingResponse)
111
  def rank_candidates(request: RankingRequest):
112
+ """
113
+ Ten endpoint przyjmuje list臋 kandydat贸w, przetwarza ich dane,
114
+ przepuszcza przez model i zwraca posortowany ranking.
115
+ """
116
  global model
117
  if model is None:
118
  # Je艣li model si臋 nie za艂adowa艂 przy starcie, zwr贸膰 b艂膮d
 
122
  return {"ranked_candidates": []}
123
 
124
  try:
125
+ # 1. Konwertuj list臋 kandydat贸w
126
  candidate_data_list = [c.model_dump(by_alias=True) for c in request.candidates]
127
  identifiers = [c['identifier'] for c in candidate_data_list]
128
 
129
+ # 2. Stw贸rz DataFrame
130
  df = pd.DataFrame(candidate_data_list)
131
+
132
+ # Upewnij si臋, 偶e brakuje tylko kolumny 'identifier', a reszta pasuje
133
  features_df = df.drop(columns=['identifier'])
134
+
135
+ # Ustaw kolejno艣膰 kolumn DOK艁ADNIE tak, jak w treningu
136
  features_df_ordered = features_df[MODEL_FEATURES_ORDER]
137
 
138
+ # 3. Predykcja
139
  probabilities = model.predict_proba(features_df_ordered)[:, 1]
140
 
141
+ # 4. Tworzenie odpowiedzi
142
  ranked_list = []
143
  for i, identifier in enumerate(identifiers):
144
  ranked_list.append(RankedCandidate(
 
146
  score=probabilities[i]
147
  ))
148
 
149
+ # 5. Sortowanie
150
  sorted_ranked_list = sorted(ranked_list, key=lambda x: x.score, reverse=True)
151
 
152
  return {"ranked_candidates": sorted_ranked_list}
 
159
  # Uruchomienie aplikacji (dla test贸w lokalnych)
160
  if __name__ == "__main__":
161
  import uvicorn
162
+ # Uwaga: przy starcie z __main__ lifespan nie zadzia艂a automatycznie
163
+ # Trzeba by go wywo艂a膰 r臋cznie lub po prostu polega膰 na te艣cie z uvicorn
164
+ print("Uruchamianie lokalne - model zostanie za艂adowany przez 'lifespan' po starcie uvicorn.")
165
  uvicorn.run(app, host="0.0.0.0", port=8000)
166
+