feat: персональные AI модели, оптимизация задач, фильтрация словаря

- Добавлена поддержка персональных AI моделей для каждого пользователя
- Оптимизация создания заданий: батч-запрос к AI вместо N запросов
- Фильтрация слов по языку изучения (source_lang) в словаре
- Удалены неиспользуемые колонки examples и category из vocabulary
- Миграции для ai_model_id и удаления колонок

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-08 16:43:08 +03:00
parent 6138af4e63
commit 16a7df0343
13 changed files with 507 additions and 142 deletions

View File

@@ -158,22 +158,16 @@ async def add_single_word(callback: CallbackQuery, state: FSMContext):
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
# Проверяем, нет ли уже такого слова
existing = await VocabularyService.get_word_by_original(
session, user_id, word_data['word']
session, user_id, word_data['word'], source_lang=user.learning_language
)
if existing:
async with async_session_maker() as session:
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
lang = (user.language_interface if user else 'ru') or 'ru'
lang = get_user_lang(user)
await callback.answer(t(lang, 'words.already_exists', word=word_data['word']), show_alert=True)
return
# Добавляем слово
# Формируем examples с учётом языков
learn = user.learning_language if user else 'en'
translation_lang = get_user_translation_lang(user)
ex = word_data.get('example')
examples = ([{learn: ex, translation_lang: ''}] if ex else [])
await VocabularyService.add_word(
session=session,
@@ -183,10 +177,8 @@ async def add_single_word(callback: CallbackQuery, state: FSMContext):
source_lang=user.learning_language if user else None,
translation_lang=translation_lang,
transcription=word_data.get('transcription'),
examples=examples,
source=WordSource.SUGGESTED,
category=data.get('theme', 'general'),
difficulty_level=data.get('level')
difficulty_level=data.get('level'),
source=WordSource.SUGGESTED
)
async with async_session_maker() as session:
@@ -203,7 +195,6 @@ async def add_all_words(callback: CallbackQuery, state: FSMContext):
data = await state.get_data()
words = data.get('words', [])
user_id = data.get('user_id')
theme = data.get('theme', 'general')
added_count = 0
skipped_count = 0
@@ -213,7 +204,7 @@ async def add_all_words(callback: CallbackQuery, state: FSMContext):
for word_data in words:
# Проверяем, нет ли уже такого слова
existing = await VocabularyService.get_word_by_original(
session, user_id, word_data['word']
session, user_id, word_data['word'], source_lang=user.learning_language
)
if existing:
@@ -221,10 +212,7 @@ async def add_all_words(callback: CallbackQuery, state: FSMContext):
continue
# Добавляем слово
learn = user.learning_language if user else 'en'
translation_lang = get_user_translation_lang(user)
ex = word_data.get('example')
examples = ([{learn: ex, translation_lang: ''}] if ex else [])
await VocabularyService.add_word(
session=session,
@@ -234,10 +222,8 @@ async def add_all_words(callback: CallbackQuery, state: FSMContext):
source_lang=user.learning_language if user else None,
translation_lang=translation_lang,
transcription=word_data.get('transcription'),
examples=examples,
source=WordSource.SUGGESTED,
category=theme,
difficulty_level=data.get('level')
difficulty_level=data.get('level'),
source=WordSource.SUGGESTED
)
added_count += 1