controller.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # -*- coding: utf-8 -*-
  2. from fastapi import APIRouter, Depends, Path, Body, WebSocket
  3. from fastapi.responses import JSONResponse, StreamingResponse
  4. from app.common.response import StreamResponse, SuccessResponse
  5. from app.common.request import PaginationService
  6. from app.core.base_params import PaginationQueryParam
  7. from app.core.dependencies import AuthPermission
  8. from app.core.logger import log
  9. from app.api.v1.module_system.auth.schema import AuthSchema
  10. from app.core.router_class import OperationLogRoute
  11. from .service import McpService
  12. from .schema import McpCreateSchema, McpUpdateSchema, ChatQuerySchema, McpQueryParam
  13. import json
  14. import asyncio
  15. AIRouter = APIRouter(route_class=OperationLogRoute, prefix="/ai", tags=["MCP智能助手"])
  16. @AIRouter.post("/chat", summary="智能对话", description="与MCP智能助手进行对话")
  17. async def chat_controller(
  18. query: ChatQuerySchema,
  19. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:chat"]))
  20. ) -> StreamingResponse:
  21. """
  22. 智能对话接口
  23. 参数:
  24. - query (ChatQuerySchema): 聊天查询模型
  25. 返回:
  26. - StreamingResponse: 流式响应,每次返回一个聊天响应
  27. """
  28. user_name = auth.user.name if auth.user else "未知用户"
  29. log.info(f"用户 {user_name} 发起智能对话: {query.message[:50]}...")
  30. async def generate_response():
  31. try:
  32. async for chunk in McpService.chat_query(query=query):
  33. # 确保返回的是字节串
  34. if chunk:
  35. yield chunk.encode('utf-8') if isinstance(chunk, str) else chunk
  36. except Exception as e:
  37. log.error(f"流式响应出错: {str(e)}")
  38. yield f"抱歉,处理您的请求时出现了错误: {str(e)}".encode('utf-8')
  39. return StreamResponse(generate_response(), media_type="text/plain; charset=utf-8")
  40. @AIRouter.get("/detail/{id}", summary="获取 MCP 服务器详情", description="获取 MCP 服务器详情")
  41. async def detail_controller(
  42. id: int = Path(..., description="MCP ID"),
  43. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:query"]))
  44. ) -> JSONResponse:
  45. """
  46. 获取 MCP 服务器详情接口
  47. 参数:
  48. - id (int): MCP 服务器ID
  49. 返回:
  50. - JSONResponse: 包含 MCP 服务器详情的 JSON 响应
  51. """
  52. result_dict = await McpService.detail_service(auth=auth, id=id)
  53. log.info(f"获取 MCP 服务器详情成功 {id}")
  54. return SuccessResponse(data=result_dict, msg="获取 MCP 服务器详情成功")
  55. @AIRouter.get("/list", summary="查询 MCP 服务器列表", description="查询 MCP 服务器列表")
  56. async def list_controller(
  57. page: PaginationQueryParam = Depends(),
  58. search: McpQueryParam = Depends(),
  59. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:query"]))
  60. ) -> JSONResponse:
  61. """
  62. 查询 MCP 服务器列表接口
  63. 参数:
  64. - page (PaginationQueryParam): 分页查询参数模型
  65. - search (McpQueryParam): 查询参数模型
  66. - auth (AuthSchema): 认证信息模型
  67. 返回:
  68. - JSONResponse: 包含 MCP 服务器列表的 JSON 响应
  69. """
  70. result_dict_list = await McpService.list_service(auth=auth, search=search, order_by=page.order_by)
  71. result_dict = await PaginationService.paginate(data_list=result_dict_list, page_no=page.page_no, page_size=page.page_size)
  72. log.info(f"查询 MCP 服务器列表成功")
  73. return SuccessResponse(data=result_dict, msg="查询 MCP 服务器列表成功")
  74. @AIRouter.post("/create", summary="创建 MCP 服务器", description="创建 MCP 服务器")
  75. async def create_controller(
  76. data: McpCreateSchema,
  77. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:create"]))
  78. ) -> JSONResponse:
  79. """
  80. 创建 MCP 服务器接口
  81. 参数:
  82. - data (McpCreateSchema): 创建 MCP 服务器模型
  83. - auth (AuthSchema): 认证信息模型
  84. 返回:
  85. - JSONResponse: 包含创建 MCP 服务器结果的 JSON 响应
  86. """
  87. result_dict = await McpService.create_service(auth=auth, data=data)
  88. log.info(f"创建 MCP 服务器成功: {result_dict}")
  89. return SuccessResponse(data=result_dict, msg="创建 MCP 服务器成功")
  90. @AIRouter.put("/update/{id}", summary="修改 MCP 服务器", description="修改 MCP 服务器")
  91. async def update_controller(
  92. data: McpUpdateSchema,
  93. id: int = Path(..., description="MCP ID"),
  94. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:update"]))
  95. ) -> JSONResponse:
  96. """
  97. 修改 MCP 服务器接口
  98. 参数:
  99. - data (McpUpdateSchema): 修改 MCP 服务器模型
  100. - id (int): MCP 服务器ID
  101. - auth (AuthSchema): 认证信息模型
  102. 返回:
  103. - JSONResponse: 包含修改 MCP 服务器结果的 JSON 响应
  104. """
  105. result_dict = await McpService.update_service(auth=auth, id=id, data=data)
  106. log.info(f"修改 MCP 服务器成功: {result_dict}")
  107. return SuccessResponse(data=result_dict, msg="修改 MCP 服务器成功")
  108. @AIRouter.delete("/delete", summary="删除 MCP 服务器", description="删除 MCP 服务器")
  109. async def delete_controller(
  110. ids: list[int] = Body(..., description="ID列表"),
  111. auth: AuthSchema = Depends(AuthPermission(["module_application:ai:delete"]))
  112. ) -> JSONResponse:
  113. """
  114. 删除 MCP 服务器接口
  115. 参数:
  116. - ids (list[int]): MCP 服务器ID列表
  117. - auth (AuthSchema): 认证信息模型
  118. 返回:
  119. - JSONResponse: 包含删除 MCP 服务器结果的 JSON 响应
  120. """
  121. await McpService.delete_service(auth=auth, ids=ids)
  122. log.info(f"删除 MCP 服务器成功: {ids}")
  123. return SuccessResponse(msg="删除 MCP 服务器成功")
  124. @AIRouter.websocket("/ws/chat", name="WebSocket聊天")
  125. async def websocket_chat_controller(
  126. websocket: WebSocket,
  127. ):
  128. await websocket.accept()
  129. try:
  130. while True:
  131. data = await websocket.receive_text()
  132. # 流式发送响应
  133. try:
  134. async for chunk in McpService.chat_query(query=ChatQuerySchema(message=data)):
  135. if chunk:
  136. await websocket.send_text(chunk)
  137. except Exception as e:
  138. log.error(f"处理聊天查询出错: {str(e)}")
  139. await websocket.send_text(f"抱歉,处理您的请求时出现了错误: {str(e)}")
  140. except Exception as e:
  141. log.error(f"WebSocket聊天出错: {str(e)}")
  142. finally:
  143. await websocket.close()