Underground-Digital/Workflow-Engine
0
1import logging2 3from flask_restful import fields, marshal_with, reqparse4from flask_restful.inputs import int_range5from werkzeug.exceptions import InternalServerError, NotFound6 7import services8from controllers.web import api9from controllers.web.error import (10 AppMoreLikeThisDisabledError,11 AppSuggestedQuestionsAfterAnswerDisabledError,12 CompletionRequestError,13 NotChatAppError,14 NotCompletionAppError,15 ProviderModelCurrentlyNotSupportError,16 ProviderNotInitializeError,17 ProviderQuotaExceededError,18)19from controllers.web.wraps import WebApiResource20from core.app.entities.app_invoke_entities import InvokeFrom21from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError22from core.model_runtime.errors.invoke import InvokeError23from fields.conversation_fields import message_file_fields24from fields.message_fields import agent_thought_fields25from fields.raws import FilesContainedField26from libs import helper27from libs.helper import TimestampField, uuid_value28from models.model import AppMode29from services.app_generate_service import AppGenerateService30from services.errors.app import MoreLikeThisDisabledError31from services.errors.conversation import ConversationNotExistsError32from services.errors.message import MessageNotExistsError, SuggestedQuestionsAfterAnswerDisabledError33from services.message_service import MessageService34 35 36class MessageListApi(WebApiResource):37 feedback_fields = {"rating": fields.String}38 39 retriever_resource_fields = {40 "id": fields.String,41 "message_id": fields.String,42 "position": fields.Integer,43 "dataset_id": fields.String,44 "dataset_name": fields.String,45 "document_id": fields.String,46 "document_name": fields.String,47 "data_source_type": fields.String,48 "segment_id": fields.String,49 "score": fields.Float,50 "hit_count": fields.Integer,51 "word_count": fields.Integer,52 "segment_position": fields.Integer,53 "index_node_hash": fields.String,54 "content": fields.String,55 "created_at": TimestampField,56 }57 58 message_fields = {59 "id": fields.String,60 "conversation_id": fields.String,61 "parent_message_id": fields.String,62 "inputs": FilesContainedField,63 "query": fields.String,64 "answer": fields.String(attribute="re_sign_file_url_answer"),65 "message_files": fields.List(fields.Nested(message_file_fields)),66 "feedback": fields.Nested(feedback_fields, attribute="user_feedback", allow_null=True),67 "retriever_resources": fields.List(fields.Nested(retriever_resource_fields)),68 "created_at": TimestampField,69 "agent_thoughts": fields.List(fields.Nested(agent_thought_fields)),70 "status": fields.String,71 "error": fields.String,72 }73 74 message_infinite_scroll_pagination_fields = {75 "limit": fields.Integer,76 "has_more": fields.Boolean,77 "data": fields.List(fields.Nested(message_fields)),78 }79 80 @marshal_with(message_infinite_scroll_pagination_fields)81 def get(self, app_model, end_user):82 app_mode = AppMode.value_of(app_model.mode)83 if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:84 raise NotChatAppError()85 86 parser = reqparse.RequestParser()87 parser.add_argument("conversation_id", required=True, type=uuid_value, location="args")88 parser.add_argument("first_id", type=uuid_value, location="args")89 parser.add_argument("limit", type=int_range(1, 100), required=False, default=20, location="args")90 args = parser.parse_args()91 92 try:93 return MessageService.pagination_by_first_id(94 app_model, end_user, args["conversation_id"], args["first_id"], args["limit"], "desc"95 )96 except services.errors.conversation.ConversationNotExistsError:97 raise NotFound("Conversation Not Exists.")98 except services.errors.message.FirstMessageNotExistsError:99 raise NotFound("First Message Not Exists.")100 101 102class MessageFeedbackApi(WebApiResource):103 def post(self, app_model, end_user, message_id):104 message_id = str(message_id)105 106 parser = reqparse.RequestParser()107 parser.add_argument("rating", type=str, choices=["like", "dislike", None], location="json")108 args = parser.parse_args()109 110 try:111 MessageService.create_feedback(app_model, message_id, end_user, args["rating"])112 except services.errors.message.MessageNotExistsError:113 raise NotFound("Message Not Exists.")114 115 return {"result": "success"}116 117 118class MessageMoreLikeThisApi(WebApiResource):119 def get(self, app_model, end_user, message_id):120 if app_model.mode != "completion":121 raise NotCompletionAppError()122 123 message_id = str(message_id)124 125 parser = reqparse.RequestParser()126 parser.add_argument(127 "response_mode", type=str, required=True, choices=["blocking", "streaming"], location="args"128 )129 args = parser.parse_args()130 131 streaming = args["response_mode"] == "streaming"132 133 try:134 response = AppGenerateService.generate_more_like_this(135 app_model=app_model,136 user=end_user,137 message_id=message_id,138 invoke_from=InvokeFrom.WEB_APP,139 streaming=streaming,140 )141 142 return helper.compact_generate_response(response)143 except MessageNotExistsError:144 raise NotFound("Message Not Exists.")145 except MoreLikeThisDisabledError:146 raise AppMoreLikeThisDisabledError()147 except ProviderTokenNotInitError as ex:148 raise ProviderNotInitializeError(ex.description)149 except QuotaExceededError:150 raise ProviderQuotaExceededError()151 except ModelCurrentlyNotSupportError:152 raise ProviderModelCurrentlyNotSupportError()153 except InvokeError as e:154 raise CompletionRequestError(e.description)155 except ValueError as e:156 raise e157 except Exception:158 logging.exception("internal server error.")159 raise InternalServerError()160 161 162class MessageSuggestedQuestionApi(WebApiResource):163 def get(self, app_model, end_user, message_id):164 app_mode = AppMode.value_of(app_model.mode)165 if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:166 raise NotCompletionAppError()167 168 message_id = str(message_id)169 170 try:171 questions = MessageService.get_suggested_questions_after_answer(172 app_model=app_model, user=end_user, message_id=message_id, invoke_from=InvokeFrom.WEB_APP173 )174 except MessageNotExistsError:175 raise NotFound("Message not found")176 except ConversationNotExistsError:177 raise NotFound("Conversation not found")178 except SuggestedQuestionsAfterAnswerDisabledError:179 raise AppSuggestedQuestionsAfterAnswerDisabledError()180 except ProviderTokenNotInitError as ex:181 raise ProviderNotInitializeError(ex.description)182 except QuotaExceededError:183 raise ProviderQuotaExceededError()184 except ModelCurrentlyNotSupportError:185 raise ProviderModelCurrentlyNotSupportError()186 except InvokeError as e:187 raise CompletionRequestError(e.description)188 except Exception:189 logging.exception("internal server error.")190 raise InternalServerError()191 192 return {"data": questions}193 194 195api.add_resource(MessageListApi, "/messages")196api.add_resource(MessageFeedbackApi, "/messages/<uuid:message_id>/feedbacks")197api.add_resource(MessageMoreLikeThisApi, "/messages/<uuid:message_id>/more-like-this")198api.add_resource(MessageSuggestedQuestionApi, "/messages/<uuid:message_id>/suggested-questions")199 