Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

conversation.py 8.9KB

2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
2 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. from flask_restx import fields, marshal_with, reqparse
  2. from flask_restx.inputs import int_range
  3. from sqlalchemy.orm import Session
  4. from werkzeug.exceptions import NotFound
  5. from controllers.web import web_ns
  6. from controllers.web.error import NotChatAppError
  7. from controllers.web.wraps import WebApiResource
  8. from core.app.entities.app_invoke_entities import InvokeFrom
  9. from extensions.ext_database import db
  10. from fields.conversation_fields import conversation_infinite_scroll_pagination_fields, simple_conversation_fields
  11. from libs.helper import uuid_value
  12. from models.model import AppMode
  13. from services.conversation_service import ConversationService
  14. from services.errors.conversation import ConversationNotExistsError, LastConversationNotExistsError
  15. from services.web_conversation_service import WebConversationService
  16. @web_ns.route("/conversations")
  17. class ConversationListApi(WebApiResource):
  18. @web_ns.doc("Get Conversation List")
  19. @web_ns.doc(description="Retrieve paginated list of conversations for a chat application.")
  20. @web_ns.doc(
  21. params={
  22. "last_id": {"description": "Last conversation ID for pagination", "type": "string", "required": False},
  23. "limit": {
  24. "description": "Number of conversations to return (1-100)",
  25. "type": "integer",
  26. "required": False,
  27. "default": 20,
  28. },
  29. "pinned": {
  30. "description": "Filter by pinned status",
  31. "type": "string",
  32. "enum": ["true", "false"],
  33. "required": False,
  34. },
  35. "sort_by": {
  36. "description": "Sort order",
  37. "type": "string",
  38. "enum": ["created_at", "-created_at", "updated_at", "-updated_at"],
  39. "required": False,
  40. "default": "-updated_at",
  41. },
  42. }
  43. )
  44. @web_ns.doc(
  45. responses={
  46. 200: "Success",
  47. 400: "Bad Request",
  48. 401: "Unauthorized",
  49. 403: "Forbidden",
  50. 404: "App Not Found or Not a Chat App",
  51. 500: "Internal Server Error",
  52. }
  53. )
  54. @marshal_with(conversation_infinite_scroll_pagination_fields)
  55. def get(self, app_model, end_user):
  56. app_mode = AppMode.value_of(app_model.mode)
  57. if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
  58. raise NotChatAppError()
  59. parser = reqparse.RequestParser()
  60. parser.add_argument("last_id", type=uuid_value, location="args")
  61. parser.add_argument("limit", type=int_range(1, 100), required=False, default=20, location="args")
  62. parser.add_argument("pinned", type=str, choices=["true", "false", None], location="args")
  63. parser.add_argument(
  64. "sort_by",
  65. type=str,
  66. choices=["created_at", "-created_at", "updated_at", "-updated_at"],
  67. required=False,
  68. default="-updated_at",
  69. location="args",
  70. )
  71. args = parser.parse_args()
  72. pinned = None
  73. if "pinned" in args and args["pinned"] is not None:
  74. pinned = args["pinned"] == "true"
  75. try:
  76. with Session(db.engine) as session:
  77. return WebConversationService.pagination_by_last_id(
  78. session=session,
  79. app_model=app_model,
  80. user=end_user,
  81. last_id=args["last_id"],
  82. limit=args["limit"],
  83. invoke_from=InvokeFrom.WEB_APP,
  84. pinned=pinned,
  85. sort_by=args["sort_by"],
  86. )
  87. except LastConversationNotExistsError:
  88. raise NotFound("Last Conversation Not Exists.")
  89. @web_ns.route("/conversations/<uuid:c_id>")
  90. class ConversationApi(WebApiResource):
  91. delete_response_fields = {
  92. "result": fields.String,
  93. }
  94. @web_ns.doc("Delete Conversation")
  95. @web_ns.doc(description="Delete a specific conversation.")
  96. @web_ns.doc(params={"c_id": {"description": "Conversation UUID", "type": "string", "required": True}})
  97. @web_ns.doc(
  98. responses={
  99. 204: "Conversation deleted successfully",
  100. 400: "Bad Request",
  101. 401: "Unauthorized",
  102. 403: "Forbidden",
  103. 404: "Conversation Not Found or Not a Chat App",
  104. 500: "Internal Server Error",
  105. }
  106. )
  107. @marshal_with(delete_response_fields)
  108. def delete(self, app_model, end_user, c_id):
  109. app_mode = AppMode.value_of(app_model.mode)
  110. if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
  111. raise NotChatAppError()
  112. conversation_id = str(c_id)
  113. try:
  114. ConversationService.delete(app_model, conversation_id, end_user)
  115. except ConversationNotExistsError:
  116. raise NotFound("Conversation Not Exists.")
  117. return {"result": "success"}, 204
  118. @web_ns.route("/conversations/<uuid:c_id>/name")
  119. class ConversationRenameApi(WebApiResource):
  120. @web_ns.doc("Rename Conversation")
  121. @web_ns.doc(description="Rename a specific conversation with a custom name or auto-generate one.")
  122. @web_ns.doc(params={"c_id": {"description": "Conversation UUID", "type": "string", "required": True}})
  123. @web_ns.doc(
  124. params={
  125. "name": {"description": "New conversation name", "type": "string", "required": False},
  126. "auto_generate": {
  127. "description": "Auto-generate conversation name",
  128. "type": "boolean",
  129. "required": False,
  130. "default": False,
  131. },
  132. }
  133. )
  134. @web_ns.doc(
  135. responses={
  136. 200: "Conversation renamed successfully",
  137. 400: "Bad Request",
  138. 401: "Unauthorized",
  139. 403: "Forbidden",
  140. 404: "Conversation Not Found or Not a Chat App",
  141. 500: "Internal Server Error",
  142. }
  143. )
  144. @marshal_with(simple_conversation_fields)
  145. def post(self, app_model, end_user, c_id):
  146. app_mode = AppMode.value_of(app_model.mode)
  147. if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
  148. raise NotChatAppError()
  149. conversation_id = str(c_id)
  150. parser = reqparse.RequestParser()
  151. parser.add_argument("name", type=str, required=False, location="json")
  152. parser.add_argument("auto_generate", type=bool, required=False, default=False, location="json")
  153. args = parser.parse_args()
  154. try:
  155. return ConversationService.rename(app_model, conversation_id, end_user, args["name"], args["auto_generate"])
  156. except ConversationNotExistsError:
  157. raise NotFound("Conversation Not Exists.")
  158. @web_ns.route("/conversations/<uuid:c_id>/pin")
  159. class ConversationPinApi(WebApiResource):
  160. pin_response_fields = {
  161. "result": fields.String,
  162. }
  163. @web_ns.doc("Pin Conversation")
  164. @web_ns.doc(description="Pin a specific conversation to keep it at the top of the list.")
  165. @web_ns.doc(params={"c_id": {"description": "Conversation UUID", "type": "string", "required": True}})
  166. @web_ns.doc(
  167. responses={
  168. 200: "Conversation pinned successfully",
  169. 400: "Bad Request",
  170. 401: "Unauthorized",
  171. 403: "Forbidden",
  172. 404: "Conversation Not Found or Not a Chat App",
  173. 500: "Internal Server Error",
  174. }
  175. )
  176. @marshal_with(pin_response_fields)
  177. def patch(self, app_model, end_user, c_id):
  178. app_mode = AppMode.value_of(app_model.mode)
  179. if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
  180. raise NotChatAppError()
  181. conversation_id = str(c_id)
  182. try:
  183. WebConversationService.pin(app_model, conversation_id, end_user)
  184. except ConversationNotExistsError:
  185. raise NotFound("Conversation Not Exists.")
  186. return {"result": "success"}
  187. @web_ns.route("/conversations/<uuid:c_id>/unpin")
  188. class ConversationUnPinApi(WebApiResource):
  189. unpin_response_fields = {
  190. "result": fields.String,
  191. }
  192. @web_ns.doc("Unpin Conversation")
  193. @web_ns.doc(description="Unpin a specific conversation to remove it from the top of the list.")
  194. @web_ns.doc(params={"c_id": {"description": "Conversation UUID", "type": "string", "required": True}})
  195. @web_ns.doc(
  196. responses={
  197. 200: "Conversation unpinned successfully",
  198. 400: "Bad Request",
  199. 401: "Unauthorized",
  200. 403: "Forbidden",
  201. 404: "Conversation Not Found or Not a Chat App",
  202. 500: "Internal Server Error",
  203. }
  204. )
  205. @marshal_with(unpin_response_fields)
  206. def patch(self, app_model, end_user, c_id):
  207. app_mode = AppMode.value_of(app_model.mode)
  208. if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}:
  209. raise NotChatAppError()
  210. conversation_id = str(c_id)
  211. WebConversationService.unpin(app_model, conversation_id, end_user)
  212. return {"result": "success"}