Добавлены основные функции MVP: тематические подборки, импорт слов, диалоговая практика, напоминания и тест уровня
Новые команды: - /words [тема] - AI-генерация тематических подборок слов (10 слов по теме с учётом уровня) - /import - извлечение до 15 ключевых слов из текста (книги, статьи, песни) - /practice - диалоговая практика с AI в 6 сценариях (ресторан, магазин, путешествие, работа, врач, общение) - /reminder - настройка ежедневных напоминаний по расписанию - /level_test - тест из 7 вопросов для определения уровня английского (A1-C2) Основные изменения: - AI сервис: добавлены методы generate_thematic_words, extract_words_from_text, start_conversation, continue_conversation, generate_level_test - Диалоговая практика: исправление ошибок в реальном времени, подсказки, перевод реплик - Напоминания: APScheduler для ежедневной отправки напоминаний в выбранное время - Тест уровня: автоматическое определение уровня при регистрации, можно пропустить - База данных: добавлены поля reminders_enabled, last_reminder_sent - Vocabulary service: метод get_word_by_original для проверки дубликатов - Зависимости: apscheduler==3.10.4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -171,6 +171,361 @@ class AIService:
|
||||
"translation": f"Мне нравится {word} каждый день."
|
||||
}
|
||||
|
||||
async def generate_thematic_words(self, theme: str, level: str = "B1", count: int = 10) -> List[Dict]:
|
||||
"""
|
||||
Сгенерировать подборку слов по теме
|
||||
|
||||
Args:
|
||||
theme: Тема для подборки слов
|
||||
level: Уровень сложности (A1-C2)
|
||||
count: Количество слов
|
||||
|
||||
Returns:
|
||||
Список словарей с информацией о словах
|
||||
"""
|
||||
prompt = f"""Создай подборку из {count} английских слов по теме "{theme}" для уровня {level}.
|
||||
|
||||
Верни ответ в формате JSON:
|
||||
{{
|
||||
"theme": "{theme}",
|
||||
"words": [
|
||||
{{
|
||||
"word": "английское слово",
|
||||
"translation": "перевод на русский",
|
||||
"transcription": "транскрипция в IPA",
|
||||
"example": "пример использования на английском"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
|
||||
Слова должны быть:
|
||||
- Полезными и часто используемыми
|
||||
- Соответствовать уровню {level}
|
||||
- Связаны с темой "{theme}"
|
||||
- Разнообразными (существительные, глаголы, прилагательные)"""
|
||||
|
||||
try:
|
||||
response = await self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "Ты - преподаватель английского языка. Подбирай полезные и актуальные слова."},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(response.choices[0].message.content)
|
||||
return result.get('words', [])
|
||||
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
async def extract_words_from_text(self, text: str, level: str = "B1", max_words: int = 15) -> List[Dict]:
|
||||
"""
|
||||
Извлечь ключевые слова из текста для изучения
|
||||
|
||||
Args:
|
||||
text: Текст на английском языке
|
||||
level: Уровень пользователя (A1-C2)
|
||||
max_words: Максимальное количество слов для извлечения
|
||||
|
||||
Returns:
|
||||
Список словарей с информацией о словах
|
||||
"""
|
||||
prompt = f"""Проанализируй следующий английский текст и извлеки из него до {max_words} самых полезных слов для изучения на уровне {level}.
|
||||
|
||||
Текст:
|
||||
{text}
|
||||
|
||||
Верни ответ в формате JSON:
|
||||
{{
|
||||
"words": [
|
||||
{{
|
||||
"word": "английское слово (в базовой форме)",
|
||||
"translation": "перевод на русский",
|
||||
"transcription": "транскрипция в IPA",
|
||||
"context": "предложение из текста, где используется это слово"
|
||||
}}
|
||||
]
|
||||
}}
|
||||
|
||||
Критерии отбора слов:
|
||||
- Выбирай самые важные и полезные слова из текста
|
||||
- Слова должны быть интересны для уровня {level}
|
||||
- Не включай простейшие слова (a, the, is, и т.д.)
|
||||
- Слова должны быть в базовой форме (инфинитив для глаголов, ед.число для существительных)
|
||||
- Разнообразие: существительные, глаголы, прилагательные, устойчивые выражения"""
|
||||
|
||||
try:
|
||||
response = await self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "Ты - преподаватель английского языка. Помогаешь извлекать полезные слова для изучения из текстов."},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.5,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(response.choices[0].message.content)
|
||||
return result.get('words', [])
|
||||
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
async def start_conversation(self, scenario: str, level: str = "B1") -> Dict:
|
||||
"""
|
||||
Начать диалоговую практику с AI
|
||||
|
||||
Args:
|
||||
scenario: Сценарий диалога (restaurant, shopping, travel, etc.)
|
||||
level: Уровень пользователя (A1-C2)
|
||||
|
||||
Returns:
|
||||
Dict с начальной репликой и контекстом
|
||||
"""
|
||||
scenarios = {
|
||||
"restaurant": "ресторан - заказ еды",
|
||||
"shopping": "магазин - покупка одежды",
|
||||
"travel": "аэропорт/отель - путешествие",
|
||||
"work": "офис - рабочая встреча",
|
||||
"doctor": "клиника - визит к врачу",
|
||||
"casual": "повседневный разговор"
|
||||
}
|
||||
|
||||
scenario_desc = scenarios.get(scenario, "повседневный разговор")
|
||||
|
||||
prompt = f"""Ты - собеседник для практики английского языка уровня {level}.
|
||||
Начни диалог в сценарии: {scenario_desc}.
|
||||
|
||||
Верни ответ в формате JSON:
|
||||
{{
|
||||
"message": "твоя первая реплика на английском",
|
||||
"translation": "перевод на русский",
|
||||
"context": "краткое описание ситуации на русском",
|
||||
"suggestions": ["подсказка 1", "подсказка 2", "подсказка 3"]
|
||||
}}
|
||||
|
||||
Требования:
|
||||
- Говори естественно, используй уровень {level}
|
||||
- Создай интересную ситуацию
|
||||
- Задай вопрос или начни разговор
|
||||
- Подсказки должны помочь пользователю ответить"""
|
||||
|
||||
try:
|
||||
response = await self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "Ты - дружелюбный собеседник для практики английского. Веди естественный диалог."},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.8,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(response.choices[0].message.content)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"message": "Hello! How are you today?",
|
||||
"translation": "Привет! Как дела сегодня?",
|
||||
"context": "Повседневный разговор",
|
||||
"suggestions": ["I'm fine, thank you!", "Good, and you?", "Not bad!"]
|
||||
}
|
||||
|
||||
async def continue_conversation(
|
||||
self,
|
||||
conversation_history: List[Dict],
|
||||
user_message: str,
|
||||
scenario: str,
|
||||
level: str = "B1"
|
||||
) -> Dict:
|
||||
"""
|
||||
Продолжить диалог и проверить ответ пользователя
|
||||
|
||||
Args:
|
||||
conversation_history: История диалога
|
||||
user_message: Сообщение пользователя
|
||||
scenario: Сценарий диалога
|
||||
level: Уровень пользователя
|
||||
|
||||
Returns:
|
||||
Dict с ответом AI, проверкой и подсказками
|
||||
"""
|
||||
# Формируем историю для контекста
|
||||
history_text = "\n".join([
|
||||
f"{'AI' if msg['role'] == 'assistant' else 'User'}: {msg['content']}"
|
||||
for msg in conversation_history[-6:] # Последние 6 сообщений
|
||||
])
|
||||
|
||||
prompt = f"""Ты ведешь диалог на английском языке уровня {level} в сценарии "{scenario}".
|
||||
|
||||
История диалога:
|
||||
{history_text}
|
||||
User: {user_message}
|
||||
|
||||
Верни ответ в формате JSON:
|
||||
{{
|
||||
"response": "твой ответ на английском",
|
||||
"translation": "перевод твоего ответа на русский",
|
||||
"feedback": {{
|
||||
"has_errors": true/false,
|
||||
"corrections": "исправления ошибок пользователя (если есть)",
|
||||
"comment": "краткий комментарий об ответе пользователя"
|
||||
}},
|
||||
"suggestions": ["подсказка 1 для следующего ответа", "подсказка 2"]
|
||||
}}
|
||||
|
||||
Требования:
|
||||
- Продолжай естественный диалог
|
||||
- Если у пользователя есть грамматические или лексические ошибки, укажи их в corrections
|
||||
- Будь дружелюбным и поддерживающим
|
||||
- Используй лексику уровня {level}"""
|
||||
|
||||
try:
|
||||
# Формируем сообщения для API
|
||||
messages = [
|
||||
{"role": "system", "content": f"Ты - дружелюбный собеседник для практики английского языка уровня {level}. Веди естественный диалог и помогай исправлять ошибки."}
|
||||
]
|
||||
|
||||
# Добавляем историю
|
||||
for msg in conversation_history[-6:]:
|
||||
messages.append(msg)
|
||||
|
||||
# Добавляем текущее сообщение пользователя
|
||||
messages.append({"role": "user", "content": user_message})
|
||||
|
||||
# Добавляем инструкцию для форматирования ответа
|
||||
messages.append({"role": "user", "content": prompt})
|
||||
|
||||
response = await self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=messages,
|
||||
temperature=0.8,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(response.choices[0].message.content)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"response": "I see. Tell me more about that.",
|
||||
"translation": "Понятно. Расскажи мне больше об этом.",
|
||||
"feedback": {
|
||||
"has_errors": False,
|
||||
"corrections": "",
|
||||
"comment": "Good!"
|
||||
},
|
||||
"suggestions": ["Sure!", "Well...", "Actually..."]
|
||||
}
|
||||
|
||||
async def generate_level_test(self) -> List[Dict]:
|
||||
"""
|
||||
Сгенерировать тест для определения уровня английского
|
||||
|
||||
Returns:
|
||||
Список из 7 вопросов разной сложности
|
||||
"""
|
||||
prompt = """Создай тест из 7 вопросов для определения уровня английского языка (A1-C2).
|
||||
|
||||
Верни ответ в формате JSON:
|
||||
{
|
||||
"questions": [
|
||||
{
|
||||
"question": "текст вопроса на английском",
|
||||
"question_ru": "перевод вопроса на русский",
|
||||
"options": ["вариант A", "вариант B", "вариант C", "вариант D"],
|
||||
"correct": 0,
|
||||
"level": "A1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Требования:
|
||||
- Вопросы 1-2: уровень A1 (базовый)
|
||||
- Вопросы 3-4: уровень A2-B1 (элементарный-средний)
|
||||
- Вопросы 5-6: уровень B2-C1 (продвинутый)
|
||||
- Вопрос 7: уровень C2 (профессиональный)
|
||||
- Каждый вопрос с 4 вариантами ответа
|
||||
- correct - индекс правильного ответа (0-3)
|
||||
- Вопросы на грамматику, лексику и понимание"""
|
||||
|
||||
try:
|
||||
response = await self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "Ты - эксперт по тестированию уровня английского языка. Создавай объективные тесты."},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.7,
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
|
||||
import json
|
||||
result = json.loads(response.choices[0].message.content)
|
||||
return result.get('questions', [])
|
||||
|
||||
except Exception as e:
|
||||
# Fallback с базовыми вопросами
|
||||
return [
|
||||
{
|
||||
"question": "What is your name?",
|
||||
"question_ru": "Как тебя зовут?",
|
||||
"options": ["My name is", "I am name", "Name my is", "Is name my"],
|
||||
"correct": 0,
|
||||
"level": "A1"
|
||||
},
|
||||
{
|
||||
"question": "I ___ to school every day.",
|
||||
"question_ru": "Я ___ в школу каждый день.",
|
||||
"options": ["go", "goes", "going", "went"],
|
||||
"correct": 0,
|
||||
"level": "A1"
|
||||
},
|
||||
{
|
||||
"question": "She ___ been to Paris twice.",
|
||||
"question_ru": "Она ___ в Париже дважды.",
|
||||
"options": ["have", "has", "had", "having"],
|
||||
"correct": 1,
|
||||
"level": "A2"
|
||||
},
|
||||
{
|
||||
"question": "If I ___ rich, I would travel the world.",
|
||||
"question_ru": "Если бы я был богат, я бы путешествовал по миру.",
|
||||
"options": ["am", "was", "were", "be"],
|
||||
"correct": 2,
|
||||
"level": "B1"
|
||||
},
|
||||
{
|
||||
"question": "The project ___ by next Monday.",
|
||||
"question_ru": "Проект ___ к следующему понедельнику.",
|
||||
"options": ["will complete", "will be completed", "completes", "is completing"],
|
||||
"correct": 1,
|
||||
"level": "B2"
|
||||
},
|
||||
{
|
||||
"question": "Had I known about the meeting, I ___ attended.",
|
||||
"question_ru": "Если бы я знал о встрече, я бы посетил.",
|
||||
"options": ["would have", "will have", "would", "will"],
|
||||
"correct": 0,
|
||||
"level": "C1"
|
||||
},
|
||||
{
|
||||
"question": "The nuances of his argument were so ___ that few could grasp them.",
|
||||
"question_ru": "Нюансы его аргумента были настолько ___, что немногие могли их понять.",
|
||||
"options": ["subtle", "obvious", "simple", "clear"],
|
||||
"correct": 0,
|
||||
"level": "C2"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
# Глобальный экземпляр сервиса
|
||||
ai_service = AIService()
|
||||
|
||||
Reference in New Issue
Block a user