From 06dd4d6e000f0464b1dcc0a8402e42a0b19b8f84 Mon Sep 17 00:00:00 2001 From: Guangdong Liu Date: Thu, 28 Aug 2025 09:21:42 +0800 Subject: [PATCH] feat: migrate part of the web chat module to Flask-RESTX (#24664) --- api/controllers/web/audio.py | 40 ++++++++++++++++++++++++++-- api/controllers/web/conversation.py | 17 +++++++++++- api/controllers/web/message.py | 10 +++++++ api/controllers/web/saved_message.py | 10 +++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/api/controllers/web/audio.py b/api/controllers/web/audio.py index 7b7dabcc1..2c0f6c975 100644 --- a/api/controllers/web/audio.py +++ b/api/controllers/web/audio.py @@ -1,6 +1,7 @@ import logging from flask import request +from flask_restx import fields, marshal_with, reqparse from werkzeug.exceptions import InternalServerError import services @@ -32,7 +33,26 @@ logger = logging.getLogger(__name__) class AudioApi(WebApiResource): + audio_to_text_response_fields = { + "text": fields.String, + } + + @marshal_with(audio_to_text_response_fields) + @api.doc("Audio to Text") + @api.doc(description="Convert audio file to text using speech-to-text service.") + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 413: "Audio file too large", + 415: "Unsupported audio type", + 500: "Internal Server Error", + } + ) def post(self, app_model: App, end_user): + """Convert audio to text""" file = request.files["file"] try: @@ -66,9 +86,25 @@ class AudioApi(WebApiResource): class TextApi(WebApiResource): - def post(self, app_model: App, end_user): - from flask_restx import reqparse + text_to_audio_response_fields = { + "audio_url": fields.String, + "duration": fields.Float, + } + @marshal_with(text_to_audio_response_fields) + @api.doc("Text to Audio") + @api.doc(description="Convert text to audio using text-to-speech service.") + @api.doc( + responses={ + 200: "Success", + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 500: "Internal Server Error", + } + ) + def post(self, app_model: App, end_user): + """Convert text to audio""" try: parser = reqparse.RequestParser() parser.add_argument("message_id", type=str, required=False, location="json") diff --git a/api/controllers/web/conversation.py b/api/controllers/web/conversation.py index cea8e442f..ea4138826 100644 --- a/api/controllers/web/conversation.py +++ b/api/controllers/web/conversation.py @@ -1,4 +1,4 @@ -from flask_restx import marshal_with, reqparse +from flask_restx import fields, marshal_with, reqparse from flask_restx.inputs import int_range from sqlalchemy.orm import Session from werkzeug.exceptions import NotFound @@ -58,6 +58,11 @@ class ConversationListApi(WebApiResource): class ConversationApi(WebApiResource): + delete_response_fields = { + "result": fields.String, + } + + @marshal_with(delete_response_fields) def delete(self, app_model, end_user, c_id): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: @@ -94,6 +99,11 @@ class ConversationRenameApi(WebApiResource): class ConversationPinApi(WebApiResource): + pin_response_fields = { + "result": fields.String, + } + + @marshal_with(pin_response_fields) def patch(self, app_model, end_user, c_id): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: @@ -110,6 +120,11 @@ class ConversationPinApi(WebApiResource): class ConversationUnPinApi(WebApiResource): + unpin_response_fields = { + "result": fields.String, + } + + @marshal_with(unpin_response_fields) def patch(self, app_model, end_user, c_id): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: diff --git a/api/controllers/web/message.py b/api/controllers/web/message.py index a6856b7e0..17e06e885 100644 --- a/api/controllers/web/message.py +++ b/api/controllers/web/message.py @@ -85,6 +85,11 @@ class MessageListApi(WebApiResource): class MessageFeedbackApi(WebApiResource): + feedback_response_fields = { + "result": fields.String, + } + + @marshal_with(feedback_response_fields) def post(self, app_model, end_user, message_id): message_id = str(message_id) @@ -152,6 +157,11 @@ class MessageMoreLikeThisApi(WebApiResource): class MessageSuggestedQuestionApi(WebApiResource): + suggested_questions_response_fields = { + "data": fields.List(fields.String), + } + + @marshal_with(suggested_questions_response_fields) def get(self, app_model, end_user, message_id): app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: diff --git a/api/controllers/web/saved_message.py b/api/controllers/web/saved_message.py index a0912499f..7a9d24114 100644 --- a/api/controllers/web/saved_message.py +++ b/api/controllers/web/saved_message.py @@ -30,6 +30,10 @@ class SavedMessageListApi(WebApiResource): "data": fields.List(fields.Nested(message_fields)), } + post_response_fields = { + "result": fields.String, + } + @marshal_with(saved_message_infinite_scroll_pagination_fields) def get(self, app_model, end_user): if app_model.mode != "completion": @@ -42,6 +46,7 @@ class SavedMessageListApi(WebApiResource): return SavedMessageService.pagination_by_last_id(app_model, end_user, args["last_id"], args["limit"]) + @marshal_with(post_response_fields) def post(self, app_model, end_user): if app_model.mode != "completion": raise NotCompletionAppError() @@ -59,6 +64,11 @@ class SavedMessageListApi(WebApiResource): class SavedMessageApi(WebApiResource): + delete_response_fields = { + "result": fields.String, + } + + @marshal_with(delete_response_fields) def delete(self, app_model, end_user, message_id): message_id = str(message_id)