Spaces:
Sleeping
Sleeping
Commit
·
b36a746
0
Parent(s):
feat: Fresh initial commit with LFS
Browse files- .gitattributes +2 -0
- .gitignore +28 -0
- Dockerfile +24 -0
- main.py +98 -0
- mon_modele_darija_final/config.json +54 -0
- mon_modele_darija_final/model.safetensors +3 -0
- mon_modele_darija_final/special_tokens_map.json +7 -0
- mon_modele_darija_final/tokenizer.json +0 -0
- mon_modele_darija_final/tokenizer_config.json +58 -0
- mon_modele_darija_final/training_args.bin +3 -0
- mon_modele_darija_final/vocab.txt +0 -0
- requirements.txt +14 -0
.gitattributes
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ==================================
|
2 |
+
# Environnements Virtuels Python
|
3 |
+
# ==================================
|
4 |
+
/venv/
|
5 |
+
/.venv/
|
6 |
+
/env/
|
7 |
+
/.env/
|
8 |
+
/ENV/
|
9 |
+
|
10 |
+
# ==================================
|
11 |
+
# Caches Python et fichiers compilés
|
12 |
+
# ==================================
|
13 |
+
__pycache__/
|
14 |
+
*.py[cod]
|
15 |
+
*$py.class
|
16 |
+
|
17 |
+
# ==================================
|
18 |
+
# Fichiers et dossiers des éditeurs
|
19 |
+
# ==================================
|
20 |
+
.vscode/
|
21 |
+
.idea/
|
22 |
+
|
23 |
+
# ==================================
|
24 |
+
# Autres
|
25 |
+
# ==================================
|
26 |
+
*.egg-info/
|
27 |
+
dist/
|
28 |
+
build/
|
Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Étape 1: Utiliser une image de base Python officielle
|
2 |
+
FROM python:3.9-slim
|
3 |
+
|
4 |
+
# Étape 2: Définir le répertoire de travail dans le container
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Étape 3: Copier le fichier des dépendances
|
8 |
+
COPY requirements.txt requirements.txt
|
9 |
+
|
10 |
+
# Étape 4: Installer les dépendances
|
11 |
+
# --no-cache-dir pour garder l'image légère
|
12 |
+
RUN pip install --no-cache-dir --upgrade pip
|
13 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
14 |
+
|
15 |
+
# Étape 5: Copier tout le reste de votre projet dans le container
|
16 |
+
# Cela inclut main.py et le dossier de votre modèle (ex: "marbert-darija-nlu-aicc")
|
17 |
+
COPY . .
|
18 |
+
|
19 |
+
# Étape 6: Exposer le port que votre API utilise
|
20 |
+
EXPOSE 8000
|
21 |
+
|
22 |
+
# Étape 7: La commande pour lancer l'API quand le container démarre
|
23 |
+
# Uvicorn est lancé avec host="0.0.0.0" pour être accessible de l'extérieur du container
|
24 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
main.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# main.py
|
2 |
+
|
3 |
+
import torch
|
4 |
+
from fastapi import FastAPI, HTTPException
|
5 |
+
from pydantic import BaseModel
|
6 |
+
from transformers import pipeline, AutoModelForSequenceClassification, AutoTokenizer
|
7 |
+
from typing import Dict, Any
|
8 |
+
|
9 |
+
# --- Configuration ---
|
10 |
+
# Chemin vers votre modèle fine-tuné. Assurez-vous que ce dossier est correct.
|
11 |
+
MODEL_PATH = "./mon_modele_darija_final"
|
12 |
+
|
13 |
+
# --- Chargement du modèle (partie critique) ---
|
14 |
+
# Cette partie est exécutée une seule fois, au démarrage du serveur.
|
15 |
+
# C'est une bonne pratique pour éviter de recharger le modèle à chaque requête.
|
16 |
+
try:
|
17 |
+
print("Chargement du tokenizer et du modèle MARBERT fine-tuné...")
|
18 |
+
|
19 |
+
# On spécifie le device (GPU si disponible, sinon CPU)
|
20 |
+
device = 0 if torch.cuda.is_available() else -1
|
21 |
+
|
22 |
+
# Création du pipeline de classification de texte de Hugging Face.
|
23 |
+
# C'est la manière la plus simple d'utiliser un modèle pour l'inférence.
|
24 |
+
nlu_pipeline = pipeline(
|
25 |
+
"text-classification",
|
26 |
+
model=MODEL_PATH,
|
27 |
+
tokenizer=MODEL_PATH,
|
28 |
+
device=device # Utilise le GPU si disponible
|
29 |
+
)
|
30 |
+
print("Modèle chargé avec succès !")
|
31 |
+
|
32 |
+
except Exception as e:
|
33 |
+
# Si le modèle ne peut pas être chargé, on lève une erreur claire.
|
34 |
+
print(f"Erreur critique lors du chargement du modèle: {e}")
|
35 |
+
nlu_pipeline = None
|
36 |
+
|
37 |
+
# --- Définition de l'application FastAPI ---
|
38 |
+
app = FastAPI(
|
39 |
+
title="API de NLU pour Darija Marocaine",
|
40 |
+
description="Une API pour classifier l'intention d'un texte en Darija, basée sur MARBERT.",
|
41 |
+
version="1.0.0"
|
42 |
+
)
|
43 |
+
|
44 |
+
# --- Définition des modèles de données (Pydantic) ---
|
45 |
+
# C'est pour la validation automatique des requêtes.
|
46 |
+
|
47 |
+
class TextInput(BaseModel):
|
48 |
+
"""Modèle pour le corps de la requête de prédiction."""
|
49 |
+
text: str # Le champ doit s'appeler 'text'
|
50 |
+
# Exemple de requête JSON attendue: {"text": "3afak bghit nchouf lfactura"}
|
51 |
+
|
52 |
+
class PredictionResponse(BaseModel):
|
53 |
+
"""Modèle pour la réponse de l'API."""
|
54 |
+
intent: str
|
55 |
+
confidence: float
|
56 |
+
|
57 |
+
# --- Définition des routes de l'API ---
|
58 |
+
|
59 |
+
@app.get("/", tags=["Général"])
|
60 |
+
def read_root() -> Dict[str, str]:
|
61 |
+
"""Route principale qui retourne un message de bienvenue."""
|
62 |
+
return {"message": "Bienvenue sur l'API de NLU Darija. Utilisez le endpoint /predict pour faire une prédiction."}
|
63 |
+
|
64 |
+
|
65 |
+
@app.get("/health", tags=["Général"])
|
66 |
+
def health_check() -> Dict[str, str]:
|
67 |
+
"""Route de 'health check' pour vérifier si le service est en ligne et le modèle chargé."""
|
68 |
+
if nlu_pipeline is None:
|
69 |
+
raise HTTPException(status_code=500, detail="Erreur: Le modèle NLP n'a pas pu être chargé.")
|
70 |
+
return {"status": "ok", "model_status": "loaded"}
|
71 |
+
|
72 |
+
|
73 |
+
@app.post("/predict", response_model=PredictionResponse, tags=["Prédiction"])
|
74 |
+
def predict_intent(request: TextInput) -> PredictionResponse:
|
75 |
+
"""
|
76 |
+
Endpoint principal pour la prédiction d'intention.
|
77 |
+
Prend un texte en entrée et retourne l'intention prédite et son score de confiance.
|
78 |
+
"""
|
79 |
+
if nlu_pipeline is None:
|
80 |
+
raise HTTPException(status_code=503, detail="Le service est indisponible car le modèle n'est pas chargé.")
|
81 |
+
|
82 |
+
if not request.text or not request.text.strip():
|
83 |
+
raise HTTPException(status_code=400, detail="Le champ 'text' ne peut pas être vide.")
|
84 |
+
|
85 |
+
try:
|
86 |
+
# Utilisation du pipeline pour faire la prédiction
|
87 |
+
prediction = nlu_pipeline(request.text, top_k=1)[0]
|
88 |
+
|
89 |
+
# Le pipeline retourne un dictionnaire avec 'label' et 'score'
|
90 |
+
# On renomme pour correspondre à notre modèle de réponse
|
91 |
+
intent = prediction['label']
|
92 |
+
confidence = prediction['score']
|
93 |
+
|
94 |
+
return PredictionResponse(intent=intent, confidence=confidence)
|
95 |
+
|
96 |
+
except Exception as e:
|
97 |
+
# Gestion d'erreurs inattendues pendant la prédiction
|
98 |
+
raise HTTPException(status_code=500, detail=f"Une erreur interne est survenue: {str(e)}")
|
mon_modele_darija_final/config.json
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"architectures": [
|
3 |
+
"BertForSequenceClassification"
|
4 |
+
],
|
5 |
+
"attention_probs_dropout_prob": 0.1,
|
6 |
+
"classifier_dropout": null,
|
7 |
+
"directionality": "bidi",
|
8 |
+
"gradient_checkpointing": false,
|
9 |
+
"hidden_act": "gelu",
|
10 |
+
"hidden_dropout_prob": 0.1,
|
11 |
+
"hidden_size": 768,
|
12 |
+
"id2label": {
|
13 |
+
"0": "consulter_solde",
|
14 |
+
"1": "declarer_panne",
|
15 |
+
"2": "demander_agent_humain",
|
16 |
+
"3": "hors_scope",
|
17 |
+
"4": "info_forfait",
|
18 |
+
"5": "reclamer_facture",
|
19 |
+
"6": "recuperer_mot_de_passe",
|
20 |
+
"7": "remerciements",
|
21 |
+
"8": "salutations"
|
22 |
+
},
|
23 |
+
"initializer_range": 0.02,
|
24 |
+
"intermediate_size": 3072,
|
25 |
+
"label2id": {
|
26 |
+
"consulter_solde": 0,
|
27 |
+
"declarer_panne": 1,
|
28 |
+
"demander_agent_humain": 2,
|
29 |
+
"hors_scope": 3,
|
30 |
+
"info_forfait": 4,
|
31 |
+
"reclamer_facture": 5,
|
32 |
+
"recuperer_mot_de_passe": 6,
|
33 |
+
"remerciements": 7,
|
34 |
+
"salutations": 8
|
35 |
+
},
|
36 |
+
"layer_norm_eps": 1e-12,
|
37 |
+
"max_position_embeddings": 512,
|
38 |
+
"model_type": "bert",
|
39 |
+
"num_attention_heads": 12,
|
40 |
+
"num_hidden_layers": 12,
|
41 |
+
"pad_token_id": 0,
|
42 |
+
"pooler_fc_size": 768,
|
43 |
+
"pooler_num_attention_heads": 12,
|
44 |
+
"pooler_num_fc_layers": 3,
|
45 |
+
"pooler_size_per_head": 128,
|
46 |
+
"pooler_type": "first_token_transform",
|
47 |
+
"position_embedding_type": "absolute",
|
48 |
+
"problem_type": "single_label_classification",
|
49 |
+
"torch_dtype": "float32",
|
50 |
+
"transformers_version": "4.52.4",
|
51 |
+
"type_vocab_size": 2,
|
52 |
+
"use_cache": true,
|
53 |
+
"vocab_size": 100000
|
54 |
+
}
|
mon_modele_darija_final/model.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:08322d4ab747d8187518d1d649c0bd36e7592fe4224f6b9885c3d2abe821d689
|
3 |
+
size 651416604
|
mon_modele_darija_final/special_tokens_map.json
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cls_token": "[CLS]",
|
3 |
+
"mask_token": "[MASK]",
|
4 |
+
"pad_token": "[PAD]",
|
5 |
+
"sep_token": "[SEP]",
|
6 |
+
"unk_token": "[UNK]"
|
7 |
+
}
|
mon_modele_darija_final/tokenizer.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
mon_modele_darija_final/tokenizer_config.json
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"added_tokens_decoder": {
|
3 |
+
"0": {
|
4 |
+
"content": "[PAD]",
|
5 |
+
"lstrip": false,
|
6 |
+
"normalized": false,
|
7 |
+
"rstrip": false,
|
8 |
+
"single_word": false,
|
9 |
+
"special": true
|
10 |
+
},
|
11 |
+
"1": {
|
12 |
+
"content": "[UNK]",
|
13 |
+
"lstrip": false,
|
14 |
+
"normalized": false,
|
15 |
+
"rstrip": false,
|
16 |
+
"single_word": false,
|
17 |
+
"special": true
|
18 |
+
},
|
19 |
+
"2": {
|
20 |
+
"content": "[CLS]",
|
21 |
+
"lstrip": false,
|
22 |
+
"normalized": false,
|
23 |
+
"rstrip": false,
|
24 |
+
"single_word": false,
|
25 |
+
"special": true
|
26 |
+
},
|
27 |
+
"3": {
|
28 |
+
"content": "[SEP]",
|
29 |
+
"lstrip": false,
|
30 |
+
"normalized": false,
|
31 |
+
"rstrip": false,
|
32 |
+
"single_word": false,
|
33 |
+
"special": true
|
34 |
+
},
|
35 |
+
"4": {
|
36 |
+
"content": "[MASK]",
|
37 |
+
"lstrip": false,
|
38 |
+
"normalized": false,
|
39 |
+
"rstrip": false,
|
40 |
+
"single_word": false,
|
41 |
+
"special": true
|
42 |
+
}
|
43 |
+
},
|
44 |
+
"clean_up_tokenization_spaces": true,
|
45 |
+
"cls_token": "[CLS]",
|
46 |
+
"do_basic_tokenize": true,
|
47 |
+
"do_lower_case": true,
|
48 |
+
"extra_special_tokens": {},
|
49 |
+
"mask_token": "[MASK]",
|
50 |
+
"model_max_length": 1000000000000000019884624838656,
|
51 |
+
"never_split": null,
|
52 |
+
"pad_token": "[PAD]",
|
53 |
+
"sep_token": "[SEP]",
|
54 |
+
"strip_accents": null,
|
55 |
+
"tokenize_chinese_chars": true,
|
56 |
+
"tokenizer_class": "BertTokenizer",
|
57 |
+
"unk_token": "[UNK]"
|
58 |
+
}
|
mon_modele_darija_final/training_args.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:1bd13abe00ada94ffbf7c954ed271cc6b814dccf8eb05202ad4977182cdba021
|
3 |
+
size 5304
|
mon_modele_darija_final/vocab.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
requirements.txt
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# ---- Core API Framework ----
|
2 |
+
fastapi
|
3 |
+
uvicorn
|
4 |
+
|
5 |
+
# ---- Machine Learning Model & Pipeline ----
|
6 |
+
# On ne spécifie pas la version de torch car il est préférable de l'installer séparément
|
7 |
+
# ou de laisser pip résoudre la dépendance en fonction de la plateforme (CPU/GPU)
|
8 |
+
# mais pour une image Docker déterministe, la figer est une option.
|
9 |
+
torch==2.7.1
|
10 |
+
transformers==4.52.4
|
11 |
+
|
12 |
+
# ---- FastAPI Specific ----
|
13 |
+
# Nécessaire pour gérer les formulaires et le téléversement de fichiers, bonne pratique.
|
14 |
+
python-multipart
|