files.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import io
  2. from typing import Optional, List
  3. import requests
  4. from fastapi import Depends, APIRouter, HTTPException, UploadFile, File, Query, Form
  5. from pydantic import BaseModel
  6. from sqlalchemy.orm import Session
  7. from starlette.responses import StreamingResponse
  8. from werkzeug.utils import send_file
  9. from app.api import Response, get_current_user, ResponseList
  10. from app.config.config import settings
  11. from app.config.const import DOCUMENT_TO_REPORT, IMAGE_TO_TEXT, DOCUMENT_TO_REPORT_TITLE, DOCUMENT_IA_QUESTIONS, \
  12. DOCUMENT_TO_PAPER
  13. from app.models import MenuCapacityModel
  14. from app.models.agent_model import AgentType, AgentModel
  15. from app.models.base_model import get_db
  16. from app.models.user_model import UserModel
  17. from app.service.basic import BasicService
  18. from app.service.bisheng import BishengService
  19. from app.service.v2.api_token import DfTokenDao
  20. from app.service.difyService import DifyService
  21. from app.service.ragflow import RagflowService
  22. from app.service.service_token import get_ragflow_token, get_bisheng_token
  23. import urllib.parse
  24. router = APIRouter()
  25. @router.post("/upload/{agent_id}", response_model=Response)
  26. async def upload_files(
  27. agent_id: str,
  28. file: List[UploadFile] = File(...), # 修改这里,接受文件列表
  29. chat_id: str = Query(None, description="The ID of the chat"),
  30. db: Session = Depends(get_db),
  31. current_user: UserModel = Depends(get_current_user)
  32. ):
  33. agent = db.query(MenuCapacityModel).filter(MenuCapacityModel.chat_id == agent_id).first()
  34. if not agent:
  35. return ResponseList(code=404, msg="Agent not found")
  36. agent_type = int(agent.capacity_type)
  37. # 检查 agent 类型,确定是否允许上传多个文件
  38. if agent_type in [AgentType.RAGFLOW, AgentType.BISHENG]:
  39. if len(file) > 1:
  40. return Response(code=400, msg="这个智能体只支持传单个文件")
  41. if agent_type == AgentType.RAGFLOW or agent_type == AgentType.BISHENG:
  42. file = file[0]
  43. # 读取上传的文件内容
  44. try:
  45. file_content = await file.read()
  46. except Exception as e:
  47. return Response(code=400, msg=str(e))
  48. if agent_type == AgentType.RAGFLOW:
  49. token = await get_ragflow_token(db, current_user.id)
  50. ragflow_service = RagflowService(base_url=settings.fwr_base_url)
  51. # 查询会话是否存在,不存在先创建会话
  52. history = await ragflow_service.get_session_history(token, chat_id)
  53. if len(history) == 0:
  54. message = {"role": "user", "message": file.filename}
  55. await ragflow_service.set_session(token, agent_id, message, chat_id, True)
  56. doc_ids = await ragflow_service.upload_and_parse(token, chat_id, file.filename, file_content)
  57. # 对于多文件,可能需要收集所有doc_ids
  58. return Response(code=200, msg="", data={"doc_ids": doc_ids, "file_name": file.filename})
  59. elif agent_type == AgentType.BISHENG:
  60. bisheng_service = BishengService(base_url=settings.sgb_base_url)
  61. try:
  62. token = await get_bisheng_token(db, current_user.id)
  63. result = await bisheng_service.upload(token, file.filename, file_content)
  64. except Exception as e:
  65. raise HTTPException(status_code=500, detail=str(e))
  66. result["file_name"] = file.filename
  67. return Response(code=200, msg="", data=result)
  68. elif agent_type == AgentType.BASIC:
  69. if agent_id == "basic_excel_talk":
  70. # 处理单个文件的情况
  71. file_list = file
  72. if len(file) == 1: # and agent.agent_type != AgentType.BASIC
  73. file_list = [file[0]] # 如果只有一个文件,确保它是一个列表
  74. service = BasicService(base_url=settings.basic_base_url)
  75. # 遍历file_list,存到files 列表中
  76. files = []
  77. for item in file_list:
  78. file_content = await item.read()
  79. files.append(('files', (item.filename, file_content, 'application/octet-stream')))
  80. result = await service.excel_talk_upload(chat_id, files)
  81. if not result:
  82. return Response(code=400, msg="上传文件出错")
  83. return Response(code=200, msg="", data=result)
  84. elif agent_id == "basic_paper_agent":
  85. ...
  86. # service = BasicService(base_url=settings.basic_paper_url)
  87. # result = await service.paper_file_upload(chat_id, file.filename, file_content)
  88. elif agent_type == AgentType.DIFY:
  89. dify_service = DifyService(base_url=settings.dify_base_url)
  90. if agent.chat_type == "imageTalk":
  91. token = DfTokenDao(db).get_token_by_id(IMAGE_TO_TEXT)
  92. if not token:
  93. raise HTTPException(status_code=500, detail="获取token失败,image_and_text_conversion!")
  94. file = file[0]
  95. # 读取上传的文件内容
  96. try:
  97. file_content = await file.read()
  98. except Exception as e:
  99. return Response(code=400, msg=str(e))
  100. try:
  101. data = await dify_service.upload(token, file.filename, file_content, current_user.id)
  102. except Exception as e:
  103. raise HTTPException(status_code=500, detail=str(e))
  104. elif agent.chat_type == "reportWorkflow" or agent.chat_type == "documentIa" or agent.chat_type == "paperTalk":
  105. token_dict = {
  106. "reportWorkflow": DOCUMENT_TO_REPORT_TITLE,
  107. "documentIa": DOCUMENT_IA_QUESTIONS,
  108. "paperTalk": DOCUMENT_TO_PAPER,
  109. }
  110. token = DfTokenDao(db).get_token_by_id(token_dict[agent.chat_type])
  111. if not token:
  112. raise HTTPException(status_code=500, detail="获取token失败,document_to_report!")
  113. result = []
  114. for f in file:
  115. try:
  116. file_content = await f.read()
  117. except Exception as e:
  118. return Response(code=400, msg=str(e))
  119. try:
  120. file_upload = await dify_service.upload(token, f.filename, file_content, current_user.id)
  121. result.append(file_upload)
  122. except Exception as e:
  123. raise HTTPException(status_code=500, detail=str(e))
  124. # result["file_name"] = file.filename
  125. data = {"files": result}
  126. return Response(code=200, msg="", data=data)
  127. @router.get("/download/", response_model=Response)
  128. async def download_file(
  129. url: Optional[str] = Query(None, description="URL of the file to download for bisheng"),
  130. agent_id: str = Query(..., description="Agent ID"),
  131. doc_id: Optional[str] = Query(None, description="Optional doc id for ragflow agents"),
  132. doc_name: Optional[str] = Query(None, description="Optional doc name for ragflow agents"),
  133. file_id: Optional[str] = Query(None, description="Optional file id for basic agents"),
  134. file_type: Optional[str] = Query(None, description="Optional file type for basic agents"),
  135. db: Session = Depends(get_db)
  136. ):
  137. # agent = db.query(AgentModel).filter(AgentModel.id == agent_id).first()
  138. agent = db.query(MenuCapacityModel).filter(MenuCapacityModel.chat_id == agent_id).first()
  139. if not agent:
  140. return Response(code=404, msg="Agent not found")
  141. agent_type = int(agent.capacity_type)
  142. if agent_type == AgentType.BISHENG:
  143. url = urllib.parse.unquote(url)
  144. # 从 URL 中提取文件名
  145. parsed_url = urllib.parse.urlparse(url)
  146. filename = urllib.parse.unquote(parsed_url.path.split('/')[-1])
  147. url = url.replace("http://minio:9000", settings.sgb_base_url)
  148. elif agent_type == AgentType.RAGFLOW:
  149. if not doc_id:
  150. return Response(code=400, msg="doc_id is required")
  151. url = f"{settings.fwr_base_url}/v1/document/get/{doc_id}"
  152. filename = doc_name
  153. elif agent_type == AgentType.BASIC:
  154. if agent_id == "basic_excel_talk":
  155. return await download_basic_file(file_id, file_type)
  156. elif agent_id == "basic_question_talk":
  157. return await download_basic_file(file_id, file_type)
  158. else:
  159. return Response(code=400, msg="Unsupported agent type")
  160. try:
  161. # 发送GET请求获取文件内容
  162. response = requests.get(url, stream=True)
  163. response.raise_for_status() # 检查请求是否成功
  164. # 返回流式响应
  165. return StreamingResponse(
  166. response.iter_content(chunk_size=1024),
  167. media_type="application/octet-stream",
  168. headers={"Content-Disposition": f"attachment; filename*=utf-8''{urllib.parse.quote(filename)}"}
  169. )
  170. except Exception as e:
  171. raise HTTPException(status_code=400, detail=f"Error downloading file: {e}")
  172. async def download_basic_file(file_id: str, file_type: str):
  173. service = BasicService(base_url=settings.basic_base_url)
  174. if not file_type or not file_id:
  175. return Response(code=400, msg="file_type and file_id is required")
  176. if file_type == "image":
  177. content, filename, mimetype = await service.excel_talk_image_download(file_id)
  178. return StreamingResponse(
  179. io.BytesIO(content),
  180. media_type=mimetype,
  181. headers={"Content-Disposition": f"attachment; filename={filename}"}
  182. )
  183. elif file_type == "excel":
  184. content, filename, mimetype = await service.excel_talk_excel_download(file_id)
  185. return StreamingResponse(
  186. io.BytesIO(content),
  187. media_type=mimetype,
  188. headers={"Content-Disposition": f"attachment; filename={filename}"}
  189. )
  190. elif file_type == "word":
  191. content, filename, mimetype = await service.questions_talk_word_download(file_id)
  192. return StreamingResponse(
  193. io.BytesIO(content),
  194. media_type=mimetype,
  195. headers={"Content-Disposition": f"attachment; filename={filename}"}
  196. )
  197. else:
  198. return Response(code=400, msg="Unsupported file type")
  199. @router.get("/image/{imageId}", response_model=Response)
  200. async def download_image_file(imageId: str, db=Depends(get_db)):
  201. file_path = f"app/images/{imageId}.png"
  202. def generate():
  203. with open(file_path, "rb") as file:
  204. while True:
  205. data = file.read(1048576) # 读取1MB
  206. if not data:
  207. break
  208. yield data
  209. return StreamingResponse(generate(), media_type="application/octet-stream")