feat: POST /corrections/ee — DeepSeek rapport complet — 73/73 tests

This commit is contained in:
Hermann_Kitio 2026-04-16 17:14:45 +03:00
parent a6ee76d4a8
commit 77d5a8373e
6 changed files with 385 additions and 23 deletions

91
src/lib/deepseek.ts Normal file
View file

@ -0,0 +1,91 @@
const DEEPSEEK_API_KEY = process.env.DEEPSEEK_API_KEY ?? ''
const DEEPSEEK_BASE_URL = 'https://api.deepseek.com'
export interface EECritere {
nom: string
score: number
commentaire: string
}
export interface EERapport {
score: number
nclc: number
criteres: EECritere[]
erreurs: string[]
production_modele: string
suggestions_idees: string[]
exercices: string[]
}
const SYSTEM_PROMPT = `Tu es un examinateur officiel du TCF Canada (Test de connaissance du français).
Tu évalues une production écrite selon les 4 critères officiels de l'Expression Écrite :
1. Cohérence et cohésion
2. Lexique (étendue et maîtrise du vocabulaire)
3. Morphosyntaxe (grammaire et structures)
4. Pertinence (adéquation à la consigne)
Tu dois retourner un JSON strict avec cette structure exacte :
{
"score": <number 0-20>,
"nclc": <number 4-12>,
"criteres": [
{ "nom": "Cohérence et cohésion", "score": <number 0-5>, "commentaire": "<string>" },
{ "nom": "Lexique", "score": <number 0-5>, "commentaire": "<string>" },
{ "nom": "Morphosyntaxe", "score": <number 0-5>, "commentaire": "<string>" },
{ "nom": "Pertinence", "score": <number 0-5>, "commentaire": "<string>" }
],
"erreurs": ["<erreur 1>", "<erreur 2>", ...],
"production_modele": "<texte modèle corrigé>",
"suggestions_idees": ["<idée 1>", "<idée 2>", ...],
"exercices": ["<exercice recommandé 1>", "<exercice recommandé 2>", ...]
}
Règles :
- score est la note globale sur 20
- nclc est le niveau NCLC estimé (entre 4 et 12)
- Chaque critère a un score de 0 à 5
- Retourne UNIQUEMENT le JSON, sans texte avant ni après`
export async function correctEE(contenu: string, tache: string): Promise<EERapport> {
const response = await fetch(`${DEEPSEEK_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${DEEPSEEK_API_KEY}`,
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [
{ role: 'system', content: SYSTEM_PROMPT },
{
role: 'user',
content: `Tâche : ${tache}\n\nProduction de l'étudiant :\n${contenu}`,
},
],
temperature: 0.3,
response_format: { type: 'json_object' },
}),
})
if (!response.ok) {
throw new Error(`DeepSeek API error: ${response.status} ${response.statusText}`)
}
const data = await response.json()
const content = data.choices?.[0]?.message?.content
if (!content) {
throw new Error('DeepSeek API: réponse vide')
}
const rapport: EERapport = JSON.parse(content)
if (rapport.score < 0 || rapport.score > 20) {
throw new Error(`Score invalide: ${rapport.score} (attendu 0-20)`)
}
if (rapport.nclc < 4 || rapport.nclc > 12) {
throw new Error(`NCLC invalide: ${rapport.nclc} (attendu 4-12)`)
}
return rapport
}