| from flask import Flask, request, jsonify |
| from flask_cors import CORS |
| import requests |
| import os |
| import json |
|
|
| app = Flask(__name__) |
| CORS(app) |
|
|
| |
| |
| API_KEY = os.environ.get("Cle5") |
|
|
| |
| ALBERT_URL = "https://albert.api.etalab.gouv.fr/v1/chat/completions" |
|
|
| @app.route('/') |
| def home(): |
| return "Serveur Albert Dictée (Mode Français Unique v1.0) en ligne !" |
|
|
| @app.route('/verify', methods=['POST']) |
| def verify_dictation(): |
| |
| if not API_KEY: |
| return jsonify({"error": "Clé API manquante. Vérifiez vos Secrets Hugging Face."}), 500 |
|
|
| |
| data = request.json |
| user_text = data.get('userText', '') |
| reference_text = data.get('referenceText', '') |
|
|
| |
| if not user_text or not reference_text: |
| return jsonify({"error": "Données incomplètes (texte élève ou référence manquant)."}), 400 |
|
|
| |
| system_prompt = ( |
| "Tu es un professeur de français bienveillant et rigoureux pour une classe de 6ème. " |
| "Ta mission est de corriger une dictée." |
| "\n\nCONSIGNES :" |
| "1. Compare le texte de l'élève au texte de référence." |
| "2. Repère précisément les fautes d'orthographe, de grammaire (accords), de conjugaison et de ponctuation." |
| "3. Attribue une note sur 20. Enlève des points pour chaque faute (ex: -1 par faute majeure, -0.5 par faute mineure ou ponctuation). " |
| "Si le texte est vide ou hors sujet, mets 0." |
| "\n\nFORMAT DU FEEDBACK (Markdown) :" |
| "- Commence par une appréciation générale encourageante." |
| "- Utilise une liste à puces pour détailler les erreurs principales : cite le mot erroné de l'élève -> la correction -> une brève explication de la règle (ex: 'accord sujet-verbe')." |
| "- Ne sois pas trop long, reste accessible pour un élève de 6ème." |
| "\n\nFORMAT DE SORTIE (JSON STRICT) :" |
| "Réponds UNIQUEMENT avec cet objet JSON :" |
| "{ \"isCorrect\": boolean, \"grade\": number, \"feedback\": \"ton_message_markdown\" }" |
| "\nNote : 'isCorrect' doit être true seulement si la note est supérieure ou égale à 15/20." |
| ) |
| |
| user_prompt = f"TEXTE DE RÉFÉRENCE : \"{reference_text}\"\n\nTEXTE DE L'ÉLÈVE : \"{user_text}\"" |
|
|
| |
| payload = { |
| "model": "openai/gpt-oss-120b", |
| "temperature": 0.1, |
| "messages": [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_prompt} |
| ] |
| } |
|
|
| headers = { |
| "Authorization": f"Bearer {API_KEY}", |
| "Content-Type": "application/json" |
| } |
|
|
| try: |
| response = requests.post(ALBERT_URL, json=payload, headers=headers) |
| response.raise_for_status() |
| albert_data = response.json() |
| |
| |
| content = albert_data['choices'][0]['message']['content'] |
| |
| |
| try: |
| |
| start_index = content.find('{') |
| end_index = content.rfind('}') + 1 |
| |
| if start_index != -1 and end_index > start_index: |
| json_str = content[start_index:end_index] |
| |
| json_str = json_str.replace('\n', '\\n').replace('\r', '').replace('\t', ' ') |
| return jsonify(json.loads(json_str)) |
| |
| |
| return jsonify({ |
| "isCorrect": False, |
| "grade": 0, |
| "feedback": content, |
| "raw_error": "JSON_NOT_FOUND" |
| }) |
| |
| except json.JSONDecodeError: |
| return jsonify({ |
| "isCorrect": False, |
| "grade": 0, |
| "feedback": content, |
| "raw_error": "JSON_DECODE_ERROR" |
| }) |
|
|
| except Exception as e: |
| return jsonify({"error": str(e)}), 500 |
|
|
| if __name__ == '__main__': |
| app.run(host='0.0.0.0', port=7860) |