diff --git a/myproject/products/services/ai/bouquet_names.py b/myproject/products/services/ai/bouquet_names.py index 2857380..02e5dd5 100644 --- a/myproject/products/services/ai/bouquet_names.py +++ b/myproject/products/services/ai/bouquet_names.py @@ -19,6 +19,12 @@ class BouquetNameGenerator(BaseAIProductService): "Избегайте общих терминов. Фокусируйтесь на эмоциях, эстетике" ) + # Константы + MAX_TOKENS_GENERATION = 3000 + DEFAULT_COUNT = 500 + MAX_GENERATION_COUNT = 1000 + SKIP_PREFIXES = {'here', 'names', "i'm", 'sorry', 'i hope', 'hope'} + def generate( self, count: int = 500, @@ -38,17 +44,17 @@ class BouquetNameGenerator(BaseAIProductService): Returns: Tuple: (success, message, data) где data содержит список названий """ + # Валидация параметров + if count > self.MAX_GENERATION_COUNT: + count = self.MAX_GENERATION_COUNT + logger.warning(f"Count reduced to {self.MAX_GENERATION_COUNT}") + logger.info(f"Генерация {count} названий для букетов") # Получаем доступный AI-сервис - glm_service = self.get_glm_service() - if not glm_service: - openrouter_service = self.get_openrouter_service() - if not openrouter_service: - return False, "Нет активных AI-интеграций", None - service = openrouter_service - else: - service = glm_service + service = self.get_glm_service() or self.get_openrouter_service() + if not service: + return False, "Нет активных AI-интеграций", None # Формируем промпт prompt = f"Сгенерируй {count} креативных и привлекательных названий для букетов цветов" @@ -98,9 +104,7 @@ class BouquetNameGenerator(BaseAIProductService): for line in lines: line = line.strip() # Пропускаем пустые строки и заголовки - if not line or line.lower().startswith('here') or line.lower().startswith('names') or \ - line.lower().startswith('i\'m') or line.lower().startswith('sorry') or \ - line.lower().startswith('i hope') or line.lower().startswith('hope'): + if not line or any(line.lower().startswith(prefix) for prefix in self.SKIP_PREFIXES): continue # Удаляем номера списка @@ -119,7 +123,9 @@ class BouquetNameGenerator(BaseAIProductService): line = line.replace('**', '').replace('*', '').replace('"', '').replace("'", '').strip() if line: - names.append(line) + # Приводим к нужному формату: первое слово с заглавной, остальные строчные + normalized_line = self._normalize_case(line) + names.append(normalized_line) # Удаляем дубликаты unique_names = [] @@ -131,6 +137,28 @@ class BouquetNameGenerator(BaseAIProductService): return unique_names + def _normalize_case(self, text: str) -> str: + """ + Приводит текст к формату: первое слово с заглавной буквы, остальные строчные + Например: "романтический БУКЕТ роз" -> "Романтический букет роз" + Но сохраняет имена собственные: "Букет Van Gogh" -> "Букет Van Gogh" + """ + if not text: + return text + + # Разбиваем текст на слова + words = text.split() + + if not words: + return text + + # Первое слово с заглавной буквы, остальные как есть (сохраняем имена собственные) + first_word = words[0].capitalize() + remaining_words = words[1:] + + # Собираем обратно в строку + return ' '.join([first_word] + remaining_words) + def generate_and_store( self, count: int = 500, @@ -142,23 +170,33 @@ class BouquetNameGenerator(BaseAIProductService): Генерирует названия и сохраняет в базу данных """ from products.models import BouquetName - + success, msg, data = self.generate(count, characteristics, occasion, language) if success and data: # Сохраняем названия в базу stored_count = 0 - for name in data['names']: - BouquetName.objects.get_or_create( - name=name, - language=language, - defaults={ - 'is_approved': False - } - ) - stored_count += 1 + failed_count = 0 - return True, f"Сгенерировано и сохранено {stored_count} названий для букетов", data + for name in data['names']: + try: + BouquetName.objects.get_or_create( + name=name, + language=language, + defaults={ + 'is_approved': False + } + ) + stored_count += 1 + except Exception as e: + logger.error(f"Ошибка сохранения названия '{name}': {e}") + failed_count += 1 + + success_msg = f"Сгенерировано и сохранено {stored_count} названий для букетов" + if failed_count > 0: + success_msg += f", не удалось сохранить {failed_count} названий" + + return True, success_msg, data return success, msg, data