feat(corrections): aligner schéma rapport DeepSeek — renommages + feedback_court
This commit is contained in:
parent
c65a2a0157
commit
f67bd2dc95
2 changed files with 50 additions and 17 deletions
|
|
@ -3,6 +3,8 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
const VALID_RAPPORT = {
|
const VALID_RAPPORT = {
|
||||||
score: 14.5,
|
score: 14.5,
|
||||||
nclc: 8,
|
nclc: 8,
|
||||||
|
feedback_court:
|
||||||
|
'Bonne production générale. Quelques points à améliorer sur le lexique et la morphosyntaxe.',
|
||||||
criteres: [
|
criteres: [
|
||||||
{ nom: 'Coherence et cohesion', score: 4, commentaire: 'Bonne organisation.' },
|
{ nom: 'Coherence et cohesion', score: 4, commentaire: 'Bonne organisation.' },
|
||||||
{ nom: 'Lexique', score: 3, commentaire: 'Vocabulaire correct mais limite.' },
|
{ nom: 'Lexique', score: 3, commentaire: 'Vocabulaire correct mais limite.' },
|
||||||
|
|
@ -10,8 +12,8 @@ const VALID_RAPPORT = {
|
||||||
{ nom: 'Pertinence', score: 3.5, commentaire: 'Adequation partielle a la consigne.' },
|
{ nom: 'Pertinence', score: 3.5, commentaire: 'Adequation partielle a la consigne.' },
|
||||||
],
|
],
|
||||||
erreurs: ['Connecteurs logiques insuffisants', 'Quelques fautes accord'],
|
erreurs: ['Connecteurs logiques insuffisants', 'Quelques fautes accord'],
|
||||||
production_modele: 'Texte modele corrige ici.',
|
modele: 'Texte modele corrige ici.',
|
||||||
suggestions_idees: ['Developper argumentation', 'Ajouter des exemples concrets'],
|
idees: ['Developper argumentation', 'Ajouter des exemples concrets'],
|
||||||
exercices: ['Exercice connecteurs logiques', 'Exercice accords sujet-verbe'],
|
exercices: ['Exercice connecteurs logiques', 'Exercice accords sujet-verbe'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,14 +43,17 @@ describe('deepseek.correctEE', () => {
|
||||||
|
|
||||||
expect(rapport).toHaveProperty('score')
|
expect(rapport).toHaveProperty('score')
|
||||||
expect(rapport).toHaveProperty('nclc')
|
expect(rapport).toHaveProperty('nclc')
|
||||||
|
expect(rapport).toHaveProperty('feedback_court')
|
||||||
expect(rapport).toHaveProperty('criteres')
|
expect(rapport).toHaveProperty('criteres')
|
||||||
expect(rapport).toHaveProperty('erreurs')
|
expect(rapport).toHaveProperty('erreurs')
|
||||||
expect(rapport).toHaveProperty('production_modele')
|
expect(rapport).toHaveProperty('modele')
|
||||||
expect(rapport).toHaveProperty('suggestions_idees')
|
expect(rapport).toHaveProperty('idees')
|
||||||
expect(rapport).toHaveProperty('exercices')
|
expect(rapport).toHaveProperty('exercices')
|
||||||
expect(rapport.criteres).toHaveLength(4)
|
expect(rapport.criteres).toHaveLength(4)
|
||||||
|
expect(typeof rapport.feedback_court).toBe('string')
|
||||||
|
expect(rapport.feedback_court.length).toBeGreaterThan(0)
|
||||||
expect(Array.isArray(rapport.erreurs)).toBe(true)
|
expect(Array.isArray(rapport.erreurs)).toBe(true)
|
||||||
expect(Array.isArray(rapport.suggestions_idees)).toBe(true)
|
expect(Array.isArray(rapport.idees)).toBe(true)
|
||||||
expect(Array.isArray(rapport.exercices)).toBe(true)
|
expect(Array.isArray(rapport.exercices)).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -86,6 +91,17 @@ describe('deepseek.correctEE', () => {
|
||||||
await expect(correctEE('Texte', 'EE_T1')).rejects.toThrow('NCLC invalide')
|
await expect(correctEE('Texte', 'EE_T1')).rejects.toThrow('NCLC invalide')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('lance une erreur si feedback_court est absent ou vide', async () => {
|
||||||
|
// Cas 1 : champ absent (JSON.stringify drop les undefined)
|
||||||
|
mockFetchSuccess({ ...VALID_RAPPORT, feedback_court: undefined })
|
||||||
|
const { correctEE } = await import('../deepseek')
|
||||||
|
await expect(correctEE('Texte', 'EE_T1')).rejects.toThrow('feedback_court invalide')
|
||||||
|
|
||||||
|
// Cas 2 : chaîne vide (whitespace uniquement)
|
||||||
|
mockFetchSuccess({ ...VALID_RAPPORT, feedback_court: ' ' })
|
||||||
|
await expect(correctEE('Texte', 'EE_T1')).rejects.toThrow('feedback_court invalide')
|
||||||
|
})
|
||||||
|
|
||||||
it('erreur HTTP depuis DeepSeek API', async () => {
|
it('erreur HTTP depuis DeepSeek API', async () => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
'fetch',
|
'fetch',
|
||||||
|
|
@ -132,6 +148,8 @@ describe('deepseek.correctEE', () => {
|
||||||
const VALID_RAPPORT_EO = {
|
const VALID_RAPPORT_EO = {
|
||||||
score: 12,
|
score: 12,
|
||||||
nclc: 7,
|
nclc: 7,
|
||||||
|
feedback_court:
|
||||||
|
'Bonne production générale. Quelques points à améliorer sur le lexique et la morphosyntaxe.',
|
||||||
criteres: [
|
criteres: [
|
||||||
{ nom: 'Coherence et cohesion', score: 4, commentaire: 'Discours structure.' },
|
{ nom: 'Coherence et cohesion', score: 4, commentaire: 'Discours structure.' },
|
||||||
{ nom: 'Lexique', score: 4, commentaire: 'Vocabulaire varie.' },
|
{ nom: 'Lexique', score: 4, commentaire: 'Vocabulaire varie.' },
|
||||||
|
|
@ -139,8 +157,8 @@ const VALID_RAPPORT_EO = {
|
||||||
{ nom: 'Phonologie', score: 0, commentaire: 'Non evalue sur transcription textuelle.' },
|
{ nom: 'Phonologie', score: 0, commentaire: 'Non evalue sur transcription textuelle.' },
|
||||||
],
|
],
|
||||||
erreurs: ['Hesitations frequentes', 'Registre parfois familier'],
|
erreurs: ['Hesitations frequentes', 'Registre parfois familier'],
|
||||||
production_modele: 'Transcription corrigee ici.',
|
modele: 'Transcription corrigee ici.',
|
||||||
suggestions_idees: ['Structurer les reponses', 'Enrichir le vocabulaire'],
|
idees: ['Structurer les reponses', 'Enrichir le vocabulaire'],
|
||||||
exercices: ['Exercice fluidite orale', 'Exercice registre formel'],
|
exercices: ['Exercice fluidite orale', 'Exercice registre formel'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,12 +176,15 @@ describe('deepseek.correctEO', () => {
|
||||||
|
|
||||||
expect(rapport).toHaveProperty('score')
|
expect(rapport).toHaveProperty('score')
|
||||||
expect(rapport).toHaveProperty('nclc')
|
expect(rapport).toHaveProperty('nclc')
|
||||||
|
expect(rapport).toHaveProperty('feedback_court')
|
||||||
expect(rapport).toHaveProperty('criteres')
|
expect(rapport).toHaveProperty('criteres')
|
||||||
expect(rapport.criteres).toHaveLength(4)
|
expect(rapport.criteres).toHaveLength(4)
|
||||||
expect(rapport).toHaveProperty('erreurs')
|
expect(rapport).toHaveProperty('erreurs')
|
||||||
expect(rapport).toHaveProperty('production_modele')
|
expect(rapport).toHaveProperty('modele')
|
||||||
expect(rapport).toHaveProperty('suggestions_idees')
|
expect(rapport).toHaveProperty('idees')
|
||||||
expect(rapport).toHaveProperty('exercices')
|
expect(rapport).toHaveProperty('exercices')
|
||||||
|
expect(typeof rapport.feedback_court).toBe('string')
|
||||||
|
expect(rapport.feedback_court.length).toBeGreaterThan(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('phonologie est a 0', async () => {
|
it('phonologie est a 0', async () => {
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,11 @@ export interface EECritere {
|
||||||
export interface EERapport {
|
export interface EERapport {
|
||||||
score: number
|
score: number
|
||||||
nclc: number
|
nclc: number
|
||||||
|
feedback_court: string
|
||||||
criteres: EECritere[]
|
criteres: EECritere[]
|
||||||
erreurs: string[]
|
erreurs: string[]
|
||||||
production_modele: string
|
modele: string
|
||||||
suggestions_idees: string[]
|
idees: string[]
|
||||||
exercices: string[]
|
exercices: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,10 +27,11 @@ export interface EOCritere {
|
||||||
export interface EORapport {
|
export interface EORapport {
|
||||||
score: number
|
score: number
|
||||||
nclc: number
|
nclc: number
|
||||||
|
feedback_court: string
|
||||||
criteres: EOCritere[]
|
criteres: EOCritere[]
|
||||||
erreurs: string[]
|
erreurs: string[]
|
||||||
production_modele: string
|
modele: string
|
||||||
suggestions_idees: string[]
|
idees: string[]
|
||||||
exercices: string[]
|
exercices: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,6 +46,7 @@ Tu dois retourner un JSON strict avec cette structure exacte :
|
||||||
{
|
{
|
||||||
"score": <number 0-20>,
|
"score": <number 0-20>,
|
||||||
"nclc": <number 4-12>,
|
"nclc": <number 4-12>,
|
||||||
|
"feedback_court": "<2 à 3 lignes de feedback global, orientées action>",
|
||||||
"criteres": [
|
"criteres": [
|
||||||
{ "nom": "Cohérence et cohésion", "score": <number 0-5>, "commentaire": "<string>" },
|
{ "nom": "Cohérence et cohésion", "score": <number 0-5>, "commentaire": "<string>" },
|
||||||
{ "nom": "Lexique", "score": <number 0-5>, "commentaire": "<string>" },
|
{ "nom": "Lexique", "score": <number 0-5>, "commentaire": "<string>" },
|
||||||
|
|
@ -51,14 +54,15 @@ Tu dois retourner un JSON strict avec cette structure exacte :
|
||||||
{ "nom": "Pertinence", "score": <number 0-5>, "commentaire": "<string>" }
|
{ "nom": "Pertinence", "score": <number 0-5>, "commentaire": "<string>" }
|
||||||
],
|
],
|
||||||
"erreurs": ["<erreur 1>", "<erreur 2>", ...],
|
"erreurs": ["<erreur 1>", "<erreur 2>", ...],
|
||||||
"production_modele": "<texte modèle corrigé>",
|
"modele": "<texte modèle corrigé>",
|
||||||
"suggestions_idees": ["<idée 1>", "<idée 2>", ...],
|
"idees": ["<idée 1>", "<idée 2>", ...],
|
||||||
"exercices": ["<exercice recommandé 1>", "<exercice recommandé 2>", ...]
|
"exercices": ["<exercice recommandé 1>", "<exercice recommandé 2>", ...]
|
||||||
}
|
}
|
||||||
|
|
||||||
Règles :
|
Règles :
|
||||||
- score est la note globale sur 20
|
- score est la note globale sur 20
|
||||||
- nclc est le niveau NCLC estimé (entre 4 et 12)
|
- nclc est le niveau NCLC estimé (entre 4 et 12)
|
||||||
|
- feedback_court est un résumé de 2 à 3 lignes, toujours renseigné (visible pour tous les plans)
|
||||||
- Chaque critère a un score de 0 à 5
|
- Chaque critère a un score de 0 à 5
|
||||||
- Retourne UNIQUEMENT le JSON, sans texte avant ni après`
|
- Retourne UNIQUEMENT le JSON, sans texte avant ni après`
|
||||||
|
|
||||||
|
|
@ -104,6 +108,9 @@ export async function correctEE(contenu: string, tache: string): Promise<EERappo
|
||||||
if (rapport.nclc < 4 || rapport.nclc > 12) {
|
if (rapport.nclc < 4 || rapport.nclc > 12) {
|
||||||
throw new Error(`NCLC invalide: ${rapport.nclc} (attendu 4-12)`)
|
throw new Error(`NCLC invalide: ${rapport.nclc} (attendu 4-12)`)
|
||||||
}
|
}
|
||||||
|
if (typeof rapport.feedback_court !== 'string' || rapport.feedback_court.trim().length === 0) {
|
||||||
|
throw new Error('feedback_court invalide: attendu une chaîne non vide')
|
||||||
|
}
|
||||||
|
|
||||||
return rapport
|
return rapport
|
||||||
}
|
}
|
||||||
|
|
@ -119,6 +126,7 @@ Tu dois retourner un JSON strict avec cette structure exacte :
|
||||||
{
|
{
|
||||||
"score": <number 0-20>,
|
"score": <number 0-20>,
|
||||||
"nclc": <number 4-12>,
|
"nclc": <number 4-12>,
|
||||||
|
"feedback_court": "<2 à 3 lignes de feedback global, orientées action>",
|
||||||
"criteres": [
|
"criteres": [
|
||||||
{ "nom": "Cohérence et cohésion", "score": <number 0-5>, "commentaire": "<string>" },
|
{ "nom": "Cohérence et cohésion", "score": <number 0-5>, "commentaire": "<string>" },
|
||||||
{ "nom": "Lexique", "score": <number 0-5>, "commentaire": "<string>" },
|
{ "nom": "Lexique", "score": <number 0-5>, "commentaire": "<string>" },
|
||||||
|
|
@ -126,14 +134,15 @@ Tu dois retourner un JSON strict avec cette structure exacte :
|
||||||
{ "nom": "Phonologie", "score": 0, "commentaire": "Non évalué sur transcription textuelle." }
|
{ "nom": "Phonologie", "score": 0, "commentaire": "Non évalué sur transcription textuelle." }
|
||||||
],
|
],
|
||||||
"erreurs": ["<erreur 1>", "<erreur 2>", ...],
|
"erreurs": ["<erreur 1>", "<erreur 2>", ...],
|
||||||
"production_modele": "<version corrigée de la transcription>",
|
"modele": "<version corrigée de la transcription>",
|
||||||
"suggestions_idees": ["<idée 1>", "<idée 2>", ...],
|
"idees": ["<idée 1>", "<idée 2>", ...],
|
||||||
"exercices": ["<exercice recommandé 1>", "<exercice recommandé 2>", ...]
|
"exercices": ["<exercice recommandé 1>", "<exercice recommandé 2>", ...]
|
||||||
}
|
}
|
||||||
|
|
||||||
Règles :
|
Règles :
|
||||||
- score est la note globale sur 20 (basée uniquement sur les 3 critères évalués)
|
- score est la note globale sur 20 (basée uniquement sur les 3 critères évalués)
|
||||||
- nclc est le niveau NCLC estimé (entre 4 et 12)
|
- nclc est le niveau NCLC estimé (entre 4 et 12)
|
||||||
|
- feedback_court est un résumé de 2 à 3 lignes, toujours renseigné (visible pour tous les plans)
|
||||||
- Phonologie est toujours à 0 avec le commentaire "Non évalué sur transcription textuelle."
|
- Phonologie est toujours à 0 avec le commentaire "Non évalué sur transcription textuelle."
|
||||||
- Retourne UNIQUEMENT le JSON, sans texte avant ni après`
|
- Retourne UNIQUEMENT le JSON, sans texte avant ni après`
|
||||||
|
|
||||||
|
|
@ -179,6 +188,9 @@ export async function correctEO(transcript: string, tache: string): Promise<EORa
|
||||||
if (rapport.nclc < 4 || rapport.nclc > 12) {
|
if (rapport.nclc < 4 || rapport.nclc > 12) {
|
||||||
throw new Error(`NCLC invalide: ${rapport.nclc} (attendu 4-12)`)
|
throw new Error(`NCLC invalide: ${rapport.nclc} (attendu 4-12)`)
|
||||||
}
|
}
|
||||||
|
if (typeof rapport.feedback_court !== 'string' || rapport.feedback_court.trim().length === 0) {
|
||||||
|
throw new Error('feedback_court invalide: attendu une chaîne non vide')
|
||||||
|
}
|
||||||
|
|
||||||
return rapport
|
return rapport
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue