diff --git a/aiws.py b/aiws.py index ee0cb86..fab7e92 100644 --- a/aiws.py +++ b/aiws.py @@ -133,7 +133,7 @@ async def start_scheduler(service: GenerationService): try: logger.info("Running scheduler for stacked generation killing") await service.cleanup_stale_generations() - await service.cleanup_old_data(days=2) + await service.cleanup_old_data(days=5) except asyncio.CancelledError: break except Exception as e: diff --git a/api/service/generation_service.py b/api/service/generation_service.py index fd675e0..81c8bd3 100644 --- a/api/service/generation_service.py +++ b/api/service/generation_service.py @@ -9,7 +9,6 @@ from uuid import uuid4 import httpx from aiogram import Bot from aiogram.types import BufferedInputFile -from fastapi import HTTPException from adapters.Exception import GoogleGenerationException from adapters.google_adapter import GoogleAdapter @@ -134,9 +133,6 @@ class GenerationService: gen_id = None generation_model = None - if generation_request.environment_id and not generation_request.linked_character_id: - raise HTTPException(status_code=400, detail="environment_id can only be used when linked_character_id is provided") - try: generation_model = Generation(**generation_request.model_dump(exclude={'count'})) if user_id: @@ -190,40 +186,45 @@ class GenerationService: logger.info(f"Processing generation {generation.id}. Character ID: {generation.linked_character_id}") # 2. Получаем ассеты-референсы (если они есть) + reference_assets: List[Asset] = [] media_group_bytes: List[bytes] = [] generation_prompt = generation.prompt - - # 2.1 Аватар персонажа (всегда первый, если включен) +# generation_prompt = f""" + +# Create detailed image of character in scene. + +# SCENE DESCRIPTION: {generation.prompt} + +# Rules: +# - Integrate the character's appearance naturally into the scene description. +# - Focus on lighting, texture, and composition. +# """ if generation.linked_character_id is not None: char_info = await self.dao.chars.get_character(generation.linked_character_id) if char_info is None: raise Exception(f"Character ID {generation.linked_character_id} not found") - - if generation.use_profile_image and char_info.avatar_asset_id: - avatar_asset = await self.dao.assets.get_asset(char_info.avatar_asset_id) - if avatar_asset: - img_data = await self._get_asset_data(avatar_asset) - if img_data: - media_group_bytes.append(img_data) + if generation.use_profile_image: + if char_info.avatar_asset_id is not None: + avatar_asset = await self.dao.assets.get_asset(char_info.avatar_asset_id) + if avatar_asset and avatar_asset.data: + media_group_bytes.append(avatar_asset.data) + # generation_prompt = generation_prompt.replace("$char_bio_inserted", f"1. CHARACTER BIO (Must be strictly followed): {char_info.character_bio}") - # 2.2 Явно указанные ассеты - if generation.assets_list: - explicit_assets = await self.dao.assets.get_assets_by_ids(generation.assets_list) - for asset in explicit_assets: - ref_asset_data = await self._get_asset_data(asset) - if ref_asset_data: - media_group_bytes.append(ref_asset_data) - - # 2.3 Ассеты из окружения (в самый конец) - if generation.environment_id: - env = await self.dao.environments.get_env(generation.environment_id) - if env and env.asset_ids: - logger.info(f"Loading {len(env.asset_ids)} assets from environment {env.name} ({env.id})") - env_assets = await self.dao.assets.get_assets_by_ids(env.asset_ids) - for asset in env_assets: - img_data = await self._get_asset_data(asset) - if img_data: - media_group_bytes.append(img_data) + reference_assets = await self.dao.assets.get_assets_by_ids(generation.assets_list) + + # Извлекаем данные (bytes) из ассетов для отправки в Gemini + for asset in reference_assets: + if asset.content_type != AssetContentType.IMAGE: + continue + + img_data = None + if asset.minio_object_name: + img_data = await self.s3_adapter.get_file(asset.minio_object_name) + elif asset.data: + img_data = asset.data + + if img_data: + media_group_bytes.append(img_data) if media_group_bytes: generation_prompt += " \n\n[Reference Image Guidance]: Use the provided image(s) as the STRICT reference for the main character's facial features and hair, enviroment or clothes. Maintain high fidelity to the reference identity." @@ -340,14 +341,6 @@ class GenerationService: logger.error(f"Failed to send assets to Telegram ID {generation.telegram_id}: {e}") - async def _get_asset_data(self, asset: Asset) -> Optional[bytes]: - if asset.content_type != AssetContentType.IMAGE: - return None - - if asset.minio_object_name: - return await self.s3_adapter.get_file(asset.minio_object_name) - return asset.data - async def _simulate_progress(self, generation: Generation): """ Increments progress from 0 to 90 over ~20 seconds. @@ -493,7 +486,7 @@ class GenerationService: except Exception as e: logger.error(f"Error cleaning up stale generations: {e}") - async def cleanup_old_data(self, days: int = 2): + async def cleanup_old_data(self, days: int = 30): """ Очистка старых данных: 1. Мягко удаляет генерации старше N дней