ArrowCrisis's picture
Update app.py
9b725e3 verified
from flask import Flask, request, jsonify
from flask_cors import CORS
import requests
import os
import json
app = Flask(__name__)
CORS(app)
# Récupération de la clé API
# Assurez-vous de définir cette variable dans les "Settings" -> "Variables and secrets" de votre Space Hugging Face
API_KEY = os.environ.get("Cle5")
# URL API Albert
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():
# 1. Vérification Clé API
if not API_KEY:
return jsonify({"error": "Clé API manquante. Vérifiez vos Secrets Hugging Face."}), 500
# 2. Récupération des données
data = request.json
user_text = data.get('userText', '')
reference_text = data.get('referenceText', '')
# Validation des entrées
if not user_text or not reference_text:
return jsonify({"error": "Données incomplètes (texte élève ou référence manquant)."}), 400
# 3. Construction du Prompt Système (Spécialisé Prof de Français)
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}\""
# 4. Envoi à l'API Albert
payload = {
"model": "openai/gpt-oss-120b", # Modèle performant disponible sur Albert
"temperature": 0.1, # Température faible pour une correction cohérente
"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()
# Extraction du contenu
content = albert_data['choices'][0]['message']['content']
# 5. Nettoyage et Parsing JSON
try:
# On cherche le premier '{' et le dernier '}' pour extraire le JSON valide
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]
# Nettoyage préventif des sauts de ligne dans les chaînes JSON qui pourraient casser le parseur
json_str = json_str.replace('\n', '\\n').replace('\r', '').replace('\t', ' ')
return jsonify(json.loads(json_str))
# Si pas de JSON trouvé, on renvoie le texte brut comme feedback
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)