Loren commited on
Commit
333cede
·
verified ·
1 Parent(s): 5907da4

Upload 8 files

Browse files
Files changed (8) hide show
  1. Dockerfile +32 -0
  2. app.py +184 -0
  3. config.py +20 -0
  4. data/260717_FAQ_Miss_Terry_developpeur.json +1381 -0
  5. embeddings.py +188 -0
  6. faq_loader.py +99 -0
  7. models.py +62 -0
  8. requirements.txt +9 -0
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Définir le répertoire de travail
4
+ WORKDIR /app
5
+
6
+ # Installer les dépendances système (optionnel mais utile pour torch)
7
+ RUN apt-get update && apt-get install -y \
8
+ build-essential \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copier les fichiers de requirements
12
+ COPY requirements.txt .
13
+
14
+ # Installer les dépendances Python
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Copier le code de l'application
18
+ COPY app.py .
19
+ COPY config.py .
20
+ COPY models.py .
21
+ COPY faq_loader.py .
22
+ COPY embeddings.py .
23
+
24
+ # Copier les données
25
+ COPY data/ data/
26
+
27
+ # Port utilisé par HF Spaces (7860 par défaut)
28
+ EXPOSE 7860
29
+
30
+ # Lancer l'application
31
+ # HF Spaces redirige le port 7860 vers le port de l'interface web
32
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Application FastAPI pour répondre aux questions FAQ via embeddings multilingues."""
2
+ import logging
3
+ import sys
4
+ from contextlib import asynccontextmanager
5
+
6
+ from fastapi import FastAPI, HTTPException
7
+ from fastapi.responses import HTMLResponse, Response
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+
10
+ from config import FAQ_JSON_PATH
11
+ from embeddings import EmbeddingManager
12
+ from faq_loader import FAQEntry, load_faq_data
13
+ from models import AnswerOutput, HealthResponse, QuestionInput
14
+
15
+ # Configuration du logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Variables globales
23
+ embedding_manager: EmbeddingManager | None = None
24
+ faq_entries: list[FAQEntry] = []
25
+
26
+
27
+ @asynccontextmanager
28
+ async def lifespan(app: FastAPI):
29
+ """
30
+ Gestion du cycle de vie de l'application FastAPI.
31
+
32
+ Au démarrage: charger les FAQ et les embeddings dans ChromaDB
33
+ À l'arrêt: nettoyer les ressources
34
+ """
35
+ # --- Startup ---
36
+ logger.info("🚀 Démarrage de l'application...")
37
+
38
+ global embedding_manager, faq_entries
39
+
40
+ try:
41
+ # Initialiser le gestionnaire d'embeddings
42
+ embedding_manager = EmbeddingManager()
43
+
44
+ # Charger les données FAQ
45
+ logger.info("📚 Chargement des données FAQ...")
46
+ faq_entries = load_faq_data(FAQ_JSON_PATH)
47
+
48
+ # Peupler ChromaDB
49
+ embedding_manager.populate_collection(faq_entries)
50
+
51
+ logger.info(f"✓ Application prête - {embedding_manager.get_collection_size()} FAQs indexées")
52
+
53
+ except Exception as e:
54
+ logger.error(f"❌ Erreur au démarrage: {e}")
55
+ # En cas d'erreur fatale au démarrage, quitter le process pour éviter
56
+ # que la plateforme (ex: Hugging Face Spaces) reste en 'starting'.
57
+ sys.exit(1)
58
+
59
+ yield
60
+
61
+ # --- Shutdown ---
62
+ logger.info("🛑 Arrêt de l'application...")
63
+ embedding_manager = None
64
+ faq_entries = []
65
+
66
+
67
+ # Créer l'application FastAPI
68
+ app = FastAPI(
69
+ title="API FAQ Search",
70
+ description="API pour répondre à des questions via recherche de similarité sur une base FAQ",
71
+ version="1.0.0",
72
+ lifespan=lifespan,
73
+ )
74
+
75
+ # Configuration CORS (adapter selon vos besoins)
76
+ app.add_middleware(
77
+ CORSMiddleware,
78
+ allow_origins=["*"],
79
+ allow_credentials=True,
80
+ allow_methods=["*"],
81
+ allow_headers=["*"],
82
+ )
83
+
84
+
85
+ @app.get("/health", response_model=HealthResponse)
86
+ async def health_check() -> HealthResponse:
87
+ """
88
+ Endpoint de vérification de l'état du service.
89
+
90
+ Returns:
91
+ HealthResponse avec status et nombre de FAQs indexées
92
+ """
93
+ if embedding_manager is None:
94
+ raise HTTPException(
95
+ status_code=503,
96
+ detail="Service non initialisé - les embeddings ne sont pas chargés",
97
+ )
98
+
99
+ faq_count: int = embedding_manager.get_collection_size()
100
+
101
+ return HealthResponse(
102
+ status="ok",
103
+ faq_count=faq_count,
104
+ )
105
+
106
+
107
+ @app.post("/ask", response_model=AnswerOutput)
108
+ async def ask_question(input_data: QuestionInput) -> AnswerOutput:
109
+ """
110
+ Endpoint principal pour poser une question à la base FAQ.
111
+
112
+ Reçoit une question en texte libre, génère son embedding multilingue,
113
+ et retourne la réponse la plus similaire avec un score de confiance.
114
+
115
+ Args:
116
+ input_data: Requête contenant la question
117
+
118
+ Returns:
119
+ AnswerOutput avec la réponse trouvée, la formulation, le theme, et le score de similarité
120
+
121
+ Raises:
122
+ HTTPException: Si le service n'est pas initialisé ou aucun match trouvé au-dessus du seuil
123
+ """
124
+ if embedding_manager is None:
125
+ raise HTTPException(
126
+ status_code=503,
127
+ detail="Service non initialisé - les embeddings ne sont pas chargés",
128
+ )
129
+
130
+ question: str = input_data.question
131
+ logger.info(f"📝 Question reçue: {question}")
132
+
133
+ # Rechercher la FAQ similaire (le seuil peut être fourni dans `input_data.threshold`)
134
+ result = embedding_manager.search_similar_faq(input_data)
135
+
136
+ # `search_similar_faq` renvoie déjà un `AnswerOutput` (avec `confidence=False` si pas de match)
137
+ logger.info(f"✓ Réponse préparée pour: {question}")
138
+ return result
139
+
140
+
141
+ @app.get("/list")
142
+ async def list_faq_entries() -> Response:
143
+ """Retourner toutes les FAQ sous forme de chaîne Markdown."""
144
+ if not faq_entries:
145
+ raise HTTPException(
146
+ status_code=503,
147
+ detail="Service non initialisé - les FAQ ne sont pas chargées",
148
+ )
149
+
150
+ markdown_output: str = "\n\n".join(
151
+ f"**{entry.formulation}**\n{entry.response}" for entry in faq_entries
152
+ )
153
+
154
+ return Response(content=markdown_output, media_type="text/markdown")
155
+
156
+
157
+ @app.get("/", response_class=HTMLResponse)
158
+ async def root() -> str:
159
+ """Endpoint root avec information sur l'API."""
160
+ #return {
161
+ # "message": "Bienvenue sur l'API FAQ - Embeddings multilingues",
162
+ # "docs": "/docs",
163
+ # "health": "/health",
164
+ # "ask": "/ask",
165
+ #}
166
+ return """
167
+ <html>
168
+ <head><title>Page d'accueil</title></head>
169
+ <body>
170
+ <h1>Welcome on the FAQ API !</h1>
171
+ </body>
172
+ </html>
173
+ """
174
+
175
+ if __name__ == "__main__":
176
+ import uvicorn
177
+
178
+ uvicorn.run(
179
+ "app:app",
180
+ host="0.0.0.0",
181
+ port=8000,
182
+ reload=True,
183
+ log_level="info",
184
+ )
config.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration centralisée pour l'API FAQ."""
2
+ import os
3
+ from pathlib import Path
4
+
5
+ # Répertoires
6
+ BASE_DIR: Path = Path(__file__).parent
7
+ DATA_DIR: Path = BASE_DIR / "data"
8
+
9
+ # Chemin du fichier JSON FAQ
10
+ FAQ_JSON_PATH: str = str(DATA_DIR / "260717_FAQ_Miss_Terry_developpeur.json")
11
+
12
+ # Configuration des embeddings
13
+ MODEL_NAME: str = os.getenv("MODEL_NAME", "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
14
+
15
+ # Configuration ChromaDB
16
+ CHROMA_COLLECTION_NAME: str = "faq"
17
+
18
+ # Configuration de similarité
19
+ SIMILARITY_THRESHOLD: float = float(os.getenv("SIMILARITY_THRESHOLD", "0.85"))
20
+
data/260717_FAQ_Miss_Terry_developpeur.json ADDED
@@ -0,0 +1,1381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "schema_version": "1.0.0",
3
+ "name": "Miss Terry - FAQ Guild Open Tech",
4
+ "language": "fr-FR",
5
+ "source_file": "260717_FAQ_Miss_Terry_x_formulations.xlsx",
6
+ "generated_at": "2026-07-17T12:33:28.801421+00:00",
7
+ "matching": {
8
+ "strategy": "intent_classification",
9
+ "recommended_order": [
10
+ "exact_or_normalized_match_on_utterances",
11
+ "semantic_similarity_against_utterances",
12
+ "RAG_or_LLM_fallback",
13
+ "human_handoff_for_ambiguous_or_individual_cases"
14
+ ],
15
+ "response_policy": "Return the canonical response associated with the best matching intent.",
16
+ "normalization_recommendations": [
17
+ "lowercase",
18
+ "trim_whitespace",
19
+ "collapse_multiple_spaces",
20
+ "remove_terminal_punctuation_for_matching",
21
+ "accent_insensitive_comparison as a secondary normalization only"
22
+ ]
23
+ },
24
+ "intents": [
25
+ {
26
+ "id": "got_faq_001",
27
+ "source_id": 1,
28
+ "category": "Comprendre GOT",
29
+ "intent_key": "qu_est_ce_que_guild_open_tech",
30
+ "canonical_question": "Qu’est-ce que Guild Open Tech ?",
31
+ "utterances": [
32
+ "Qu’est-ce que Guild Open Tech ?",
33
+ "C’est quoi Guild Open Tech ?",
34
+ "Comment ça marche ?",
35
+ "GOT, c’est quoi au juste ?",
36
+ "À quoi sert votre association ?",
37
+ "Tu peux m’expliquer ce qu’est Guild Open Tech ? GOT ?"
38
+ ],
39
+ "response": "Guild Open Tech est une association qui permet de développer et de partager des compétences utilisables dans le milieu informatique, en développement, gestion de projet, ou RH. Tu participes bénévolement à des projets collaboratifs et open source. Chez GOT, on apprend principalement en faisant, avec d’autres personnes qui ont des expériences et des niveaux différents.",
40
+ "enabled": true
41
+ },
42
+ {
43
+ "id": "got_faq_002",
44
+ "source_id": 2,
45
+ "category": "Comprendre GOT",
46
+ "intent_key": "est_ce_que_c_est_gratuit",
47
+ "canonical_question": "Est-ce que c’est gratuit ?",
48
+ "utterances": [
49
+ "Est-ce que c’est gratuit ?",
50
+ "C’est vraiment gratuit ?",
51
+ "Il faut payer pour participer ?",
52
+ "L’adhésion est payante ?",
53
+ "Ça coûte combien de rejoindre GOT ?",
54
+ "Il y a une cotisation ou des frais ?"
55
+ ],
56
+ "response": "Oui. L’adhésion et la participation aux projets de Guild Open Tech sont gratuites. Il n’y a ni frais de formation ni cotisation obligatoire pour contribuer aux projets.",
57
+ "enabled": true
58
+ },
59
+ {
60
+ "id": "got_faq_003",
61
+ "source_id": 3,
62
+ "category": "Comprendre GOT",
63
+ "intent_key": "comment_rejoindre_guild_open_tech",
64
+ "canonical_question": "Comment rejoindre Guild Open Tech ?",
65
+ "utterances": [
66
+ "Comment rejoindre Guild Open Tech ?",
67
+ "Comment je peux vous rejoindre ?",
68
+ "Je fais comment pour m’inscrire ?",
69
+ "Comment devenir membre de GOT ?",
70
+ "Où est-ce que je peux candidater ?",
71
+ "Quelles sont les étapes pour vous rejoindre ?"
72
+ ],
73
+ "response": "Tu peux soit 'tinscrire, soit commencer ta candidature depuis le bouton « Inscription » du site. Tu renseigneras ton profil, tes compétences et les domaines qui t’intéressent afin que l’équipe puisse étudier ta candidature.",
74
+ "enabled": true
75
+ },
76
+ {
77
+ "id": "got_faq_004",
78
+ "source_id": 4,
79
+ "category": "Comprendre GOT",
80
+ "intent_key": "comment_candidater_a_un_projet",
81
+ "canonical_question": "Comment candidater à un projet ?",
82
+ "utterances": [
83
+ "Comment candidater à un projet ?",
84
+ "Comment postuler sur un projet ?",
85
+ "Je fais comment pour rejoindre une équipe ?",
86
+ "Où est-ce que je peux candidater ?",
87
+ "Comment proposer ma candidature pour un projet ?",
88
+ "Je voudrais participer à un projet, comment faire ?"
89
+ ],
90
+ "response": "La candidature se fait en ligne depuis le bouton « Inscription». Le service RH va te contacter pour enregistrer ton profil dans BEN, notre ERP. Puis l’équipe regarde notamment tes compétences, ce que tu souhaites développer et les besoins des projets en cours. Dans tous les cas tu vas t'inscrire sur notre serveur Discord.",
91
+ "enabled": true
92
+ },
93
+ {
94
+ "id": "got_faq_005",
95
+ "source_id": 5,
96
+ "category": "Comprendre GOT",
97
+ "intent_key": "est_ce_que_je_dois_deja_etre_developpeur_ou_travailler_dans_l_informatique",
98
+ "canonical_question": "Est-ce que je dois déjà être développeur ou travailler dans l’informatique ?",
99
+ "utterances": [
100
+ "Est-ce que je dois déjà être développeur ou travailler dans l’informatique ?",
101
+ "Il faut forcément être développeur ?",
102
+ "Vous prenez seulement des profils tech ?",
103
+ "Je ne travaille pas dans l’informatique, je peux quand même participer ?",
104
+ "Il faut déjà avoir un métier dans la tech ?",
105
+ "Les profils non-développeurs peuvent vous rejoindre ?"
106
+ ],
107
+ "response": "Les projets informatiques ont besoin de profils développeurs mais aussi UX/UI, produit, gestion de projet, communication, marketing ou création de contenus, RH, juridique ou administratif. Tu dois surtout pouvoir apporter une compétence utile au projet ou avoir des bases suffisantes pour y contribuer sérieusement.",
108
+ "enabled": true
109
+ },
110
+ {
111
+ "id": "got_faq_006",
112
+ "source_id": 6,
113
+ "category": "Comprendre GOT",
114
+ "intent_key": "les_profils_non_techniques_sont_ils_acceptes",
115
+ "canonical_question": "Les profils non techniques sont-ils acceptés ?",
116
+ "utterances": [
117
+ "Les profils non techniques sont-ils acceptés ?",
118
+ "Vous recrutez aussi des profils non-tech ?",
119
+ "Est-ce qu’il y a des missions en RH ou communication ?",
120
+ "Je ne code pas, est-ce que je peux quand même contribuer ?",
121
+ "Vous avez besoin de profils produit, UX ou gestion de projet ?",
122
+ "Les fonctions support peuvent rejoindre GOT ?"
123
+ ],
124
+ "response": "Les projets informatiques ont besoin de profils développeurs mais aussi UX/UI, produit, gestion de projet, communication, marketing ou création de contenus, RH, juridique ou administratif. Tu dois surtout pouvoir apporter une compétence utile au projet ou avoir des bases suffisantes pour y contribuer sérieusement.",
125
+ "enabled": true
126
+ },
127
+ {
128
+ "id": "got_faq_007",
129
+ "source_id": 7,
130
+ "category": "Comprendre GOT",
131
+ "intent_key": "est_ce_que_les_debutants_sont_acceptes",
132
+ "canonical_question": "Est-ce que les débutants sont acceptés ?",
133
+ "utterances": [
134
+ "Est-ce que les débutants sont acceptés ?",
135
+ "Vous acceptez les débutants ?",
136
+ "Je débute, est-ce que je peux quand même venir ?",
137
+ "Il faut déjà avoir un bon niveau ?",
138
+ "C’est ouvert aux juniors ?",
139
+ "Je n’ai pas beaucoup d’expérience, ma candidature peut être acceptée ?"
140
+ ],
141
+ "response": "Oui, selon le projet et le niveau d’autonomie nécessaire. Guild Open Tech permet justement de progresser en travaillant sur des projets concrets, mais ce n’est pas un cours où quelqu’un réalise le travail à ta place. Il faut donc être prêt à chercher, essayer et collaborer.",
142
+ "enabled": true
143
+ },
144
+ {
145
+ "id": "got_faq_008",
146
+ "source_id": 8,
147
+ "category": "Comprendre GOT",
148
+ "intent_key": "combien_de_temps_faut_il_consacrer_a_l_association",
149
+ "canonical_question": "Combien de temps faut-il consacrer à l’association ?",
150
+ "utterances": [
151
+ "Combien de temps faut-il consacrer à l’association ?",
152
+ "Il faut prévoir combien d’heures par semaine ?",
153
+ "Ça prend combien de temps de participer ?",
154
+ "Quel temps faut-il donner à GOT ?",
155
+ "Vous demandez combien de disponibilité ?",
156
+ "Il faut être disponible combien de temps ?"
157
+ ],
158
+ "response": "Le temps nécessaire dépend du projet, du rôle et des engagements pris avec l’équipe. Le plus important est d’annoncer une disponibilité réaliste et de respecter ce qui a été convenu, car une contribution irrégulière peut bloquer les autres membres.",
159
+ "enabled": true
160
+ },
161
+ {
162
+ "id": "got_faq_009",
163
+ "source_id": 9,
164
+ "category": "Organisation et engagement",
165
+ "intent_key": "y_a_t_il_un_nombre_d_heures_minimum_par_semaine",
166
+ "canonical_question": "Y a-t-il un nombre d’heures minimum par semaine ?",
167
+ "utterances": [
168
+ "Y a-t-il un nombre d’heures minimum par semaine ?",
169
+ "Il faut faire un minimum d’heures ?",
170
+ "Vous demandez combien d’heures chaque semaine ?",
171
+ "Il y a un quota d’heures à respecter ?",
172
+ "Je dois m’engager sur combien d’heures ?",
173
+ "Est-ce qu’il y a une disponibilité minimale ?"
174
+ ],
175
+ "response": "Le temps nécessaire dépend du projet, du rôle et des engagements pris avec l’équipe. Le plus important est d’annoncer une disponibilité réaliste et de respecter ce qui a été convenu, car une contribution irrégulière peut bloquer les autres membres.",
176
+ "enabled": true
177
+ },
178
+ {
179
+ "id": "got_faq_010",
180
+ "source_id": 10,
181
+ "category": "Comprendre GOT",
182
+ "intent_key": "est_ce_du_benevolat",
183
+ "canonical_question": "Est-ce du bénévolat ?",
184
+ "utterances": [
185
+ "Est-ce du bénévolat ?",
186
+ "C’est une mission bénévole ?",
187
+ "On participe comme bénévole ?",
188
+ "C’est un emploi ou du bénévolat ?",
189
+ "Quel est le statut des participants ?",
190
+ "Je serai bénévole chez GOT ?"
191
+ ],
192
+ "response": "Oui. Les membres contribuent bénévolement aux activités et aux projets de l’association, sans contrepartie financière. Un contrat de bénévolat encadre la collaboration et les responsabilités de chacun.",
193
+ "enabled": true
194
+ },
195
+ {
196
+ "id": "got_faq_011",
197
+ "source_id": 11,
198
+ "category": "Comprendre GOT",
199
+ "intent_key": "est_ce_une_formation",
200
+ "canonical_question": "Est-ce une formation ?",
201
+ "utterances": [
202
+ "Est-ce une formation ?",
203
+ "Vous êtes un organisme de formation ?",
204
+ "C’est une école informatique ?",
205
+ "On suit une formation chez vous ?",
206
+ "GOT propose un parcours de formation ?",
207
+ "Est-ce que je vais avoir des cours comme dans une école ?"
208
+ ],
209
+ "response": "Guild Open Tech n’est pas un organisme de formation. Aujourd’hui, l’apprentissage se fait principalement par la participation à des projets collaboratifs réels. Cependant, nous avons un projet GOT-Learn, qui doit proposer des sujets de formation plus structurés. C'est encore en cours de développement.",
210
+ "enabled": true
211
+ },
212
+ {
213
+ "id": "got_faq_012",
214
+ "source_id": 12,
215
+ "category": "Comprendre GOT",
216
+ "intent_key": "est_ce_que_vous_proposez_des_cours",
217
+ "canonical_question": "Est-ce que vous proposez des cours ?",
218
+ "utterances": [
219
+ "Est-ce que vous proposez des cours ?",
220
+ "Vous donnez des cours ?",
221
+ "Il y a des cours en ligne ?",
222
+ "Vous avez un catalogue de cours ?",
223
+ "Est-ce qu’on peut suivre des leçons chez GOT ?",
224
+ "Vous proposez des modules de cours ?"
225
+ ],
226
+ "response": "Il n'y a pas actuellement un catalogue de cours en e-learning. On développe surtout ses compétences en participant aux projets. Le projet GOT-Learn a pour objectif de proposer des contenus et des sujets de formation structurée, mais il est encore en cours de développement.",
227
+ "enabled": true
228
+ },
229
+ {
230
+ "id": "got_faq_013",
231
+ "source_id": 13,
232
+ "category": "Comprendre GOT",
233
+ "intent_key": "est_ce_que_je_peux_obtenir_une_certification",
234
+ "canonical_question": "Est-ce que je peux obtenir une certification ?",
235
+ "utterances": [
236
+ "Est-ce que je peux obtenir une certification ?",
237
+ "Vous délivrez des certifications ?",
238
+ "Est-ce qu’il y a un certificat à la fin ?",
239
+ "Je peux passer une certification avec GOT ?",
240
+ "Vos parcours sont certifiants ?",
241
+ "Est-ce que GOT donne un diplôme ou une certification ?"
242
+ ],
243
+ "response": "Les certifications font partie des objectifs futurs de Guild Open Tech, mais elles ne sont pas disponibles actuellement.",
244
+ "enabled": true
245
+ },
246
+ {
247
+ "id": "got_faq_014",
248
+ "source_id": 14,
249
+ "category": "Comprendre GOT",
250
+ "intent_key": "quels_projets_sont_actuellement_disponibles",
251
+ "canonical_question": "Quels projets sont actuellement disponibles ?",
252
+ "utterances": [
253
+ "Quels projets sont actuellement disponibles ?",
254
+ "Quels projets peut-on rejoindre en ce moment ?",
255
+ "Vous avez quoi comme projets ouverts ?",
256
+ "Sur quels projets je peux candidater ?",
257
+ "Quels sont les projets en cours ?",
258
+ "Il y a quels projets disponibles actuellement ?"
259
+ ],
260
+ "response": "Les projets et les besoins évoluent selon leur avancement et la composition des équipes. Tu peux consulter les projets présentés sur le site et aborder ceux qui tintéressent en cours d'entretien de recrutement. L’équipe pourra ensuite te préciser les possibilités réellement ouvertes au moment de ta candidature.",
261
+ "enabled": true
262
+ },
263
+ {
264
+ "id": "got_faq_015",
265
+ "source_id": 15,
266
+ "category": "Comprendre GOT",
267
+ "intent_key": "quelles_technologies_utilisez_vous",
268
+ "canonical_question": "Quelles technologies utilisez-vous ?",
269
+ "utterances": [
270
+ "Quelles technologies utilisez-vous ?",
271
+ "Vous travaillez avec quelles technos ?",
272
+ "C’est quoi votre stack technique ?",
273
+ "Quels langages et outils utilisez-vous ?",
274
+ "Vous développez avec quoi ?",
275
+ "Quelles technologies sont utilisées dans vos projets ?"
276
+ ],
277
+ "response": "Les technologies dépendent des projets. Guild Open Tech travaille notamment sur des applications web, des API, du cloud, de l’intelligence artificielle et différents outils open source. Les technologies utilisées sont précisées dans la présentation ou les besoins de chaque projet.",
278
+ "enabled": true
279
+ },
280
+ {
281
+ "id": "got_faq_016",
282
+ "source_id": 16,
283
+ "category": "Comprendre GOT",
284
+ "intent_key": "puis_je_rejoindre_un_projet_sur_une_technologie_que_je_ne_maitrise_pas_encore",
285
+ "canonical_question": "Puis-je rejoindre un projet sur une technologie que je ne maîtrise pas encore ?",
286
+ "utterances": [
287
+ "Puis-je rejoindre un projet sur une technologie que je ne maîtrise pas encore ?",
288
+ "Je peux candidater si je ne connais pas encore la techno ?",
289
+ "On peut apprendre une nouvelle technologie sur un projet ?",
290
+ "Il faut déjà maîtriser la stack pour participer ?",
291
+ "Je peux rejoindre une équipe pour découvrir une techno ?",
292
+ "Est-ce que je peux participer sans connaître tous les outils du projet ?"
293
+ ],
294
+ "response": "Oui, à condition d’avoir des bases qui te permettent de contribuer et d’être un minimum autonome dans ton apprentissage. Tu peux apporter les compétences que tu maîtrises déjà tout en développant une nouvelle compétence avec d'autres membres plus seniors dans l’équipe.",
295
+ "enabled": true
296
+ },
297
+ {
298
+ "id": "got_faq_017",
299
+ "source_id": 17,
300
+ "category": "Comprendre GOT",
301
+ "intent_key": "puis_je_developper_une_competence_differente_de_celle_que_j_utilise_dans_mon_emploi",
302
+ "canonical_question": "Puis-je développer une compétence différente de celle que j’utilise dans mon emploi ?",
303
+ "utterances": [
304
+ "Puis-je développer une compétence différente de celle que j’utilise dans mon emploi ?",
305
+ "Je peux travailler sur autre chose que dans mon poste actuel ?",
306
+ "Est-ce que je peux explorer une compétence qu’on ne me laisse pas utiliser au travail ?",
307
+ "Je suis déjà développeur, mais je veux découvrir l’IA : c’est possible ?",
308
+ "Je peux venir pour élargir mes compétences professionnelles ?",
309
+ "Est-ce que GOT permet de tester un nouveau domaine sans changer de métier ?"
310
+ ],
311
+ "response": "Oui, c’est même l’un des intérêts des projets GOT. Tu peux explorer une technologie ou un rôle auquel tu n’as pas accès dans ton poste actuel, tout en apportant au projet ton expérience professionnelle. C’est toujours plus motivant que de tester seul dans son coin 😉.",
312
+ "enabled": true
313
+ },
314
+ {
315
+ "id": "got_faq_018",
316
+ "source_id": 18,
317
+ "category": "Comprendre GOT",
318
+ "intent_key": "est_ce_que_je_serai_accompagne_dans_le_projet",
319
+ "canonical_question": "Est-ce que je serai accompagné dans le projet ?",
320
+ "utterances": [
321
+ "Est-ce que je serai accompagné dans le projet ?",
322
+ "Est-ce que quelqu’un va m’accompagner ?",
323
+ "Je serai laissé seul sur mes tâches ?",
324
+ "Il y a un référent dans les équipes ?",
325
+ "Est-ce qu’on est guidé quand on rejoint un projet ?",
326
+ "Qui peut m’aider si je bloque ?"
327
+ ],
328
+ "response": "Tu travailleras avec une équipe et un responsable de projet. L’objectif est de partager les connaissances et de progresser collectivement. En revanche, nous ne pouvons pas garantir un mentor individuel disponible en permanence.",
329
+ "enabled": true
330
+ },
331
+ {
332
+ "id": "got_faq_019",
333
+ "source_id": 19,
334
+ "category": "Comprendre GOT",
335
+ "intent_key": "pourquoi_certaines_fonctionnalites_du_site_ne_fonctionnent_elles_pas_encore",
336
+ "canonical_question": "Pourquoi certaines fonctionnalités du site ne fonctionnent-elles pas encore ?",
337
+ "utterances": [
338
+ "Pourquoi certaines fonctionnalités du site ne fonctionnent-elles pas encore ?",
339
+ "Pourquoi le site n’est pas complètement fonctionnel ?",
340
+ "Pourquoi certains boutons ne marchent pas ?",
341
+ "Il y a des fonctions encore indisponibles ?",
342
+ "Le site est-il toujours en développement ?",
343
+ "Quand les fonctionnalités manquantes seront-elles ajoutées ?"
344
+ ],
345
+ "response": "Parce que le compte membre et plusieurs services du site sont encore en cours de développement dans BEN, l'ERP de GOT. Nous les ouvrons progressivement lorsqu’ils sont suffisamment fiables et sécurisés.",
346
+ "enabled": true
347
+ },
348
+ {
349
+ "id": "got_faq_020",
350
+ "source_id": 20,
351
+ "category": "Organisation et engagement",
352
+ "intent_key": "puis_je_participer_seulement_le_soir_ou_le_week_end",
353
+ "canonical_question": "Puis-je participer seulement le soir ou le week-end ?",
354
+ "utterances": [
355
+ "Puis-je participer seulement le soir ou le week-end ?",
356
+ "Je peux contribuer uniquement le soir ?",
357
+ "C’est possible de travailler sur les projets le week-end ?",
358
+ "Je suis disponible après le travail, ça convient ?",
359
+ "Est-ce que je peux participer en dehors des horaires de bureau ?",
360
+ "Mes disponibilités sont surtout le soir et le week-end, c’est compatible ?"
361
+ ],
362
+ "response": "Les bénévoles organisent leur contribution en fonction de leurs disponibilités, mais certaines réunions d’équipe peuvent avoir des horaires définis collectivement. Avant de rejoindre un projet, vérifie simplement que son fonctionnement est compatible avec ton emploi du temps. Il te faudra parfois un peu de flexibilité pour avancer.",
363
+ "enabled": true
364
+ },
365
+ {
366
+ "id": "got_faq_021",
367
+ "source_id": 21,
368
+ "category": "Organisation et engagement",
369
+ "intent_key": "est_ce_que_les_horaires_sont_imposes",
370
+ "canonical_question": "Est-ce que les horaires sont imposés ?",
371
+ "utterances": [
372
+ "Est-ce que les horaires sont imposés ?",
373
+ "Il y a des horaires fixes ?",
374
+ "Je dois me connecter à des heures précises ?",
375
+ "Les équipes imposent-elles un planning ?",
376
+ "Est-ce que je choisis mes horaires ?",
377
+ "Comment sont organisés les horaires de travail ?"
378
+ ],
379
+ "response": "Il n’y a pas d’horaires salariés. Chaque équipe définit néanmoins ses temps de synchronisation et ses règles de fonctionnement. Il faut donc pouvoir participer aux échanges nécessaires pour ne pas travailler complètement à côté de l’équipe.",
380
+ "enabled": true
381
+ },
382
+ {
383
+ "id": "got_faq_022",
384
+ "source_id": 22,
385
+ "category": "Organisation et engagement",
386
+ "intent_key": "est_ce_que_tout_se_fait_a_distance",
387
+ "canonical_question": "Est-ce que tout se fait à distance ?",
388
+ "utterances": [
389
+ "Est-ce que tout se fait à distance ?",
390
+ "C’est du 100 % distanciel ?",
391
+ "On peut tout faire en ligne ?",
392
+ "Il faut venir sur place ?",
393
+ "Vos projets se font à distance ?",
394
+ "Est-ce que les équipes travaillent entièrement en remote ?"
395
+ ],
396
+ "response": "La totalité des activités et du travail sur les projets se déroule à distance, notamment grâce à Discord et aux outils collaboratifs et/ou asynchrones de l’association.",
397
+ "enabled": true
398
+ },
399
+ {
400
+ "id": "got_faq_023",
401
+ "source_id": 23,
402
+ "category": "Organisation et engagement",
403
+ "intent_key": "puis_je_participer_depuis_une_autre_region_ou_un_autre_pays",
404
+ "canonical_question": "Puis-je participer depuis une autre région ou un autre pays ?",
405
+ "utterances": [
406
+ "Puis-je participer depuis une autre région ou un autre pays ?",
407
+ "Vous acceptez des membres partout en France ?",
408
+ "Je vis à l’étranger, est-ce que je peux rejoindre GOT ?",
409
+ "La distance est-elle un problème pour candidater ?",
410
+ "Je suis dans une autre région, est-ce compatible ?"
411
+ ],
412
+ "response": "Le fonctionnement à distance permet de participer quelle que soit la zone de connexion. Pour une personne située à l’étranger, il faut surtout préciser et vérifier la compatibilité des horaires avec le collectif du projet concerné.",
413
+ "enabled": true
414
+ },
415
+ {
416
+ "id": "got_faq_024",
417
+ "source_id": 24,
418
+ "category": "Organisation et engagement",
419
+ "intent_key": "combien_de_temps_dure_un_engagement_dans_un_projet",
420
+ "canonical_question": "Combien de temps dure un engagement dans un projet ?",
421
+ "utterances": [
422
+ "Combien de temps dure un engagement dans un projet ?",
423
+ "On s’engage pour combien de mois ?",
424
+ "Quelle est la durée d’une mission ?",
425
+ "Il faut rester jusqu’à la fin du projet ?",
426
+ "Combien de temps dois-je prévoir de participer ?",
427
+ "Les engagements sont-ils à durée fixe ?"
428
+ ],
429
+ "response": "Il n’y a pas de durée identique pour tous les projets. Le contrat de bénévolat est conclu pour une durée indéterminée et tu peux mettre fin à ton engagement. L’idéal est simplement d’anticiper ton départ pour permettre à l’équipe de s’organiser.",
430
+ "enabled": true
431
+ },
432
+ {
433
+ "id": "got_faq_025",
434
+ "source_id": 25,
435
+ "category": "Organisation et engagement",
436
+ "intent_key": "puis_je_arreter_si_ma_situation_change",
437
+ "canonical_question": "Puis-je arrêter si ma situation change ?",
438
+ "utterances": [
439
+ "Puis-je arrêter si ma situation change ?",
440
+ "Je peux quitter le projet si je n’ai plus le temps ?",
441
+ "Que se passe-t-il si je dois arrêter ?",
442
+ "Est-ce que je peux mettre fin à mon bénévolat ?",
443
+ "Je suis libre de partir en cours de projet ?",
444
+ "Si ma situation professionnelle change, je peux arrêter ?"
445
+ ],
446
+ "response": "Dans tous les cas, tu restes libre de mettre fin à ton engagement. Dans la mesure du possible, nous te demandons de prévenir suffisamment tôt et de transmettre proprement les informations utiles à l’équipe.",
447
+ "enabled": true
448
+ },
449
+ {
450
+ "id": "got_faq_026",
451
+ "source_id": 26,
452
+ "category": "Organisation et engagement",
453
+ "intent_key": "puis_je_changer_de_projet",
454
+ "canonical_question": "Puis-je changer de projet ?",
455
+ "utterances": [
456
+ "Puis-je changer de projet ?",
457
+ "Je peux passer sur un autre projet ?",
458
+ "Est-ce qu’on peut changer d’équipe ?",
459
+ "Si un autre sujet m’intéresse davantage, je peux bouger ?",
460
+ "Je peux demander à rejoindre un autre projet ?",
461
+ "Est-ce possible d’évoluer d’un projet à l’autre ?"
462
+ ],
463
+ "response": "C’est possible si cela correspond à ton évolution et aux besoins des équipes. Il faut en discuter avec les responsables concernés afin de terminer ou transmettre correctement ce que tu avais commencé.",
464
+ "enabled": true
465
+ },
466
+ {
467
+ "id": "got_faq_027",
468
+ "source_id": 27,
469
+ "category": "Organisation et engagement",
470
+ "intent_key": "que_se_passe_t_il_si_je_suis_indisponible_pendant_quelque_temps",
471
+ "canonical_question": "Que se passe-t-il si je suis indisponible pendant quelque temps ?",
472
+ "utterances": [
473
+ "Que se passe-t-il si je suis indisponible pendant quelque temps ?",
474
+ "Je fais quoi si je dois faire une pause ?",
475
+ "Est-ce grave si je suis absent quelques semaines ?",
476
+ "Comment prévenir d’une indisponibilité ?",
477
+ "Je peux suspendre temporairement ma participation ?",
478
+ "Que se passe-t-il si je ne peux plus contribuer pendant un moment ?"
479
+ ],
480
+ "response": "Préviens ton équipe dès que possible. Une indisponibilité temporaire n’est pas un problème lorsqu’elle est annoncée et que le travail peut être réorganisé. Le silence prolongé, lui, peut vraiment bloquer un projet.",
481
+ "enabled": true
482
+ },
483
+ {
484
+ "id": "got_faq_028",
485
+ "source_id": 28,
486
+ "category": "Organisation et engagement",
487
+ "intent_key": "dois_je_participer_aux_reunions",
488
+ "canonical_question": "Dois-je participer aux réunions ?",
489
+ "utterances": [
490
+ "Dois-je participer aux réunions ?",
491
+ "Les réunions sont obligatoires ?",
492
+ "Je dois assister à tous les points d’équipe ?",
493
+ "Il y a beaucoup de réunions à suivre ?",
494
+ "Est-ce que je peux contribuer sans venir aux réunions ?",
495
+ "Quels rendez-vous d’équipe faut-il suivre ?"
496
+ ],
497
+ "response": "Tu dois participer aux réunions nécessaires à ton rôle et au bon fonctionnement de ton équipe. Toutes les réunions ne sont pas obligatoires pour tout le monde, mais contribuer à un projet collectif suppose de rester synchronisé avec les autres.",
498
+ "enabled": true
499
+ },
500
+ {
501
+ "id": "got_faq_029",
502
+ "source_id": 29,
503
+ "category": "Candidature et compte",
504
+ "intent_key": "que_se_passe_t_il_apres_l_envoi_de_ma_candidature",
505
+ "canonical_question": "Que se passe-t-il après l’envoi de ma candidature ?",
506
+ "utterances": [
507
+ "Que se passe-t-il après l’envoi de ma candidature ?",
508
+ "Quelle est la suite après avoir postulé ?",
509
+ "Qui regarde ma candidature ?",
510
+ "Que se passe-t-il une fois le formulaire envoyé ?",
511
+ "Est-ce que je serai contacté après ma candidature ?",
512
+ "Quelles sont les étapes après l’inscription ?"
513
+ ],
514
+ "response": "Le pôle RH étudie les informations transmises et peut te proposer un premier échange. Si ton profil correspond à un besoin, il peut ensuite être transmis au responsable du pôle ou du projet concerné pour poursuivre les échanges.",
515
+ "enabled": true
516
+ },
517
+ {
518
+ "id": "got_faq_030",
519
+ "source_id": 30,
520
+ "category": "Candidature et compte",
521
+ "intent_key": "combien_de_temps_faut_il_pour_recevoir_une_reponse",
522
+ "canonical_question": "Combien de temps faut-il pour recevoir une réponse ?",
523
+ "utterances": [
524
+ "Combien de temps faut-il pour recevoir une réponse ?",
525
+ "Vous répondez sous combien de temps ?",
526
+ "Quel est le délai après une candidature ?",
527
+ "Quand vais-je avoir un retour ?",
528
+ "Il faut attendre combien de jours ?",
529
+ "Pourquoi je n’ai pas encore reçu de réponse ?"
530
+ ],
531
+ "response": "Le délai peut varier selon le nombre de candidatures, les disponibilités des bénévoles RH et les besoins des projets. Nous faisons au mieux pour répondre, mais l’association fonctionne elle aussi grâce à des bénévoles.",
532
+ "enabled": true
533
+ },
534
+ {
535
+ "id": "got_faq_031",
536
+ "source_id": 31,
537
+ "category": "Candidature et compte",
538
+ "intent_key": "est_ce_que_toutes_les_candidatures_sont_acceptees",
539
+ "canonical_question": "Est-ce que toutes les candidatures sont acceptées ?",
540
+ "utterances": [
541
+ "Est-ce que toutes les candidatures sont acceptées ?",
542
+ "Vous acceptez tout le monde ?",
543
+ "Est-ce qu’on peut être refusé ?",
544
+ "Ma candidature est-elle automatiquement validée ?",
545
+ "Quelles sont mes chances d’être accepté ?",
546
+ "Est-ce que rejoindre GOT est garanti après le formulaire ?"
547
+ ],
548
+ "response": "Tout d'abord tu seras invité sur notre serveur Discord. Par la suite tu passeras un entretien avec les services RH pour évaluer tes besoins, ton domaine de compétences, ce que tu souhaites apporter. Une candidature peut ne pas correspondre aux besoins actuels, au niveau d’autonomie attendu ou aux places disponibles dans les équipes, tu seras tout de même membre du Discord, en attente de projet. Tous les profils sont intéressants, il faut simplement les intégrer dans le bon projet, au bon niveau.",
549
+ "enabled": true
550
+ },
551
+ {
552
+ "id": "got_faq_032",
553
+ "source_id": 32,
554
+ "category": "Candidature et compte",
555
+ "intent_key": "est_ce_que_je_dois_passer_un_entretien",
556
+ "canonical_question": "Est-ce que je dois passer un entretien ?",
557
+ "utterances": [
558
+ "Est-ce que je dois passer un entretien ?",
559
+ "Il y a un entretien avant d’être accepté ?",
560
+ "Est-ce qu’on échange avec les RH ?",
561
+ "Je vais avoir un rendez-vous avec le responsable du projet ?",
562
+ "Comment se passe l’entretien de candidature ?",
563
+ "Faut-il passer plusieurs entretiens ?"
564
+ ],
565
+ "response": "Un échange va organisé avec le pôle RH dans les délais de leurs disponibilités, puis si ton profil correspond à un besoin immédiat, tu échangeras avec le responsable du projet ou du pôle concerné. Cela permet de vérifier les attentes, les compétences et la compatibilité avec le fonctionnement de l’équipe.",
566
+ "enabled": true
567
+ },
568
+ {
569
+ "id": "got_faq_033",
570
+ "source_id": 33,
571
+ "category": "Candidature et compte",
572
+ "intent_key": "quels_documents_dois_je_fournir",
573
+ "canonical_question": "Quels documents dois-je fournir ?",
574
+ "utterances": [
575
+ "Quels documents dois-je fournir ?",
576
+ "Il faut envoyer un CV ?",
577
+ "Quels justificatifs sont demandés ?",
578
+ "Je dois fournir mon portfolio ou mon GitHub ?",
579
+ "Qu’est-ce qu’il faut préparer pour candidater ?",
580
+ "Quels documents sont nécessaires pour le dossier ?"
581
+ ],
582
+ "response": "Le formulaire précise les informations nécessaires à la candidature, nous recueillons le minimum de données. Lors de l'échange avec les RH, il peut être utile de présenter ton CV, communiquer des liens vers ton portfolio, ton GitHub ou quelques réalisations, mais les éléments demandés peuvent varier selon le rôle. dans tous les cas les informations recueillies entreront dans ton profil de membre auquel seul le service RH aura accès.",
583
+ "enabled": true
584
+ },
585
+ {
586
+ "id": "got_faq_034",
587
+ "source_id": 34,
588
+ "category": "Candidature et compte",
589
+ "intent_key": "pourquoi_ma_candidature_peut_elle_etre_refusee",
590
+ "canonical_question": "Pourquoi ma candidature peut-elle être refusée ?",
591
+ "utterances": [
592
+ "Pourquoi ma candidature peut-elle être refusée ?",
593
+ "Pour quelles raisons peut-on refuser mon profil ?",
594
+ "Qu’est-ce qui peut bloquer une candidature ?",
595
+ "Pourquoi je n’ai pas été retenu ?",
596
+ "Est-ce qu’un manque de place peut entraîner un refus ?",
597
+ "Quels sont les motifs possibles de non-sélection ?"
598
+ ],
599
+ "response": "Parce qu’aucun projet ne correspond actuellement à ton profil, que l’équipe est complète, que le niveau d’autonomie attendu est différent ou que les disponibilités ne sont pas compatibles. Nous devons aussi préserver un fonctionnement équilibré pour les équipes déjà en place ou à venir. Dans tous les cas tu resteras membre du Discord, et tu auras accès à un canal de recrutement par les chef(fe)s de projet.",
600
+ "enabled": true
601
+ },
602
+ {
603
+ "id": "got_faq_035",
604
+ "source_id": 35,
605
+ "category": "Candidature et compte",
606
+ "intent_key": "ou_se_trouve_le_formulaire_de_candidature",
607
+ "canonical_question": "Où se trouve le formulaire de candidature ?",
608
+ "utterances": [
609
+ "Où se trouve le formulaire de candidature ?",
610
+ "Où est le formulaire pour postuler ?",
611
+ "Je ne trouve pas la candidature en ligne",
612
+ "Sur quel bouton faut-il cliquer pour candidater ?",
613
+ "Comment accéder au formulaire d’inscription ?",
614
+ "Où déposer ma candidature ?"
615
+ ],
616
+ "response": "Tu peux y accéder depuis le bouton « Inscription » du site.",
617
+ "enabled": true
618
+ },
619
+ {
620
+ "id": "got_faq_036",
621
+ "source_id": 36,
622
+ "category": "Candidature et compte",
623
+ "intent_key": "dois_je_creer_un_compte_pour_candidater",
624
+ "canonical_question": "Dois-je créer un compte pour candidater ?",
625
+ "utterances": [
626
+ "Dois-je créer un compte pour candidater ?",
627
+ "Il faut s’inscrire avant de postuler ?",
628
+ "Je dois avoir un compte membre pour envoyer ma candidature ?",
629
+ "Peut-on candidater sans compte ?",
630
+ "Le formulaire crée-t-il automatiquement un compte ?",
631
+ "Qu’est-ce qu’on me demande pour déposer ma candidature ?"
632
+ ],
633
+ "response": "Le parcours accessible depuis « Inscription » te demande les informations nécessaires pour déposer ta candidature. Le compte membre complet, avec l’ensemble de ses futures fonctionnalités, est encore en cours de développement.",
634
+ "enabled": true
635
+ },
636
+ {
637
+ "id": "got_faq_037",
638
+ "source_id": 37,
639
+ "category": "Niveau et compétences",
640
+ "intent_key": "quel_niveau_faut_il_avoir_pour_rejoindre_un_projet",
641
+ "canonical_question": "Quel niveau faut-il avoir pour rejoindre un projet ?",
642
+ "utterances": [
643
+ "Quel niveau faut-il avoir pour rejoindre un projet ?",
644
+ "Quel niveau technique est demandé ?",
645
+ "Il faut être junior, confirmé ou senior ?",
646
+ "Comment savoir si j’ai le niveau ?",
647
+ "Quels prérequis faut-il avoir ?",
648
+ "Vous attendez quel niveau d’autonomie ?"
649
+ ],
650
+ "response": "Cela dépend du projet et du rôle. Certains besoins sont accessibles à des profils juniors, d’autres demandent davantage d’autonomie ou d’expérience. Ta candidature permet justement de vérifier où tu pourras contribuer utilement tout en progressant.",
651
+ "enabled": true
652
+ },
653
+ {
654
+ "id": "got_faq_038",
655
+ "source_id": 38,
656
+ "category": "Niveau et compétences",
657
+ "intent_key": "dois_je_maitriser_toutes_les_technologies_du_projet",
658
+ "canonical_question": "Dois-je maîtriser toutes les technologies du projet ?",
659
+ "utterances": [
660
+ "Dois-je maîtriser toutes les technologies du projet ?",
661
+ "Il faut connaître toute la stack ?",
662
+ "Je dois savoir utiliser tous les outils du projet ?",
663
+ "Est-ce bloquant si je ne maîtrise qu’une partie des technos ?",
664
+ "On peut rejoindre une équipe sans tout connaître ?",
665
+ "Vous demandez de maîtriser chaque technologie avant de candidater ?"
666
+ ],
667
+ "response": "Personne ne maîtrise nécessairement toute la stack d’un projet. Il faut surtout disposer de bases suffisantes pour ton rôle, être capable de chercher des solutions et savoir demander de l’aide de manière constructive.",
668
+ "enabled": true
669
+ },
670
+ {
671
+ "id": "got_faq_039",
672
+ "source_id": 39,
673
+ "category": "Niveau et compétences",
674
+ "intent_key": "est_ce_que_je_peux_participer_sans_experience_professionnelle",
675
+ "canonical_question": "Est-ce que je peux participer sans expérience professionnelle ?",
676
+ "utterances": [
677
+ "Est-ce que je peux participer sans expérience professionnelle ?",
678
+ "Je n’ai jamais travaillé dans la tech, je peux candidater ?",
679
+ "Vous acceptez les personnes sans expérience professionnelle ?",
680
+ "Je n’ai que ma formation, est-ce suffisant ?",
681
+ "Je cherche ma première expérience, est-ce possible ?",
682
+ "Est-ce qu’un profil sans expérience en entreprise peut participer ?"
683
+ ],
684
+ "response": "Oui, certains projets peuvent accueillir des personnes qui ont surtout une expérience scolaire, personnelle ou associative. La décision dépendra de ton niveau actuel, de ton autonomie et des besoins de l’équipe.",
685
+ "enabled": true
686
+ },
687
+ {
688
+ "id": "got_faq_040",
689
+ "source_id": 40,
690
+ "category": "Niveau et compétences",
691
+ "intent_key": "est_ce_que_je_peux_contribuer_avec_seulement_des_projets_scolaires_ou_personnels",
692
+ "canonical_question": "Est-ce que je peux contribuer avec seulement des projets scolaires ou personnels ?",
693
+ "utterances": [
694
+ "Est-ce que je peux contribuer avec seulement des projets scolaires ou personnels ?",
695
+ "Mes projets d’école peuvent compter ?",
696
+ "Je n’ai que des projets perso à montrer, ça suffit ?",
697
+ "Vous regardez les projets GitHub personnels ?",
698
+ "Est-ce que mes réalisations de formation peuvent servir pour candidater ?"
699
+ ],
700
+ "response": "Oui. Si tu en as,ces projets permettent déjà d’évaluer ta manière de travailler, les technologies que tu connais et ce que tu es capable de produire. Présente-les clairement dans ta candidature.",
701
+ "enabled": true
702
+ },
703
+ {
704
+ "id": "got_faq_041",
705
+ "source_id": 41,
706
+ "category": "Niveau et compétences",
707
+ "intent_key": "y_a_t_il_des_tests_techniques",
708
+ "canonical_question": "Y a-t-il des tests techniques ?",
709
+ "utterances": [
710
+ "Y a-t-il des tests techniques ?",
711
+ "Vous faites passer un test technique ?",
712
+ "Il y a un exercice avant d’être accepté ?",
713
+ "Est-ce qu’on doit coder pendant l’entretien ?",
714
+ "Comment se passe l’évaluation technique ?",
715
+ "Vous demandez une épreuve technique pour rejoindre un projet ?"
716
+ ],
717
+ "response": "Non, pas d'entretien technique chez GOT. L’objectif n’est pas de te piéger, mais d’éviter de te placer dans une mission qui ne te conviendrait pas.",
718
+ "enabled": true
719
+ },
720
+ {
721
+ "id": "got_faq_042",
722
+ "source_id": 42,
723
+ "category": "Niveau et compétences",
724
+ "intent_key": "comment_mon_niveau_est_il_evalue",
725
+ "canonical_question": "Comment mon niveau est-il évalué ?",
726
+ "utterances": [
727
+ "Comment mon niveau est-il évalué ?",
728
+ "Comment vous évaluez les candidats ?",
729
+ "Sur quoi vous vous basez pour juger mon niveau ?",
730
+ "Vous regardez quoi dans mon profil ?",
731
+ "Comment savez-vous ce que je sais faire ?",
732
+ "Quels éléments servent à évaluer mes compétences ?"
733
+ ],
734
+ "response": "À partir des informations de ta candidature, de tes expériences, de tes projets et des échanges avec l’équipe. Nous cherchons autant à comprendre ce que tu sais déjà faire que ce que tu souhaites développer puisque c'est l'objectif principal de GOT. Même un Senior ou Mentor aura l'occasion de progresser dans sa capacité à transmettre ou dans la découverte de nouveaux environnements.",
735
+ "enabled": true
736
+ },
737
+ {
738
+ "id": "got_faq_043",
739
+ "source_id": 43,
740
+ "category": "Niveau et compétences",
741
+ "intent_key": "comment_etes_vous_surs_que_le_projet_correspond_a_mes_competences",
742
+ "canonical_question": "Comment êtes-vous sûrs que le projet correspond à mes compétences ?",
743
+ "utterances": [
744
+ "Comment êtes-vous sûrs que le projet correspond à mes compétences ?",
745
+ "Comment choisissez-vous le bon projet pour moi ?",
746
+ "Qui vérifie que mon profil correspond à l’équipe ?",
747
+ "Comment évitez-vous de me mettre sur un projet trop difficile ?",
748
+ "Comment se fait la mise en relation entre mon profil et un projet ?",
749
+ "Comment savoir si la mission va vraiment me convenir ?"
750
+ ],
751
+ "response": "Nous croisons les besoins du projet avec ton expérience, ton niveau d’autonomie et tes objectifs. Ce n’est pas une science exacte, donc l’échange avec le responsable de projet reste important pour vérifier que les attentes sont claires des deux côtés.",
752
+ "enabled": true
753
+ },
754
+ {
755
+ "id": "got_faq_044",
756
+ "source_id": 44,
757
+ "category": "Niveau et compétences",
758
+ "intent_key": "puis_je_apporter_mes_competences_actuelles_tout_en_apprenant_autre_chose",
759
+ "canonical_question": "Puis-je apporter mes compétences actuelles tout en apprenant autre chose ?",
760
+ "utterances": [
761
+ "Puis-je apporter mes compétences actuelles tout en apprenant autre chose ?",
762
+ "Je peux aider avec ce que je sais déjà faire et apprendre en parallèle ?",
763
+ "Est-ce que je peux avoir un rôle mixte dans le projet ?",
764
+ "Je peux contribuer sur mes points forts tout en découvrant une nouvelle techno ?",
765
+ "On peut être à la fois utile et en apprentissage ?",
766
+ "Je dois choisir entre transmettre et apprendre ?"
767
+ ],
768
+ "response": "Oui, c’est même une très bonne manière de contribuer. Tu peux sécuriser une partie du projet grâce à ce que tu maîtrises déjà et profiter du travail collectif pour développer une nouvelle compétence.",
769
+ "enabled": true
770
+ },
771
+ {
772
+ "id": "got_faq_045",
773
+ "source_id": 45,
774
+ "category": "Projets et équipes",
775
+ "intent_key": "quels_sont_les_projets_de_guild_open_tech",
776
+ "canonical_question": "Quels sont les projets de Guild Open Tech ?",
777
+ "utterances": [
778
+ "Quels sont les projets de Guild Open Tech ?",
779
+ "Vous développez quoi chez GOT ?",
780
+ "Quels sont vos projets principaux ?",
781
+ "Sur quoi travaillent les équipes ?",
782
+ "Vous avez quelles applications en cours ?",
783
+ "Quels types de projets propose l’association ?"
784
+ ],
785
+ "response": "Guild Open Tech développe plusieurs projets numériques collaboratifs, certains sont présentés sur le site institutionnel. Leur état d’avancement et leurs besoins évoluent. Et tu peux présenter ton propre projet, nous t'aiderons à le faire naître.",
786
+ "enabled": true
787
+ },
788
+ {
789
+ "id": "got_faq_046",
790
+ "source_id": 46,
791
+ "category": "Projets et équipes",
792
+ "intent_key": "a_quel_stade_en_sont_les_projets",
793
+ "canonical_question": "À quel stade en sont les projets ?",
794
+ "utterances": [
795
+ "À quel stade en sont les projets ?",
796
+ "Les projets sont déjà en ligne ?",
797
+ "Ils en sont où vos projets ?",
798
+ "Quels projets sont encore en développement ?",
799
+ "Est-ce que certains projets sont déjà terminés ?",
800
+ "Comment connaître l’avancement de chaque projet ?"
801
+ ],
802
+ "response": "Certains projets sont en cours de développement, d’autres évoluent déjà par versions successives. Le site présente leur objectif général, mais l’équipe pourra te donner un état plus précis lors de ta candidature.",
803
+ "enabled": true
804
+ },
805
+ {
806
+ "id": "got_faq_047",
807
+ "source_id": 47,
808
+ "category": "Projets et équipes",
809
+ "intent_key": "comment_puis_je_savoir_quels_projets_recrutent",
810
+ "canonical_question": "Comment puis-je savoir quels projets recrutent ?",
811
+ "utterances": [
812
+ "Comment puis-je savoir quels projets recrutent ?",
813
+ "Où voir les projets qui cherchent du monde ?",
814
+ "Comment savoir quelles équipes ont besoin de bénévoles ?",
815
+ "Vous publiez les postes ouverts quelque part ?",
816
+ "Quels projets recrutent actuellement ?",
817
+ "Où sont affichés les besoins des projets ?"
818
+ ],
819
+ "response": "Candidate en indiquant les domaines, rôles et projets qui t’intéressent. Les besoins pouvant évoluer rapidement, l’équipe vérifiera les possibilités ouvertes au moment où elle étudiera ton profil.",
820
+ "enabled": true
821
+ },
822
+ {
823
+ "id": "got_faq_048",
824
+ "source_id": 48,
825
+ "category": "Projets et équipes",
826
+ "intent_key": "comment_les_equipes_sont_elles_constituees",
827
+ "canonical_question": "Comment les équipes sont-elles constituées ?",
828
+ "utterances": [
829
+ "Comment les équipes sont-elles constituées ?",
830
+ "Comment vous formez les équipes ?",
831
+ "Qui décide dans quel projet on va ?",
832
+ "Comment sont répartis les bénévoles ?",
833
+ "Vous mettez quels profils ensemble ?",
834
+ "Comment choisissez-vous la composition d’une équipe ?"
835
+ ],
836
+ "response": "Les équipes sont constituées en fonction des besoins du projet, des compétences disponibles et des objectifs de progression des bénévoles. Nous cherchons à créer un équilibre entre autonomie, complémentarité et apprentissage collectif.",
837
+ "enabled": true
838
+ },
839
+ {
840
+ "id": "got_faq_049",
841
+ "source_id": 49,
842
+ "category": "Projets et équipes",
843
+ "intent_key": "qui_dirige_ou_coordonne_les_projets",
844
+ "canonical_question": "Qui dirige ou coordonne les projets ?",
845
+ "utterances": [
846
+ "Qui dirige ou coordonne les projets ?",
847
+ "Qui pilote les projets ?",
848
+ "Il y a un chef de projet dans chaque équipe ?",
849
+ "Qui organise le travail ?",
850
+ "Qui prend les décisions sur le projet ?",
851
+ "À qui doit-on s’adresser dans l’équipe ?"
852
+ ],
853
+ "response": "Chaque projet a un€ Chef(fe) de projet chargé de définir le périmètre, de coordonner le travail, les priorités et si besoin les échanges avec les autres pôles de l’association.",
854
+ "enabled": true
855
+ },
856
+ {
857
+ "id": "got_faq_050",
858
+ "source_id": 50,
859
+ "category": "Projets et équipes",
860
+ "intent_key": "comment_se_passe_le_travail_en_equipe",
861
+ "canonical_question": "Comment se passe le travail en équipe ?",
862
+ "utterances": [
863
+ "Comment se passe le travail en équipe ?",
864
+ "Comment vous travaillez au quotidien ?",
865
+ "Comment les bénévoles collaborent-ils ?",
866
+ "Les tâches sont organisées comment ?",
867
+ "Comment se déroulent les échanges dans une équipe ?",
868
+ "C’est quoi votre façon de travailler sur les projets ?"
869
+ ],
870
+ "response": "Nous avons un GoogleWorkplace. Les membres collaborent à distance, partagent l’avancement de leur travail, organisent les tâches et échangent régulièrement sur les difficultés rencontrées. Le but n’est pas d’empiler des contributions individuelles, mais de construire quelque chose ensemble. Nous utilisons Taïga mais selon le nombre de membres dans l'équipe ça peut se faire sur d'autres outils gratuits... c'est à discuter avec l'équipe en début de projet.",
871
+ "enabled": true
872
+ },
873
+ {
874
+ "id": "got_faq_051",
875
+ "source_id": 51,
876
+ "category": "Projets et équipes",
877
+ "intent_key": "quels_outils_collaboratifs_utilisez_vous",
878
+ "canonical_question": "Quels outils collaboratifs utilisez-vous ?",
879
+ "utterances": [
880
+ "Quels outils collaboratifs utilisez-vous ?",
881
+ "Vous utilisez quels outils pour travailler ?",
882
+ "Les équipes communiquent où ?",
883
+ "Vous utilisez GitHub et Discord ?",
884
+ "Quels logiciels faut-il connaître ?",
885
+ "Comment sont gérés les projets à distance ?"
886
+ ],
887
+ "response": "Discord est utilisé pour les échanges de la communauté et des équipes. Selon les projets, nous utilisons également GitHub et différents outils de gestion, de documentation, de conception ou de partage de fichiers.",
888
+ "enabled": true
889
+ },
890
+ {
891
+ "id": "got_faq_052",
892
+ "source_id": 52,
893
+ "category": "Projets et équipes",
894
+ "intent_key": "le_code_est_il_disponible_sur_github",
895
+ "canonical_question": "Le code est-il disponible sur GitHub ?",
896
+ "utterances": [
897
+ "Le code est-il disponible sur GitHub ?",
898
+ "Je peux voir votre code sur GitHub ?",
899
+ "Les dépôts sont-ils publics ?",
900
+ "Où trouver le code des projets ?",
901
+ "Votre GitHub est accessible à tout le monde ?",
902
+ "Le code source est publié en ligne ?"
903
+ ],
904
+ "response": "Les projets open source ont vocation à rendre leur code accessible publiquement sur GitHub. Certaines ressources de travail, données ou informations internes restent toutefois protégées.",
905
+ "enabled": true
906
+ },
907
+ {
908
+ "id": "got_faq_053",
909
+ "source_id": 53,
910
+ "category": "Projets et équipes",
911
+ "intent_key": "les_projets_sont_ils_tous_open_source",
912
+ "canonical_question": "Les projets sont-ils tous open source ?",
913
+ "utterances": [
914
+ "Les projets sont-ils tous open source ?",
915
+ "Tout ce que vous développez est open source ?",
916
+ "Vos applications sont-elles publiques ?",
917
+ "Quel type de licence utilisez-vous ?",
918
+ "Est-ce que tous les dépôts sont ouverts ?",
919
+ "Les projets GOT sont-ils libres et accessibles ?"
920
+ ],
921
+ "response": "L’open source est au cœur du fonctionnement de Guild Open Tech. Cela ne signifie pas pour autant que toutes les informations, tous les accès ou toutes les données d’un projet sont publics. Le code publié et les informations internes ne relèvent pas des mêmes règles.",
922
+ "enabled": true
923
+ },
924
+ {
925
+ "id": "got_faq_054",
926
+ "source_id": 54,
927
+ "category": "Projets et équipes",
928
+ "intent_key": "puis_je_voir_les_projets_avant_de_candidater",
929
+ "canonical_question": "Puis-je voir les projets avant de candidater ?",
930
+ "utterances": [
931
+ "Puis-je voir les projets avant de candidater ?",
932
+ "Je peux regarder les projets avant de m’inscrire ?",
933
+ "Où voir ce que vous avez déjà réalisé ?",
934
+ "Est-ce que je peux consulter les projets sans être membre ?",
935
+ "Je voudrais voir le projet avant de postuler, c’est possible ?",
936
+ "Les présentations des projets sont-elles publiques ?"
937
+ ],
938
+ "response": "Oui, tu peux consulter leur présentation sur le site et, lorsqu’ils sont publics, leurs ressources open source. La candidature permet ensuite d’obtenir davantage d’informations sur le rôle proposé et les besoins actuels.",
939
+ "enabled": true
940
+ },
941
+ {
942
+ "id": "got_faq_055",
943
+ "source_id": 55,
944
+ "category": "Projets et équipes",
945
+ "intent_key": "puis_je_proposer_mon_propre_projet",
946
+ "canonical_question": "Puis-je proposer mon propre projet ?",
947
+ "utterances": [
948
+ "Puis-je proposer mon propre projet ?",
949
+ "Je peux venir avec une idée de projet ?",
950
+ "GOT accepte les projets proposés par les membres ?",
951
+ "Comment soumettre un nouveau projet ?",
952
+ "Je voudrais lancer une application avec l’association, c’est possible ?",
953
+ "Comment choisissez-vous les nouveaux projets ?"
954
+ ],
955
+ "response": "Un membre peut proposer un projet. Il devra néanmoins être étudié afin de vérifier sa cohérence avec les valeurs de l’association, sa faisabilité, son intérêt collectif et les ressources nécessaires.",
956
+ "enabled": true
957
+ },
958
+ {
959
+ "id": "got_faq_056",
960
+ "source_id": 56,
961
+ "category": "Projets et équipes",
962
+ "intent_key": "puis_je_participer_a_un_projet_d_intelligence_artificielle_ou_de_chatbot",
963
+ "canonical_question": "Puis-je participer à un projet d’intelligence artificielle ou de chatbot ?",
964
+ "utterances": [
965
+ "Puis-je participer à un projet d’intelligence artificielle ou de chatbot ?",
966
+ "Vous avez des projets en IA ?",
967
+ "Je voudrais travailler sur un chatbot, c’est possible ?",
968
+ "Est-ce qu’on peut contribuer sur des LLM ou du RAG ?",
969
+ "Vous recrutez pour des projets d’intelligence artificielle ?",
970
+ "Je peux candidater sur un sujet IA même si ce n’est pas mon métier actuel ?"
971
+ ],
972
+ "response": "Cela dépend des besoins ouverts sur les projets concernés et de ton profil. Tu peux indiquer ton intérêt pour l’IA, les LLM, le RAG ou les chatbots dans ta candidature afin que l’équipe puisse étudier les possibilités.",
973
+ "enabled": true
974
+ },
975
+ {
976
+ "id": "got_faq_057",
977
+ "source_id": 57,
978
+ "category": "Apprentissage",
979
+ "intent_key": "est_ce_que_quelqu_un_va_m_apprendre_la_technologie",
980
+ "canonical_question": "Est-ce que quelqu’un va m’apprendre la technologie ?",
981
+ "utterances": [
982
+ "Est-ce que quelqu’un va m’apprendre la technologie ?",
983
+ "Est-ce qu’on va me former à la techno ?",
984
+ "Quelqu’un m’explique tout au début ?",
985
+ "Vous avez des formateurs pour les projets ?",
986
+ "Est-ce que je serai guidé pas à pas ?",
987
+ "Qui va m’apprendre les outils que je ne connais pas ?"
988
+ ],
989
+ "response": "Tu pourras bénéficier de l’expérience et des retours des autres membres, mais tu restes acteur de ton apprentissage. GOT n’est pas une école avec un formateur chargé de te transmettre tout le programme étape par étape.",
990
+ "enabled": true
991
+ },
992
+ {
993
+ "id": "got_faq_058",
994
+ "source_id": 58,
995
+ "category": "Apprentissage",
996
+ "intent_key": "est_ce_que_j_aurai_un_senior_ou_un_mentor",
997
+ "canonical_question": "Est-ce que j’aurai un senior ou un mentor ?",
998
+ "utterances": [
999
+ "Est-ce que j’aurai un senior ou un mentor ?",
1000
+ "Vous attribuez un senior ou un mentor à chaque membre ?",
1001
+ "Est-ce qu’un senior va me suivre ?"
1002
+ ],
1003
+ "response": "L’entraide et le partage de connaissances font partie du fonctionnement de GOT, mais nous ne garantissons pas l’attribution d’un senior dans chaque projet. L’accompagnement dépend de l’équipe, du projet et des compétences disponibles.",
1004
+ "enabled": true
1005
+ },
1006
+ {
1007
+ "id": "got_faq_059",
1008
+ "source_id": 59,
1009
+ "category": "Apprentissage",
1010
+ "intent_key": "quelle_difference_y_a_t_il_entre_got_et_une_ecole_ou_une_formation",
1011
+ "canonical_question": "Quelle différence y a-t-il entre GOT et une école ou une formation ?",
1012
+ "utterances": [
1013
+ "Quelle différence y a-t-il entre GOT et une école ou une formation ?",
1014
+ "En quoi GOT est différent d’une école ?",
1015
+ "Quelle est la différence avec une formation classique ?",
1016
+ "Pourquoi rejoindre GOT plutôt qu’un cours en ligne ?",
1017
+ "Est-ce un bootcamp ?",
1018
+ "Votre approche est différente d’un organisme de formation comment ?"
1019
+ ],
1020
+ "response": "Une école ou une formation suit généralement un programme pédagogique défini. Chez GOT, tu développes surtout tes compétences en contribuant à des projets collaboratifs, avec les contraintes et les responsabilités d’une réalisation réelle.",
1021
+ "enabled": true
1022
+ },
1023
+ {
1024
+ "id": "got_faq_060",
1025
+ "source_id": 60,
1026
+ "category": "Apprentissage",
1027
+ "intent_key": "est_ce_que_got_learn_est_deja_disponible",
1028
+ "canonical_question": "Est-ce que GOT-Learn est déjà disponible ?",
1029
+ "utterances": [
1030
+ "Est-ce que GOT-Learn est déjà disponible ?",
1031
+ "GOT-Learn est ouvert ?",
1032
+ "On peut déjà accéder à GOT-Learn ?",
1033
+ "La plateforme de formation fonctionne déjà ?",
1034
+ "GOT-Learn est en ligne ?",
1035
+ "Est-ce que je peux m’inscrire à GOT-Learn maintenant ?"
1036
+ ],
1037
+ "response": "Non. GOT-Learn est encore en cours de développement.",
1038
+ "enabled": true
1039
+ },
1040
+ {
1041
+ "id": "got_faq_061",
1042
+ "source_id": 61,
1043
+ "category": "Apprentissage",
1044
+ "intent_key": "que_proposera_got_learn",
1045
+ "canonical_question": "Que proposera GOT-Learn ?",
1046
+ "utterances": [
1047
+ "Que proposera GOT-Learn ?",
1048
+ "GOT-Learn va servir à quoi ?",
1049
+ "Qu’est-ce qu’on trouvera dans GOT-Learn ?",
1050
+ "Quels contenus sont prévus sur GOT-Learn ?",
1051
+ "Ce sera une plateforme de cours ?",
1052
+ "Quel est l’objectif du projet GOT-Learn ?"
1053
+ ],
1054
+ "response": "GOT-Learn a pour objectif de proposer des contenus et des sujets de formation structurée autour de compétences utiles aux membres. Le projet étant encore en développement, son contenu définitif et ses modalités d’accès ne sont pas encore disponibles.",
1055
+ "enabled": true
1056
+ },
1057
+ {
1058
+ "id": "got_faq_062",
1059
+ "source_id": 62,
1060
+ "category": "Apprentissage",
1061
+ "intent_key": "les_certifications_sont_elles_deja_accessibles",
1062
+ "canonical_question": "Les certifications sont-elles déjà accessibles ?",
1063
+ "utterances": [
1064
+ "Les certifications sont-elles déjà accessibles ?",
1065
+ "On peut déjà passer une certification ?",
1066
+ "Les certifications GOT sont disponibles ?",
1067
+ "Quand est-ce que les certifications ouvrent ?",
1068
+ "Vous certifiez déjà les compétences ?",
1069
+ "Est-ce qu’il existe actuellement un parcours certifiant ?"
1070
+ ],
1071
+ "response": "Non. Les certifications font partie des objectifs futurs de Guild Open Tech, mais elles ne sont pas disponibles actuellement.",
1072
+ "enabled": true
1073
+ },
1074
+ {
1075
+ "id": "got_faq_063",
1076
+ "source_id": 63,
1077
+ "category": "Insertion professionnelle",
1078
+ "intent_key": "est_ce_que_got_fournit_une_attestation_de_benevolat",
1079
+ "canonical_question": "Est-ce que GOT fournit une attestation de bénévolat ?",
1080
+ "utterances": [
1081
+ "Est-ce que GOT fournit une attestation de bénévolat ?",
1082
+ "Est-ce que vous donnez une attestation ?",
1083
+ "Je peux obtenir une preuve de ma participation ?",
1084
+ "GOT délivre-t-elle un certificat de bénévolat ?",
1085
+ "Est-ce qu’une attestation peut être remise à la fin ?",
1086
+ "Comment faire reconnaître officiellement mon bénévolat ?"
1087
+ ],
1088
+ "response": "Une attestation peut être envisagée à partir d’une participation réelle et vérifiable. Elle doit correspondre aux missions effectivement réalisées et ne peut pas être délivrée automatiquement dès l’adhésion.",
1089
+ "enabled": true
1090
+ },
1091
+ {
1092
+ "id": "got_faq_064",
1093
+ "source_id": 64,
1094
+ "category": "Insertion professionnelle",
1095
+ "intent_key": "est_ce_que_la_participation_aide_a_trouver_un_emploi",
1096
+ "canonical_question": "Est-ce que la participation aide à trouver un emploi ?",
1097
+ "utterances": [
1098
+ "Est-ce que la participation aide à trouver un emploi ?",
1099
+ "Est-ce que GOT peut m’aider professionnellement ?",
1100
+ "Participer peut-il améliorer mes chances d’embauche ?",
1101
+ "Est-ce utile pour chercher un travail ?",
1102
+ "Les projets peuvent-ils m’aider à gagner en expérience ?",
1103
+ "Est-ce que cela peut m’aider à m’insérer dans la tech ?"
1104
+ ],
1105
+ "response": "Elle peut t’aider à développer des compétences, travailler en équipe et acquérir une expérience concrète. Cela peut renforcer ton profil, mais Guild Open Tech ne peut évidemment pas garantir un recrutement.",
1106
+ "enabled": true
1107
+ },
1108
+ {
1109
+ "id": "got_faq_065",
1110
+ "source_id": 65,
1111
+ "category": "Insertion professionnelle",
1112
+ "intent_key": "est_ce_que_got_met_les_membres_en_relation_avec_des_entreprises",
1113
+ "canonical_question": "Est-ce que GOT met les membres en relation avec des entreprises ?",
1114
+ "utterances": [
1115
+ "Est-ce que GOT met les membres en relation avec des entreprises ?",
1116
+ "Vous avez des entreprises partenaires ?",
1117
+ "Est-ce que vous transmettez des profils à des recruteurs ?",
1118
+ "Il y a des opportunités de networking avec des entreprises ?",
1119
+ "GOT organise-t-elle des mises en relation professionnelles ?",
1120
+ "Les membres peuvent-ils rencontrer des employeurs grâce à l’association ?"
1121
+ ],
1122
+ "response": "L’insertion professionnelle fait partie des objectifs de l’association. Des opportunités de réseau ou de mise en relation peuvent exister, mais elles dépendent des partenariats et des actions disponibles à ce moment-là.",
1123
+ "enabled": true
1124
+ },
1125
+ {
1126
+ "id": "got_faq_066",
1127
+ "source_id": 66,
1128
+ "category": "Insertion professionnelle",
1129
+ "intent_key": "est_ce_que_participer_garantit_de_trouver_un_emploi",
1130
+ "canonical_question": "Est-ce que participer garantit de trouver un emploi ?",
1131
+ "utterances": [
1132
+ "Est-ce que participer garantit de trouver un emploi ?",
1133
+ "Est-ce que je trouverai forcément un travail après ?",
1134
+ "Vous garantissez une embauche ?",
1135
+ "Est-ce que GOT place les membres en entreprise ?",
1136
+ "Participer assure-t-il de décrocher un poste ?",
1137
+ "Y a-t-il une promesse d’emploi à la fin ?"
1138
+ ],
1139
+ "response": "Non. Aucun projet associatif ne peut garantir un emploi. GOT peut t’aider à développer des compétences, acquérir de l’expérience et rencontrer d’autres professionnels, mais le recrutement reste une décision de l’employeur.",
1140
+ "enabled": true
1141
+ },
1142
+ {
1143
+ "id": "got_faq_067",
1144
+ "source_id": 67,
1145
+ "category": "Juridique et données",
1146
+ "intent_key": "a_qui_appartient_le_code_que_je_developpe",
1147
+ "canonical_question": "À qui appartient le code que je développe ?",
1148
+ "utterances": [
1149
+ "À qui appartient le code que je développe ?",
1150
+ "Qui possède mes contributions ?",
1151
+ "Le code que j’écris reste-t-il à moi ?",
1152
+ "Est-ce que GOT devient propriétaire de mon travail ?",
1153
+ "Quels droits ai-je sur le code produit ?",
1154
+ "Comment est gérée la propriété intellectuelle ?"
1155
+ ],
1156
+ "response": "Les contributions réalisées dans le cadre du bénévolat sont encadrées par le contrat signé avec l’association. Celui-ci prévoit notamment une licence d’exploitation permettant à GOT d’utiliser et de faire évoluer les contributions. Les modalités précises doivent être consultées dans le contrat avant sa signature.",
1157
+ "enabled": true
1158
+ },
1159
+ {
1160
+ "id": "got_faq_068",
1161
+ "source_id": 68,
1162
+ "category": "Juridique et données",
1163
+ "intent_key": "puis_je_reutiliser_certaines_parties_du_code_ailleurs",
1164
+ "canonical_question": "Puis-je réutiliser certaines parties du code ailleurs ?",
1165
+ "utterances": [
1166
+ "Puis-je réutiliser certaines parties du code ailleurs ?",
1167
+ "Je peux reprendre mon code pour un autre projet ?",
1168
+ "Est-ce que j’ai le droit de réutiliser une contribution ?",
1169
+ "Puis-je copier une partie du dépôt dans mon projet personnel ?",
1170
+ "La licence m’autorise-t-elle à reprendre le code ?",
1171
+ "Quelles sont les règles pour réutiliser le code open source ?"
1172
+ ],
1173
+ "response": "Cela dépend de la licence du projet, de la nature du code et des engagements prévus dans ton contrat. Le fait qu’un projet soit open source ne signifie pas que tout peut être repris sans respecter sa licence ou les droits des autres contributeurs.",
1174
+ "enabled": true
1175
+ },
1176
+ {
1177
+ "id": "got_faq_069",
1178
+ "source_id": 69,
1179
+ "category": "Juridique et données",
1180
+ "intent_key": "dois_je_signer_un_contrat_de_benevolat",
1181
+ "canonical_question": "Dois-je signer un contrat de bénévolat ?",
1182
+ "utterances": [
1183
+ "Dois-je signer un contrat de bénévolat ?",
1184
+ "Il faut signer un contrat pour participer ?",
1185
+ "Pourquoi un contrat si c’est bénévole ?",
1186
+ "Est-ce obligatoire de signer quelque chose ?",
1187
+ "Quand signe-t-on le contrat de bénévolat ?",
1188
+ "Je peux rejoindre un projet sans contrat ?"
1189
+ ],
1190
+ "response": "Oui, lorsque ta candidature est acceptée et que tu rejoins un projet ou un pôle nous t'enverrons différents documents, dont le Contrat de bénévolat, la Charte membre, la Politique de confidentialité, le Réglement interne, le Droit à l'image. Le contrat formalise la collaboration, les responsabilités, la confidentialité et l’utilisation des contributions.",
1191
+ "enabled": true
1192
+ },
1193
+ {
1194
+ "id": "got_faq_070",
1195
+ "source_id": 70,
1196
+ "category": "Juridique et données",
1197
+ "intent_key": "pourquoi_faut_il_signer_un_contrat",
1198
+ "canonical_question": "Pourquoi faut-il signer un contrat ?",
1199
+ "utterances": [
1200
+ "Pourquoi faut-il signer un contrat ?",
1201
+ "À quoi sert le contrat de bénévolat ?",
1202
+ "Pourquoi encadrer juridiquement une mission bénévole ?",
1203
+ "Qu’est-ce que le contrat protège ?",
1204
+ "Pourquoi autant de formalités pour une association ?",
1205
+ "Le contrat est-il vraiment nécessaire ?"
1206
+ ],
1207
+ "response": "Parce qu’un projet collectif implique des accès, des données, du code et des responsabilités. Le contrat protège à la fois le bénévole, l’association, les autres membres et les projets.",
1208
+ "enabled": true
1209
+ },
1210
+ {
1211
+ "id": "got_faq_071",
1212
+ "source_id": 71,
1213
+ "category": "Juridique et données",
1214
+ "intent_key": "dois_je_respecter_une_clause_de_confidentialite",
1215
+ "canonical_question": "Dois-je respecter une clause de confidentialité ?",
1216
+ "utterances": [
1217
+ "Dois-je respecter une clause de confidentialité ?",
1218
+ "Il y a une obligation de confidentialité ?",
1219
+ "Qu’est-ce que je n’ai pas le droit de partager ?",
1220
+ "La confidentialité continue-t-elle après mon départ ?",
1221
+ "Est-ce que je peux parler publiquement du projet ?",
1222
+ "Quels éléments doivent rester internes ?"
1223
+ ],
1224
+ "response": "Oui. Tu peux accéder à des informations internes, des données personnelles, des identifiants ou des éléments stratégiques qui ne doivent pas être diffusés. Cette obligation peut continuer à s’appliquer après ton départ.",
1225
+ "enabled": true
1226
+ },
1227
+ {
1228
+ "id": "got_faq_072",
1229
+ "source_id": 72,
1230
+ "category": "Juridique et données",
1231
+ "intent_key": "quelles_donnees_personnelles_sont_collectees",
1232
+ "canonical_question": "Quelles données personnelles sont collectées ?",
1233
+ "utterances": [
1234
+ "Quelles données personnelles sont collectées ?",
1235
+ "Quelles informations gardez-vous sur moi ?",
1236
+ "Que collecte le formulaire de candidature ?",
1237
+ "Vous enregistrez quelles données personnelles ?",
1238
+ "Est-ce que vous récupérez mon adresse IP ?",
1239
+ "Pourquoi avez-vous besoin de mes informations professionnelles ?"
1240
+ ],
1241
+ "response": "Selon ton utilisation du site et ta candidature, GOT peut collecter des données d’identification et de contact, des informations sur ton expérience professionnelle, ainsi que les données nécessaires à la gestion de ta participation. Seules les informations utiles aux finalités annoncées doivent être utilisées.",
1242
+ "enabled": true
1243
+ },
1244
+ {
1245
+ "id": "got_faq_073",
1246
+ "source_id": 73,
1247
+ "category": "Juridique et données",
1248
+ "intent_key": "est_ce_que_mes_donnees_sont_revendues",
1249
+ "canonical_question": "Est-ce que mes données sont revendues ?",
1250
+ "utterances": [
1251
+ "Est-ce que mes données sont revendues ?",
1252
+ "Vous vendez mes données ?",
1253
+ "Mes informations sont-elles utilisées à des fins commerciales ?",
1254
+ "Est-ce que des entreprises peuvent acheter mes données ?",
1255
+ "Vous partagez mon profil avec des annonceurs ?",
1256
+ "Que faites-vous commercialement de mes données ?"
1257
+ ],
1258
+ "response": "Non. Guild Open Tech s’engage à ne pas utiliser tes données personnelles à des fins commerciales.",
1259
+ "enabled": true
1260
+ },
1261
+ {
1262
+ "id": "got_faq_074",
1263
+ "source_id": 74,
1264
+ "category": "Juridique et données",
1265
+ "intent_key": "ou_sont_hebergees_mes_donnees",
1266
+ "canonical_question": "Où sont hébergées mes données ?",
1267
+ "utterances": [
1268
+ "Où sont hébergées mes données ?",
1269
+ "Mes données sont stockées où ?",
1270
+ "Vous utilisez quel hébergeur ?",
1271
+ "Les applications sont hébergées sur quel cloud ?",
1272
+ "Est-ce que mes données restent en Europe ?",
1273
+ "GOT utilise Google Cloud ?"
1274
+ ],
1275
+ "response": "Les services de Guild Open Tech utilisent Google Cloud Platform, notamment Cloud Run pour les applications, ainsi que des outils Google pour certaines données et ressources collaboratives. Des informations complémentaires sont disponibles dans la politique de confidentialité.",
1276
+ "enabled": true
1277
+ },
1278
+ {
1279
+ "id": "got_faq_075",
1280
+ "source_id": 75,
1281
+ "category": "Juridique et données",
1282
+ "intent_key": "comment_demander_la_suppression_de_mes_donnees",
1283
+ "canonical_question": "Comment demander la suppression de mes données ?",
1284
+ "utterances": [
1285
+ "Comment demander la suppression de mes données ?",
1286
+ "Comment faire effacer mes informations ?",
1287
+ "Je veux supprimer mon compte et mes données",
1288
+ "À qui écrire pour exercer mon droit à l’effacement ?",
1289
+ "Comment demander la rectification de mes données ?",
1290
+ "Quelle adresse utiliser pour une demande RGPD ?"
1291
+ ],
1292
+ "response": "Tu peux exercer tes droits d’accès, de rectification ou de suppression en contactant l’adresse RGPD indiquée dans la politique de confidentialité : rgpd@guildopentech.org. Précise les données concernées et la demande que tu souhaites exercer.",
1293
+ "enabled": true
1294
+ },
1295
+ {
1296
+ "id": "got_faq_076",
1297
+ "source_id": 76,
1298
+ "category": "Juridique et données",
1299
+ "intent_key": "qui_contacter_en_cas_de_probleme",
1300
+ "canonical_question": "Qui contacter en cas de problème ?",
1301
+ "utterances": [
1302
+ "Qui contacter en cas de problème ?",
1303
+ "À qui écrire si j’ai une question ?",
1304
+ "Quel est votre mail de contact ?",
1305
+ "Qui contacter pour un souci sur mon projet ?",
1306
+ "Où signaler un problème avec mes données ?",
1307
+ "Comment joindre Guild Open Tech ?"
1308
+ ],
1309
+ "response": "Pour une question générale, tu peux écrire à contact@guildopentech.org. Pour un sujet lié à tes données personnelles, utilise rgpd@guildopentech.org. Pour un problème concernant ton équipe ou ton engagement, contacte d’abord ton responsable de pôle ou de projet.",
1310
+ "enabled": true
1311
+ },
1312
+ {
1313
+ "id": "got_faq_077",
1314
+ "source_id": 77,
1315
+ "category": "Juridique et données",
1316
+ "intent_key": "quelle_est_l_adresse_de_l_association",
1317
+ "canonical_question": "Quelle est l’adresse de l’association ?",
1318
+ "utterances": [
1319
+ "Quelle est l’adresse de l’association ?",
1320
+ "Où est situé le siège de GOT ?",
1321
+ "Quelle est votre adresse postale ?",
1322
+ "L’association est basée où ?",
1323
+ "Vous êtes situés à Paris ?",
1324
+ "À quelle adresse peut-on écrire ?"
1325
+ ],
1326
+ "response": "Le siège social de Guild Open Tech est situé au 197 avenue de Versailles, 75016 Paris.",
1327
+ "enabled": true
1328
+ },
1329
+ {
1330
+ "id": "got_faq_078",
1331
+ "source_id": 78,
1332
+ "category": "Juridique et données",
1333
+ "intent_key": "quels_sont_les_reseaux_officiels_de_got",
1334
+ "canonical_question": "Quels sont les réseaux officiels de GOT ?",
1335
+ "utterances": [
1336
+ "Quels sont les réseaux officiels de GOT ?",
1337
+ "Vous êtes sur quels réseaux sociaux ?",
1338
+ "Où peut-on vous suivre ?",
1339
+ "Vous avez un LinkedIn ?",
1340
+ "Est-ce que GOT est sur Discord ?",
1341
+ "Quels sont vos comptes officiels ?"
1342
+ ],
1343
+ "response": "Guild Open Tech est présente sur LinkedIn et Discord.",
1344
+ "enabled": true
1345
+ },
1346
+ {
1347
+ "id": "got_faq_079",
1348
+ "source_id": 79,
1349
+ "category": "Juridique et données",
1350
+ "intent_key": "comment_rejoindre_le_serveur_discord",
1351
+ "canonical_question": "Comment rejoindre le serveur Discord ?",
1352
+ "utterances": [
1353
+ "Comment rejoindre le serveur Discord ?",
1354
+ "Où est le lien Discord ?",
1355
+ "Comment accéder à votre communauté Discord ?",
1356
+ "Je peux rejoindre Discord avant de candidater ?",
1357
+ "Le serveur Discord est-il public ?",
1358
+ "Comment recevoir une invitation Discord ?"
1359
+ ],
1360
+ "response": "Le lien d’accès à Discord est disponible depuis le site de Guild Open Tech. Une fois ta candidature acceptée, des espaces complémentaires pourront t’être ouverts selon ton projet ou ton rôle.",
1361
+ "enabled": true
1362
+ },
1363
+ {
1364
+ "id": "got_faq_080",
1365
+ "source_id": 80,
1366
+ "category": "Juridique et données",
1367
+ "intent_key": "que_se_passe_t_il_quand_je_quitte_un_projet",
1368
+ "canonical_question": "Que se passe-t-il quand je quitte un projet ?",
1369
+ "utterances": [
1370
+ "Que se passe-t-il quand je quitte un projet ?",
1371
+ "Que dois-je faire avant de partir ?",
1372
+ "Comment se déroule la fin d’une mission ?",
1373
+ "Est-ce que mes accès sont supprimés ?",
1374
+ "Je dois transmettre mon travail à quelqu’un ?",
1375
+ "Quelles obligations restent après mon départ ?"
1376
+ ],
1377
+ "response": "Tu dois prévenir l’équipe, transmettre les informations nécessaires et restituer ou supprimer les accès et informations confidentielles que tu détiens. Les accès aux ressources liées à ta mission seront ensuite retirés. Au bout de 6 mois tes données seront automatiquement supprimées ou anonymisées dans le respect de la législation.",
1378
+ "enabled": true
1379
+ }
1380
+ ]
1381
+ }
embeddings.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gestion des embeddings avec ChromaDB et Hugging Face Transformers."""
2
+ import os
3
+ # Règle d’or : toute variable d’environnement qui influence le cache Hugging Face doit être
4
+ # définie avant d’importer datasets ou transformers, sinon elle sera ignorée.
5
+ cache_dir = "/tmp"
6
+ os.makedirs(cache_dir, exist_ok=True)
7
+
8
+ # Rediriger le cache HF globalement
9
+ os.environ["HF_HOME"] = cache_dir
10
+ os.environ["HF_DATASETS_CACHE"] = os.path.join(cache_dir, "datasets")
11
+ os.environ["TRANSFORMERS_CACHE"] = os.path.join(cache_dir, "transformers")
12
+
13
+ import logging
14
+ from typing import Optional
15
+ from models import QuestionInput, AnswerOutput
16
+
17
+ import chromadb
18
+ from sentence_transformers import SentenceTransformer
19
+ import torch
20
+ from config import (
21
+ CHROMA_COLLECTION_NAME,
22
+ MODEL_NAME,
23
+ SIMILARITY_THRESHOLD,
24
+ )
25
+ from faq_loader import FAQEntry
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ class EmbeddingManager:
31
+ """Gestionnaire des embeddings et de ChromaDB."""
32
+
33
+ def __init__(
34
+ self,
35
+ model_name: str = MODEL_NAME,
36
+ collection_name: str = CHROMA_COLLECTION_NAME,
37
+ ) -> None:
38
+ """
39
+ Initialiser le gestionnaire d'embeddings.
40
+
41
+ Args:
42
+ model_name: Nom du modèle Sentence-Transformers à utiliser
43
+ collection_name: Nom de la collection ChromaDB
44
+ """
45
+
46
+ # Creation du Sentence transformer model
47
+ logger.info(f"Initialisation du modèle d'embeddings: {model_name}")
48
+ device = "cuda" if torch.cuda.is_available() else "cpu"
49
+ self.model = SentenceTransformer(MODEL_NAME, device=device)
50
+
51
+ # Initialiser ChromaDB en mémoire (EphemeralClient)
52
+ # Idéal pour HF Spaces: pas de persistance disque, plus rapide au startup
53
+ logger.info("Initialisation ChromaDB en mémoire (EphemeralClient)")
54
+ self.client: chromadb.Client = chromadb.EphemeralClient()
55
+
56
+ # Créer ou récupérer la collection
57
+ self.collection = self.client.get_or_create_collection(
58
+ name=collection_name,
59
+ embedding_function=None,
60
+ metadata={"hnsw:space": "ip"} # Utiliser produit scalaire => normaliser les embeddings
61
+ )
62
+
63
+ self.collection_name: str = collection_name
64
+ logger.info(f"✓ EmbeddingManager initialisé (collection: {collection_name})")
65
+
66
+ def populate_collection(self, faq_entries: list[FAQEntry]) -> None:
67
+ """
68
+ Remplir la collection ChromaDB avec les embeddings des FAQ.
69
+
70
+ Args:
71
+ faq_entries: Liste d'objets FAQEntry à indexer
72
+ """
73
+ logger.info(f"Population de ChromaDB avec {len(faq_entries)} entrées...")
74
+
75
+ # Vider la collection existante (optionnel, mais plus propre)
76
+ # Récupérer l'ID de collection pour supprimer les anciens documents
77
+ existing_ids = self.collection.get()["ids"]
78
+ if existing_ids:
79
+ logger.info(f"Suppression de {len(existing_ids)} anciens documents...")
80
+ self.collection.delete(ids=existing_ids)
81
+
82
+ # Générer les embeddings pour toutes les formulations
83
+ formulations: list[str] = ["passage: " + entry.formulation for entry in faq_entries]
84
+ logger.info("Génération des embeddings...")
85
+ embeddings = self.model.encode(formulations, show_progress_bar=True,
86
+ convert_to_numpy=True, normalize_embeddings=True)
87
+
88
+ # Ajouter à ChromaDB
89
+ logger.info("Ajout des documents à ChromaDB...")
90
+ self.collection.add(
91
+ ids=[f"faq_{i}" for i in range(len(faq_entries))],
92
+ embeddings=embeddings.tolist(),
93
+ documents=formulations,
94
+ metadatas=[
95
+ {
96
+ "theme": entry.theme,
97
+ "response": entry.response,
98
+ }
99
+ for entry in faq_entries
100
+ ],
101
+ )
102
+
103
+ logger.info(f"✓ ChromaDB peuplée avec {len(faq_entries)} entrées")
104
+
105
+ def search_similar_faq(self, payload: QuestionInput) -> AnswerOutput:
106
+ """
107
+ Rechercher dans la FAQ la formulation laplus similaire à une question donnée.
108
+
109
+ Args:
110
+ question: Question à chercher
111
+ threshold: Seuil de confiance minimum pour retourner une réponse
112
+
113
+ Returns:
114
+ Tuple (formulation, theme, response, similarity_score) ou None si aucun match
115
+ """
116
+ # Récupérer la question et le seuil depuis le payload
117
+ question = payload.question
118
+ threshold = payload.threshold if payload.threshold is not None else SIMILARITY_THRESHOLD
119
+
120
+ # Générer l'embedding de la question
121
+ question_embedding = self.model.encode(["query: " + question], convert_to_numpy=True,
122
+ normalize_embeddings=True).tolist()
123
+
124
+ # Rechercher dans ChromaDB
125
+ results = self.collection.query(
126
+ query_embeddings=question_embedding,
127
+ n_results=1,
128
+ include=["documents", "metadatas", "distances"]
129
+ )
130
+
131
+ if not results["ids"] or not results["ids"][0]:
132
+ logger.warning(f"Aucun résultat trouvé pour: {question}")
133
+ return AnswerOutput(
134
+ question=question,
135
+ formulation="unknown",
136
+ answer="Je ne dispose pas d'une réponse suffisamment pertinente pour cette question.",
137
+ theme="unknown",
138
+ similarity_score=0.0,
139
+ confidence=False,
140
+ )
141
+
142
+ # Extraire le meilleur résultat
143
+ # ChromaDB retourne les produits scalaires, on convertit en similarité cosinus
144
+ distance = results["distances"][0][0]
145
+ similarity_score: float = 1 - distance
146
+
147
+ # Extraire les métadonnées
148
+ metadata = results["metadatas"][0][0]
149
+ formulation = results["documents"][0][0]
150
+ theme = metadata["theme"]
151
+ response = metadata["response"]
152
+
153
+ # Vérifier le seuil
154
+ if similarity_score < threshold:
155
+ logger.info(
156
+ f"Score de similarité {similarity_score:.3f} < seuil {threshold}. "
157
+ f"Question: {question}"
158
+ )
159
+ return AnswerOutput(
160
+ question=question,
161
+ formulation=formulation,
162
+ answer="Je ne dispose pas d'une réponse suffisamment pertinente pour cette question.",
163
+ theme=theme,
164
+ similarity_score=round(similarity_score, 4),
165
+ confidence=False,
166
+ )
167
+
168
+ logger.info(
169
+ f"Match trouvé - Theme: {theme}, Score: {similarity_score:.3f}"
170
+ )
171
+
172
+ return AnswerOutput(
173
+ question=question,
174
+ formulation=formulation,
175
+ answer=response,
176
+ theme=theme,
177
+ similarity_score=round(similarity_score, 4),
178
+ confidence=True,
179
+ )
180
+
181
+ def get_collection_size(self) -> int:
182
+ """
183
+ Obtenir le nombre de documents dans la collection.
184
+
185
+ Returns:
186
+ Nombre de documents
187
+ """
188
+ return self.collection.count()
faq_loader.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Chargement et traitement des données FAQ à partir d'un fichier JSON."""
2
+ import json
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Any, List
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ class FAQEntry:
11
+ """Représentation d'une entrée FAQ."""
12
+
13
+ def __init__(self, formulation: str, theme: str, response: str) -> None:
14
+ """
15
+ Initialiser une entrée FAQ.
16
+
17
+ Args:
18
+ formulation: La question de la FAQ
19
+ theme: Le thème/catégorie de la FAQ
20
+ response: La réponse associée
21
+ """
22
+ self.formulation: str = formulation
23
+ self.theme: str = theme
24
+ self.response: str = response
25
+
26
+
27
+ def load_faq_data(json_path: str) -> List[FAQEntry]:
28
+ """
29
+ Charger les données FAQ à partir d'un fichier JSON.
30
+
31
+ Le fichier JSON contient une structure avec une clé "intents". Pour chaque intent
32
+ ayant enabled=True, on crée une FAQEntry à partir de :
33
+ - formulation : la liste d'utterances
34
+ - theme : intent_key
35
+ - response : response
36
+
37
+ Args:
38
+ json_path: Chemin vers le fichier JSON contenant les intents FAQ.
39
+
40
+ Returns:
41
+ Liste d'objets FAQEntry contenant formulation, theme et réponse.
42
+
43
+ Raises:
44
+ FileNotFoundError: Si le fichier JSON n'existe pas.
45
+ ValueError: Si le JSON est vide ou mal formé.
46
+ """
47
+ path = Path(json_path)
48
+
49
+ if not path.exists():
50
+ raise FileNotFoundError(f"Fichier non trouvé: {json_path}")
51
+
52
+ try:
53
+ logger.info(f"Chargement FAQ depuis le JSON: {json_path}")
54
+ with path.open("r", encoding="utf-8") as handle:
55
+ payload: dict[str, Any] = json.load(handle)
56
+ except json.JSONDecodeError as exc:
57
+ raise ValueError(f"Erreur lors du parsing du JSON: {exc}") from exc
58
+
59
+ intents = payload.get("intents")
60
+ if not isinstance(intents, list):
61
+ raise ValueError("Le JSON ne contient pas de liste 'intents' valide")
62
+
63
+ faq_entries: List[FAQEntry] = []
64
+ for intent in intents:
65
+ if not isinstance(intent, dict):
66
+ continue
67
+
68
+ enabled = intent.get("enabled", False)
69
+ if not enabled:
70
+ continue
71
+
72
+ utterances = intent.get("utterances")
73
+ if not isinstance(utterances, list) or not utterances:
74
+ continue
75
+
76
+ intent_key = intent.get("intent_key")
77
+ response = intent.get("response")
78
+ if not isinstance(intent_key, str) or not intent_key.strip():
79
+ continue
80
+ if not isinstance(response, str) or not response.strip():
81
+ continue
82
+
83
+ for formulation in utterances:
84
+ if not isinstance(formulation, str) or not formulation.strip():
85
+ continue
86
+
87
+ faq_entries.append(
88
+ FAQEntry(
89
+ formulation=formulation.strip(),
90
+ theme=intent_key.strip(),
91
+ response=response.strip(),
92
+ )
93
+ )
94
+
95
+ if not faq_entries:
96
+ raise ValueError("Aucune entrée FAQ valide trouvée dans le JSON")
97
+
98
+ logger.info(f"✓ {len(faq_entries)} entrées FAQ chargées avec succès depuis le JSON")
99
+ return faq_entries
models.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Modèles Pydantic pour les requêtes et réponses API."""
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, Field, ConfigDict
5
+
6
+
7
+ class QuestionInput(BaseModel):
8
+ """Modèle pour une question d'entrée."""
9
+ question: str = Field(..., min_length=1, max_length=500, description="Question en texte libre")
10
+ threshold: Optional[float] = Field(
11
+ None,
12
+ ge=0.0,
13
+ le=1.0,
14
+ description="Seuil de similarité cosinus souhaité entre 0.0 et 1.0. Si omis, la valeur par défaut du service est utilisée.",
15
+ )
16
+
17
+ model_config = ConfigDict(
18
+ json_schema_extra={
19
+ "example": {
20
+ "question": "On a besoin de télécharger une application côté famille ?",
21
+ "threshold": 0.85
22
+ }
23
+ }
24
+ )
25
+
26
+
27
+ class AnswerOutput(BaseModel):
28
+ """Modèle pour une réponse de sortie."""
29
+ question: str = Field(..., description="Question posée")
30
+ formulation: str = Field(..., description="Formulation de la question trouvée dans la base FAQ")
31
+ answer: str = Field(..., description="Réponse trouvée dans la base FAQ")
32
+ theme: str = Field(..., description="Thème/catégorie de la réponse")
33
+ similarity_score: float = Field(..., ge=0.0, le=1.0, description="Score de similarité cosinus [0, 1]")
34
+ confidence: bool = Field(..., description="True si score >= seuil de confiance, False sinon")
35
+
36
+ model_config = ConfigDict(
37
+ json_schema_extra={
38
+ "example": {
39
+ "question": "On a besoin de télécharger une application côté famille ?",
40
+ "formulation": "Les parents ont-ils besoin de télécharger une application ?",
41
+ "answer": "Non. Les parents accèdent aux médias via un lien web reçu par e-mail, sans installation requise.",
42
+ "theme": "need_download_family_app",
43
+ "similarity_score": 0.889,
44
+ "confidence": True
45
+ }
46
+ }
47
+ )
48
+
49
+
50
+ class HealthResponse(BaseModel):
51
+ """Modèle pour la réponse health check."""
52
+ status: str = Field(..., description="État du service")
53
+ faq_count: int = Field(..., description="Nombre de questions dans la base FAQ")
54
+
55
+ model_config = ConfigDict(
56
+ json_schema_extra={
57
+ "example": {
58
+ "status": "ok",
59
+ "faq_count": 3
60
+ }
61
+ }
62
+ )
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.104.1
2
+ uvicorn[standard]==0.24.0
3
+ pydantic==2.5.0
4
+ chromadb==0.4.24
5
+ sentence-transformers==2.5.0
6
+ torch==2.1.1
7
+ transformers==4.36.0
8
+ pandas==2.1.3
9
+ python-dotenv==1.0.0