Merge pull request #7 from Tbruand/deploy/hf-sync
Browse filesfeat: ajout du déploiement automatique vers Hugging Face via GitHub Actions
- .github/workflows/cd.yml +26 -0
- README.md +45 -0
- app/handler.py +6 -4
- tests/test_handler.py +10 -1
- tox.ini +1 -2
.github/workflows/cd.yml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: CD - Déploiement Hugging Face Space
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- main # 🛑 Le CD ne se déclenche que sur la branche main
|
7 |
+
workflow_dispatch: # 🔘 Option pour lancer manuellement le CD
|
8 |
+
|
9 |
+
jobs:
|
10 |
+
deploy:
|
11 |
+
needs: ci # ➕ Attend que le job CI passe avant de lancer le CD
|
12 |
+
runs-on: ubuntu-latest
|
13 |
+
|
14 |
+
steps:
|
15 |
+
- name: Checkout repository
|
16 |
+
uses: actions/checkout@v3
|
17 |
+
with:
|
18 |
+
fetch-depth: 0
|
19 |
+
lfs: true
|
20 |
+
|
21 |
+
- name: Push to Hugging Face Space
|
22 |
+
env:
|
23 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
24 |
+
run: |
|
25 |
+
git remote add space https://Tbruand:$HF_TOKEN@huggingface.co/spaces/Tbruand/toxicheck || true
|
26 |
+
git push space main --force
|
README.md
CHANGED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: ToxiCheck
|
3 |
+
emoji: 🧪
|
4 |
+
colorFrom: indigo
|
5 |
+
colorTo: pink
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 4.25.0
|
8 |
+
app_file: main.py
|
9 |
+
pinned: false
|
10 |
+
---
|
11 |
+
|
12 |
+
# 🧪 ToxiCheck — Détection de commentaires toxiques en français
|
13 |
+
|
14 |
+
ToxiCheck est une interface Gradio qui permet de détecter automatiquement la toxicité d’un texte en français à l’aide d’un modèle **CamemBERT** fine-tuné.
|
15 |
+
|
16 |
+
Ce projet intègre :
|
17 |
+
- Une interface utilisateur interactive (via Gradio),
|
18 |
+
- Deux onglets : `Documentation` & `Inférence`,
|
19 |
+
- Un pipeline NLP complet : tokenizer, prédiction, interprétation.
|
20 |
+
|
21 |
+
---
|
22 |
+
|
23 |
+
## 🔗 Modèle utilisé
|
24 |
+
|
25 |
+
Modèle hébergé sur Hugging Face :
|
26 |
+
👉 [ymokay/toxicheck-camembert](https://huggingface.co/ymokay/toxicheck-camembert)
|
27 |
+
|
28 |
+
---
|
29 |
+
|
30 |
+
## ⚙️ Technologies
|
31 |
+
|
32 |
+
- 🧠 Transformers (CamemBERT)
|
33 |
+
- 🖼️ Gradio
|
34 |
+
- 🧪 PyTorch
|
35 |
+
- 🐍 Python 3.10
|
36 |
+
|
37 |
+
---
|
38 |
+
|
39 |
+
## 🛠️ Lancement local
|
40 |
+
|
41 |
+
```bash
|
42 |
+
git clone https://github.com/Tbruand/toxicheck.git
|
43 |
+
cd toxicheck
|
44 |
+
pip install -r requirements.txt
|
45 |
+
python main.py
|
app/handler.py
CHANGED
@@ -1,17 +1,19 @@
|
|
1 |
from models.zero_shot import ZeroShotModel
|
2 |
from models.few_shot import FewShotModel
|
3 |
-
from models.fine_tuned import FineTunedModel
|
4 |
|
5 |
zero_shot_model = ZeroShotModel()
|
6 |
few_shot_model = FewShotModel()
|
7 |
-
|
|
|
|
|
|
|
8 |
|
9 |
def predict(text: str, model_type: str = "zero-shot") -> str:
|
10 |
if model_type == "few-shot":
|
11 |
results = few_shot_model.predict(text)
|
12 |
title = "Few-Shot"
|
13 |
elif model_type == "fine-tuned":
|
14 |
-
results =
|
15 |
title = "Fine-Tuned"
|
16 |
else:
|
17 |
results = zero_shot_model.predict(text)
|
@@ -19,5 +21,5 @@ def predict(text: str, model_type: str = "zero-shot") -> str:
|
|
19 |
|
20 |
output = f"### Résultat de la classification ({title}) :\n\n"
|
21 |
for label, score in results:
|
22 |
-
output += f"- **{label}** : {score*100:.1f}%\n"
|
23 |
return output
|
|
|
1 |
from models.zero_shot import ZeroShotModel
|
2 |
from models.few_shot import FewShotModel
|
|
|
3 |
|
4 |
zero_shot_model = ZeroShotModel()
|
5 |
few_shot_model = FewShotModel()
|
6 |
+
|
7 |
+
def get_fine_tuned_model():
|
8 |
+
from models.fine_tuned import FineTunedModel
|
9 |
+
return FineTunedModel()
|
10 |
|
11 |
def predict(text: str, model_type: str = "zero-shot") -> str:
|
12 |
if model_type == "few-shot":
|
13 |
results = few_shot_model.predict(text)
|
14 |
title = "Few-Shot"
|
15 |
elif model_type == "fine-tuned":
|
16 |
+
results = get_fine_tuned_model().predict(text)
|
17 |
title = "Fine-Tuned"
|
18 |
else:
|
19 |
results = zero_shot_model.predict(text)
|
|
|
21 |
|
22 |
output = f"### Résultat de la classification ({title}) :\n\n"
|
23 |
for label, score in results:
|
24 |
+
output += f"- **{label}** : {score * 100:.1f}%\n"
|
25 |
return output
|
tests/test_handler.py
CHANGED
@@ -24,4 +24,13 @@ def test_few_shot_prediction_output():
|
|
24 |
print("Résultat few-shot :", output)
|
25 |
|
26 |
assert "### Résultat de la classification" in output
|
27 |
-
assert "toxique" in output or "non-toxique" in output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
print("Résultat few-shot :", output)
|
25 |
|
26 |
assert "### Résultat de la classification" in output
|
27 |
+
assert "toxique" in output or "non-toxique" in output
|
28 |
+
|
29 |
+
def test_fine_tuned_prediction_output():
|
30 |
+
text = "Tu es stupide"
|
31 |
+
output = predict(text, model_type="fine-tuned")
|
32 |
+
|
33 |
+
print("Résultat fine-tuned :", output)
|
34 |
+
|
35 |
+
assert "### Résultat de la classification" in output
|
36 |
+
assert "toxique" in output or "non-toxique" in output
|
tox.ini
CHANGED
@@ -2,5 +2,4 @@
|
|
2 |
testpaths = tests
|
3 |
python_files = test_*.py
|
4 |
filterwarnings =
|
5 |
-
ignore::DeprecationWarning
|
6 |
-
addopts = --cov=app
|
|
|
2 |
testpaths = tests
|
3 |
python_files = test_*.py
|
4 |
filterwarnings =
|
5 |
+
ignore::DeprecationWarning
|
|