v4: conversational teacher with context memory

This commit is contained in:
Ruslan 2026-09-09 11:03:37 +00:00
parent f6cce5394a
commit 14a21dbcbe
2 changed files with 262 additions and 60 deletions

308
script.js
View File

@ -275,6 +275,7 @@ const levelsData = {
// Текущее состояние
let currentLevel = null;
let chatSessionId = null;
let chatHistory = []; // История переписки для контекста
// DOM элементы
const levelsSection = document.getElementById('levels-section');
@ -438,6 +439,12 @@ function toggleChat() {
teacherChat.classList.toggle('hidden');
if (!teacherChat.classList.contains('hidden')) {
chatInput.focus();
// Если чат открыли впервые - приветствуем
if (chatHistory.length === 0) {
setTimeout(() => {
addMessage('Hi there! 👋 I\'m your English teacher! Let\'s have a conversation! Tell me about yourself - where are you from?', 'teacher');
}, 500);
}
}
}
@ -448,26 +455,39 @@ async function sendMessage() {
// Добавляем сообщение студента
addMessage(text, 'student');
chatInput.value = '';
sendBtn.disabled = true;
// Показываем индикатор набора
showTypingIndicator();
try {
// Небольшая задержка для естественности
await new Promise(resolve => setTimeout(resolve, 600));
// Получаем ответ от ИИ
const response = await askTeacher(text);
hideTypingIndicator();
addMessage(response, 'teacher');
} catch (error) {
hideTypingIndicator();
addMessage('Извини, я временно недоступен. Попробуй ещё раз!', 'teacher');
addMessage('Hmm, I had trouble processing that. Try rephrasing? 😊', 'teacher');
console.error('Teacher error:', error);
}
sendBtn.disabled = false;
chatInput.focus();
}
function addMessage(text, type) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
messageDiv.innerHTML = `<div class="message-bubble">${text}</div>`;
// Добавляем аватарки
const avatar = type === 'teacher' ? '👨‍🏫' : '👤';
messageDiv.innerHTML = `
<div class="message-avatar">${avatar}</div>
<div class="message-bubble">${text}</div>
`;
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
@ -494,135 +514,295 @@ function hideTypingIndicator() {
if (typing) typing.remove();
}
// Готовые ответы для статической версии (без сервера)
// Готовые ответы для статической версии (без сервера) - РАЗГОВОРНЫЙ РЕЖИМ
const teacherResponses = {
greetings: {
keywords: ['hello', 'hi', 'привет', 'здравствуй', 'good morning', 'good afternoon'],
keywords: ['hello', 'hi', 'привет', 'здравствуй', 'good morning', 'good afternoon', 'hey'],
answers: [
'Hello! Great to see you! How can I help you with English today?',
'Hi there! Ready to practice English? What would you like to work on?',
'Hello! I\'m your English teacher. Ask me anything about grammar, vocabulary, or let\'s just chat!'
]
'Hello! Great to see you! 😊 How are you today? Tell me in English!',
'Hi there! Ready to practice English? What have you been doing lately?',
'Hello! I\'m your English teacher. Nice to meet you! What\'s your name?',
'Hey! How\'s it going? Did you do anything interesting today?'
],
followUp: 'Tell me about yourself! Where are you from? What do you like to do?'
},
thanks: {
keywords: ['thank', 'спасибо', 'thanks'],
keywords: ['thank', 'спасибо', 'thanks', 'благодарю'],
answers: [
'You\'re welcome! Keep up the good work! 👍',
'Anytime! That\'s what I\'m here for! 😊',
'No problem! Feel free to ask more questions!'
'You\'re welcome! 😊 You\'re making great progress! Keep it up!',
'Anytime! That\'s what I\'m here for! Do you have more questions?',
'No problem! I\'m happy to help! What else would you like to learn?'
]
},
howAreYou: {
keywords: ['how are you', 'как дела', 'how\'s it going', 'how are things'],
answers: [
'I\'m great, thank you for asking! 😊 I\'m here helping students learn English. How about you? How was your day?',
'Doing well! Excited to practice English with you! What about you? Anything new?'
]
},
name: {
keywords: ['what is your name', 'как тебя зовут', 'your name', 'кто ты'],
answers: [
'I\'m your virtual English teacher! You can call me Teacher. 😊 What\'s YOUR name?',
'I\'m your English learning companion! But I\'d love to know YOUR name. What should I call you?'
]
},
help: {
keywords: ['help', 'помощь', 'помоги', 'explain', 'объясни'],
keywords: ['help', 'помощь', 'помоги', 'explain', 'объясни', 'assist'],
answers: [
'I can help you with: grammar rules, vocabulary, pronunciation tips, or just conversation practice. What do you need?',
'Sure! I can explain grammar, check your sentences, or suggest words. What topic interests you?'
'I\'d love to help! 🎯 I can: check your sentences, explain grammar, teach new words, or just chat. What do you prefer?',
'Of course! What\'s troubling you? Grammar? Vocabulary? Or maybe you want conversation practice?'
]
},
grammar: {
keywords: ['grammar', 'грамматик', 'rule', 'правило', 'tense', 'время'],
answers: [
'Grammar is important! The key is practice. Start with Present Simple - it\'s the most common tense. Example: "I work every day." Want me to explain more?',
'English grammar has 12 tenses, but you only need 5-6 for daily conversation. Which tense would you like to learn?'
'Grammar time! 📚 Let me explain simply. Which tense confuses you? Present, Past, or Future?',
'Great question! Grammar is like puzzle pieces. Once you get the pattern, it clicks! What specifically?'
]
},
vocabulary: {
keywords: ['word', 'слово', 'vocabulary', 'translate', 'перевод', 'meaning'],
keywords: ['word', 'слово', 'vocabulary', 'translate', 'перевод', 'meaning', 'значит'],
answers: [
'Great question! Building vocabulary takes time. Try learning 5-10 new words daily and use them in sentences. What word interests you?',
'I can help with translations! Just tell me the word you want to know.'
'Vocabulary is key! 🔑 Tell me the word you want to know, or I can teach you a new one!',
'I love teaching new words! What topic interests you? Food? Travel? Work? Emotions?'
]
},
practice: {
keywords: ['practice', 'практик', 'speak', 'говорить', 'chat', 'болтать'],
keywords: ['practice', 'практик', 'speak', 'говорить', 'chat', 'болтать', 'conversation'],
answers: [
'Let\'s practice! Tell me about your day in English. Don\'t worry about mistakes - I\'ll help you correct them!',
'Great! Let\'s have a conversation. What topics interest you? Hobbies, work, travel, movies?'
'Awesome! Let\'s chat! 💬 Tell me - what did you do yesterday? Use past tense!',
'Perfect! I love conversations! So... what are your hobbies? What do you enjoy doing?'
]
},
mistake: {
keywords: ['mistake', 'ошибка', 'wrong', 'correct', 'правильно'],
keywords: ['mistake', 'ошибка', 'wrong', 'correct', 'правильно', 'right'],
answers: [
'Mistakes are how we learn! Don\'t be afraid to make them. Even native speakers make mistakes!',
'Good catch! Let me explain the rule so you remember it better.'
'Mistakes are GOLD! ✨ They show you\'re trying! Tell me what you\'re unsure about.',
'Don\'t worry about mistakes - they\'re part of learning! Even natives make them! Let\'s figure it out together.'
]
},
goodbye: {
keywords: ['bye', 'goodbye', 'пока', 'до свидания', 'see you'],
keywords: ['bye', 'goodbye', 'пока', 'до свидания', 'see you', 'gotta go', 'must go'],
answers: [
'Goodbye! Keep practicing and you\'ll improve fast! See you next time! 👋',
'Bye! Great job today! Come back when you want to practice more!'
'Bye! 🌟 You did great today! Come back soon for more practice!',
'See you later! Keep thinking in English! See you next time! 👋',
'Goodbye! Remember - consistency is key! Practice a little every day! 💪'
]
},
encouragement: {
keywords: ['hard', 'трудно', 'difficult', 'can\'t', 'не могу', 'impossible'],
keywords: ['hard', 'трудно', 'difficult', 'can\'t', 'не могу', 'impossible', 'suck', 'bad at'],
answers: [
'Learning English takes time, but you\'re doing great! Every day you\'re getting better. Keep going! 💪',
'I understand it can be challenging. Break it into small steps. What specifically is difficult? I\'ll help!'
'Hey, listen - learning a language is HARD! 🎯 But you know what? You\'re capable! Every mistake makes you stronger!',
'I get it, some days are tougher. But look how far you\'ve come! Want to take a break and chat about something fun?',
'Don\'t be so hard on yourself! Even fluent speakers started from zero. You\'ve got this! 💪 What\'s specifically difficult?'
]
},
level: {
keywords: ['level', 'уровень', 'beginner', 'intermediate', 'advanced'],
answers: [
'Choose your level from the cards above! Each level has theory, vocabulary, and exercises. Start where you feel comfortable.',
'Don\'t worry too much about levels. Just start practicing and you\'ll naturally progress!'
'Levels are just guides! 📍 Start where you feel comfy. You can always move up or review. Which feels right?',
'Don\'t stress about levels! Just pick one and start. The exercises will tell you if it\'s too easy or hard!'
]
},
hobbies: {
keywords: ['hobby', 'хобби', 'interest', 'like to do', 'enjoy', 'love doing'],
answers: [
'Hobbies are the best! 🎨 Mine is... well, teaching English! 😄 What do YOU enjoy? Sports? Music? Reading?',
'I\'d love to hear about your hobbies! What gets you excited? What do you do in free time?'
]
},
weather: {
keywords: ['weather', 'погода', 'sunny', 'rain', 'cold', 'hot', 'snow'],
answers: [
'Weather talk - classic English topic! ☀️🌧️ What\'s the weather like where you are? I\'m curious!',
'Ah, the British love talking about weather! 😄 Is it sunny? Rainy? Perfect weather for studying English!'
]
},
family: {
keywords: ['family', 'семья', 'mother', 'father', 'sister', 'brother', 'parents'],
answers: [
'Family is important! 👨‍👩‍👧‍👦 Tell me about yours! Do you have siblings? What are your parents like?',
'I\'d love to hear about your family! Are you close with them? Do they speak English too?'
]
},
work: {
keywords: ['work', 'работа', 'job', 'study', 'учеба', 'university', 'school'],
answers: [
'Work/study keeps us busy! 💼📚 What do you do? What\'s your favorite part about it?',
'Interesting! What field are you in? Or what are you studying? I\'m all ears!'
]
},
yes: {
keywords: ['yes', 'да', 'yeah', 'yep', 'sure', 'of course', 'конечно'],
answers: [
'Great! 😊 So, tell me more! I\'m listening!',
'Awesome! Keep going! What else?',
'Perfect! You\'re doing well! Continue!'
]
},
no: {
keywords: ['no', 'нет', 'nope', 'don\'t', 'не'],
answers: [
'That\'s okay! 😊 Maybe another time. What WOULD you like to talk about?',
'No problem! Everyone has different preferences. What interests you more?'
]
},
why: {
keywords: ['why', 'почему', 'wherefore'],
answers: [
'Good question! 🤔 "Why" questions are great for learning! Let me explain...',
'Why indeed! Curiosity is the key to learning! Let\'s figure this out together.'
]
},
what: {
keywords: ['what', 'что', 'какой', 'which'],
answers: [
'Hmm, let me think... 🤔 What do YOU think? Try to answer in English!',
'Great question! Let me help you figure it out. What\'s your guess?'
]
}
};
const fallbackAnswers = [
'Interesting! Tell me more about it in English. Practice makes perfect! 😊',
'I see! Can you give me an example sentence? I\'ll help you check it.',
'That\'s a great topic! What specific aspect would you like to discuss?',
'Good question! Let me think... Actually, the best way to learn is through practice. Try making a sentence with this!',
'Hmm, I\'m not sure I understand completely. Can you rephrase that? Or ask me something more specific about English.'
'Interesting! 😊 Tell me more! I\'m curious about your thoughts!',
'I see! Can you give me an example? That helps me understand better!',
'That\'s a great topic! What specifically interests you about it?',
'Hmm, tell me more! Try to use English - I\'ll help if you get stuck! 💬',
'Nice! So... what else? Ask me something or tell me about your day!',
'Got it! 🎯 Now, here\'s a question for YOU: [asks question about the topic]'
];
// Вопросы для поддержания разговора
const conversationStarters = [
'So, what did you do today?',
'What\'s your favorite hobby? Why do you like it?',
'Do you have any plans for the weekend?',
'What\'s your favorite movie? Tell me about it!',
'Do you prefer coffee or tea? Why?',
'What\'s the best place you\'ve ever visited?',
'Do you have any pets? Tell me about them!',
'What\'s your favorite food? Can you describe it?',
'Do you like music? What kind?',
'What\'s something you\'re proud of?'
];
function getFollowUpQuestion() {
return conversationStarters[Math.floor(Math.random() * conversationStarters.length)];
}
function getStaticResponse(message) {
const lower = message.toLowerCase();
// Сохраняем в историю
chatHistory.push({ role: 'user', content: message });
if (chatHistory.length > 10) chatHistory.shift(); // Храним последние 10 сообщений
// Ищем совпадения по ключевым словам
for (const [category, data] of Object.entries(teacherResponses)) {
if (data.keywords.some(kw => lower.includes(kw))) {
const answers = data.answers;
return answers[Math.floor(Math.random() * answers.length)];
let response = answers[Math.floor(Math.random() * answers.length)];
// Добавляем follow-up вопрос для продолжения разговора
if (data.followUp && Math.random() > 0.5) {
response += ' ' + data.followUp;
} else if (Math.random() > 0.6) {
response += ' ' + getFollowUpQuestion();
}
return response;
}
}
// Определяем язык
const isRussian = /[а-яА-ЯёЁ]/.test(message);
// Проверяем последние сообщения в истории
const lastUserMessage = chatHistory.filter(m => m.role === 'user').slice(-2, -1)[0];
const lastTeacherMessage = chatHistory.filter(m => m.role === 'assistant').slice(-1)[0];
if (isRussian) {
// Ответы на русском с английскими вставками
const ruResponses = [
'Отличный вопрос! Попробуй задать его на английском - я помогу с переводом и грамматикой.',
'Интересно! Расскажи подробнее. Не бойся делать ошибки - я помогу их исправить.',
'Хорошо! Давай обсудим это. Какой аспект тебя интересует?',
'Вопрос понятен! Лучший способ выучить - практиковаться. Попробуй составить предложение на эту тему!',
'Я тут, чтобы помочь! Спроси что-то конкретное о грамматике, словах или давай поболтаем на английском.'
'Отлично! 😊 Теперь попробуй сказать это на английском! Я помогу.',
'Интересно! Расскажи подробнее на английском. Не бойся ошибок!',
'Хороший вопрос! Как ты думаешь, какой будет ответ? Попробуй угадать!',
'Понятно! А что ты думаешь об этом? Tell me in English!',
'Я тебя понимаю! Давай попробуем сказать это по-английски вместе!'
];
return ruResponses[Math.floor(Math.random() * ruResponses.length)];
let response = ruResponses[Math.floor(Math.random() * ruResponses.length)];
// Добавляем вопрос для продолжения
if (Math.random() > 0.5) {
const ruQuestions = [
'А как ты это скажешь на английском?',
'Что ты думаешь об этом?',
'Расскажи подробнее!',
'А что было потом?',
'Почему ты так решил?'
];
response += ' ' + ruQuestions[Math.floor(Math.random() * ruQuestions.length)];
}
return response;
}
// English fallback
return fallbackAnswers[Math.floor(Math.random() * fallbackAnswers.length)];
// English fallback с поддержкой разговора
let response = fallbackAnswers[Math.floor(Math.random() * fallbackAnswers.length)];
// Если это длинное сообщение - задаём уточняющий вопрос
if (message.length > 30 || message.split(' ').length > 5) {
const followUps = [
' Why do you think so?',
' Tell me more!',
' What happened next?',
' How did that make you feel?',
' Really? That\'s interesting! Go on!',
' What do you mean by that?',
' Can you give me an example?'
];
response += followUps[Math.floor(Math.random() * followUps.length)];
}
return response;
}
async function askTeacher(message) {
// Пробуем серверный ИИ (если есть)
// Сохраняем сообщение пользователя в историю
chatHistory.push({ role: 'user', content: message, timestamp: Date.now() });
// Пробуем серверный ИИ (если есть) - с полной историей диалога
try {
const levelContext = currentLevel ? `Current student level: ${currentLevel}. ` : '';
const levelContext = currentLevel ? `Student level: ${currentLevel}. ` : '';
// Формируем контекст из истории
const conversationContext = chatHistory.slice(-8).map(m =>
`${m.role === 'user' ? 'Student' : 'Teacher'}: ${m.content}`
).join('\n');
const messages = [
{
role: 'system',
content: `You are a friendly and supportive English teacher. Your tasks:
1. Communicate at the student's level
2. Correct mistakes gently and explain grammar rules
3. Help with vocabulary and constructions
4. Encourage and motivate
5. Answer grammar questions
content: `You are a friendly, conversational English teacher. Have a NATURAL conversation with the student.
${levelContext}Respond briefly (2-4 sentences), in a friendly manner. If the student writes in Russian, respond in Russian with English examples. If in English, respond in English but you can add translations of difficult words.`
${levelContext}
YOUR STYLE:
- Be warm, encouraging, and curious
- Ask follow-up questions to keep conversation going
- Show genuine interest in their life, opinions, experiences
- Correct mistakes gently by rephrasing correctly
- Use emoji occasionally 😊
- Keep responses conversational (2-4 sentences)
- If they write in Russian, respond in Russian with English examples
- Always end with a question or invitation to share more
RECENT CONVERSATION:
${conversationContext}
Now respond naturally to: "${message}"`
},
{
role: 'user',
@ -636,7 +816,7 @@ ${levelContext}Respond briefly (2-4 sentences), in a friendly manner. If the stu
'Content-Type': 'application/json'
},
body: JSON.stringify({ messages }),
timeout: 5000
timeout: 8000
});
if (!response.ok) {
@ -650,11 +830,19 @@ ${levelContext}Respond briefly (2-4 sentences), in a friendly manner. If the stu
throw new Error('Empty AI response');
}
// Сохраняем ответ учителя
chatHistory.push({ role: 'assistant', content: answer, timestamp: Date.now() });
return answer.replace(/\n/g, '<br>');
} catch (error) {
// Фолбэк на статические ответы
// Фолбэк на статические ответы с разговорной логикой
console.log('Using static responses:', error.message);
return getStaticResponse(message);
const response = getStaticResponse(message);
// Сохраняем ответ в историю
chatHistory.push({ role: 'assistant', content: response, timestamp: Date.now() });
return response;
}
}

View File

@ -175,21 +175,35 @@ body {
.message {
margin-bottom: 16px;
display: flex;
align-items: flex-start;
gap: 10px;
}
.message.student {
justify-content: flex-end;
flex-direction: row-reverse;
}
.message.teacher {
justify-content: flex-start;
}
.message-avatar {
font-size: 24px;
flex-shrink: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
.message-bubble {
max-width: 80%;
padding: 12px 16px;
border-radius: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.message.teacher .message-bubble {