@@ -643,6 +643,10 @@ msgstr "" msgid "Service is currently unavailable due to high demand. Please try again later" msgstr "Сервис временно недоступен из-за высокой нагрузки. Пожалуйста, попробуйте позже" +#: ml_model/exceptions.py:135 +msgid "Image analysis error. Please try another image." +msgstr "Ошибка анализа изображения. Попробуйте другую картинку." + #: ml_model/exceptions.py:23 msgid "Your request was blocked by our moderation system" msgstr "Ваш запрос был заблокирован нашей системой модерации" @@ -2,17 +2,13 @@ import base64 import time from datetime import timedelta from decimal import Decimal -from io import BytesIO import filetype -from PIL import Image from messages.models import Message -from ml_model.services.EmbeddingService import EmbeddingService -from ml_model.services.FileService import FileProcessingService +from ml_model.exceptions import CorruptedFileError, FileExtensionNotSupported from ml_model.services.base import SimpleService from ml_model.tasks import openrouter_run -from poller.models import Proxy from tools.chats.models import Chat from tools.copywrite.models import Copywrite from tools.public_api.models import APIStore @@ -52,8 +48,12 @@ class Gemma(SimpleService): messages.append({'role': 'user', 'content': input_message.content}) if input_message.file: kind = filetype.guess(input_message.file.read(20)) + if not kind: + raise CorruptedFileError mime = kind.mime if kind else 'application/octet-stream' input_message.file.seek(0) + if kind.extension.upper() not in (available_extensions := ('JPG', 'JPEG', 'PNG', 'WEBP')): + raise FileExtensionNotSupported(available_extensions) image_url = f'data:{mime};base64,{base64.b64encode(input_message.file.read()).decode("utf-8")}' input_message.file.close() messages[-1]['content'] = [ @@ -6,7 +6,12 @@ from io import BytesIO from typing import Any from replicate.exceptions import ModelError -from ml_model.exceptions import RequestBlocked, GenerationException +from ml_model.exceptions import ( + RequestBlocked, + GenerationException, + ExceededContextLengthError, + ImageAnalysisError, +) import filetype import requests @@ -71,6 +76,10 @@ class Reve(SimpleService): except ModelError as exc: if any(error in str(exc) for error in ('E005', 'E006', 'sexual')): raise RequestBlocked + if 'INPUT_ANALYSIS_FAILURE' in str(exc): + raise ImageAnalysisError + if 'PROMPT_TOO_LONG' in str(exc): + raise ExceededContextLengthError raise GenerationException from exc process_time = timedelta(seconds=(time.time() - start_time)) self.handle_invoice(input_message.content_object.model, type=type) @@ -10,6 +10,7 @@ import requests from django.core.files import File from messages.models import Message +from ml_model.exceptions import FileExtensionNotSupported, CorruptedFileError from ml_model.services.base import SimpleService from ml_model.tasks import replicate_run @@ -51,9 +52,13 @@ class Wan_Lite(SimpleService): } ) if input_message.file: - kind = filetype.guess(input_message.file.read(20)) + kind = filetype.guess(input_message.file.read(50)) + if not kind: + raise CorruptedFileError mime = kind.mime if kind else 'application/octet-stream' input_message.file.seek(0) + if kind.extension.upper() not in (available_extensions := ('JPG', 'JPEG', 'PNG', 'WEBP')): + raise FileExtensionNotSupported(available_extensions) image = f'data:{mime};base64,{base64.b64encode(input_message.file.read()).decode("utf-8")}' input_message.file.close() callback_data.update({'image': image}) @@ -1,3 +1,5 @@ +from typing import Iterable + from django.utils.translation import gettext as _ # накинуть перевод через gettext_lazy @@ -44,12 +46,12 @@ class ModelTimeoutError(Exception): class FileExtensionNotSupported(Exception): - def __init__(self, extensions: list[str]) -> None: + def __init__(self, extensions: Iterable[str]) -> None: self.extensions = extensions def __str__(self) -> str: return _( - f'The attached file format is not supported. Available formats: %(available_extensions)s.' + 'The attached file format is not supported. Available formats: %(available_extensions)s.' ) % {'available_extensions': ', '.join(self.extensions)} @@ -99,6 +101,11 @@ class ImageContentNotFound(Exception): return _('No image content found in response. Try a different request') +class ImageAnalysisError(Exception): + def __str__(self): + return _('Image analysis error. Please try another image.') + + class InvalidStyleCombinationError(Exception): def __str__(self) -> str: return _('Use style type AUTO or GENERAL when a style preset is selected') @@ -29,6 +29,7 @@ from ml_model.exceptions import ( PromptLengthExceeded, CorruptedFileError, FileTooLargeError, + ImageAnalysisError, ) from ml_model.services.base import SimpleService from payments.exceptions.insufficient_balance import InsufficientBalance @@ -173,6 +174,7 @@ class MessagesAPIView(APIView): PromptLengthExceeded, CorruptedFileError, FileTooLargeError, + ImageAnalysisError, ) as exc: return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST) except TemplateNotFound as exc: @@ -18,10 +18,12 @@ from ml_model.exceptions import ( InvalidParameterError, InvalidStyleCombinationError, PromptLengthExceeded, + ExceededContextLengthError, FileExtensionNotSupported, ServiceHighDemandError, CorruptedFileError, FileTooLargeError, + ImageAnalysisError, ) from ml_model.models import NeuronModel from ml_model.services.base import SimpleService @@ -185,10 +187,12 @@ class MediaAPIView(APIView): InvalidStyleCombinationError, InvalidParameterError, PromptLengthExceeded, + ExceededContextLengthError, FileExtensionNotSupported, ServiceHighDemandError, CorruptedFileError, FileTooLargeError, + ImageAnalysisError, ), ): return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST)