This commit is contained in:
xds
2026-02-06 19:53:05 +03:00
parent 553335940f
commit 137279bcc5
8 changed files with 29 additions and 14 deletions

View File

@@ -15,6 +15,7 @@ from models.Asset import Asset, AssetType
from models.Generation import Generation, GenerationStatus
from models.enums import AspectRatios, Quality, GenType
from repos.dao import DAO
from adapters.s3_adapter import S3Adapter
logger = logging.getLogger(__name__)
@@ -25,7 +26,8 @@ async def generate_image_task(
media_group_bytes: List[bytes],
aspect_ratio: AspectRatios,
quality: Quality,
gemini: GoogleAdapter
gemini: GoogleAdapter,
) -> Tuple[List[bytes], Dict[str, Any]]:
"""
Обертка для вызова синхронного метода Gemini в отдельном потоке.
@@ -60,9 +62,10 @@ async def generate_image_task(
return images_bytes, metrics
class GenerationService:
def __init__(self, dao: DAO, gemini: GoogleAdapter, bot: Optional[Bot] = None):
def __init__(self, dao: DAO, gemini: GoogleAdapter, s3_adapter: S3Adapter, bot: Optional[Bot] = None):
self.dao = dao
self.gemini = gemini
self.s3_adapter = s3_adapter
self.bot = bot
@@ -169,13 +172,21 @@ class GenerationService:
generation_prompt = generation_prompt.replace("$char_bio_inserted", f"1. CHARACTER BIO (Must be strictly followed): {char_info.character_bio}")
reference_assets = await self.dao.assets.get_assets_by_ids(generation.assets_list)
# Извлекаем данные (bytes) из ассетов для отправки в Gemini
# Фильтруем, чтобы отправлять только картинки, и где есть data
media_group_bytes.extend(
asset.data
for asset in reference_assets
if asset.data is not None and asset.type == AssetType.IMAGE
)
for asset in reference_assets:
if asset.type != AssetType.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."
@@ -230,18 +241,21 @@ class GenerationService:
for idx, img_bytes in enumerate(generated_bytes_list):
# Generate thumbnail
thumbnail_bytes = None
# Assuming AssetType.IMAGE since we are in generated_bytes_list which are images usually
# Or use explicit check if we have distinct types in list (not currently)
from utils.image_utils import create_thumbnail
thumbnail_bytes = await asyncio.to_thread(create_thumbnail, img_bytes)
# Save to S3
filename = f"generated/{generation.linked_character_id}/{datetime.now().strftime('%Y%m%d_%H%M%S')}_{random.randint(1000, 9999)}.png"
await self.s3_adapter.upload_file(filename, img_bytes, content_type="image/png")
new_asset = Asset(
name=f"Generated_{generation.linked_character_id}_{random.randint(1000, 9999)}",
name=f"Generated_{generation.linked_character_id}",
type=AssetType.IMAGE,
linked_char_id=generation.linked_character_id, # Если генерация привязана к персонажу
data=img_bytes,
linked_char_id=generation.linked_character_id,
data=None, # Not storing bytes in DB anymore
minio_object_name=filename,
minio_bucket=self.s3_adapter.bucket_name,
thumbnail=thumbnail_bytes
# Остальные поля заполнятся дефолтными значениями (created_at)
)
# Сохраняем в БД