feat: batch-генерация слов дня, кнопка "Слово дня" в статистике
- Оптимизирована генерация слов дня: 2 запроса к AI вместо 11 - Добавлена кнопка "Слово дня" в /stats для быстрого доступа - Локализация для ru/en/ja 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ class WordOfDayService:
|
||||
"""
|
||||
Генерация слов дня для всех языков и уровней.
|
||||
Вызывается в 00:00 UTC.
|
||||
Использует batch-генерацию: 1 запрос на язык вместо 1 запроса на уровень.
|
||||
|
||||
Returns:
|
||||
Dict с количеством сгенерированных слов по языкам
|
||||
@@ -38,30 +39,44 @@ class WordOfDayService:
|
||||
for lang in LEARNING_LANGUAGES:
|
||||
levels = JLPT_LEVELS if lang in JLPT_LANGUAGES else CEFR_LEVELS
|
||||
|
||||
# Определяем какие уровни ещё не сгенерированы
|
||||
levels_to_generate = []
|
||||
for level in levels:
|
||||
try:
|
||||
# Проверяем, не сгенерировано ли уже
|
||||
existing = await self._get_word_for_date(
|
||||
session, today, lang, level
|
||||
)
|
||||
if existing:
|
||||
logger.debug(
|
||||
f"Слово дня уже существует: {lang}/{level}"
|
||||
)
|
||||
continue
|
||||
existing = await self._get_word_for_date(session, today, lang, level)
|
||||
if not existing:
|
||||
levels_to_generate.append(level)
|
||||
else:
|
||||
logger.debug(f"Слово дня уже существует: {lang}/{level}")
|
||||
|
||||
# Получаем список недавних слов для исключения
|
||||
excluded = await self._get_recent_words(session, lang, level, days=30)
|
||||
if not levels_to_generate:
|
||||
logger.info(f"Все слова для {lang} уже сгенерированы")
|
||||
continue
|
||||
|
||||
# Генерируем слово
|
||||
word_data = await ai_service.generate_word_of_day(
|
||||
level=level,
|
||||
learning_lang=lang,
|
||||
translation_lang="ru", # Базовый перевод на русский
|
||||
excluded_words=excluded
|
||||
)
|
||||
# Собираем исключения для каждого уровня
|
||||
excluded_words = {}
|
||||
for level in levels_to_generate:
|
||||
excluded_words[level] = await self._get_recent_words(
|
||||
session, lang, level, days=30
|
||||
)
|
||||
|
||||
if word_data:
|
||||
# Генерируем все слова одним запросом
|
||||
try:
|
||||
batch_result = await ai_service.generate_words_of_day_batch(
|
||||
language=lang,
|
||||
levels=levels_to_generate,
|
||||
translation_lang="ru",
|
||||
excluded_words=excluded_words
|
||||
)
|
||||
|
||||
if not batch_result:
|
||||
results["errors"] += len(levels_to_generate)
|
||||
logger.error(f"Не удалось сгенерировать слова для {lang}")
|
||||
continue
|
||||
|
||||
# Сохраняем каждое слово
|
||||
for level in levels_to_generate:
|
||||
word_data = batch_result.get(level)
|
||||
if word_data and word_data.get("word"):
|
||||
word_of_day = WordOfDay(
|
||||
word=word_data.get("word", ""),
|
||||
transcription=word_data.get("transcription"),
|
||||
@@ -74,7 +89,6 @@ class WordOfDayService:
|
||||
date=today
|
||||
)
|
||||
session.add(word_of_day)
|
||||
await session.commit()
|
||||
results[lang] += 1
|
||||
logger.info(
|
||||
f"Сгенерировано слово дня: {word_data.get('word')} "
|
||||
@@ -82,15 +96,13 @@ class WordOfDayService:
|
||||
)
|
||||
else:
|
||||
results["errors"] += 1
|
||||
logger.warning(
|
||||
f"Не удалось сгенерировать слово для {lang}/{level}"
|
||||
)
|
||||
logger.warning(f"Нет данных для {lang}/{level} в ответе AI")
|
||||
|
||||
except Exception as e:
|
||||
results["errors"] += 1
|
||||
logger.error(
|
||||
f"Ошибка генерации слова для {lang}/{level}: {e}"
|
||||
)
|
||||
await session.commit()
|
||||
|
||||
except Exception as e:
|
||||
results["errors"] += len(levels_to_generate)
|
||||
logger.error(f"Ошибка batch-генерации для {lang}: {e}")
|
||||
|
||||
total = results["en"] + results["ja"]
|
||||
logger.info(
|
||||
|
||||
Reference in New Issue
Block a user