🚀 MAJOR: Replace hardcoded responses with AI-powered contextual system
- REMOVED hardcoded bird-specific response arrays (unsustainable approach) - ADDED generateAIResponseToAnswer() method with server-side AI integration - ADDED /api/respond-to-answer endpoint for contextual AI responses - NOW WORKS FOR ANY TOPIC: CPU, pneumatic tools, biology, physics, etc. - AI generates contextual responses based on user's specific answer - Scalable solution that doesn't require hardcoding responses for every topic - Maintains educational approach: encourages thinking, asks follow-up questions - Fallback system for when AI services are unavailable
This commit is contained in:
@@ -176,9 +176,9 @@
|
|||||||
}, 100);
|
}, 100);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="translations.js?v=20250629155100"></script>
|
<script src="translations.js?v=20250629172300"></script>
|
||||||
<script src="ai-responses.js?v=20250629155100"></script>
|
<script src="ai-responses.js?v=20250629172300"></script>
|
||||||
<script src="script-new.js?v=20250629155100"></script>
|
<script src="script-new.js?v=20250629172300"></script>
|
||||||
|
|
||||||
<!-- Inline debugging script -->
|
<!-- Inline debugging script -->
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
// KidsAI Explorer - Interactive Learning Assistant
|
// KidsAI Explorer - Interactive Learning Assistant
|
||||||
console.log('🚀 KidsAI script-new.js is loading...');
|
console.log('🚀 KidsAI script-new.js is loading...');
|
||||||
|
|
||||||
|
// Test that AIResponses is available
|
||||||
|
console.log('🔍 Testing AIResponses availability:', typeof AIResponses);
|
||||||
|
if (typeof AIResponses !== 'undefined') {
|
||||||
|
console.log('✅ AIResponses loaded successfully:', Object.keys(AIResponses));
|
||||||
|
} else {
|
||||||
|
console.error('❌ AIResponses not loaded! Check ai-responses.js');
|
||||||
|
}
|
||||||
|
|
||||||
class KidsAIExplorer {
|
class KidsAIExplorer {
|
||||||
constructor() {
|
constructor() {
|
||||||
console.log('🏗️ KidsAI constructor started');
|
console.log('🏗️ KidsAI constructor started');
|
||||||
@@ -331,69 +339,106 @@ class KidsAIExplorer {
|
|||||||
inputArea.classList.add('answered');
|
inputArea.classList.add('answered');
|
||||||
textarea.disabled = true;
|
textarea.disabled = true;
|
||||||
|
|
||||||
// Show AI response
|
// Show AI response using server-side AI
|
||||||
let aiResponse;
|
this.generateAIResponseToAnswer(answer, stepIndex, responseDiv);
|
||||||
|
}
|
||||||
if (!answer || answer.toLowerCase().includes('nothing') || answer.toLowerCase().includes('don\'t know')) {
|
|
||||||
// Encouraging response for "nothing" or "don't know"
|
|
||||||
const encouragingResponses = [
|
|
||||||
"🌟 Great observation! You're thinking like a scientist! Starting fresh means you can discover everything step by step. Can you think of how the shape of a bird's wings helps them stay in the air and move around?",
|
|
||||||
"💡 That's the perfect starting point for learning! Every expert started by not knowing. You're right, birds do use their wings to fly. Can you think of how the wings might work differently above and below?",
|
|
||||||
"🚀 Perfect honesty! When we don't know something, it means we're about to learn something new! Maybe because the wind can flow faster on the above of the wing than on the below which creates pressure and pushes the bird up?"
|
|
||||||
];
|
|
||||||
aiResponse = encouragingResponses[Math.floor(Math.random() * encouragingResponses.length)];
|
|
||||||
} else if (answer.length < 10) {
|
|
||||||
// Short answer - provide gentle guidance like in image 2
|
|
||||||
const guidingResponses = [
|
|
||||||
"🎯 That's a great observation! Birds use their wings to create lift by taking advantage of the difference in air pressure above and below their wings. Do you know why different bird species have different wing shapes?",
|
|
||||||
"✨ You're on the right track! Can you think of how the shape of a bird's wings helps them stay in the air and move around?",
|
|
||||||
"🔍 Good thinking! You're right, birds do use their wings to fly. Can you think of how the wings might work differently above and below?"
|
|
||||||
];
|
|
||||||
aiResponse = guidingResponses[Math.floor(Math.random() * guidingResponses.length)];
|
|
||||||
} else {
|
|
||||||
// Longer, thoughtful answer - provide specific scientific guidance
|
|
||||||
const insightfulResponses = [
|
|
||||||
"🌟 Excellent thinking! You're really exploring this well! That's a great observation! Birds use their wings to create lift by taking advantage of the difference in air pressure above and below their wings. Do you know why different bird species have different wing shapes?",
|
|
||||||
"💡 Great observation! You're thinking like a scientist! You're right, birds do use their wings to fly. Can you think of how the wings might work differently above and below which creates pressure and pushes the bird up?",
|
|
||||||
"🔍 Wonderful insight! You're asking the right questions! That's exactly how flight works - the shape of a bird's wings helps them stay in the air and move around!",
|
|
||||||
"🎯 That's a thoughtful response! Keep exploring! Birds use their wings to create lift. Can you think of any other animals that can fly like birds, and how do they differ in their flying abilities?"
|
|
||||||
];
|
|
||||||
aiResponse = insightfulResponses[Math.floor(Math.random() * insightfulResponses.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
responseDiv.innerHTML = `
|
|
||||||
<div class="ai-response-content">
|
|
||||||
<div class="message-header">
|
|
||||||
<span class="ai-avatar">🤖</span>
|
|
||||||
<span class="ai-label">AI Teacher</span>
|
|
||||||
</div>
|
|
||||||
<div class="message-content">
|
|
||||||
<p>${aiResponse}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
responseDiv.style.display = 'block';
|
|
||||||
|
|
||||||
// Show next question or reveal option
|
// Generate AI response to user answer using server-side AI
|
||||||
const nextStepIndex = stepIndex + 1;
|
async generateAIResponseToAnswer(answer, stepIndex, responseDiv) {
|
||||||
const nextStep = document.querySelector(`.step-${nextStepIndex}`);
|
try {
|
||||||
|
// Show loading state
|
||||||
if (nextStep) {
|
responseDiv.innerHTML = `
|
||||||
// Show next question after a delay
|
<div class="ai-response-content">
|
||||||
setTimeout(() => {
|
<div class="message-header">
|
||||||
nextStep.classList.add('visible');
|
<span class="ai-avatar">🤖</span>
|
||||||
nextStep.scrollIntoView({ behavior: 'smooth' });
|
<span class="ai-label">AI Teacher</span>
|
||||||
}, 1500);
|
</div>
|
||||||
} else {
|
<div class="message-content">
|
||||||
// All questions answered, show reveal option
|
<p>🤔 Thinking about your answer...</p>
|
||||||
setTimeout(() => {
|
</div>
|
||||||
const revealSection = document.querySelector('.reveal-section');
|
</div>
|
||||||
if (revealSection) {
|
`;
|
||||||
revealSection.style.display = 'block';
|
responseDiv.style.display = 'block';
|
||||||
revealSection.scrollIntoView({ behavior: 'smooth' });
|
|
||||||
}
|
// Get current question context
|
||||||
}, 2000);
|
const currentQuestion = this.currentSteps && this.currentSteps[stepIndex]
|
||||||
|
? this.currentSteps[stepIndex].text
|
||||||
|
: 'the current question';
|
||||||
|
|
||||||
|
// Call server API for contextual response
|
||||||
|
const response = await fetch('/api/respond-to-answer', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
answer: answer,
|
||||||
|
question: currentQuestion,
|
||||||
|
language: this.currentLanguage,
|
||||||
|
stepIndex: stepIndex
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.success && data.response) {
|
||||||
|
responseDiv.innerHTML = `
|
||||||
|
<div class="ai-response-content">
|
||||||
|
<div class="message-header">
|
||||||
|
<span class="ai-avatar">🤖</span>
|
||||||
|
<span class="ai-label">AI Teacher</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">
|
||||||
|
<p>${data.response}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || 'Failed to generate response');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error generating AI response:', error);
|
||||||
|
// Fallback response
|
||||||
|
responseDiv.innerHTML = `
|
||||||
|
<div class="ai-response-content">
|
||||||
|
<div class="message-header">
|
||||||
|
<span class="ai-avatar">🤖</span>
|
||||||
|
<span class="ai-label">AI Teacher</span>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">
|
||||||
|
<p>🌟 Great thinking! Keep exploring - every thought helps us learn!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show next question or reveal option after response
|
||||||
|
setTimeout(() => {
|
||||||
|
const nextStepIndex = stepIndex + 1;
|
||||||
|
const nextStep = document.querySelector(`.step-${nextStepIndex}`);
|
||||||
|
|
||||||
|
if (nextStep) {
|
||||||
|
// Show next question after a delay
|
||||||
|
setTimeout(() => {
|
||||||
|
nextStep.classList.add('visible');
|
||||||
|
nextStep.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
// All questions answered, show reveal option
|
||||||
|
setTimeout(() => {
|
||||||
|
const revealSection = document.querySelector('.reveal-section');
|
||||||
|
if (revealSection) {
|
||||||
|
revealSection.style.display = 'block';
|
||||||
|
revealSection.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
askNextQuestion() {
|
askNextQuestion() {
|
||||||
|
|||||||
@@ -542,3 +542,111 @@ function getFallbackAnswer(question, language) {
|
|||||||
source: 'Educational Framework'
|
source: 'Educational Framework'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// API endpoint for responding to user answers contextually
|
||||||
|
app.post('/api/respond-to-answer', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { answer, question, language = 'en', stepIndex } = req.body;
|
||||||
|
|
||||||
|
if (!answer || !question) {
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Answer and question are required'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📝 Generating response to answer: "${answer}" for question: "${question}"`);
|
||||||
|
|
||||||
|
// Create contextual prompt for responding to the user's answer
|
||||||
|
const isGerman = language === 'de';
|
||||||
|
|
||||||
|
const contextualPrompt = isGerman ?
|
||||||
|
`Du bist ein pädagogischer KI-Assistent für Kinder. Ein Kind hat gerade auf eine Frage geantwortet.
|
||||||
|
|
||||||
|
FRAGE: "${question}"
|
||||||
|
ANTWORT DES KINDES: "${answer}"
|
||||||
|
|
||||||
|
Deine Aufgabe ist es, eine ermutigende, pädagogische Antwort zu geben, die:
|
||||||
|
1. Das Kind für seine Antwort ermutigt (egal ob richtig oder falsch)
|
||||||
|
2. Auf ihrer spezifischen Antwort aufbaut
|
||||||
|
3. Ihr Denken erweitert, ohne die Antwort direkt zu verraten
|
||||||
|
4. Eine weitere durchdachte Frage stellt, um ihr Denken zu vertiefen
|
||||||
|
5. Verwende Emojis sparsam und altersgerecht
|
||||||
|
|
||||||
|
Antworte in 2-3 Sätzen mit einer Folgefrage.` :
|
||||||
|
`You are an educational AI assistant for children. A child just answered a question.
|
||||||
|
|
||||||
|
QUESTION: "${question}"
|
||||||
|
CHILD'S ANSWER: "${answer}"
|
||||||
|
|
||||||
|
Your task is to provide an encouraging, educational response that:
|
||||||
|
1. Encourages the child for their answer (regardless of right or wrong)
|
||||||
|
2. Builds on their specific answer
|
||||||
|
3. Expands their thinking without giving away the answer directly
|
||||||
|
4. Asks a thoughtful follow-up question to deepen their thinking
|
||||||
|
5. Use emojis sparingly and age-appropriately
|
||||||
|
|
||||||
|
Respond in 2-3 sentences with a follow-up question.`;
|
||||||
|
|
||||||
|
// Try OpenAI first
|
||||||
|
if (process.env.OPENAI_API_KEY) {
|
||||||
|
try {
|
||||||
|
const completion = await openai.chat.completions.create({
|
||||||
|
model: "gpt-3.5-turbo",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: contextualPrompt
|
||||||
|
}
|
||||||
|
],
|
||||||
|
max_tokens: 200,
|
||||||
|
temperature: 0.7
|
||||||
|
});
|
||||||
|
|
||||||
|
const aiResponse = completion.choices[0]?.message?.content?.trim();
|
||||||
|
|
||||||
|
if (aiResponse && aiResponse.length > 10) {
|
||||||
|
console.log('✅ OpenAI response generated successfully');
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: aiResponse,
|
||||||
|
source: 'OpenAI GPT-3.5'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (openaiError) {
|
||||||
|
console.log('❌ OpenAI error:', openaiError.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: Generate a contextual response based on answer content
|
||||||
|
const answerLower = answer.toLowerCase();
|
||||||
|
let fallbackResponse;
|
||||||
|
|
||||||
|
if (answerLower.includes("don't know") || answerLower.includes("no idea") || answer.trim().length < 3) {
|
||||||
|
fallbackResponse = isGerman ?
|
||||||
|
"🌟 Das ist völlig in Ordnung! Nicht zu wissen bedeutet, dass wir zusammen etwas Neues entdecken können. Wenn du raten müsstest, was denkst du könnte wichtig sein?" :
|
||||||
|
"🌟 That's completely okay! Not knowing means we get to discover something new together. If you had to guess, what do you think might be important?";
|
||||||
|
} else if (answer.length < 15) {
|
||||||
|
fallbackResponse = isGerman ?
|
||||||
|
`💡 Interessante Überlegung zu "${answer}"! Du denkst in die richtige Richtung. Kannst du mir mehr darüber erzählen, wie das funktionieren könnte?` :
|
||||||
|
`💡 Interesting thinking about "${answer}"! You're on the right track. Can you tell me more about how that might work?`;
|
||||||
|
} else {
|
||||||
|
fallbackResponse = isGerman ?
|
||||||
|
`🎯 Ausgezeichnete Antwort! Du denkst wirklich gut über "${answer}" nach. Das zeigt, dass du das Konzept verstehst. Was denkst du passiert als nächstes?` :
|
||||||
|
`🎯 Excellent answer! You're really thinking well about "${answer}". This shows you understand the concept. What do you think happens next?`;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
response: fallbackResponse,
|
||||||
|
source: 'Contextual Fallback'
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error in respond-to-answer:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: 'Failed to generate response'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user