app.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. from collections.abc import Generator, Mapping
  2. from typing import Optional, Union
  3. from controllers.service_api.wraps import create_or_update_end_user_for_user_id
  4. from core.app.apps.advanced_chat.app_generator import AdvancedChatAppGenerator
  5. from core.app.apps.agent_chat.app_generator import AgentChatAppGenerator
  6. from core.app.apps.chat.app_generator import ChatAppGenerator
  7. from core.app.apps.completion.app_generator import CompletionAppGenerator
  8. from core.app.apps.workflow.app_generator import WorkflowAppGenerator
  9. from core.app.entities.app_invoke_entities import InvokeFrom
  10. from core.plugin.backwards_invocation.base import BaseBackwardsInvocation
  11. from extensions.ext_database import db
  12. from models.account import Account
  13. from models.model import App, AppMode, EndUser
  14. class PluginAppBackwardsInvocation(BaseBackwardsInvocation):
  15. @classmethod
  16. def invoke_app(
  17. cls, app_id: str,
  18. user_id: str,
  19. tenant_id: str,
  20. conversation_id: Optional[str],
  21. query: Optional[str],
  22. stream: bool,
  23. inputs: Mapping,
  24. files: list[dict],
  25. ) -> Generator[dict | str, None, None] | dict:
  26. """
  27. invoke app
  28. """
  29. app = cls._get_app(app_id, tenant_id)
  30. if not user_id:
  31. user = create_or_update_end_user_for_user_id(app)
  32. else:
  33. user = cls._get_user(user_id)
  34. conversation_id = conversation_id or ""
  35. if app.mode in [AppMode.ADVANCED_CHAT.value, AppMode.AGENT_CHAT.value, AppMode.CHAT.value]:
  36. if not query:
  37. raise ValueError("missing query")
  38. return cls.invoke_chat_app(app, user, conversation_id, query, stream, inputs, files)
  39. elif app.mode in [AppMode.WORKFLOW.value]:
  40. return cls.invoke_workflow_app(app, user, stream, inputs, files)
  41. elif app.mode in [AppMode.COMPLETION]:
  42. return cls.invoke_completion_app(app, user, stream, inputs, files)
  43. raise ValueError("unexpected app type")
  44. @classmethod
  45. def invoke_chat_app(
  46. cls,
  47. app: App,
  48. user: Account | EndUser,
  49. conversation_id: str,
  50. query: str,
  51. stream: bool,
  52. inputs: Mapping,
  53. files: list[dict],
  54. ) -> Generator[dict | str, None, None] | dict:
  55. """
  56. invoke chat app
  57. """
  58. if app.mode == AppMode.ADVANCED_CHAT.value:
  59. workflow = app.workflow
  60. if not workflow:
  61. raise ValueError("unexpected app type")
  62. return AdvancedChatAppGenerator().generate(
  63. app_model=app,
  64. workflow=workflow,
  65. user=user,
  66. args={
  67. "inputs": inputs,
  68. "query": query,
  69. "files": files,
  70. "conversation_id": conversation_id,
  71. },
  72. invoke_from=InvokeFrom.SERVICE_API,
  73. stream=stream
  74. )
  75. elif app.mode == AppMode.AGENT_CHAT.value:
  76. return AgentChatAppGenerator().generate(
  77. app_model=app,
  78. user=user,
  79. args={
  80. "inputs": inputs,
  81. "query": query,
  82. "files": files,
  83. "conversation_id": conversation_id,
  84. },
  85. invoke_from=InvokeFrom.SERVICE_API,
  86. stream=stream
  87. )
  88. elif app.mode == AppMode.CHAT.value:
  89. return ChatAppGenerator().generate(
  90. app_model=app,
  91. user=user,
  92. args={
  93. "inputs": inputs,
  94. "query": query,
  95. "files": files,
  96. "conversation_id": conversation_id,
  97. },
  98. invoke_from=InvokeFrom.SERVICE_API,
  99. stream=stream
  100. )
  101. else:
  102. raise ValueError("unexpected app type")
  103. @classmethod
  104. def invoke_workflow_app(
  105. cls,
  106. app: App,
  107. user: EndUser | Account,
  108. stream: bool,
  109. inputs: Mapping,
  110. files: list[dict],
  111. ):
  112. """
  113. invoke workflow app
  114. """
  115. workflow = app.workflow
  116. if not workflow:
  117. raise ValueError("")
  118. return WorkflowAppGenerator().generate(
  119. app_model=app,
  120. workflow=workflow,
  121. user=user,
  122. args={
  123. 'inputs': inputs,
  124. 'files': files
  125. },
  126. invoke_from=InvokeFrom.SERVICE_API,
  127. stream=stream,
  128. call_depth=1,
  129. )
  130. @classmethod
  131. def invoke_completion_app(
  132. cls,
  133. app: App,
  134. user: EndUser | Account,
  135. stream: bool,
  136. inputs: Mapping,
  137. files: list[dict],
  138. ):
  139. """
  140. invoke completion app
  141. """
  142. return CompletionAppGenerator().generate(
  143. app_model=app,
  144. user=user,
  145. args={
  146. 'inputs': inputs,
  147. 'files': files
  148. },
  149. invoke_from=InvokeFrom.SERVICE_API,
  150. stream=stream,
  151. )
  152. @classmethod
  153. def _get_user(cls, user_id: str) -> Union[EndUser, Account]:
  154. """
  155. get the user by user id
  156. """
  157. user = db.session.query(EndUser).filter(EndUser.id == user_id).first()
  158. if not user:
  159. user = db.session.query(Account).filter(Account.id == user_id).first()
  160. if not user:
  161. raise ValueError('user not found')
  162. return user
  163. @classmethod
  164. def _get_app(cls, app_id: str, tenant_id: str) -> App:
  165. """
  166. get app
  167. """
  168. try:
  169. app = db.session.query(App). \
  170. filter(App.id == app_id). \
  171. filter(App.tenant_id == tenant_id). \
  172. first()
  173. except Exception:
  174. raise ValueError("app not found")
  175. if not app:
  176. raise ValueError("app not found")
  177. return app