@@ -676,6 +676,10 @@ msgstr "" "Формат вложенного файла не поддерживается. Доступные форматы: " "%(available_extensions)s." +#: ml_model/exceptions.py:60 +msgid "The file may be corrupted. Please try another one." +msgstr "Возможно, файл повреждён. Попробуйте загрузить другой файл." + #: ml_model/exceptions.py:58 msgid "The length of the context has been exceeded." msgstr "Длина контекста превышена." @@ -9,7 +9,7 @@ from django.core.files import File from replicate.exceptions import ModelError from messages.models import Message -from ml_model.exceptions import ModelTimeoutError, ImageContentNotFound +from ml_model.exceptions import ModelTimeoutError, ImageContentNotFound, RequestBlocked, GenerationException from ml_model.services.base import SimpleService from ml_model.tasks import replicate_run @@ -57,6 +57,12 @@ class Geminiimage(SimpleService): msgs = self.save_results(input_message.content, process_time, images, save) return msgs except ModelError as exc: - if exc.prediction.error == 'No image content found in response': + if exc.prediction.error in ( + 'No image content found in response', + 'Failed to generate image.', + ): raise ImageContentNotFound + elif any(error in str(exc) for error in ('E005', 'E006', 'sexual')): + raise RequestBlocked + raise GenerationException from exc raise ModelTimeoutError @@ -9,6 +9,7 @@ import filetype from PIL import Image from messages.models import Message +from ml_model.exceptions import FileExtensionNotSupported, CorruptedFileError from ml_model.services.EmbeddingService import EmbeddingService from ml_model.services.FileService import FileProcessingService from ml_model.services.base import SimpleService @@ -59,6 +60,8 @@ class Grok_4_1_Fast(SimpleService): file_service = FileProcessingService file_bytes = input_message.file.read() kind = filetype.guess(file_bytes[:20]) + if not kind: + raise CorruptedFileError raw_file_extension = kind.extension file_extension = file_service.get_file_extension(raw_file_extension, file_bytes) if file_extension in ('pdf', 'doc', 'docx', 'xlsx'): @@ -98,7 +101,7 @@ class Grok_4_1_Fast(SimpleService): f'Используй системный промпт. Содержание файла: ' f'{chunks}. Вопрос: {input_message.content}' ) - else: + elif file_extension in ('jpg', 'jpeg', 'png', 'webp'): kind = filetype.guess(file_bytes[:20]) mime = kind.mime if kind else 'application/octet-stream' normalized_image = Image.open(input_message.file) @@ -111,6 +114,8 @@ class Grok_4_1_Fast(SimpleService): {'type': 'text', 'text': input_message.content}, {'type': 'image_url', 'image_url': {'url': image_url}}, ] + else: + raise FileExtensionNotSupported(['PDF', 'DOC', 'DOCX', 'XLSX', 'JPG', 'JPEG', 'PNG', 'WEBP']) start_time = time.time() result = openrouter_run('x-ai/grok-4.1-fast', messages, callback_data, 'Grok 4.1 Fast') process_time = timedelta(seconds=(time.time() - start_time)) @@ -13,7 +13,12 @@ from django.core.files import File from replicate.exceptions import ModelError from messages.models import Message -from ml_model.exceptions import ImageContentNotFound, GenerationException, RequestBlocked +from ml_model.exceptions import ( + ImageContentNotFound, + GenerationException, + RequestBlocked, + FileTooLargeError, +) from ml_model.services.base import SimpleService from ml_model.tasks import replicate_run from payments.exceptions.insufficient_balance import InsufficientBalance @@ -51,6 +56,8 @@ class Photon(SimpleService): } ) if input_message.file: + if input_message.file.size >= (10 << 10 << 10): + raise FileTooLargeError(10) kind = filetype.guess(input_message.file.read(20)) mime = kind.mime if kind else 'application/octet-stream' input_message.file.seek(0) @@ -53,6 +53,19 @@ class FileExtensionNotSupported(Exception): ) % {'available_extensions': ', '.join(self.extensions)} +class CorruptedFileError(Exception): + def __str__(self) -> str: + return _('The file may be corrupted. Please try another one.') + + +class FileTooLargeError(Exception): + def __init__(self, max_mb_size: int) -> None: + self.max_mb_size = max_mb_size + + def __str__(self) -> str: + return _('The file size cannot exceed %(max_mb_size)d MB') % {'max_mb_size': self.max_mb_size} + + class ExceededContextLengthError(Exception): def __str__(self) -> str: return _('The length of the context has been exceeded.') @@ -27,6 +27,8 @@ from ml_model.exceptions import ( TemplateUnknownException, RequestBlocked, PromptLengthExceeded, + CorruptedFileError, + FileTooLargeError, ) from ml_model.services.base import SimpleService from payments.exceptions.insufficient_balance import InsufficientBalance @@ -169,6 +171,8 @@ class MessagesAPIView(APIView): ExceededContextLengthError, RequestBlocked, PromptLengthExceeded, + CorruptedFileError, + FileTooLargeError, ) as exc: return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST) except TemplateNotFound as exc: @@ -20,6 +20,8 @@ from ml_model.exceptions import ( PromptLengthExceeded, FileExtensionNotSupported, ServiceHighDemandError, + CorruptedFileError, + FileTooLargeError, ) from ml_model.models import NeuronModel from ml_model.services.base import SimpleService @@ -185,6 +187,8 @@ class MediaAPIView(APIView): PromptLengthExceeded, FileExtensionNotSupported, ServiceHighDemandError, + CorruptedFileError, + FileTooLargeError, ), ): return Response({'detail': f'{exc}'}, status=HTTP_400_BAD_REQUEST)