您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

generator.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. from collections.abc import Sequence
  2. from flask_login import current_user
  3. from flask_restful import Resource, reqparse
  4. from controllers.console import api
  5. from controllers.console.app.error import (
  6. CompletionRequestError,
  7. ProviderModelCurrentlyNotSupportError,
  8. ProviderNotInitializeError,
  9. ProviderQuotaExceededError,
  10. )
  11. from controllers.console.wraps import account_initialization_required, setup_required
  12. from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
  13. from core.helper.code_executor.code_node_provider import CodeNodeProvider
  14. from core.helper.code_executor.javascript.javascript_code_provider import JavascriptCodeProvider
  15. from core.helper.code_executor.python3.python3_code_provider import Python3CodeProvider
  16. from core.llm_generator.llm_generator import LLMGenerator
  17. from core.model_runtime.errors.invoke import InvokeError
  18. from libs.login import login_required
  19. class RuleGenerateApi(Resource):
  20. @setup_required
  21. @login_required
  22. @account_initialization_required
  23. def post(self):
  24. parser = reqparse.RequestParser()
  25. parser.add_argument("instruction", type=str, required=True, nullable=False, location="json")
  26. parser.add_argument("model_config", type=dict, required=True, nullable=False, location="json")
  27. parser.add_argument("no_variable", type=bool, required=True, default=False, location="json")
  28. args = parser.parse_args()
  29. account = current_user
  30. try:
  31. rules = LLMGenerator.generate_rule_config(
  32. tenant_id=account.current_tenant_id,
  33. instruction=args["instruction"],
  34. model_config=args["model_config"],
  35. no_variable=args["no_variable"],
  36. )
  37. except ProviderTokenNotInitError as ex:
  38. raise ProviderNotInitializeError(ex.description)
  39. except QuotaExceededError:
  40. raise ProviderQuotaExceededError()
  41. except ModelCurrentlyNotSupportError:
  42. raise ProviderModelCurrentlyNotSupportError()
  43. except InvokeError as e:
  44. raise CompletionRequestError(e.description)
  45. return rules
  46. class RuleCodeGenerateApi(Resource):
  47. @setup_required
  48. @login_required
  49. @account_initialization_required
  50. def post(self):
  51. parser = reqparse.RequestParser()
  52. parser.add_argument("instruction", type=str, required=True, nullable=False, location="json")
  53. parser.add_argument("model_config", type=dict, required=True, nullable=False, location="json")
  54. parser.add_argument("no_variable", type=bool, required=True, default=False, location="json")
  55. parser.add_argument("code_language", type=str, required=False, default="javascript", location="json")
  56. args = parser.parse_args()
  57. account = current_user
  58. try:
  59. code_result = LLMGenerator.generate_code(
  60. tenant_id=account.current_tenant_id,
  61. instruction=args["instruction"],
  62. model_config=args["model_config"],
  63. code_language=args["code_language"],
  64. )
  65. except ProviderTokenNotInitError as ex:
  66. raise ProviderNotInitializeError(ex.description)
  67. except QuotaExceededError:
  68. raise ProviderQuotaExceededError()
  69. except ModelCurrentlyNotSupportError:
  70. raise ProviderModelCurrentlyNotSupportError()
  71. except InvokeError as e:
  72. raise CompletionRequestError(e.description)
  73. return code_result
  74. class RuleStructuredOutputGenerateApi(Resource):
  75. @setup_required
  76. @login_required
  77. @account_initialization_required
  78. def post(self):
  79. parser = reqparse.RequestParser()
  80. parser.add_argument("instruction", type=str, required=True, nullable=False, location="json")
  81. parser.add_argument("model_config", type=dict, required=True, nullable=False, location="json")
  82. args = parser.parse_args()
  83. account = current_user
  84. try:
  85. structured_output = LLMGenerator.generate_structured_output(
  86. tenant_id=account.current_tenant_id,
  87. instruction=args["instruction"],
  88. model_config=args["model_config"],
  89. )
  90. except ProviderTokenNotInitError as ex:
  91. raise ProviderNotInitializeError(ex.description)
  92. except QuotaExceededError:
  93. raise ProviderQuotaExceededError()
  94. except ModelCurrentlyNotSupportError:
  95. raise ProviderModelCurrentlyNotSupportError()
  96. except InvokeError as e:
  97. raise CompletionRequestError(e.description)
  98. return structured_output
  99. class InstructionGenerateApi(Resource):
  100. @setup_required
  101. @login_required
  102. @account_initialization_required
  103. def post(self):
  104. parser = reqparse.RequestParser()
  105. parser.add_argument("flow_id", type=str, required=True, default="", location="json")
  106. parser.add_argument("node_id", type=str, required=False, default="", location="json")
  107. parser.add_argument("current", type=str, required=False, default="", location="json")
  108. parser.add_argument("language", type=str, required=False, default="javascript", location="json")
  109. parser.add_argument("instruction", type=str, required=True, nullable=False, location="json")
  110. parser.add_argument("model_config", type=dict, required=True, nullable=False, location="json")
  111. parser.add_argument("ideal_output", type=str, required=False, default="", location="json")
  112. args = parser.parse_args()
  113. providers: list[type[CodeNodeProvider]] = [Python3CodeProvider, JavascriptCodeProvider]
  114. code_provider: type[CodeNodeProvider] | None = next(
  115. (p for p in providers if p.is_accept_language(args["language"])), None
  116. )
  117. code_template = code_provider.get_default_code() if code_provider else ""
  118. try:
  119. # Generate from nothing for a workflow node
  120. if (args["current"] == code_template or args["current"] == "") and args["node_id"] != "":
  121. from models import App, db
  122. from services.workflow_service import WorkflowService
  123. app = db.session.query(App).where(App.id == args["flow_id"]).first()
  124. if not app:
  125. return {"error": f"app {args['flow_id']} not found"}, 400
  126. workflow = WorkflowService().get_draft_workflow(app_model=app)
  127. if not workflow:
  128. return {"error": f"workflow {args['flow_id']} not found"}, 400
  129. nodes: Sequence = workflow.graph_dict["nodes"]
  130. node = [node for node in nodes if node["id"] == args["node_id"]]
  131. if len(node) == 0:
  132. return {"error": f"node {args['node_id']} not found"}, 400
  133. node_type = node[0]["data"]["type"]
  134. match node_type:
  135. case "llm":
  136. return LLMGenerator.generate_rule_config(
  137. current_user.current_tenant_id,
  138. instruction=args["instruction"],
  139. model_config=args["model_config"],
  140. no_variable=True,
  141. )
  142. case "agent":
  143. return LLMGenerator.generate_rule_config(
  144. current_user.current_tenant_id,
  145. instruction=args["instruction"],
  146. model_config=args["model_config"],
  147. no_variable=True,
  148. )
  149. case "code":
  150. return LLMGenerator.generate_code(
  151. tenant_id=current_user.current_tenant_id,
  152. instruction=args["instruction"],
  153. model_config=args["model_config"],
  154. code_language=args["language"],
  155. )
  156. case _:
  157. return {"error": f"invalid node type: {node_type}"}
  158. if args["node_id"] == "" and args["current"] != "": # For legacy app without a workflow
  159. return LLMGenerator.instruction_modify_legacy(
  160. tenant_id=current_user.current_tenant_id,
  161. flow_id=args["flow_id"],
  162. current=args["current"],
  163. instruction=args["instruction"],
  164. model_config=args["model_config"],
  165. ideal_output=args["ideal_output"],
  166. )
  167. if args["node_id"] != "" and args["current"] != "": # For workflow node
  168. return LLMGenerator.instruction_modify_workflow(
  169. tenant_id=current_user.current_tenant_id,
  170. flow_id=args["flow_id"],
  171. node_id=args["node_id"],
  172. current=args["current"],
  173. instruction=args["instruction"],
  174. model_config=args["model_config"],
  175. ideal_output=args["ideal_output"],
  176. )
  177. return {"error": "incompatible parameters"}, 400
  178. except ProviderTokenNotInitError as ex:
  179. raise ProviderNotInitializeError(ex.description)
  180. except QuotaExceededError:
  181. raise ProviderQuotaExceededError()
  182. except ModelCurrentlyNotSupportError:
  183. raise ProviderModelCurrentlyNotSupportError()
  184. except InvokeError as e:
  185. raise CompletionRequestError(e.description)
  186. class InstructionGenerationTemplateApi(Resource):
  187. @setup_required
  188. @login_required
  189. @account_initialization_required
  190. def post(self) -> dict:
  191. parser = reqparse.RequestParser()
  192. parser.add_argument("type", type=str, required=True, default=False, location="json")
  193. args = parser.parse_args()
  194. match args["type"]:
  195. case "prompt":
  196. from core.llm_generator.prompts import INSTRUCTION_GENERATE_TEMPLATE_PROMPT
  197. return {"data": INSTRUCTION_GENERATE_TEMPLATE_PROMPT}
  198. case "code":
  199. from core.llm_generator.prompts import INSTRUCTION_GENERATE_TEMPLATE_CODE
  200. return {"data": INSTRUCTION_GENERATE_TEMPLATE_CODE}
  201. case _:
  202. raise ValueError(f"Invalid type: {args['type']}")
  203. api.add_resource(RuleGenerateApi, "/rule-generate")
  204. api.add_resource(RuleCodeGenerateApi, "/rule-code-generate")
  205. api.add_resource(RuleStructuredOutputGenerateApi, "/rule-structured-output-generate")
  206. api.add_resource(InstructionGenerateApi, "/instruction-generate")
  207. api.add_resource(InstructionGenerationTemplateApi, "/instruction-generate/template")