Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

canvas_app.py 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #
  2. # Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. import logging
  17. import json
  18. from functools import partial
  19. from flask import request, Response
  20. from flask_login import login_required, current_user
  21. from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService
  22. from api import settings
  23. from api.utils import get_uuid
  24. from api.utils.api_utils import get_json_result, server_error_response, validate_request, get_data_error_result
  25. from agent.canvas import Canvas
  26. from peewee import MySQLDatabase, PostgresqlDatabase
  27. @manager.route('/templates', methods=['GET'])
  28. @login_required
  29. def templates():
  30. return get_json_result(data=[c.to_dict() for c in CanvasTemplateService.get_all()])
  31. @manager.route('/list', methods=['GET'])
  32. @login_required
  33. def canvas_list():
  34. return get_json_result(data=sorted([c.to_dict() for c in \
  35. UserCanvasService.query(user_id=current_user.id)],
  36. key=lambda x: x["update_time"] * -1)
  37. )
  38. @manager.route('/rm', methods=['POST'])
  39. @validate_request("canvas_ids")
  40. @login_required
  41. def rm():
  42. for i in request.json["canvas_ids"]:
  43. if not UserCanvasService.query(user_id=current_user.id, id=i):
  44. return get_json_result(
  45. data=False, message='Only owner of canvas authorized for this operation.',
  46. code=settings.RetCode.OPERATING_ERROR)
  47. UserCanvasService.delete_by_id(i)
  48. return get_json_result(data=True)
  49. @manager.route('/set', methods=['POST'])
  50. @validate_request("dsl", "title")
  51. @login_required
  52. def save():
  53. req = request.json
  54. req["user_id"] = current_user.id
  55. if not isinstance(req["dsl"], str): req["dsl"] = json.dumps(req["dsl"], ensure_ascii=False)
  56. req["dsl"] = json.loads(req["dsl"])
  57. if "id" not in req:
  58. if UserCanvasService.query(user_id=current_user.id, title=req["title"].strip()):
  59. return server_error_response(ValueError("Duplicated title."))
  60. req["id"] = get_uuid()
  61. if not UserCanvasService.save(**req):
  62. return get_data_error_result(message="Fail to save canvas.")
  63. else:
  64. if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
  65. return get_json_result(
  66. data=False, message='Only owner of canvas authorized for this operation.',
  67. code=settings.RetCode.OPERATING_ERROR)
  68. UserCanvasService.update_by_id(req["id"], req)
  69. return get_json_result(data=req)
  70. @manager.route('/get/<canvas_id>', methods=['GET'])
  71. @login_required
  72. def get(canvas_id):
  73. e, c = UserCanvasService.get_by_id(canvas_id)
  74. if not e:
  75. return get_data_error_result(message="canvas not found.")
  76. return get_json_result(data=c.to_dict())
  77. @manager.route('/completion', methods=['POST'])
  78. @validate_request("id")
  79. @login_required
  80. def run():
  81. req = request.json
  82. stream = req.get("stream", True)
  83. e, cvs = UserCanvasService.get_by_id(req["id"])
  84. if not e:
  85. return get_data_error_result(message="canvas not found.")
  86. if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
  87. return get_json_result(
  88. data=False, message='Only owner of canvas authorized for this operation.',
  89. code=settings.RetCode.OPERATING_ERROR)
  90. if not isinstance(cvs.dsl, str):
  91. cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
  92. final_ans = {"reference": [], "content": ""}
  93. message_id = req.get("message_id", get_uuid())
  94. try:
  95. canvas = Canvas(cvs.dsl, current_user.id)
  96. if "message" in req:
  97. canvas.messages.append({"role": "user", "content": req["message"], "id": message_id})
  98. if len([m for m in canvas.messages if m["role"] == "user"]) > 1:
  99. # ten = TenantService.get_info_by(current_user.id)[0]
  100. # req["message"] = full_question(ten["tenant_id"], ten["llm_id"], canvas.messages)
  101. pass
  102. canvas.add_user_input(req["message"])
  103. answer = canvas.run(stream=stream)
  104. logging.debug(canvas)
  105. except Exception as e:
  106. return server_error_response(e)
  107. assert answer is not None, "The dialog flow has no way to interact with you. Please add an 'Interact' component to the end of the flow."
  108. if stream:
  109. assert isinstance(answer,
  110. partial), "The dialog flow has no way to interact with you. Please add an 'Interact' component to the end of the flow."
  111. def sse():
  112. nonlocal answer, cvs
  113. try:
  114. for ans in answer():
  115. for k in ans.keys():
  116. final_ans[k] = ans[k]
  117. ans = {"answer": ans["content"], "reference": ans.get("reference", [])}
  118. yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
  119. canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
  120. canvas.history.append(("assistant", final_ans["content"]))
  121. if final_ans.get("reference"):
  122. canvas.reference.append(final_ans["reference"])
  123. cvs.dsl = json.loads(str(canvas))
  124. UserCanvasService.update_by_id(req["id"], cvs.to_dict())
  125. except Exception as e:
  126. yield "data:" + json.dumps({"code": 500, "message": str(e),
  127. "data": {"answer": "**ERROR**: " + str(e), "reference": []}},
  128. ensure_ascii=False) + "\n\n"
  129. yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n"
  130. resp = Response(sse(), mimetype="text/event-stream")
  131. resp.headers.add_header("Cache-control", "no-cache")
  132. resp.headers.add_header("Connection", "keep-alive")
  133. resp.headers.add_header("X-Accel-Buffering", "no")
  134. resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
  135. return resp
  136. final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else ""
  137. canvas.messages.append({"role": "assistant", "content": final_ans["content"], "id": message_id})
  138. if final_ans.get("reference"):
  139. canvas.reference.append(final_ans["reference"])
  140. cvs.dsl = json.loads(str(canvas))
  141. UserCanvasService.update_by_id(req["id"], cvs.to_dict())
  142. return get_json_result(data={"answer": final_ans["content"], "reference": final_ans.get("reference", [])})
  143. @manager.route('/reset', methods=['POST'])
  144. @validate_request("id")
  145. @login_required
  146. def reset():
  147. req = request.json
  148. try:
  149. e, user_canvas = UserCanvasService.get_by_id(req["id"])
  150. if not e:
  151. return get_data_error_result(message="canvas not found.")
  152. if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
  153. return get_json_result(
  154. data=False, message='Only owner of canvas authorized for this operation.',
  155. code=settings.RetCode.OPERATING_ERROR)
  156. canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
  157. canvas.reset()
  158. req["dsl"] = json.loads(str(canvas))
  159. UserCanvasService.update_by_id(req["id"], {"dsl": req["dsl"]})
  160. return get_json_result(data=req["dsl"])
  161. except Exception as e:
  162. return server_error_response(e)
  163. @manager.route('/test_db_connect', methods=['POST'])
  164. @validate_request("db_type", "database", "username", "host", "port", "password")
  165. @login_required
  166. def test_db_connect():
  167. req = request.json
  168. try:
  169. if req["db_type"] in ["mysql", "mariadb"]:
  170. db = MySQLDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
  171. password=req["password"])
  172. elif req["db_type"] == 'postgresql':
  173. db = PostgresqlDatabase(req["database"], user=req["username"], host=req["host"], port=req["port"],
  174. password=req["password"])
  175. db.connect()
  176. db.close()
  177. return get_json_result(data="Database Connection Successful!")
  178. except Exception as e:
  179. return server_error_response(e)