Update app.py
Browse files
app.py
CHANGED
|
@@ -24,12 +24,13 @@ try:
|
|
| 24 |
_gb.client_utils.json_schema_to_python_type = _safe
|
| 25 |
except Exception:
|
| 26 |
pass
|
|
|
|
| 27 |
try:
|
| 28 |
from llama_cpp import Llama
|
| 29 |
_LLAMA_AVAILABLE = True
|
| 30 |
except ImportError:
|
| 31 |
_LLAMA_AVAILABLE = False
|
| 32 |
-
|
| 33 |
from gtts import gTTS
|
| 34 |
from huggingface_hub import hf_hub_download
|
| 35 |
|
|
@@ -90,48 +91,37 @@ LESSONS = [
|
|
| 90 |
"title": "Leçon 1 — Sources du droit et hiérarchie des normes",
|
| 91 |
"text": """
|
| 92 |
Cours de droit civil. Introduction aux sources du droit français.
|
| 93 |
-
|
| 94 |
Première partie : Les sources formelles du droit.
|
| 95 |
-
|
| 96 |
Le droit français repose sur plusieurs sources hiérarchisées.
|
| 97 |
Au sommet se trouve la Constitution du 4 octobre 1958, loi fondamentale
|
| 98 |
de la République française. Elle établit les règles d'organisation de
|
| 99 |
l'État et garantit les droits fondamentaux des citoyens.
|
| 100 |
-
|
| 101 |
Sous la Constitution, on trouve les traités internationaux et le droit
|
| 102 |
de l'Union européenne. En vertu de l'article 55 de la Constitution,
|
| 103 |
les traités régulièrement ratifiés ont une autorité supérieure à celle
|
| 104 |
des lois ordinaires.
|
| 105 |
-
|
| 106 |
Vient ensuite la loi, votée par le Parlement. La loi ordinaire est
|
| 107 |
adoptée par l'Assemblée nationale et le Sénat selon la procédure
|
| 108 |
législative prévue par la Constitution. Les lois organiques,
|
| 109 |
quant à elles, complètent et précisent certaines dispositions
|
| 110 |
constitutionnelles et bénéficient d'un statut intermédiaire.
|
| 111 |
-
|
| 112 |
Le règlement constitue la quatrième source majeure. Il émane du
|
| 113 |
pouvoir exécutif : décrets du Président de la République et du
|
| 114 |
Premier ministre, arrêtés ministériels, préfectoraux et municipaux.
|
| 115 |
L'article 37 de la Constitution confère au gouvernement un domaine
|
| 116 |
réglementaire autonome.
|
| 117 |
-
|
| 118 |
Deuxième partie : Les sources matérielles du droit.
|
| 119 |
-
|
| 120 |
La jurisprudence, bien qu'elle ne soit pas officiellement reconnue
|
| 121 |
comme source formelle, joue un rôle fondamental dans le système
|
| 122 |
juridique français. Les décisions de la Cour de cassation et du
|
| 123 |
Conseil d'État interprètent et précisent la portée des textes légaux.
|
| 124 |
Le Conseil constitutionnel contrôle la constitutionnalité des lois.
|
| 125 |
-
|
| 126 |
La doctrine regroupe l'ensemble des travaux des juristes :
|
| 127 |
professeurs, avocats, magistrats. Sans force obligatoire, elle influence
|
| 128 |
néanmoins la jurisprudence et le législateur.
|
| 129 |
-
|
| 130 |
La coutume, source ancienne, est aujourd'hui d'application limitée.
|
| 131 |
En droit commercial, les usages professionnels conservent une importance certaine.
|
| 132 |
-
|
| 133 |
Troisième partie : Le principe de hiérarchie des normes.
|
| 134 |
-
|
| 135 |
Hans Kelsen, juriste autrichien du vingtième siècle, a théorisé
|
| 136 |
la pyramide des normes. Chaque norme tire sa validité d'une norme supérieure.
|
| 137 |
En France, le Conseil constitutionnel assure le respect de cette hiérarchie.
|
|
@@ -151,34 +141,25 @@ En France, le Conseil constitutionnel assure le respect de cette hiérarchie.
|
|
| 151 |
"title": "Leçon 2 — Le droit des contrats",
|
| 152 |
"text": """
|
| 153 |
Cours de droit civil. Le droit des contrats.
|
| 154 |
-
|
| 155 |
Première partie : Définition et conditions de validité.
|
| 156 |
-
|
| 157 |
Le contrat est un accord de volontés destiné à créer, modifier, transmettre
|
| 158 |
ou éteindre des obligations. Le Code civil, issu de l'ordonnance du 10 février 2016,
|
| 159 |
définit trois conditions de validité : le consentement des parties, leur capacité
|
| 160 |
à contracter, et un contenu licite et certain.
|
| 161 |
-
|
| 162 |
Le consentement doit être libre et éclairé. Il est vicié par l'erreur, le dol
|
| 163 |
ou la violence. L'incapacité concerne les mineurs non émancipés et les majeurs
|
| 164 |
protégés sous tutelle ou curatelle.
|
| 165 |
-
|
| 166 |
Deuxième partie : Les effets du contrat.
|
| 167 |
-
|
| 168 |
L'exécution obéit au principe de la force obligatoire : le contrat tient lieu
|
| 169 |
de loi entre les parties. En cas d'inexécution : exécution forcée, résolution
|
| 170 |
ou dommages et intérêts.
|
| 171 |
-
|
| 172 |
L'effet relatif du contrat signifie que le contrat ne crée d'obligations qu'entre
|
| 173 |
les parties contractantes. Les tiers ne peuvent en principe ni se prévaloir du contrat,
|
| 174 |
ni se le voir opposer.
|
| 175 |
-
|
| 176 |
Troisième partie : La formation du contrat.
|
| 177 |
-
|
| 178 |
La formation du contrat passe par une offre et une acceptation. L'offre doit être
|
| 179 |
précise et ferme. L'acceptation doit être pure et simple. Toute contre-proposition
|
| 180 |
constitue une nouvelle offre.
|
| 181 |
-
|
| 182 |
Les avant-contrats tels que la promesse unilatérale de vente ou le pacte de
|
| 183 |
préférence permettent d'organiser la phase précontractuelle et d'encadrer
|
| 184 |
les négociations entre les parties.
|
|
@@ -198,35 +179,26 @@ les négociations entre les parties.
|
|
| 198 |
"title": "Leçon 3 — La responsabilité civile",
|
| 199 |
"text": """
|
| 200 |
Cours de droit civil. La responsabilité civile.
|
| 201 |
-
|
| 202 |
Première partie : Distinction responsabilité civile et pénale.
|
| 203 |
-
|
| 204 |
La responsabilité civile répare le préjudice causé à autrui, contrairement
|
| 205 |
à la responsabilité pénale qui sanctionne l'auteur d'une infraction.
|
| 206 |
La responsabilité civile vise à remettre la victime dans l'état où elle
|
| 207 |
se trouvait avant le dommage, par l'octroi de dommages et intérêts.
|
| 208 |
-
|
| 209 |
Deuxième partie : La responsabilité délictuelle.
|
| 210 |
-
|
| 211 |
La responsabilité délictuelle repose sur trois conditions : faute, dommage
|
| 212 |
et lien de causalité. L'article 1240 du Code civil dispose que tout fait
|
| 213 |
de l'homme causant un dommage oblige son auteur à le réparer.
|
| 214 |
-
|
| 215 |
La faute peut être intentionnelle ou non intentionnelle. Le dommage doit être
|
| 216 |
certain, direct et personnel. Le lien de causalité entre la faute et le dommage
|
| 217 |
doit être prouvé par la victime.
|
| 218 |
-
|
| 219 |
Troisième partie : La responsabilité sans faute.
|
| 220 |
-
|
| 221 |
La responsabilité sans faute couvre trois domaines principaux.
|
| 222 |
Le fait des choses : on est responsable des dommages causés par les choses
|
| 223 |
dont on a la garde. Le fait d'autrui : les parents sont responsables des dommages
|
| 224 |
causés par leurs enfants mineurs ; les commettants répondent des fautes de leurs préposés.
|
| 225 |
Les produits défectueux : le producteur est responsable du dommage causé
|
| 226 |
par un défaut de son produit, sans que la victime ait à prouver une faute.
|
| 227 |
-
|
| 228 |
Quatrième partie : La responsabilité contractuelle.
|
| 229 |
-
|
| 230 |
Lorsque le dommage résulte de l'inexécution d'un contrat, la responsabilité
|
| 231 |
contractuelle s'applique. Elle suppose un contrat valable, une inexécution
|
| 232 |
et un préjudice. Le débiteur peut s'exonérer en prouvant la force majeure,
|
|
@@ -286,7 +258,6 @@ def evaluate_answer(question, answer, hint):
|
|
| 286 |
score = min(10, round((hits / max(len(kw), 1)) * 10))
|
| 287 |
return score, f"(Sans IA – mots-clés : {hits}/{len(kw)})"
|
| 288 |
|
| 289 |
-
# Prompt format Qwen2.5
|
| 290 |
prompt = (
|
| 291 |
"<|im_start|>system\n"
|
| 292 |
"Tu es un professeur de droit français strict et bienveillant. "
|
|
@@ -311,7 +282,6 @@ def evaluate_answer(question, answer, hint):
|
|
| 311 |
)
|
| 312 |
text = out["choices"][0]["text"].strip()
|
| 313 |
print(f"[law-app] Réponse modèle : {text}")
|
| 314 |
-
# Extraire le JSON
|
| 315 |
start = text.find("{")
|
| 316 |
end = text.rfind("}") + 1
|
| 317 |
if start == -1 or end == 0:
|
|
@@ -320,7 +290,6 @@ def evaluate_answer(question, answer, hint):
|
|
| 320 |
return max(0, min(10, int(data["score"]))), data.get("feedback", "")
|
| 321 |
except Exception as e:
|
| 322 |
print(f"[law-app] Erreur éval : {e}")
|
| 323 |
-
# Fallback mots-clés
|
| 324 |
kw = [w.strip().lower() for w in hint.split(",")]
|
| 325 |
hits = sum(1 for k in kw if k in answer.lower())
|
| 326 |
score = min(10, round((hits / max(len(kw), 1)) * 10))
|
|
@@ -385,15 +354,33 @@ def open_quiz(ss):
|
|
| 385 |
"", LESSONS[lesson_idx]["questions"][idx]["q"], "", D(state),
|
| 386 |
)
|
| 387 |
|
|
|
|
| 388 |
def submit_answer(answer, ss):
|
| 389 |
state = S(ss)
|
| 390 |
lesson_idx = state.get("lesson_idx", 0)
|
|
|
|
| 391 |
if state["phase"] != "quiz":
|
| 392 |
-
|
| 393 |
gr.update(visible=True), gr.update(visible=False),
|
| 394 |
gr.update(visible=False), gr.update(visible=False),
|
| 395 |
-
"",
|
|
|
|
|
|
|
|
|
|
| 396 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
q = LESSONS[lesson_idx]["questions"][state["question_idx"]]
|
| 398 |
score, fb = evaluate_answer(q["q"], answer, q["hint"])
|
| 399 |
total = len(LESSONS)
|
|
@@ -405,10 +392,7 @@ def submit_answer(answer, ss):
|
|
| 405 |
f"## 🎉 Bravo ! Leçon {lesson_idx + 1}/{total} réussie.\n\n"
|
| 406 |
f"**Score : {score}/10**\n\n**Commentaire :** {fb}"
|
| 407 |
)
|
| 408 |
-
if is_last
|
| 409 |
-
next_label = "🏆 Voir mon certificat"
|
| 410 |
-
else:
|
| 411 |
-
next_label = f"➡️ {LESSONS[lesson_idx + 1]['title']}"
|
| 412 |
else:
|
| 413 |
state["phase"] = "fail"
|
| 414 |
result = (
|
|
@@ -419,10 +403,14 @@ def submit_answer(answer, ss):
|
|
| 419 |
)
|
| 420 |
next_label = "🔄 Réécouter la leçon"
|
| 421 |
|
| 422 |
-
|
|
|
|
| 423 |
gr.update(visible=False), gr.update(visible=False),
|
| 424 |
gr.update(visible=True), gr.update(visible=False),
|
| 425 |
-
result,
|
|
|
|
|
|
|
|
|
|
| 426 |
)
|
| 427 |
|
| 428 |
def handle_next(ss):
|
|
@@ -480,7 +468,7 @@ with gr.Blocks(title="Cours de Droit", css=CSS) as demo:
|
|
| 480 |
audio_out = gr.Audio(label="Cours audio (français)", autoplay=False, interactive=False)
|
| 481 |
timer_info = gr.Markdown("")
|
| 482 |
with gr.Row():
|
| 483 |
-
start_btn = gr.Button("▶️ Démarrer l'écoute"+str(_LLAMA_OK), variant="primary")
|
| 484 |
check_btn = gr.Button("🔄 Vérifier le temps", variant="secondary")
|
| 485 |
quiz_btn = gr.Button("✅ Accéder au Quiz", variant="secondary", interactive=False)
|
| 486 |
|
|
@@ -511,8 +499,9 @@ with gr.Blocks(title="Cours de Droit", css=CSS) as demo:
|
|
| 511 |
timer_info, question_md, answer_box, session]
|
| 512 |
quiz_btn.click(open_quiz, [session], QUIZ_OUT)
|
| 513 |
|
|
|
|
| 514 |
RES_OUT = [listen_col, quiz_col, result_col, cert_col,
|
| 515 |
-
result_md,
|
| 516 |
submit_btn.click(submit_answer, [answer_box, session], RES_OUT)
|
| 517 |
answer_box.submit(submit_answer, [answer_box, session], RES_OUT)
|
| 518 |
|
|
@@ -523,5 +512,4 @@ with gr.Blocks(title="Cours de Droit", css=CSS) as demo:
|
|
| 523 |
threading.Thread(target=get_llm, daemon=True).start()
|
| 524 |
|
| 525 |
if __name__ == "__main__":
|
| 526 |
-
demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)
|
| 527 |
-
|
|
|
|
| 24 |
_gb.client_utils.json_schema_to_python_type = _safe
|
| 25 |
except Exception:
|
| 26 |
pass
|
| 27 |
+
|
| 28 |
try:
|
| 29 |
from llama_cpp import Llama
|
| 30 |
_LLAMA_AVAILABLE = True
|
| 31 |
except ImportError:
|
| 32 |
_LLAMA_AVAILABLE = False
|
| 33 |
+
|
| 34 |
from gtts import gTTS
|
| 35 |
from huggingface_hub import hf_hub_download
|
| 36 |
|
|
|
|
| 91 |
"title": "Leçon 1 — Sources du droit et hiérarchie des normes",
|
| 92 |
"text": """
|
| 93 |
Cours de droit civil. Introduction aux sources du droit français.
|
|
|
|
| 94 |
Première partie : Les sources formelles du droit.
|
|
|
|
| 95 |
Le droit français repose sur plusieurs sources hiérarchisées.
|
| 96 |
Au sommet se trouve la Constitution du 4 octobre 1958, loi fondamentale
|
| 97 |
de la République française. Elle établit les règles d'organisation de
|
| 98 |
l'État et garantit les droits fondamentaux des citoyens.
|
|
|
|
| 99 |
Sous la Constitution, on trouve les traités internationaux et le droit
|
| 100 |
de l'Union européenne. En vertu de l'article 55 de la Constitution,
|
| 101 |
les traités régulièrement ratifiés ont une autorité supérieure à celle
|
| 102 |
des lois ordinaires.
|
|
|
|
| 103 |
Vient ensuite la loi, votée par le Parlement. La loi ordinaire est
|
| 104 |
adoptée par l'Assemblée nationale et le Sénat selon la procédure
|
| 105 |
législative prévue par la Constitution. Les lois organiques,
|
| 106 |
quant à elles, complètent et précisent certaines dispositions
|
| 107 |
constitutionnelles et bénéficient d'un statut intermédiaire.
|
|
|
|
| 108 |
Le règlement constitue la quatrième source majeure. Il émane du
|
| 109 |
pouvoir exécutif : décrets du Président de la République et du
|
| 110 |
Premier ministre, arrêtés ministériels, préfectoraux et municipaux.
|
| 111 |
L'article 37 de la Constitution confère au gouvernement un domaine
|
| 112 |
réglementaire autonome.
|
|
|
|
| 113 |
Deuxième partie : Les sources matérielles du droit.
|
|
|
|
| 114 |
La jurisprudence, bien qu'elle ne soit pas officiellement reconnue
|
| 115 |
comme source formelle, joue un rôle fondamental dans le système
|
| 116 |
juridique français. Les décisions de la Cour de cassation et du
|
| 117 |
Conseil d'État interprètent et précisent la portée des textes légaux.
|
| 118 |
Le Conseil constitutionnel contrôle la constitutionnalité des lois.
|
|
|
|
| 119 |
La doctrine regroupe l'ensemble des travaux des juristes :
|
| 120 |
professeurs, avocats, magistrats. Sans force obligatoire, elle influence
|
| 121 |
néanmoins la jurisprudence et le législateur.
|
|
|
|
| 122 |
La coutume, source ancienne, est aujourd'hui d'application limitée.
|
| 123 |
En droit commercial, les usages professionnels conservent une importance certaine.
|
|
|
|
| 124 |
Troisième partie : Le principe de hiérarchie des normes.
|
|
|
|
| 125 |
Hans Kelsen, juriste autrichien du vingtième siècle, a théorisé
|
| 126 |
la pyramide des normes. Chaque norme tire sa validité d'une norme supérieure.
|
| 127 |
En France, le Conseil constitutionnel assure le respect de cette hiérarchie.
|
|
|
|
| 141 |
"title": "Leçon 2 — Le droit des contrats",
|
| 142 |
"text": """
|
| 143 |
Cours de droit civil. Le droit des contrats.
|
|
|
|
| 144 |
Première partie : Définition et conditions de validité.
|
|
|
|
| 145 |
Le contrat est un accord de volontés destiné à créer, modifier, transmettre
|
| 146 |
ou éteindre des obligations. Le Code civil, issu de l'ordonnance du 10 février 2016,
|
| 147 |
définit trois conditions de validité : le consentement des parties, leur capacité
|
| 148 |
à contracter, et un contenu licite et certain.
|
|
|
|
| 149 |
Le consentement doit être libre et éclairé. Il est vicié par l'erreur, le dol
|
| 150 |
ou la violence. L'incapacité concerne les mineurs non émancipés et les majeurs
|
| 151 |
protégés sous tutelle ou curatelle.
|
|
|
|
| 152 |
Deuxième partie : Les effets du contrat.
|
|
|
|
| 153 |
L'exécution obéit au principe de la force obligatoire : le contrat tient lieu
|
| 154 |
de loi entre les parties. En cas d'inexécution : exécution forcée, résolution
|
| 155 |
ou dommages et intérêts.
|
|
|
|
| 156 |
L'effet relatif du contrat signifie que le contrat ne crée d'obligations qu'entre
|
| 157 |
les parties contractantes. Les tiers ne peuvent en principe ni se prévaloir du contrat,
|
| 158 |
ni se le voir opposer.
|
|
|
|
| 159 |
Troisième partie : La formation du contrat.
|
|
|
|
| 160 |
La formation du contrat passe par une offre et une acceptation. L'offre doit être
|
| 161 |
précise et ferme. L'acceptation doit être pure et simple. Toute contre-proposition
|
| 162 |
constitue une nouvelle offre.
|
|
|
|
| 163 |
Les avant-contrats tels que la promesse unilatérale de vente ou le pacte de
|
| 164 |
préférence permettent d'organiser la phase précontractuelle et d'encadrer
|
| 165 |
les négociations entre les parties.
|
|
|
|
| 179 |
"title": "Leçon 3 — La responsabilité civile",
|
| 180 |
"text": """
|
| 181 |
Cours de droit civil. La responsabilité civile.
|
|
|
|
| 182 |
Première partie : Distinction responsabilité civile et pénale.
|
|
|
|
| 183 |
La responsabilité civile répare le préjudice causé à autrui, contrairement
|
| 184 |
à la responsabilité pénale qui sanctionne l'auteur d'une infraction.
|
| 185 |
La responsabilité civile vise à remettre la victime dans l'état où elle
|
| 186 |
se trouvait avant le dommage, par l'octroi de dommages et intérêts.
|
|
|
|
| 187 |
Deuxième partie : La responsabilité délictuelle.
|
|
|
|
| 188 |
La responsabilité délictuelle repose sur trois conditions : faute, dommage
|
| 189 |
et lien de causalité. L'article 1240 du Code civil dispose que tout fait
|
| 190 |
de l'homme causant un dommage oblige son auteur à le réparer.
|
|
|
|
| 191 |
La faute peut être intentionnelle ou non intentionnelle. Le dommage doit être
|
| 192 |
certain, direct et personnel. Le lien de causalité entre la faute et le dommage
|
| 193 |
doit être prouvé par la victime.
|
|
|
|
| 194 |
Troisième partie : La responsabilité sans faute.
|
|
|
|
| 195 |
La responsabilité sans faute couvre trois domaines principaux.
|
| 196 |
Le fait des choses : on est responsable des dommages causés par les choses
|
| 197 |
dont on a la garde. Le fait d'autrui : les parents sont responsables des dommages
|
| 198 |
causés par leurs enfants mineurs ; les commettants répondent des fautes de leurs préposés.
|
| 199 |
Les produits défectueux : le producteur est responsable du dommage causé
|
| 200 |
par un défaut de son produit, sans que la victime ait à prouver une faute.
|
|
|
|
| 201 |
Quatrième partie : La responsabilité contractuelle.
|
|
|
|
| 202 |
Lorsque le dommage résulte de l'inexécution d'un contrat, la responsabilité
|
| 203 |
contractuelle s'applique. Elle suppose un contrat valable, une inexécution
|
| 204 |
et un préjudice. Le débiteur peut s'exonérer en prouvant la force majeure,
|
|
|
|
| 258 |
score = min(10, round((hits / max(len(kw), 1)) * 10))
|
| 259 |
return score, f"(Sans IA – mots-clés : {hits}/{len(kw)})"
|
| 260 |
|
|
|
|
| 261 |
prompt = (
|
| 262 |
"<|im_start|>system\n"
|
| 263 |
"Tu es un professeur de droit français strict et bienveillant. "
|
|
|
|
| 282 |
)
|
| 283 |
text = out["choices"][0]["text"].strip()
|
| 284 |
print(f"[law-app] Réponse modèle : {text}")
|
|
|
|
| 285 |
start = text.find("{")
|
| 286 |
end = text.rfind("}") + 1
|
| 287 |
if start == -1 or end == 0:
|
|
|
|
| 290 |
return max(0, min(10, int(data["score"]))), data.get("feedback", "")
|
| 291 |
except Exception as e:
|
| 292 |
print(f"[law-app] Erreur éval : {e}")
|
|
|
|
| 293 |
kw = [w.strip().lower() for w in hint.split(",")]
|
| 294 |
hits = sum(1 for k in kw if k in answer.lower())
|
| 295 |
score = min(10, round((hits / max(len(kw), 1)) * 10))
|
|
|
|
| 354 |
"", LESSONS[lesson_idx]["questions"][idx]["q"], "", D(state),
|
| 355 |
)
|
| 356 |
|
| 357 |
+
# ── Submit avec désactivation immédiate du bouton ────────────────────────────
|
| 358 |
def submit_answer(answer, ss):
|
| 359 |
state = S(ss)
|
| 360 |
lesson_idx = state.get("lesson_idx", 0)
|
| 361 |
+
|
| 362 |
if state["phase"] != "quiz":
|
| 363 |
+
yield (
|
| 364 |
gr.update(visible=True), gr.update(visible=False),
|
| 365 |
gr.update(visible=False), gr.update(visible=False),
|
| 366 |
+
"",
|
| 367 |
+
gr.update(value="📤 Soumettre", interactive=True),
|
| 368 |
+
gr.update(interactive=True),
|
| 369 |
+
ss,
|
| 370 |
)
|
| 371 |
+
return
|
| 372 |
+
|
| 373 |
+
# ── Étape 1 : désactiver immédiatement bouton + textbox ──────────────────
|
| 374 |
+
yield (
|
| 375 |
+
gr.update(visible=False), gr.update(visible=True),
|
| 376 |
+
gr.update(visible=False), gr.update(visible=False),
|
| 377 |
+
"",
|
| 378 |
+
gr.update(value="⏳ Réponse soumise — Correction en cours…", interactive=False),
|
| 379 |
+
gr.update(interactive=False),
|
| 380 |
+
ss,
|
| 381 |
+
)
|
| 382 |
+
|
| 383 |
+
# ── Étape 2 : évaluation IA (peut prendre quelques secondes) ─────────────
|
| 384 |
q = LESSONS[lesson_idx]["questions"][state["question_idx"]]
|
| 385 |
score, fb = evaluate_answer(q["q"], answer, q["hint"])
|
| 386 |
total = len(LESSONS)
|
|
|
|
| 392 |
f"## 🎉 Bravo ! Leçon {lesson_idx + 1}/{total} réussie.\n\n"
|
| 393 |
f"**Score : {score}/10**\n\n**Commentaire :** {fb}"
|
| 394 |
)
|
| 395 |
+
next_label = "🏆 Voir mon certificat" if is_last else f"➡️ {LESSONS[lesson_idx + 1]['title']}"
|
|
|
|
|
|
|
|
|
|
| 396 |
else:
|
| 397 |
state["phase"] = "fail"
|
| 398 |
result = (
|
|
|
|
| 403 |
)
|
| 404 |
next_label = "🔄 Réécouter la leçon"
|
| 405 |
|
| 406 |
+
# ── Étape 3 : afficher résultat, réactiver bouton, mettre à jour next_btn ─
|
| 407 |
+
yield (
|
| 408 |
gr.update(visible=False), gr.update(visible=False),
|
| 409 |
gr.update(visible=True), gr.update(visible=False),
|
| 410 |
+
result,
|
| 411 |
+
gr.update(value="📤 Soumettre", interactive=True),
|
| 412 |
+
gr.update(value="", interactive=True),
|
| 413 |
+
D(state),
|
| 414 |
)
|
| 415 |
|
| 416 |
def handle_next(ss):
|
|
|
|
| 468 |
audio_out = gr.Audio(label="Cours audio (français)", autoplay=False, interactive=False)
|
| 469 |
timer_info = gr.Markdown("")
|
| 470 |
with gr.Row():
|
| 471 |
+
start_btn = gr.Button("▶️ Démarrer l'écoute" + str(_LLAMA_OK), variant="primary")
|
| 472 |
check_btn = gr.Button("🔄 Vérifier le temps", variant="secondary")
|
| 473 |
quiz_btn = gr.Button("✅ Accéder au Quiz", variant="secondary", interactive=False)
|
| 474 |
|
|
|
|
| 499 |
timer_info, question_md, answer_box, session]
|
| 500 |
quiz_btn.click(open_quiz, [session], QUIZ_OUT)
|
| 501 |
|
| 502 |
+
# ── submit_answer est un générateur → outputs inclut submit_btn et answer_box
|
| 503 |
RES_OUT = [listen_col, quiz_col, result_col, cert_col,
|
| 504 |
+
result_md, submit_btn, answer_box, session]
|
| 505 |
submit_btn.click(submit_answer, [answer_box, session], RES_OUT)
|
| 506 |
answer_box.submit(submit_answer, [answer_box, session], RES_OUT)
|
| 507 |
|
|
|
|
| 512 |
threading.Thread(target=get_llm, daemon=True).start()
|
| 513 |
|
| 514 |
if __name__ == "__main__":
|
| 515 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)
|
|
|