message.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. # -*- coding:utf-8 -*-
  2. import json
  3. import logging
  4. from typing import Generator, Union
  5. import services
  6. from controllers.console import api
  7. from controllers.console.app.error import (AppMoreLikeThisDisabledError, CompletionRequestError,
  8. ProviderModelCurrentlyNotSupportError, ProviderNotInitializeError,
  9. ProviderQuotaExceededError)
  10. from controllers.console.explore.error import (AppSuggestedQuestionsAfterAnswerDisabledError, NotChatAppError,
  11. NotCompletionAppError)
  12. from controllers.console.explore.wraps import InstalledAppResource
  13. from core.entities.application_entities import InvokeFrom
  14. from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
  15. from core.model_runtime.errors.invoke import InvokeError
  16. from fields.message_fields import message_infinite_scroll_pagination_fields
  17. from flask import Response, stream_with_context
  18. from flask_login import current_user
  19. from flask_restful import fields, marshal_with, reqparse
  20. from flask_restful.inputs import int_range
  21. from libs.helper import TimestampField, uuid_value
  22. from services.completion_service import CompletionService
  23. from services.errors.app import MoreLikeThisDisabledError
  24. from services.errors.conversation import ConversationNotExistsError
  25. from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError
  26. from services.message_service import MessageService
  27. from werkzeug.exceptions import InternalServerError, NotFound
  28. class MessageListApi(InstalledAppResource):
  29. @marshal_with(message_infinite_scroll_pagination_fields)
  30. def get(self, installed_app):
  31. app_model = installed_app.app
  32. if app_model.mode != 'chat':
  33. raise NotChatAppError()
  34. parser = reqparse.RequestParser()
  35. parser.add_argument('conversation_id', required=True, type=uuid_value, location='args')
  36. parser.add_argument('first_id', type=uuid_value, location='args')
  37. parser.add_argument('limit', type=int_range(1, 100), required=False, default=20, location='args')
  38. args = parser.parse_args()
  39. try:
  40. return MessageService.pagination_by_first_id(app_model, current_user,
  41. args['conversation_id'], args['first_id'], args['limit'])
  42. except services.errors.conversation.ConversationNotExistsError:
  43. raise NotFound("Conversation Not Exists.")
  44. except services.errors.message.FirstMessageNotExistsError:
  45. raise NotFound("First Message Not Exists.")
  46. class MessageFeedbackApi(InstalledAppResource):
  47. def post(self, installed_app, message_id):
  48. app_model = installed_app.app
  49. message_id = str(message_id)
  50. parser = reqparse.RequestParser()
  51. parser.add_argument('rating', type=str, choices=['like', 'dislike', None], location='json')
  52. args = parser.parse_args()
  53. try:
  54. MessageService.create_feedback(app_model, message_id, current_user, args['rating'])
  55. except services.errors.message.MessageNotExistsError:
  56. raise NotFound("Message Not Exists.")
  57. return {'result': 'success'}
  58. class MessageMoreLikeThisApi(InstalledAppResource):
  59. def get(self, installed_app, message_id):
  60. app_model = installed_app.app
  61. if app_model.mode != 'completion':
  62. raise NotCompletionAppError()
  63. message_id = str(message_id)
  64. parser = reqparse.RequestParser()
  65. parser.add_argument('response_mode', type=str, required=True, choices=['blocking', 'streaming'], location='args')
  66. args = parser.parse_args()
  67. streaming = args['response_mode'] == 'streaming'
  68. try:
  69. response = CompletionService.generate_more_like_this(
  70. app_model=app_model,
  71. user=current_user,
  72. message_id=message_id,
  73. invoke_from=InvokeFrom.EXPLORE,
  74. streaming=streaming
  75. )
  76. return compact_response(response)
  77. except MessageNotExistsError:
  78. raise NotFound("Message Not Exists.")
  79. except MoreLikeThisDisabledError:
  80. raise AppMoreLikeThisDisabledError()
  81. except ProviderTokenNotInitError as ex:
  82. raise ProviderNotInitializeError(ex.description)
  83. except QuotaExceededError:
  84. raise ProviderQuotaExceededError()
  85. except ModelCurrentlyNotSupportError:
  86. raise ProviderModelCurrentlyNotSupportError()
  87. except InvokeError as e:
  88. raise CompletionRequestError(e.description)
  89. except ValueError as e:
  90. raise e
  91. except Exception:
  92. logging.exception("internal server error.")
  93. raise InternalServerError()
  94. def compact_response(response: Union[dict, Generator]) -> Response:
  95. if isinstance(response, dict):
  96. return Response(response=json.dumps(response), status=200, mimetype='application/json')
  97. else:
  98. def generate() -> Generator:
  99. for chunk in response:
  100. yield chunk
  101. return Response(stream_with_context(generate()), status=200,
  102. mimetype='text/event-stream')
  103. class MessageSuggestedQuestionApi(InstalledAppResource):
  104. def get(self, installed_app, message_id):
  105. app_model = installed_app.app
  106. if app_model.mode != 'chat':
  107. raise NotCompletionAppError()
  108. message_id = str(message_id)
  109. try:
  110. questions = MessageService.get_suggested_questions_after_answer(
  111. app_model=app_model,
  112. user=current_user,
  113. message_id=message_id
  114. )
  115. except MessageNotExistsError:
  116. raise NotFound("Message not found")
  117. except ConversationNotExistsError:
  118. raise NotFound("Conversation not found")
  119. except SuggestedQuestionsAfterAnswerDisabledError:
  120. raise AppSuggestedQuestionsAfterAnswerDisabledError()
  121. except ProviderTokenNotInitError as ex:
  122. raise ProviderNotInitializeError(ex.description)
  123. except QuotaExceededError:
  124. raise ProviderQuotaExceededError()
  125. except ModelCurrentlyNotSupportError:
  126. raise ProviderModelCurrentlyNotSupportError()
  127. except InvokeError as e:
  128. raise CompletionRequestError(e.description)
  129. except Exception:
  130. logging.exception("internal server error.")
  131. raise InternalServerError()
  132. return {'data': questions}
  133. api.add_resource(MessageListApi, '/installed-apps/<uuid:installed_app_id>/messages', endpoint='installed_app_messages')
  134. api.add_resource(MessageFeedbackApi, '/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/feedbacks', endpoint='installed_app_message_feedback')
  135. api.add_resource(MessageMoreLikeThisApi, '/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/more-like-this', endpoint='installed_app_more_like_this')
  136. api.add_resource(MessageSuggestedQuestionApi, '/installed-apps/<uuid:installed_app_id>/messages/<uuid:message_id>/suggested-questions', endpoint='installed_app_suggested_question')