Diaure commited on
Commit
484a0ad
·
verified ·
1 Parent(s): a819a92

CD: update from GitHub main

Browse files
Files changed (6) hide show
  1. .github/workflows/cd.yml +30 -0
  2. .github/workflows/ci.yml +10 -2
  3. .gitignore +1 -1
  4. README.md +16 -22
  5. coverage.xml +206 -0
  6. deploy_to_hf.py +12 -0
.github/workflows/cd.yml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CD to Hugging Face
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout repository
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11.9"
20
+
21
+ - name: Install dependencies
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ python -m pip install -r requirements.txt
25
+
26
+ - name: Deploy to Hugging Face
27
+ env:
28
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
29
+ run: python deploy_to_hf.py
30
+
.github/workflows/ci.yml CHANGED
@@ -31,7 +31,15 @@ jobs:
31
  run: echo "PYTHONPATH=$PYTHONPATH:$(pwd)" >> $GITHUB_ENV
32
 
33
  - name: Run unit tests with coverage
34
- run: poetry run pytest tests/units --cov=App --cov-report=xml --cov-report=term-missing
 
 
 
 
 
 
 
 
35
 
36
  functional-tests:
37
  name: Tests fonctionnels API
@@ -42,7 +50,7 @@ jobs:
42
  - uses: actions/checkout@v4
43
  - uses: actions/setup-python@v5
44
  with:
45
- python-version: "3.11"
46
 
47
  - name: Install Poetry
48
  run: pip install poetry
 
31
  run: echo "PYTHONPATH=$PYTHONPATH:$(pwd)" >> $GITHUB_ENV
32
 
33
  - name: Run unit tests with coverage
34
+ run: poetry run pytest tests/units --cov=App --cov-report=xml --cov-report=term-missing
35
+
36
+ - name: Test FastAPI app import
37
+ run: |
38
+ python - << 'EOF'
39
+ from App.main import app
40
+ assert app is not None
41
+ print("FastAPI app loaded successfully")
42
+ EOF
43
 
44
  functional-tests:
45
  name: Tests fonctionnels API
 
50
  - uses: actions/checkout@v4
51
  - uses: actions/setup-python@v5
52
  with:
53
+ python-version: "3.11.9"
54
 
55
  - name: Install Poetry
56
  run: pip install poetry
.gitignore CHANGED
@@ -8,4 +8,4 @@ App/model/
8
  *.joblib
9
  *.json
10
  App/model/modele_final_xgb.joblib
11
- Other
 
8
  *.joblib
9
  *.json
10
  App/model/modele_final_xgb.joblib
11
+ Other
README.md CHANGED
@@ -81,7 +81,7 @@ Ce choix est justifié par:
81
  - un compromis efficace entre précision et capacité de généralisation
82
  - un temps d’inférence compatible avec une exposition via API
83
 
84
- ![image](Other\comp_modeles.PNG)
85
 
86
  ### `Sérialisation et versionnage`
87
 
@@ -371,28 +371,22 @@ L’architecture du projet repose sur une séparation claire des responsabilité
371
  │ Utilisateur │
372
  │ (Client) │
373
  └───────────────┬──────────────┘
374
- Requête POST /predict
375
 
376
- ┌──────────────────────────────┐
377
- API FastAPI
378
- │ (main.py)
379
- └───────────────┬──────────────┘
380
-
381
-
382
- ┌──────────────────────────────────┐
383
- Module de prédiction │
384
- (predict.py) │
385
- - Chargement du modèle HF Hub │
386
- │ - Validation │
387
- │ - Prédiction │
388
- └───────────────┬──────────────────┘
389
-
390
-
391
- ┌────────────────────────────────────────┐
392
- │ Base de données PostgreSQL │
393
- │ (inputs / predictions / dataset) │
394
- └────────────────────────────────────────┘
395
-
396
  ┌────────────────────────────────────────┐
397
  │ CI/CD – GitHub Actions │
398
  │ - Tests unitaires │
 
81
  - un compromis efficace entre précision et capacité de généralisation
82
  - un temps d’inférence compatible avec une exposition via API
83
 
84
+ ![Comparaison des modèles](https://raw.githubusercontent.com/Diaure/Futurisys_ML_API/develop/Other/comp_modeles.PNG)
85
 
86
  ### `Sérialisation et versionnage`
87
 
 
371
  │ Utilisateur │
372
  │ (Client) │
373
  └───────────────┬──────────────┘
374
+
375
 
376
+ ┌────────────────────────────────────────────
377
+ API FastAPI
378
+ │ (endpoint - POST /predict)
379
+ ────────────────────┬─────────────────────┬
380
+ | |
381
+ ▼ ▼
382
+ ┌────────────────┐ ┌──────────────┐ ┌───────────────────────────
383
+ Vérification & | | Modèle ML | | Base PostgreSQL (stockage)|
384
+ | Validation | - Chargement | | - Inputs |
385
+ | | | - Prédiction | | - Prédictions |
386
+ └────────────────┘ └──────────────┘ └───────────────────────────┘
387
+
388
+ |
389
+ |
 
 
 
 
 
 
390
  ┌────────────────────────────────────────┐
391
  │ CI/CD – GitHub Actions │
392
  │ - Tests unitaires │
coverage.xml ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" ?>
2
+ <coverage version="7.13.1" timestamp="1768992069241" lines-valid="167" lines-covered="123" line-rate="0.7365" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
3
+ <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.13.1 -->
4
+ <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
5
+ <sources>
6
+ <source>C:\Users\Lenovo\Documents\WCS\GitHub\Futurisys_ML_API\App</source>
7
+ </sources>
8
+ <packages>
9
+ <package name="." line-rate="0.7365" branch-rate="0" complexity="0">
10
+ <classes>
11
+ <class name="database.py" filename="database.py" complexity="0" line-rate="0.84" branch-rate="0">
12
+ <methods/>
13
+ <lines>
14
+ <line number="1" hits="1"/>
15
+ <line number="2" hits="1"/>
16
+ <line number="5" hits="1"/>
17
+ <line number="6" hits="1"/>
18
+ <line number="7" hits="1"/>
19
+ <line number="8" hits="1"/>
20
+ <line number="9" hits="0"/>
21
+ <line number="10" hits="0"/>
22
+ <line number="12" hits="1"/>
23
+ <line number="15" hits="1"/>
24
+ <line number="16" hits="1"/>
25
+ <line number="17" hits="1"/>
26
+ <line number="19" hits="1"/>
27
+ <line number="20" hits="1"/>
28
+ <line number="22" hits="1"/>
29
+ <line number="23" hits="1"/>
30
+ <line number="24" hits="1"/>
31
+ <line number="25" hits="1"/>
32
+ <line number="26" hits="1"/>
33
+ <line number="27" hits="1"/>
34
+ <line number="29" hits="1"/>
35
+ <line number="31" hits="1"/>
36
+ <line number="32" hits="1"/>
37
+ <line number="35" hits="0"/>
38
+ <line number="36" hits="0"/>
39
+ </lines>
40
+ </class>
41
+ <class name="main.py" filename="main.py" complexity="0" line-rate="0" branch-rate="0">
42
+ <methods/>
43
+ <lines>
44
+ <line number="1" hits="0"/>
45
+ <line number="2" hits="0"/>
46
+ <line number="3" hits="0"/>
47
+ <line number="5" hits="0"/>
48
+ <line number="11" hits="0"/>
49
+ <line number="12" hits="0"/>
50
+ <line number="13" hits="0"/>
51
+ <line number="15" hits="0"/>
52
+ <line number="16" hits="0"/>
53
+ <line number="20" hits="0"/>
54
+ </lines>
55
+ </class>
56
+ <class name="model.py" filename="model.py" complexity="0" line-rate="0.9583" branch-rate="0">
57
+ <methods/>
58
+ <lines>
59
+ <line number="1" hits="1"/>
60
+ <line number="3" hits="1"/>
61
+ <line number="4" hits="1"/>
62
+ <line number="5" hits="1"/>
63
+ <line number="7" hits="1"/>
64
+ <line number="8" hits="1"/>
65
+ <line number="10" hits="1"/>
66
+ <line number="11" hits="1"/>
67
+ <line number="12" hits="1"/>
68
+ <line number="13" hits="1"/>
69
+ <line number="14" hits="1"/>
70
+ <line number="15" hits="1"/>
71
+ <line number="16" hits="1"/>
72
+ <line number="17" hits="1"/>
73
+ <line number="18" hits="1"/>
74
+ <line number="19" hits="1"/>
75
+ <line number="20" hits="1"/>
76
+ <line number="21" hits="1"/>
77
+ <line number="22" hits="1"/>
78
+ <line number="23" hits="1"/>
79
+ <line number="24" hits="1"/>
80
+ <line number="25" hits="1"/>
81
+ <line number="26" hits="1"/>
82
+ <line number="27" hits="1"/>
83
+ <line number="28" hits="1"/>
84
+ <line number="29" hits="1"/>
85
+ <line number="30" hits="1"/>
86
+ <line number="31" hits="1"/>
87
+ <line number="32" hits="1"/>
88
+ <line number="33" hits="1"/>
89
+ <line number="34" hits="1"/>
90
+ <line number="35" hits="1"/>
91
+ <line number="36" hits="1"/>
92
+ <line number="37" hits="1"/>
93
+ <line number="38" hits="1"/>
94
+ <line number="39" hits="1"/>
95
+ <line number="40" hits="1"/>
96
+ <line number="42" hits="1"/>
97
+ <line number="44" hits="1"/>
98
+ <line number="45" hits="1"/>
99
+ <line number="46" hits="1"/>
100
+ <line number="47" hits="1"/>
101
+ <line number="49" hits="1"/>
102
+ <line number="50" hits="1"/>
103
+ <line number="51" hits="1"/>
104
+ <line number="53" hits="1"/>
105
+ <line number="55" hits="0"/>
106
+ <line number="56" hits="0"/>
107
+ </lines>
108
+ </class>
109
+ <class name="predict.py" filename="predict.py" complexity="0" line-rate="0.4615" branch-rate="0">
110
+ <methods/>
111
+ <lines>
112
+ <line number="1" hits="1"/>
113
+ <line number="2" hits="1"/>
114
+ <line number="3" hits="1"/>
115
+ <line number="4" hits="1"/>
116
+ <line number="5" hits="1"/>
117
+ <line number="6" hits="1"/>
118
+ <line number="10" hits="1"/>
119
+ <line number="11" hits="1"/>
120
+ <line number="12" hits="1"/>
121
+ <line number="13" hits="1"/>
122
+ <line number="14" hits="1"/>
123
+ <line number="15" hits="0"/>
124
+ <line number="16" hits="0"/>
125
+ <line number="17" hits="0"/>
126
+ <line number="18" hits="0"/>
127
+ <line number="19" hits="0"/>
128
+ <line number="22" hits="1"/>
129
+ <line number="25" hits="1"/>
130
+ <line number="26" hits="1"/>
131
+ <line number="27" hits="1"/>
132
+ <line number="31" hits="1"/>
133
+ <line number="34" hits="1"/>
134
+ <line number="35" hits="1"/>
135
+ <line number="38" hits="1"/>
136
+ <line number="40" hits="1"/>
137
+ <line number="41" hits="1"/>
138
+ <line number="44" hits="1"/>
139
+ <line number="45" hits="1"/>
140
+ <line number="48" hits="1"/>
141
+ <line number="49" hits="0"/>
142
+ <line number="51" hits="0"/>
143
+ <line number="53" hits="0"/>
144
+ <line number="54" hits="0"/>
145
+ <line number="56" hits="0"/>
146
+ <line number="57" hits="0"/>
147
+ <line number="60" hits="0"/>
148
+ <line number="61" hits="0"/>
149
+ <line number="62" hits="0"/>
150
+ <line number="64" hits="0"/>
151
+ <line number="65" hits="0"/>
152
+ <line number="67" hits="0"/>
153
+ <line number="68" hits="0"/>
154
+ <line number="69" hits="0"/>
155
+ <line number="70" hits="0"/>
156
+ <line number="73" hits="0"/>
157
+ <line number="74" hits="0"/>
158
+ <line number="75" hits="0"/>
159
+ <line number="77" hits="0"/>
160
+ <line number="78" hits="0"/>
161
+ <line number="79" hits="0"/>
162
+ <line number="82" hits="0"/>
163
+ <line number="85" hits="0"/>
164
+ </lines>
165
+ </class>
166
+ <class name="schemas.py" filename="schemas.py" complexity="0" line-rate="1" branch-rate="0">
167
+ <methods/>
168
+ <lines>
169
+ <line number="1" hits="1"/>
170
+ <line number="3" hits="1"/>
171
+ <line number="4" hits="1"/>
172
+ <line number="5" hits="1"/>
173
+ <line number="6" hits="1"/>
174
+ <line number="7" hits="1"/>
175
+ <line number="8" hits="1"/>
176
+ <line number="9" hits="1"/>
177
+ <line number="10" hits="1"/>
178
+ <line number="11" hits="1"/>
179
+ <line number="12" hits="1"/>
180
+ <line number="13" hits="1"/>
181
+ <line number="14" hits="1"/>
182
+ <line number="15" hits="1"/>
183
+ <line number="16" hits="1"/>
184
+ <line number="17" hits="1"/>
185
+ <line number="18" hits="1"/>
186
+ <line number="19" hits="1"/>
187
+ <line number="20" hits="1"/>
188
+ <line number="21" hits="1"/>
189
+ <line number="22" hits="1"/>
190
+ <line number="23" hits="1"/>
191
+ <line number="24" hits="1"/>
192
+ <line number="25" hits="1"/>
193
+ <line number="26" hits="1"/>
194
+ <line number="27" hits="1"/>
195
+ <line number="28" hits="1"/>
196
+ <line number="29" hits="1"/>
197
+ <line number="30" hits="1"/>
198
+ <line number="31" hits="1"/>
199
+ <line number="32" hits="1"/>
200
+ <line number="33" hits="1"/>
201
+ </lines>
202
+ </class>
203
+ </classes>
204
+ </package>
205
+ </packages>
206
+ </coverage>
deploy_to_hf.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import HfApi
2
+ import os
3
+
4
+ api = HfApi()
5
+
6
+ api.upload_folder(
7
+ folder_path=".",
8
+ repo_id="Diaure/Futurisys_API_ML",
9
+ repo_type="space",
10
+ token=os.environ["HF_TOKEN"],
11
+ commit_message="CD: update from GitHub main"
12
+ )