mediani commited on
Commit
b36a746
·
0 Parent(s):

feat: Fresh initial commit with LFS

Browse files
.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