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.
|
- 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.
|
- 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.
|
- 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.
|
- 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:
|
- La conf nginx reelle route:
|
||||||
- `/api/` vers `tutor-backend:8000`
|
- `/api/` vers `tutor-backend:8000`
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ Règles :
|
|||||||
- Tu enseignes principalement le programme national français niveau primaire/cycle 3.
|
- Tu enseignes principalement le programme national français niveau primaire/cycle 3.
|
||||||
""".strip()
|
""".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 = [
|
TTS_PROFILES = [
|
||||||
{
|
{
|
||||||
"id": "rigolote",
|
"id": "rigolote",
|
||||||
@@ -130,6 +139,7 @@ def build_llm_reply(db: Session, student_id: int, user_message: str) -> str:
|
|||||||
model="gpt-4.1-mini",
|
model="gpt-4.1-mini",
|
||||||
input=[
|
input=[
|
||||||
{"role": "system", "content": SYSTEM_PROMPT},
|
{"role": "system", "content": SYSTEM_PROMPT},
|
||||||
|
{"role": "system", "content": TURN_TAKING_PROMPT},
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": f"Contexte pédagogique:\n{context}\n\nMessage de l'élève:\n{user_message}",
|
"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 [messages, setMessages] = useState([])
|
||||||
const [currentInstruction, setCurrentInstruction] = useState('')
|
const [currentInstruction, setCurrentInstruction] = useState('')
|
||||||
|
const [lastStudentTransmission, setLastStudentTransmission] = useState('')
|
||||||
const [sessionActive, setSessionActive] = useState(false)
|
const [sessionActive, setSessionActive] = useState(false)
|
||||||
const [currentFocusSkill, setCurrentFocusSkill] = useState(null)
|
const [currentFocusSkill, setCurrentFocusSkill] = useState(null)
|
||||||
const [exerciseStatus, setExerciseStatus] = useState('not-started')
|
const [exerciseStatus, setExerciseStatus] = useState('not-started')
|
||||||
@@ -288,6 +289,7 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
setSessionActive(false)
|
setSessionActive(false)
|
||||||
setAssessment(null)
|
setAssessment(null)
|
||||||
setAssessmentAnswer('')
|
setAssessmentAnswer('')
|
||||||
|
setLastStudentTransmission('')
|
||||||
setCurrentFocusSkill(null)
|
setCurrentFocusSkill(null)
|
||||||
setExerciseStatus('not-started')
|
setExerciseStatus('not-started')
|
||||||
if (selectedStudentId) {
|
if (selectedStudentId) {
|
||||||
@@ -459,6 +461,7 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
appendMessage('user', `Reponse au mini-test: ${assessmentAnswer}`)
|
appendMessage('user', `Reponse au mini-test: ${assessmentAnswer}`)
|
||||||
|
setLastStudentTransmission(assessmentAnswer)
|
||||||
appendMessage('assistant', data.feedback)
|
appendMessage('assistant', data.feedback)
|
||||||
setCurrentInstruction(data.feedback)
|
setCurrentInstruction(data.feedback)
|
||||||
setExerciseStatus(data.correct ? 'resolved' : 'needs-review')
|
setExerciseStatus(data.correct ? 'resolved' : 'needs-review')
|
||||||
@@ -492,6 +495,7 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
setAssessment(null)
|
setAssessment(null)
|
||||||
setAssessmentAnswer('')
|
setAssessmentAnswer('')
|
||||||
setInput('')
|
setInput('')
|
||||||
|
setLastStudentTransmission('')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleSession() {
|
async function toggleSession() {
|
||||||
@@ -617,6 +621,7 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
throw new Error('Choisis un élève avant d’envoyer un message.')
|
throw new Error('Choisis un élève avant d’envoyer un message.')
|
||||||
}
|
}
|
||||||
appendMessage('user', text)
|
appendMessage('user', text)
|
||||||
|
setLastStudentTransmission(text)
|
||||||
setInput('')
|
setInput('')
|
||||||
setErrorMessage('')
|
setErrorMessage('')
|
||||||
const data = await apiFetch('/chat', {
|
const data = await apiFetch('/chat', {
|
||||||
@@ -652,6 +657,7 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLastStudentTransmission(transcript)
|
||||||
if (autoSend && selectedStudentId) {
|
if (autoSend && selectedStudentId) {
|
||||||
setVoiceStatus('Texte reconnu, envoi automatique...')
|
setVoiceStatus('Texte reconnu, envoi automatique...')
|
||||||
pushAudioDebug('Envoi automatique du message transcrit')
|
pushAudioDebug('Envoi automatique du message transcrit')
|
||||||
@@ -1008,6 +1014,11 @@ function TutorApp({ currentUser, onLogout }) {
|
|||||||
</form>
|
</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">
|
<form onSubmit={assessment ? submitAssessment : sendMessage} className="composer">
|
||||||
<input
|
<input
|
||||||
value={assessment ? assessmentAnswer : input}
|
value={assessment ? assessmentAnswer : input}
|
||||||
|
|||||||
@@ -136,6 +136,28 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
.messages { display: none; }
|
.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 {
|
.message {
|
||||||
max-width: 92%;
|
max-width: 92%;
|
||||||
margin-bottom: 0.45rem;
|
margin-bottom: 0.45rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user