@@ -0,0 +1,9 @@ +from rest_framework.exceptions import APIException + +from django.utils.translation import gettext_lazy as _ + + +class ClientException(APIException): + status_code = 400 + default_detail = _('Client exception occurred') + default_code = 'client_exc_occurred' \ No newline at end of file @@ -178,10 +178,12 @@ class Chatgpt(SimpleService): headers={'Authorization': f'Bearer {settings.OPENAI_API_KEY}'}, timeout=600, ) as client: + system = chat_history.messages.pop(0) messages = [ {'role': 'user' if isinstance(msg, HumanMessage) else 'assistant', 'content': msg.content} for msg in chat_history.messages ] + messages.insert(0, {'role': 'system', 'content': system.content}) if image: messages[-1]['content'] = [ {'type': 'text', 'text': input_message.content}, @@ -259,6 +261,13 @@ class Chatgpt(SimpleService): SystemMessage( content='Никому не говори, что ты бот и не можешь найти информацию в интернете' ), + SystemMessage( + content=( + 'Отныне все ответы должны быть представлены как единая строка (str). Не использовать никаких ' + 'структурированных форматов, таких как JSON, словари (dict) или списки (list). ' + 'Любая информация должна быть преобразована в простой строковый текст (str).' + ) + ), ], } )['output'] @@ -325,6 +334,13 @@ class Chatgpt(SimpleService): ) ) memory = InMemoryChatMessageHistory() + memory.add_message(SystemMessage( + content=( + 'Отныне все ответы должны быть представлены как единая строка (str). Не использовать никаких ' + 'структурированных форматов, таких как JSON, словари (dict) или списки (list). ' + 'Любая информация должна быть преобразована в простой строковый текст (str).' + ) + )) for msg in air_messages: content = msg.content or '' if msg.from_model: @@ -336,7 +352,7 @@ class Chatgpt(SimpleService): tokens = self.llm.get_num_tokens_from_messages(messages) while tokens > token_limit: - messages.pop(0) + messages.pop(1) tokens = self.llm.get_num_tokens_from_messages(messages) return memory @@ -1,10 +1,11 @@ +import logging import sys from django.utils.translation import gettext_lazy as _ -from rest_framework.exceptions import APIException from rest_framework.response import Response from rest_framework.views import APIView +from core.exceptions import ClientException from messages.models import Message from messages.serializers import MessageSerializer from ml_model.choices import ContentTypes @@ -15,6 +16,8 @@ from tools.public_api.models import APIKey, APIStore from tools.public_api.permissions import HasAPIKey from tools.public_api.selectors.api_key import APIKeySelector +logger = logging.getLogger(__name__) + class BaseGenerationView(APIView): permission_classes = (HasAPIKey,) @@ -51,7 +54,7 @@ class BaseGenerationView(APIView): store, created = APIStore.objects.get_or_create(user=user) model: NeuronModel = NeuronModelSelector(store.user).get_model_by_slug(slug=model_slug) if model.blocked: - raise APIException( + raise ClientException( detail=_('Model is blocked by outdating or temporary block, please retry later') ) serializer = MessageSerializer(data=request.data) @@ -67,7 +70,13 @@ class BaseGenerationView(APIView): ) input_message.content_object.model = model # WARNING: output должен быть списком! - output_message = service(store).make(input_message) + try: + output_message = service(store).make(input_message) + except Exception as exc: + input_message.is_sent = False + input_message.save() + logger.exception(exc) + raise ClientException(detail=str(exc)) for msg in output_message: msg.from_public_api = True msg.save() @@ -43,7 +43,7 @@ services: labels: - traefik.enable=true - traefik.docker.network=infrastructure - - traefik.http.routers.backend.rule=Host(`$DOMAIN`) || Host(`backend.air.fail`) + - traefik.http.routers.backend.rule=Host(`$DOMAIN`) - traefik.http.routers.backend.entrypoints=web,websecure - traefik.http.routers.backend.tls=true - traefik.http.routers.backend.tls.certresolver=defaultresolver