Major improvement: Detect child confusion and provide explanations. Always show input area after AI explanations so kids can ask follow-up questions about concepts like prisms.
This commit is contained in:
@@ -426,22 +426,13 @@ class KidsAIExplorer {
|
||||
|
||||
const isOnlyWhyQuestion = answerLower === 'warum' || answerLower === 'why' || answerLower === 'warum?' || answerLower === 'why?';
|
||||
|
||||
// Check if child is asking for a definition or explanation
|
||||
const isAskingForDefinition = answerLower.startsWith('was ist') || answerLower.startsWith('what is') ||
|
||||
answerLower.includes('was bedeutet') || answerLower.includes('what does') ||
|
||||
answerLower.includes('was heißt') || answerLower.includes('what means') ||
|
||||
(answerLower.includes('?') && (answerLower.includes('ist ein') || answerLower.includes('is a')));
|
||||
|
||||
// Check if child is asking a specific "how/why" question that deserves explanation
|
||||
const isAskingSpecificQuestion = answerLower.includes('woher kommt') || answerLower.includes('where does') ||
|
||||
answerLower.includes('wie entsteht') || answerLower.includes('how does') ||
|
||||
answerLower.includes('warum ist das so') || answerLower.includes('why is that') ||
|
||||
answerLower.includes('ich verstehe nicht') || answerLower.includes("i don't understand") ||
|
||||
(answerLower.includes('?') && (answerLower.includes('woher') || answerLower.includes('wie') || answerLower.includes('warum'))) ||
|
||||
(answer.length > 30 && answerLower.includes('verstehe') && answerLower.includes('nicht'));
|
||||
|
||||
// Combine both definition and specific question detection
|
||||
const needsExplanation = isAskingForDefinition || isAskingSpecificQuestion;
|
||||
// Check if child is expressing confusion and needs explanation
|
||||
const isExpressingConfusion = answerLower.includes('verstehe nicht') || answerLower.includes("don't understand") ||
|
||||
answerLower.includes('versteh das nicht') || answerLower.includes('verstehe es nicht') ||
|
||||
answerLower.includes('ich verstehe nicht warum') || answerLower.includes("i don't understand why") ||
|
||||
answerLower.includes('aber ich verstehe nicht') || answerLower.includes("but i don't understand") ||
|
||||
answerLower.includes('fällt mir nicht ein') || answerLower.includes("can't think of") ||
|
||||
answerLower.includes('mehr fällt mir nicht ein');
|
||||
|
||||
// Check if it's a substantial answer (has thinking beyond just "don't know")
|
||||
const hasSubstantialThinking = answer.length > 15 && (
|
||||
@@ -452,18 +443,13 @@ class KidsAIExplorer {
|
||||
);
|
||||
|
||||
// Pure "don't know" without additional thinking
|
||||
const isPureDontKnow = (hasDontKnowPhrase || isOnlyWhyQuestion || answer.trim().length < 5) && !hasSubstantialThinking && !needsExplanation;
|
||||
const isPureDontKnow = (hasDontKnowPhrase || isOnlyWhyQuestion || answer.trim().length < 5) && !hasSubstantialThinking;
|
||||
|
||||
let response;
|
||||
|
||||
if (needsExplanation) {
|
||||
// Child is asking for explanation - provide simple, concrete explanation
|
||||
console.log('📤 Sending explanation request to /api/respond-to-answer');
|
||||
|
||||
const contextType = isAskingForDefinition ? 'definition_request' : 'specific_question';
|
||||
const instructionText = this.currentLanguage === 'de'
|
||||
? 'Das Kind stellt eine spezifische Frage und möchte verstehen. Gib eine EINFACHE, konkrete Erklärung für Kinder. Beantworte die spezifische Frage direkt aber kindgerecht. Verwende Analogien und alltägliche Vergleiche. Für "woher kommt die farbe" erkläre einfach, dass weißes Licht alle Farben enthält, wie ein unsichtbarer Regenbogen. Keine weiteren Fragen stellen.'
|
||||
: 'The child is asking a specific question and wants to understand. Give a SIMPLE, concrete explanation for children. Answer the specific question directly but age-appropriately. Use analogies and everyday comparisons. For "where does color come from" explain simply that white light contains all colors, like an invisible rainbow. Don\'t ask more questions.';
|
||||
if (isExpressingConfusion) {
|
||||
// Child is expressing confusion - provide a simple explanation
|
||||
console.log('📤 Sending explanation request for confused child');
|
||||
|
||||
response = await fetch('/api/respond-to-answer', {
|
||||
method: 'POST',
|
||||
@@ -475,9 +461,11 @@ class KidsAIExplorer {
|
||||
question: currentQuestion,
|
||||
originalTopic: originalQuestion,
|
||||
language: this.currentLanguage,
|
||||
context: contextType,
|
||||
context: 'confusion_explanation',
|
||||
stepIndex: questionIndex,
|
||||
instructions: instructionText
|
||||
instructions: this.currentLanguage === 'de'
|
||||
? 'Das Kind ist verwirrt und braucht eine einfache Erklärung. Gib eine klare, konkrete Antwort für Kinder. Erkläre das Konzept mit alltäglichen Beispielen. Verwende einfache Wörter und lade zum Ausprobieren ein. Keine weiteren Fragen stellen - erst erklären!'
|
||||
: 'The child is confused and needs a simple explanation. Give a clear, concrete answer for children. Explain the concept with everyday examples. Use simple words and invite experimentation. Don\'t ask more questions - explain first!'
|
||||
})
|
||||
});
|
||||
} else if (isNegative || isPureDontKnow) {
|
||||
@@ -624,22 +612,13 @@ class KidsAIExplorer {
|
||||
|
||||
const isOnlyWhyQuestion = answerLower === 'warum' || answerLower === 'why' || answerLower === 'warum?' || answerLower === 'why?';
|
||||
|
||||
// Check if child is asking for a definition or explanation
|
||||
const isAskingForDefinition = answerLower.startsWith('was ist') || answerLower.startsWith('what is') ||
|
||||
answerLower.includes('was bedeutet') || answerLower.includes('what does') ||
|
||||
answerLower.includes('was heißt') || answerLower.includes('what means') ||
|
||||
(answerLower.includes('?') && (answerLower.includes('ist ein') || answerLower.includes('is a')));
|
||||
|
||||
// Check if child is asking a specific "how/why" question that deserves explanation
|
||||
const isAskingSpecificQuestion = answerLower.includes('woher kommt') || answerLower.includes('where does') ||
|
||||
answerLower.includes('wie entsteht') || answerLower.includes('how does') ||
|
||||
answerLower.includes('warum ist das so') || answerLower.includes('why is that') ||
|
||||
answerLower.includes('ich verstehe nicht') || answerLower.includes("i don't understand") ||
|
||||
(answerLower.includes('?') && (answerLower.includes('woher') || answerLower.includes('wie') || answerLower.includes('warum'))) ||
|
||||
(answer.length > 30 && answerLower.includes('verstehe') && answerLower.includes('nicht'));
|
||||
|
||||
// Combine both definition and specific question detection
|
||||
const needsExplanation = isAskingForDefinition || isAskingSpecificQuestion;
|
||||
// Check if child is expressing confusion and needs explanation
|
||||
const isExpressingConfusion = answerLower.includes('verstehe nicht') || answerLower.includes("don't understand") ||
|
||||
answerLower.includes('versteh das nicht') || answerLower.includes('verstehe es nicht') ||
|
||||
answerLower.includes('ich verstehe nicht warum') || answerLower.includes("i don't understand why") ||
|
||||
answerLower.includes('aber ich verstehe nicht') || answerLower.includes("but i don't understand") ||
|
||||
answerLower.includes('fällt mir nicht ein') || answerLower.includes("can't think of") ||
|
||||
answerLower.includes('mehr fällt mir nicht ein');
|
||||
|
||||
// Check if it's a substantial answer (has thinking beyond just "don't know")
|
||||
const hasSubstantialThinking = answer.length > 15 && (
|
||||
@@ -650,41 +629,17 @@ class KidsAIExplorer {
|
||||
);
|
||||
|
||||
// Pure "don't know" without additional thinking
|
||||
const isPureDontKnow = (hasDontKnowPhrase || isOnlyWhyQuestion || answer.trim().length < 5) && !hasSubstantialThinking && !needsExplanation;
|
||||
const isPureDontKnow = (hasDontKnowPhrase || isOnlyWhyQuestion || answer.trim().length < 5) && !hasSubstantialThinking;
|
||||
|
||||
let response;
|
||||
|
||||
if (needsExplanation) {
|
||||
// Child is asking for explanation - provide simple, concrete explanation
|
||||
console.log('📤 Sending explanation request to /api/respond-to-answer');
|
||||
|
||||
const contextType = isAskingForDefinition ? 'definition_request' : 'specific_question';
|
||||
const instructionText = this.currentLanguage === 'de'
|
||||
? 'Das Kind stellt eine spezifische Frage und möchte verstehen. Gib eine EINFACHE, konkrete Erklärung für Kinder. Beantworte die spezifische Frage direkt aber kindgerecht. Verwende Analogien und alltägliche Vergleiche. Für "woher kommt die farbe" erkläre einfach, dass weißes Licht alle Farben enthält, wie ein unsichtbarer Regenbogen. Keine weiteren Fragen stellen.'
|
||||
: 'The child is asking a specific question and wants to understand. Give a SIMPLE, concrete explanation for children. Answer the specific question directly but age-appropriately. Use analogies and everyday comparisons. For "where does color come from" explain simply that white light contains all colors, like an invisible rainbow. Don\'t ask more questions.';
|
||||
|
||||
response = await fetch('/api/respond-to-answer', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
answer: answer,
|
||||
question: currentQuestion,
|
||||
originalTopic: originalQuestion,
|
||||
language: this.currentLanguage,
|
||||
context: contextType,
|
||||
stepIndex: questionIndex,
|
||||
instructions: instructionText
|
||||
})
|
||||
});
|
||||
} else if (isNegative || isPureDontKnow) {
|
||||
if (isNegative || isPureDontKnow) {
|
||||
// For pure "no" or "don't know" answers without thinking, get Socratic guidance questions
|
||||
console.log('📤 Sending guidance request to /api/ask for Socratic questioning');
|
||||
|
||||
const guidancePrompt = this.currentLanguage === 'de'
|
||||
? `Ein Kind hat "${answer}" geantwortet auf die Frage "${currentQuestion}". Das Kind weiß die Antwort nicht. Führe es durch 2-3 aufbauende Socratic Fragen zur Entdeckung, ohne direkte Antworten zu geben. Beginne mit einfachen Beobachtungen, die das Kind kennt.`
|
||||
: `A child answered "${answer}" to the question "${currentQuestion}". The child doesn't know the answer. Guide them through 2-3 building Socratic questions to discovery without giving direct answers. Start with simple observations the child would know.`;
|
||||
? `Ein Kind hat "${answer}" geantwortet auf die Frage "${currentQuestion}" über das Thema "${originalQuestion}". Das Kind weiß die Antwort nicht und braucht einfachere Grundlagen. Gib KEINE weiteren abstrakten Fragen! Stattdessen: 1) Beschreibe eine einfache Beobachtung, die das Kind machen kann (z.B. "Hast du schon mal Licht durch ein Glas Wasser gesehen?") 2) Lade zum praktischen Ausprobieren ein 3) Baue auf dem auf, was das Kind bereits kennt. Verwende konkrete, sichtbare Beispiele statt abstrakter Konzepte.`
|
||||
: `A child answered "${answer}" to the question "${currentQuestion}" about the topic "${originalQuestion}". The child doesn't know and needs simpler foundations. Give NO more abstract questions! Instead: 1) Describe a simple observation the child can make (e.g. "Have you ever seen light through a glass of water?") 2) Invite practical experimentation 3) Build on what the child already knows. Use concrete, visible examples instead of abstract concepts.`;
|
||||
|
||||
response = await fetch('/api/ask', {
|
||||
method: 'POST',
|
||||
@@ -696,6 +651,21 @@ class KidsAIExplorer {
|
||||
language: this.currentLanguage
|
||||
})
|
||||
});
|
||||
} else if (isExpressingConfusion) {
|
||||
// If the child is confused, provide an explanation instead of more questions
|
||||
console.log('📤 Sending explanation request to /api/explain');
|
||||
|
||||
response = await fetch('/api/explain', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
question: currentQuestion,
|
||||
language: this.currentLanguage,
|
||||
userAnswer: answer
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// For substantial answers, acknowledge and validate
|
||||
console.log('📤 Sending validation request to /api/respond-to-answer');
|
||||
@@ -772,11 +742,22 @@ class KidsAIExplorer {
|
||||
// Check if AI response contains a question that needs answering
|
||||
const hasQuestion = data.response && data.response.includes('?');
|
||||
|
||||
if (hasQuestion) {
|
||||
// AI asked a follow-up question, provide input area
|
||||
// Check if AI response contains explanations or new concepts that might trigger questions
|
||||
const containsExplanation = data.response && (
|
||||
data.response.includes('passiert, weil') || data.response.includes('happens because') ||
|
||||
data.response.includes('Das liegt daran') || data.response.includes('This is because') ||
|
||||
data.response.includes('Prisma') || data.response.includes('prism') ||
|
||||
data.response.includes('Licht') || data.response.includes('light') ||
|
||||
data.response.includes('besteht aus') || data.response.includes('consists of') ||
|
||||
data.response.includes('brechen') || data.response.includes('break') ||
|
||||
data.response.length > 150 // Longer responses likely contain explanations
|
||||
);
|
||||
|
||||
if (hasQuestion || containsExplanation) {
|
||||
// AI asked a question or gave an explanation - provide input area for follow-up questions
|
||||
this.addUserInputArea();
|
||||
} else {
|
||||
// No question in response, show choice buttons
|
||||
// Simple response without question or explanation, show choice buttons
|
||||
this.addContinueChoiceButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,15 +557,14 @@ app.post('/api/respond-to-answer', async (req, res) => {
|
||||
|
||||
console.log(`📝 Generating response to answer: "${answer}" for question: "${question}" with context: ${context}`);
|
||||
|
||||
// Handle definition requests and specific questions specially
|
||||
if ((context === 'definition_request' || context === 'specific_question') && instructions) {
|
||||
// For definition requests and specific questions, use the provided instructions
|
||||
// Handle confusion explanation requests specially
|
||||
if (context === 'confusion_explanation' && instructions) {
|
||||
const explanationPrompt = `${instructions}
|
||||
|
||||
CHILD'S QUESTION: "${answer}"
|
||||
CONTEXT: The child asked this while learning about: "${question}"
|
||||
CHILD'S CONFUSED RESPONSE: "${answer}"
|
||||
ORIGINAL QUESTION: "${question}"
|
||||
|
||||
Provide a simple, concrete explanation for children using everyday comparisons and practical examples.`;
|
||||
The child is expressing confusion and needs help understanding. Provide a clear, simple explanation using everyday examples and concrete comparisons that a child can understand.`;
|
||||
|
||||
// Try OpenAI first for explanations
|
||||
if (process.env.OPENAI_API_KEY) {
|
||||
@@ -585,44 +584,28 @@ Provide a simple, concrete explanation for children using everyday comparisons a
|
||||
const aiResponse = completion.choices[0]?.message?.content?.trim();
|
||||
|
||||
if (aiResponse && aiResponse.length > 10) {
|
||||
console.log('✅ OpenAI explanation response generated successfully');
|
||||
console.log('✅ OpenAI confusion explanation generated successfully');
|
||||
return res.json({
|
||||
success: true,
|
||||
response: aiResponse,
|
||||
source: `OpenAI GPT-3.5 (${context})`
|
||||
source: 'OpenAI GPT-3.5 (Confusion Explanation)'
|
||||
});
|
||||
}
|
||||
} catch (openaiError) {
|
||||
console.log('❌ OpenAI error for explanation:', openaiError.message);
|
||||
console.log('❌ OpenAI error for confusion explanation:', openaiError.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Enhanced fallbacks for specific questions
|
||||
const answerLower = answer.toLowerCase();
|
||||
let explanationFallback;
|
||||
|
||||
if (answerLower.includes('woher kommt') && answerLower.includes('farbe')) {
|
||||
explanationFallback = language === 'de' ?
|
||||
'🌈 Weißes Sonnenlicht ist wie ein unsichtbarer Regenbogen! Es enthält alle Farben gleichzeitig - rot, orange, gelb, grün, blau, violett. Wenn das Licht durch Wassertropfen geht, werden diese versteckten Farben sichtbar gemacht - wie Magie! Du kannst das mit einem Gartenschlauch im Sonnenschein ausprobieren!' :
|
||||
'🌈 White sunlight is like an invisible rainbow! It contains all colors at once - red, orange, yellow, green, blue, violet. When light goes through water drops, these hidden colors become visible - like magic! You can try this with a garden hose in the sunshine!';
|
||||
} else if (answerLower.includes('prisma') || answerLower.includes('prism')) {
|
||||
explanationFallback = language === 'de' ?
|
||||
'🔍 Ein Prisma ist wie ein magisches Glas, das weißes Licht in alle Regenbogenfarben zerlegt! Du kannst das selbst ausprobieren: Halte ein Glas Wasser ins Sonnenlicht und schau, welche Farben entstehen!' :
|
||||
'🔍 A prism is like a magic glass that breaks white light into all the rainbow colors! You can try this yourself: hold a glass of water in the sunlight and see what colors appear!';
|
||||
} else if (answerLower.includes('verstehe nicht') || answerLower.includes("don't understand")) {
|
||||
explanationFallback = language === 'de' ?
|
||||
'💡 Kein Problem! Das ist wirklich faszinierend. Lass es mich einfacher erklären: Stell dir vor, weißes Licht ist wie eine Süßigkeitentüte mit vielen verschiedenen Farben drin. Normalerweise siehst du nur die Tüte (weißes Licht), aber Wasser kann die Tüte "öffnen" und alle bunten Süßigkeiten (Farben) zeigen!' :
|
||||
'💡 No problem! This is really fascinating. Let me explain it simpler: Imagine white light is like a candy bag with many different colors inside. Usually you only see the bag (white light), but water can "open" the bag and show all the colorful candies (colors)!';
|
||||
} else {
|
||||
explanationFallback = language === 'de' ?
|
||||
'🤔 Das ist eine wirklich gute Frage! Lass mich das Schritt für Schritt erklären...' :
|
||||
'🤔 That\'s a really good question! Let me explain this step by step...';
|
||||
}
|
||||
// Fallback for confusion explanations
|
||||
const isGerman = language === 'de';
|
||||
const confusionFallback = isGerman ?
|
||||
'Das passiert, weil Sonnenlicht aus vielen verschiedenen Farben besteht! Wenn Licht durch Regentropfen geht, werden diese Farben getrennt - wie bei einem Prisma. Du kannst das selbst ausprobieren: Halte ein Glas Wasser ins Sonnenlicht und schau, welche Farben entstehen! 🌈' :
|
||||
'This happens because sunlight is made of many different colors! When light goes through raindrops, these colors get separated - just like with a prism. You can try this yourself: hold a glass of water in sunlight and see what colors appear! 🌈';
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
response: explanationFallback,
|
||||
source: 'Enhanced Explanation Fallback'
|
||||
response: confusionFallback,
|
||||
source: 'Fallback Confusion Explanation'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user