transmis au prof
This commit is contained in:
@@ -37,6 +37,9 @@ Ce projet est un POC de professeur virtuel pour enfants, avec:
|
||||
- Les options TTS visibles doivent etre libellees `Voix Douce`, `Voix Rigolote`, etc.; la mention "Voix IA non humaine..." est portee par un tooltip.
|
||||
- Le declenchement manuel de mini-test/exercice doit disparaitre de l'interface eleve; le programme doit etre determine par Professeur TOP.
|
||||
- A prevoir cote admin: tableau par eleve et prompts/instructions personnalises pour guider Professeur TOP par eleve.
|
||||
- L'ecran eleve affiche une petite card "Transmis au prof" au-dessus de la zone de saisie pour montrer le texte capte/envoye.
|
||||
- Le backend ajoute une consigne de tours de parole courts pour que Professeur TOP laisse le temps a l'enfant de repondre.
|
||||
- Gestion interruption a prevoir: detection de parole pendant TTS, pause audio, transcription, classification pertinent/accidentel, puis reprise courte.
|
||||
- Le vrai `docker-compose.yml` de production n'est pas dans ce repo. Il est situe un niveau au-dessus sur le serveur.
|
||||
- La conf nginx reelle route:
|
||||
- `/api/` vers `tutor-backend:8000`
|
||||
|
||||
@@ -20,6 +20,15 @@ Règles :
|
||||
- Tu enseignes principalement le programme national français niveau primaire/cycle 3.
|
||||
""".strip()
|
||||
|
||||
TURN_TAKING_PROMPT = """
|
||||
Consignes de rythme oral:
|
||||
- Fais des tours de parole courts: 1 a 3 phrases maximum, sauf demande explicite.
|
||||
- Termine souvent par une question ou une consigne courte pour laisser l'enfant parler.
|
||||
- Ne fais pas de longs monologues: une idee a la fois.
|
||||
- Si l'eleve t'interrompt, arrete-toi, ecoute son message, puis reprends seulement si c'est utile.
|
||||
- Si l'interruption semble accidentelle ou hors sujet, reponds tres brievement puis continue.
|
||||
""".strip()
|
||||
|
||||
TTS_PROFILES = [
|
||||
{
|
||||
"id": "rigolote",
|
||||
@@ -130,6 +139,7 @@ def build_llm_reply(db: Session, student_id: int, user_message: str) -> str:
|
||||
model="gpt-4.1-mini",
|
||||
input=[
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "system", "content": TURN_TAKING_PROMPT},
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"Contexte pédagogique:\n{context}\n\nMessage de l'élève:\n{user_message}",
|
||||
|
||||
@@ -190,6 +190,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
})
|
||||
const [messages, setMessages] = useState([])
|
||||
const [currentInstruction, setCurrentInstruction] = useState('')
|
||||
const [lastStudentTransmission, setLastStudentTransmission] = useState('')
|
||||
const [sessionActive, setSessionActive] = useState(false)
|
||||
const [currentFocusSkill, setCurrentFocusSkill] = useState(null)
|
||||
const [exerciseStatus, setExerciseStatus] = useState('not-started')
|
||||
@@ -288,6 +289,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
setSessionActive(false)
|
||||
setAssessment(null)
|
||||
setAssessmentAnswer('')
|
||||
setLastStudentTransmission('')
|
||||
setCurrentFocusSkill(null)
|
||||
setExerciseStatus('not-started')
|
||||
if (selectedStudentId) {
|
||||
@@ -459,6 +461,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
}),
|
||||
})
|
||||
appendMessage('user', `Reponse au mini-test: ${assessmentAnswer}`)
|
||||
setLastStudentTransmission(assessmentAnswer)
|
||||
appendMessage('assistant', data.feedback)
|
||||
setCurrentInstruction(data.feedback)
|
||||
setExerciseStatus(data.correct ? 'resolved' : 'needs-review')
|
||||
@@ -492,6 +495,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
setAssessment(null)
|
||||
setAssessmentAnswer('')
|
||||
setInput('')
|
||||
setLastStudentTransmission('')
|
||||
}
|
||||
|
||||
async function toggleSession() {
|
||||
@@ -617,6 +621,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
throw new Error('Choisis un élève avant d’envoyer un message.')
|
||||
}
|
||||
appendMessage('user', text)
|
||||
setLastStudentTransmission(text)
|
||||
setInput('')
|
||||
setErrorMessage('')
|
||||
const data = await apiFetch('/chat', {
|
||||
@@ -652,6 +657,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
return
|
||||
}
|
||||
|
||||
setLastStudentTransmission(transcript)
|
||||
if (autoSend && selectedStudentId) {
|
||||
setVoiceStatus('Texte reconnu, envoi automatique...')
|
||||
pushAudioDebug('Envoi automatique du message transcrit')
|
||||
@@ -1008,6 +1014,11 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
</form>
|
||||
)}
|
||||
|
||||
<section className="student-transmission">
|
||||
<span>Transmis au prof</span>
|
||||
<p>{lastStudentTransmission || 'Le texte reconnu par le micro ou envoye au clavier apparaitra ici.'}</p>
|
||||
</section>
|
||||
|
||||
<form onSubmit={assessment ? submitAssessment : sendMessage} className="composer">
|
||||
<input
|
||||
value={assessment ? assessmentAnswer : input}
|
||||
|
||||
@@ -136,6 +136,28 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.messages { display: none; }
|
||||
.student-transmission {
|
||||
flex: 0 0 auto;
|
||||
border: 1px solid #dbeafe;
|
||||
border-radius: 14px;
|
||||
background: #f8fbff;
|
||||
padding: 0.7rem 0.85rem;
|
||||
}
|
||||
.student-transmission span {
|
||||
display: block;
|
||||
color: #2563eb;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.25rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.student-transmission p {
|
||||
margin: 0;
|
||||
color: #14213d;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.message {
|
||||
max-width: 92%;
|
||||
margin-bottom: 0.45rem;
|
||||
|
||||
Reference in New Issue
Block a user