refactor: simplify AI payload construction and update system prompt for professional ECF synthesis
This commit is contained in:
parent
227a03f6f8
commit
bbe7f2ccee
File diff suppressed because one or more lines are too long
2
dist/index.html
vendored
2
dist/index.html
vendored
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Bilans de compétences</title>
|
||||
<script type="module" crossorigin src="/assets/index-CCT8mUTJ.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CPsAkw2K.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-hUIr4MzD.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -546,44 +546,22 @@ const Bilan = () => {
|
||||
);
|
||||
|
||||
const buildPayloadForAI = useCallback(() => {
|
||||
const selected = items.filter((item) => item.checked);
|
||||
const byBucket = (array, bucket) =>
|
||||
array.filter((item) => item.bucket === bucket).map((item) => item.label);
|
||||
|
||||
const acquis = selected.filter((item) => item.level === "ac");
|
||||
const maitrise = selected.filter((item) => item.level === "ma");
|
||||
const inProgress = selected.filter((item) => item.level === "ec");
|
||||
const notAcquired = selected.filter((item) => item.level === "na");
|
||||
const validated = items.filter(
|
||||
(item) => item.checked && (item.level === "ac" || item.level === "ma")
|
||||
);
|
||||
const byBucket = (bucket) =>
|
||||
validated.filter((item) => item.bucket === bucket).map((item) => item.label);
|
||||
|
||||
return {
|
||||
prenom: firstName.trim(),
|
||||
nom: lastName.trim(),
|
||||
tone: aiTone,
|
||||
counts: {
|
||||
total: items.length,
|
||||
selected: selected.length,
|
||||
acquis: acquis.length,
|
||||
maitrise: maitrise.length,
|
||||
inProgress: inProgress.length,
|
||||
notAcquired: notAcquired.length,
|
||||
},
|
||||
performance: {
|
||||
acquis: byBucket(acquis, "Performance"),
|
||||
maitrise: byBucket(maitrise, "Performance"),
|
||||
improve: byBucket([...notAcquired, ...inProgress], "Performance"),
|
||||
},
|
||||
competence: {
|
||||
acquis: byBucket(acquis, "Competence"),
|
||||
maitrise: byBucket(maitrise, "Competence"),
|
||||
improve: byBucket([...notAcquired, ...inProgress], "Competence"),
|
||||
},
|
||||
connaissance: {
|
||||
acquis: byBucket(acquis, "Connaissance"),
|
||||
maitrise: byBucket(maitrise, "Connaissance"),
|
||||
improve: byBucket([...notAcquired, ...inProgress], "Connaissance"),
|
||||
},
|
||||
cp: currentCp,
|
||||
cpTitle: titles[currentCp]?.h2 || "",
|
||||
apprenant: `${firstName.trim()} ${lastName.trim()}`.trim(),
|
||||
validatedCount: validated.length,
|
||||
performance: byBucket("Performance"),
|
||||
competence: byBucket("Competence"),
|
||||
connaissance: byBucket("Connaissance"),
|
||||
};
|
||||
}, [aiTone, firstName, items, lastName]);
|
||||
}, [currentCp, firstName, items, lastName]);
|
||||
|
||||
const generateAISummaryMistral = useCallback(async () => {
|
||||
if (!MISTRAL_API_KEY) {
|
||||
@ -592,16 +570,31 @@ const Bilan = () => {
|
||||
}
|
||||
|
||||
const payload = buildPayloadForAI();
|
||||
if (!payload.counts.selected) {
|
||||
showStatus("Sélectionne quelques critères avant d'utiliser l'IA.", "error");
|
||||
if (!payload.validatedCount) {
|
||||
showStatus("Aucune compétence validée (Acquis/Maîtrisé) à synthétiser.", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const observationTexte = observation.trim();
|
||||
const notesFormateur = aiNotes.trim();
|
||||
|
||||
setIsAiLoading(true);
|
||||
showStatus("Génération du résumé via Mistral…", "info", true);
|
||||
showStatus("Génération de la synthèse ECF via Mistral…", "info", true);
|
||||
|
||||
const formatBucket = (label, items) =>
|
||||
items.length ? `${label} :\n${items.map((c) => `- ${c}`).join("\n")}` : "";
|
||||
|
||||
const userMessage = [
|
||||
`CP évalué : ${payload.cp} — ${payload.cpTitle}`,
|
||||
payload.apprenant ? `Apprenant : ${payload.apprenant}` : "",
|
||||
"",
|
||||
"Compétences validées (Acquis / Maîtrisé) :",
|
||||
formatBucket("Performance", payload.performance),
|
||||
formatBucket("Compétence", payload.competence),
|
||||
formatBucket("Connaissance", payload.connaissance),
|
||||
notesFormateur ? `\nNotes du formateur : ${notesFormateur}` : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
|
||||
const callMistral = async (model) => {
|
||||
const response = await fetch("https://api.mistral.ai/v1/chat/completions", {
|
||||
@ -612,23 +605,21 @@ const Bilan = () => {
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model,
|
||||
temperature: 0.6,
|
||||
temperature: 0.4,
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: `Tu es ingénieur pédagogique spécialisé dans la formation CDUI (Titre Professionnel Concepteur Développeur d'Interfaces Utilisateur, niveau 6). Tu maîtrises parfaitement les référentiels de compétences du titre, les CP1 à CP9, et les exigences de France Compétences.
|
||||
À partir des données de l'évaluation (critères et niveaux d'acquisition), du bilan automatique et des notes du formateur, rédige une synthèse pédagogique finale de 8 à 10 phrases.
|
||||
Contraintes : valoriser les réussites de l'apprenant, évoquer les axes de progression avec bienveillance, reformuler et enrichir les notes du formateur, varier le vocabulaire et les connecteurs, adopter un ton professionnel et encourageant, en lien avec les attendus du titre CDUI.`,
|
||||
content: `Tu es ingénieur pédagogique expert du Titre Professionnel CDUI (Concepteur Développeur d'Interfaces Utilisateur, niveau 6). Tu rédiges des synthèses pour les bilans ECF (Évaluation en Cours de Formation), documents officiels du Ministère du Travail.
|
||||
|
||||
À partir des compétences validées (Acquis et Maîtrisé) organisées par Performance, Compétence et Connaissance, rédige une synthèse ECF en 4 à 5 lignes maximum.
|
||||
- Réponds aux attendus officiels du CP évalué.
|
||||
- Formule un jugement pédagogique global : ne liste pas les critères un à un.
|
||||
- Sois synthétique et précis, sans fioritures ni répétitions.
|
||||
- Adopte un registre professionnel et factuel, adapté à un document officiel.`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `Données JSON : ${JSON.stringify(payload)}
|
||||
|
||||
Observation affichée :
|
||||
${observationTexte}
|
||||
|
||||
Notes formateur :
|
||||
${notesFormateur}`,
|
||||
content: userMessage,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@ -687,7 +678,6 @@ ${notesFormateur}`,
|
||||
dismissProgressToasts,
|
||||
insertAISummaryIntoObservation,
|
||||
mistralModel,
|
||||
observation,
|
||||
showStatus,
|
||||
]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user